Merge branch 'craftyguy/f0rmz' into 'master'

f0rmz: new subproject to create a form/wizard setup thing

See merge request postmarketOS/buffybox!62
This commit is contained in:
Johannes Marbach 2025-09-23 08:48:35 +00:00
commit d15c3fa086
36 changed files with 4693 additions and 241 deletions

View file

@ -10,6 +10,8 @@ BuffyBox is a suite of graphical applications for the terminal.
**[unl0kr]** Disk unlocking UI for the initramfs
**[f0rmz]** A form/setup wizard for the initramfs
### Utilities
**[squeek2lvgl]** Converter for transforming [Squeekboard] layouts into [LVGL]-compatible C code

View file

@ -39,15 +39,10 @@ static void print_usage();
*/
static void init_opts(bb_cli_opts *opts) {
bbx_cli_init_common_opts(&opts->common);
opts->num_config_files = 0;
opts->config_files = NULL;
opts->hor_res = -1;
opts->ver_res = -1;
opts->x_offset = 0;
opts->y_offset = 0;
opts->dpi = 0;
opts->rotation = LV_DISPLAY_ROTATION_0;
opts->verbose = false;
int fd_rotate = open("/sys/class/graphics/fbcon/rotate", O_RDONLY);
if (fd_rotate < 0) {
@ -148,16 +143,12 @@ void bb_cli_parse_opts(int argc, char *argv[], bb_cli_opts *opts) {
opts->num_config_files++;
break;
case 'g':
if (sscanf(optarg, "%ix%i@%i,%i", &(opts->hor_res), &(opts->ver_res), &(opts->x_offset), &(opts->y_offset)) != 4) {
if (sscanf(optarg, "%ix%i", &(opts->hor_res), &(opts->ver_res)) != 2) {
bbx_log(BBX_LOG_LEVEL_ERROR, "Invalid geometry argument \"%s\"\n", optarg);
if (bbx_cli_parse_geometry(optarg, &opts->common) != 0) {
exit(EXIT_FAILURE);
}
}
break;
case 'd':
if (sscanf(optarg, "%i", &(opts->dpi)) != 1) {
bbx_log(BBX_LOG_LEVEL_ERROR, "Invalid dpi argument \"%s\"\n", optarg);
if (bbx_cli_parse_dpi(optarg, &opts->common) != 0) {
exit(EXIT_FAILURE);
}
break;
@ -187,11 +178,11 @@ void bb_cli_parse_opts(int argc, char *argv[], bb_cli_opts *opts) {
print_usage();
exit(EXIT_SUCCESS);
case 'v':
opts->verbose = true;
opts->common.verbose = true;
break;
case 'V':
fprintf(stderr, "buffyboard %s\n", PROJECT_VERSION);
exit(0);
bbx_cli_print_version_and_exit("unl0kr");
break;
default:
print_usage();
exit(EXIT_FAILURE);

View file

@ -8,29 +8,20 @@
#define BB_COMMAND_LINE_H
#include "lvgl/lvgl.h"
#include "../shared/cli_common.h"
/**
* Options parsed from command line arguments
*/
typedef struct {
/* Common cli options */
bbx_cli_common_opts common;
/* Number of config files */
int num_config_files;
/* Paths of config file */
const char **config_files;
/* Horizontal display resolution */
int hor_res;
/* Vertical display resolution */
int ver_res;
/* Horizontal display offset */
int x_offset;
/* Vertical display offset */
int y_offset;
/* DPI */
int dpi;
/* Display rotation */
lv_display_rotation_t rotation;
/* Verbose mode. If true, provide more detailed logging output on STDERR. */
bool verbose;
} bb_cli_opts;
/**

View file

@ -158,7 +158,7 @@ int main(int argc, char *argv[]) {
bb_cli_parse_opts(argc, argv, &cli_opts);
/* Set up log level */
if (cli_opts.verbose) {
if (cli_opts.common.verbose) {
bbx_log_set_level(BBX_LOG_LEVEL_VERBOSE);
}
@ -194,12 +194,12 @@ int main(int argc, char *argv[]) {
lv_display_get_vertical_resolution(disp));
/* Override display properties with command line options if necessary */
lv_display_set_offset(disp, cli_opts.x_offset, cli_opts.y_offset);
if (cli_opts.hor_res > 0 && cli_opts.ver_res > 0) {
lv_display_set_resolution(disp, cli_opts.hor_res, cli_opts.ver_res);
lv_display_set_offset(disp, cli_opts.common.x_offset, cli_opts.common.y_offset);
if (cli_opts.common.hor_res > 0 && cli_opts.common.ver_res > 0) {
lv_display_set_resolution(disp, cli_opts.common.hor_res, cli_opts.common.ver_res);
}
if (cli_opts.dpi > 0) {
lv_display_set_dpi(disp, cli_opts.dpi);
if (cli_opts.common.dpi > 0) {
lv_display_set_dpi(disp, cli_opts.common.dpi);
}
/* Set up display rotation */

147
f0rmz/README.md Normal file
View file

@ -0,0 +1,147 @@
f0rmz
=====
Form collection tool for the initramfs based on [LVGL].
[[_TOC_]]
# About
f0rmz is a standalone form collection tool built on [LVGL], with rendering directly to the Linux framebuffer. It shares the same look and feel as [unl0kr] while providing a way to collect structured user input through configurable forms.
f0rmz was created for use cases like prompting for username, passphrases, and hostname during "first boot" in the initramfs, before creating LUKS partitions or generating configuration files.
# Status
f0rmz provides a complete form collection workflow:
- **Intro Page**: Configurable welcome screen with title and body text
- **Multi-field Forms**: Runtime-configurable forms via INI files using the same format as unl0kr
- **Touch-optimized UI**: One field per page for simplified display on small screens
- **Field Types**: Text and password input fields with validation
- **Summary Screen**: Review all values with click-to-edit capability
- **Input Support**: On-screen keyboard with layout switching, physical keyboard, mouse, and touchscreen
- **Theming**: Light and dark themes with runtime switching (shared with unl0kr)
- **Structured Output**: Key=value pairs printed to stdout for easy parsing
# Usage
f0rmz can be invoked with various command line options:
```
$ f0rmz --help
Usage: f0rmz [OPTION]
-C, --config Path to form configuration file
-g, --geometry=NxM[@X,Y] Force display size and offset
-d, --dpi=N Override display DPI
-h, --help Show this help
-v, --verbose Enable verbose logging
-V, --version Show version
```
f0rmz reads configuration files in the following order:
- `/usr/share/f0rmz/f0rmz.conf`
- `/usr/share/f0rmz/f0rmz.conf.d/*` (alphabetically)
- `/etc/f0rmz.conf`
- `/etc/f0rmz.conf.d/*` (alphabetically)
- Custom config file (specified with `-C`)
## Configuration
### Basic Example
```ini
[intro]
title=Welcome to postmarketOS!
body=Let's set up your device with a few quick questions.
[form.username]
type=text
label=Username
required=true
[form.password]
type=password
label=Password
required=true
[form.hostname]
type=text
label=Hostname
required=false
```
### Configuration Sections
#### `[intro]`
- `title` - Welcome screen title text
- `body` - Welcome screen body text
#### `[form.fieldname]`
Define form fields where `fieldname` is the output key name.
- `type` - Field type: `text` or `password`
- `label` - Display label for the field
- `required` - Whether field is required: `true` or `false` (default: `true`)
#### Shared Sections
f0rmz supports the same configuration sections as unl0kr for theming, keyboard, and input device settings. See [unl0kr.conf] for examples of `[general]`, `[keyboard]`, `[textarea]`, `[theme]`, `[input]`, and `[quirks]` sections.
## Navigation Flow
1. **Intro Page** - Welcome screen with "Get Started" button
2. **Field Pages** - One field per page with Previous/Next navigation
3. **Summary Screen** - Review all values, click any field to edit
4. **Output** - Print `key=value` pairs to stdout and exit
## Output Format
f0rmz outputs structured data as key=value pairs:
```
username=alice
password=secretpass
hostname=mydevice
```
# Development
## Dependencies
- [inih] - INI file parsing
- [lvgl] (git submodule / linked statically)
- [squeek2lvgl] (linked statically)
- [libinput] - Input device handling
- [libudev] - Device enumeration
- [libxkbcommon] - Keyboard layout support
- evdev kernel module
## Backends
f0rmz uses the same backend system as unl0kr:
- fbdev (default)
- drm (optional, if [libdrm] is available)
The active backend can be selected via the `general.backend` option in the configuration file.
## Keyboard layouts
f0rmz uses [squeekboard layouts] converted to C via [squeek2lvgl], the same as unl0kr. To regenerate the layouts, ensure that you have pipenv installed and run:
```
$ ./regenerate-layouts.sh
```
[LVGL]: https://lvgl.io
[unl0kr]: ../unl0kr
[inih]: https://github.com/benhoyt/inih
[lvgl]: https://github.com/lvgl/lvgl
[squeek2lvgl]: ../squeek2lvgl
[libinput]: https://gitlab.freedesktop.org/libinput/libinput
[libudev]: https://github.com/systemd/systemd/tree/main/src/libudev
[libxkbcommon]: https://github.com/xkbcommon/libxkbcommon
[libdrm]: https://gitlab.freedesktop.org/mesa/drm
[squeekboard layouts]: https://gitlab.gnome.org/World/Phosh/squeekboard/-/tree/master/data/keyboards
[unl0kr.conf]: ../unl0kr/unl0kr.conf

73
f0rmz/command_line.c Normal file
View file

@ -0,0 +1,73 @@
/**
* Copyright 2025 Clayton Craft
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "command_line.h"
#include "../shared/log.h"
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
static void init_opts(f0_cli_opts *opts) {
bbx_cli_init_common_opts(&opts->common);
opts->config_file = NULL;
}
static void print_usage() {
fprintf(stderr,
"Usage: f0rmz [OPTION]\n"
"\n"
" -C, --config Path to form configuration file\n"
" -g, --geometry=NxM[@X,Y] Force display size and offset\n"
" -d, --dpi=N Override display DPI\n"
" -h, --help Show this help\n"
" -v, --verbose Enable verbose logging\n"
" -V, --version Show version\n");
}
void f0_cli_parse_opts(int argc, char *argv[], f0_cli_opts *opts) {
init_opts(opts);
struct option long_opts[] = {
{ "config", required_argument, NULL, 'C' },
{ "geometry", required_argument, NULL, 'g' },
{ "dpi", required_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
int opt;
while ((opt = getopt_long(argc, argv, "C:g:d:hvV", long_opts, NULL)) != -1) {
switch (opt) {
case 'C':
opts->config_file = optarg;
break;
case 'g':
if (bbx_cli_parse_geometry(optarg, &opts->common) != 0) {
exit(EXIT_FAILURE);
}
break;
case 'd':
if (bbx_cli_parse_dpi(optarg, &opts->common) != 0) {
exit(EXIT_FAILURE);
}
break;
case 'h':
print_usage();
exit(EXIT_SUCCESS);
case 'v':
opts->common.verbose = true;
break;
case 'V':
bbx_cli_print_version_and_exit("f0rmz");
break;
default:
print_usage();
exit(EXIT_FAILURE);
}
}
}

18
f0rmz/command_line.h Normal file
View file

@ -0,0 +1,18 @@
/**
* Copyright 2025 Clayton Craft
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef F0_COMMAND_LINE_H
#define F0_COMMAND_LINE_H
#include "../shared/cli_common.h"
typedef struct {
bbx_cli_common_opts common;
const char *config_file;
} f0_cli_opts;
void f0_cli_parse_opts(int argc, char *argv[], f0_cli_opts *opts);
#endif /* F0_COMMAND_LINE_H */

216
f0rmz/config.c Normal file
View file

@ -0,0 +1,216 @@
/**
* Copyright 2025 Clayton Craft
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "config.h"
#include "../shared/config.h"
#include "../shared/log.h"
#include "../squeek2lvgl/sq2lv.h"
#include <ini.h>
#include <stdlib.h>
#include <string.h>
/**
* Static prototypes
*/
/**
* Handle parsing events from INIH.
*
* @param user_data pointer to user data
* @param section current section name
* @param key option key
* @param value option value
* @return 0 on error, non-0 otherwise
*/
static int parsing_handler(void* user_data, const char* section, const char* key, const char* value);
/**
* Static functions
*/
static int parsing_handler(void* user_data, const char* section, const char* key, const char* value) {
f0_config_opts *opts = (f0_config_opts *)user_data;
if (strcmp(section, "general") == 0) {
if (strcmp(key, "backend") == 0) {
bbx_backends_backend_id_t id = bbx_backends_find_backend_with_name(value);
if (id != BBX_BACKENDS_BACKEND_NONE) {
opts->general.backend = id;
return 1;
}
}
} else if (strcmp(section, "keyboard") == 0) {
if (strcmp(key, "autohide") == 0) {
if (bbx_config_parse_bool(value, &(opts->keyboard.autohide))) {
return 1;
}
} else if (strcmp(key, "layout") == 0) {
sq2lv_layout_id_t id = sq2lv_find_layout_with_short_name(value);
if (id != SQ2LV_LAYOUT_NONE) {
opts->keyboard.layout_id = id;
return 1;
}
} else if (strcmp(key, "popovers") == 0) {
if (bbx_config_parse_bool(value, &(opts->keyboard.popovers))) {
return 1;
}
}
} else if (strcmp(section, "theme") == 0) {
if (strcmp(key, "default") == 0) {
bbx_themes_theme_id_t id = bbx_themes_find_theme_with_name(value);
if (id != BBX_THEMES_THEME_NONE) {
opts->theme.default_id = id;
return 1;
}
} else if (strcmp(key, "alternate") == 0) {
bbx_themes_theme_id_t id = bbx_themes_find_theme_with_name(value);
if (id != BBX_THEMES_THEME_NONE) {
opts->theme.alternate_id = id;
return 1;
}
}
} else if (strcmp(section, "input") == 0) {
if (strcmp(key, "keyboard") == 0) {
if (bbx_config_parse_bool(value, &(opts->input.keyboard))) {
return 1;
}
} else if (strcmp(key, "pointer") == 0) {
if (bbx_config_parse_bool(value, &(opts->input.pointer))) {
return 1;
}
} else if (strcmp(key, "touchscreen") == 0) {
if (bbx_config_parse_bool(value, &(opts->input.touchscreen))) {
return 1;
}
}
} else if (strcmp(section, "quirks") == 0) {
if (strcmp(key, "fbdev_force_refresh") == 0) {
if (bbx_config_parse_bool(value, &(opts->quirks.fbdev_force_refresh))) {
return 1;
}
} else if (strcmp(key, "terminal_prevent_graphics_mode") == 0) {
if (bbx_config_parse_bool(value, &(opts->quirks.terminal_prevent_graphics_mode))) {
return 1;
}
} else if (strcmp(key, "terminal_allow_keyboard_input") == 0) {
if (bbx_config_parse_bool(value, &(opts->quirks.terminal_allow_keyboard_input))) {
return 1;
}
}
} else if (strcmp(section, "intro") == 0) {
if (strcmp(key, "title") == 0) {
char *title = strdup(value);
if (title) {
opts->intro.title = title;
return 1;
}
} else if (strcmp(key, "body") == 0) {
char *body = strdup(value);
if (body) {
opts->intro.body = body;
return 1;
}
}
} else if (strncmp(section, "form.", 5) == 0) {
/* Extract field name */
const char *field_name = section + 5;
/* Find or create field */
f0_form_field_t *field = NULL;
for (int i = 0; i < opts->num_fields; i++) {
if (strcmp(opts->fields[i].name, field_name) == 0) {
field = &opts->fields[i];
break;
}
}
if (!field) {
/* Create new field */
opts->fields = realloc(opts->fields, (opts->num_fields + 1) * sizeof(f0_form_field_t));
field = &opts->fields[opts->num_fields];
lv_memzero(field, sizeof(f0_form_field_t));
field->name = strdup(field_name);
opts->num_fields++;
}
/* Parse field properties */
if (strcmp(key, "type") == 0) {
if (strcmp(value, "text") == 0) {
field->type = F0_FIELD_TYPE_TEXT;
return 1;
} else if (strcmp(value, "password") == 0) {
field->type = F0_FIELD_TYPE_PASSWORD;
return 1;
}
} else if (strcmp(key, "label") == 0) {
field->label = strdup(value);
return 1;
} else if (strcmp(key, "required") == 0) {
if (bbx_config_parse_bool(value, &field->required)) {
return 1;
}
}
}
bbx_log(BBX_LOG_LEVEL_ERROR, "Ignoring invalid config value \"%s\" for key \"%s\" in section \"%s\"", value, key, section);
return 1; /* Return 1 (true) so that we can use the return value of ini_parse exclusively for file-level errors */
}
/**
* Public functions
*/
void f0_config_init_opts(f0_config_opts *opts) {
opts->general.backend = bbx_backends_backends[0] == NULL ? BBX_BACKENDS_BACKEND_NONE : 0;
opts->intro.title = "A Form!";
opts->intro.body = "Please complete the following form.";
opts->theme.default_id = BBX_THEMES_THEME_BREEZY_DARK;
opts->theme.alternate_id = BBX_THEMES_THEME_BREEZY_LIGHT;
opts->keyboard.autohide = true;
opts->keyboard.layout_id = SQ2LV_LAYOUT_US;
opts->keyboard.popovers = true;
opts->textarea.obscured = true;
opts->textarea.bullet = LV_SYMBOL_BULLET;
opts->input.keyboard = true;
opts->input.pointer = true;
opts->input.touchscreen = true;
opts->quirks.fbdev_force_refresh = false;
opts->quirks.terminal_prevent_graphics_mode = false;
opts->quirks.terminal_allow_keyboard_input = false;
opts->fields = NULL;
opts->num_fields = 0;
}
void f0_config_parse_directory(const char *path, f0_config_opts *opts) {
/* Find files in directory */
char **found = NULL;
int num_found = 0;
bbx_config_find_files(path, &found, &num_found);
/* Sort and parse files */
qsort(found, num_found, sizeof(char *), bbx_config_compare_strings);
f0_config_parse_files((const char **)found, num_found, opts);
/* Free memory */
for (int i = 0; i < num_found; ++i) {
free(found[i]);
}
free(found);
}
void f0_config_parse_files(const char **files, int num_files, f0_config_opts *opts) {
for (int i = 0; i < num_files; ++i) {
f0_config_parse_file(files[i], opts);
}
}
void f0_config_parse_file(const char *path, f0_config_opts *opts) {
bbx_log(BBX_LOG_LEVEL_VERBOSE, "Parsing config file %s", path);
if (ini_parse(path, parsing_handler, opts) != 0) {
bbx_log(BBX_LOG_LEVEL_ERROR, "Ignoring invalid config file %s", path);
}
}

167
f0rmz/config.h Normal file
View file

@ -0,0 +1,167 @@
/**
* Copyright 2025 Clayton Craft
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef F0_CONFIG_H
#define F0_CONFIG_H
#include "../shared/backends.h"
#include "../shared/config.h"
#include "../shared/themes.h"
#include "sq2lv_layouts.h"
#include <stdbool.h>
#include <stdint.h>
/**
* General options
*/
typedef struct {
/* Backend to use */
bbx_backends_backend_id_t backend;
} f0_config_opts_general;
/**
* Options related to the keyboard
*/
typedef struct {
/* If true, hide the keyboard on launch when a hardware keyboard is connected */
bool autohide;
/* Keyboard layout */
sq2lv_layout_id_t layout_id;
/* If true, display key popovers on press */
bool popovers;
} f0_config_opts_keyboard;
/**
* Options related to the theme
*/
typedef struct {
/* Default theme */
bbx_themes_theme_id_t default_id;
/* Alternate theme */
bbx_themes_theme_id_t alternate_id;
} f0_config_opts_theme;
/**
* Options related to the password textarea
*/
typedef struct {
/* If true, disguise the entered text with dots */
bool obscured;
/* The character to use for disguising the entered text */
const char *bullet;
} f0_config_opts_textarea;
/**
* Options related to input devices
*/
typedef struct {
/* If true and a keyboard device is connected, use it for input */
bool keyboard;
/* If true and a pointer device is connected, use it for input */
bool pointer;
/* If true and a touchscreen device is connected, use it for input */
bool touchscreen;
} f0_config_opts_input;
/**
* (Normally unneeded) quirky options
*/
typedef struct {
/* If true and using the framebuffer backend, force a refresh on every draw operation */
bool fbdev_force_refresh;
/* If true, do *not* switch terminal into graphics mode (will show terminal command prompt) */
bool terminal_prevent_graphics_mode;
/* If true, do *not* turn off terminal keyboard input (will show entered characters) */
bool terminal_allow_keyboard_input;
} f0_config_opts_quirks;
/**
* Form configuration options
*/
/**
* Intro section configuration
*/
typedef struct {
/* Welcome screen title */
const char *title;
/* Welcome screen body text */
const char *body;
} f0_config_intro;
/**
* Form field types
*/
typedef enum {
F0_FIELD_TYPE_TEXT,
F0_FIELD_TYPE_PASSWORD
} f0_field_type_t;
/**
* Form field definition
*/
typedef struct {
char *name;
f0_field_type_t type;
char *label;
bool required;
} f0_form_field_t;
typedef struct {
/* General options */
f0_config_opts_general general;
/* Options related to the keyboard */
f0_config_opts_keyboard keyboard;
/* Options related to the theme */
f0_config_opts_theme theme;
/* Options related to the password textarea */
f0_config_opts_textarea textarea;
/* Options related to input devices */
f0_config_opts_input input;
/* Options related to (normally unneeded) quirks */
f0_config_opts_quirks quirks;
/* Intro section */
f0_config_intro intro;
/* Form fields */
f0_form_field_t *fields;
/* Number of form fields/pages */
int num_fields;
} f0_config_opts;
/**
* Initialize config options with default values.
*
* @param opts pointer to the options struct
*/
void f0_config_init_opts(f0_config_opts *opts);
/**
* Find configuration files in a directory and parse them in alphabetic order.
*
* @param path directory path
* @param opts pointer for writing the parsed options into
*/
void f0_config_parse_directory(const char *path, f0_config_opts *opts);
/**
* Parse one or more configuration files.
*
* @param files paths to configuration files
* @param num_files number of configuration files
* @param opts pointer for writing the parsed options into
*/
void f0_config_parse_files(const char **files, int num_files, f0_config_opts *opts);
/**
* Parse a configuration file.
*
* @param path path to configuration file
* @param opts pointer for writing the parsed options into
*/
void f0_config_parse_file(const char *path, f0_config_opts *opts);
#endif /* F0_CONFIG_H */

117
f0rmz/lv_conf.defaults Normal file
View file

@ -0,0 +1,117 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# Manual post-processing steps for the generated lv_conf.h
# 1. Comment LV_USE_LINUX_DRM (handled by meson.build)
# 2. Remove LV_BIG_ENDIAN_SYSTEM (handled by meson.build)
# 3. Add `#define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(bbx_font_32)` (a bug in generate_lv_conf.py)
LV_COLOR_DEPTH 32
LV_USE_STDLIB_MALLOC LV_STDLIB_CLIB
LV_USE_STDLIB_STRING LV_STDLIB_CLIB
LV_USE_STDLIB_SPRINTF LV_STDLIB_CLIB
LV_USE_DRAW_SW 1
LV_DRAW_SW_COMPLEX 1
LV_DRAW_SW_SUPPORT_RGB565 0
LV_DRAW_SW_SUPPORT_RGB565_SWAPPED 0
LV_DRAW_SW_SUPPORT_RGB565A8 0
LV_DRAW_SW_SUPPORT_RGB888 1
LV_DRAW_SW_SUPPORT_XRGB8888 1
LV_DRAW_SW_SUPPORT_ARGB8888 1
LV_DRAW_SW_SUPPORT_ARGB8888_PREMULTIPLIED 0
LV_DRAW_SW_SUPPORT_L8 0
LV_DRAW_SW_SUPPORT_AL88 0
LV_DRAW_SW_SUPPORT_A8 0
LV_DRAW_SW_SUPPORT_I1 0
LV_USE_LOG 1
LV_LOG_LEVEL LV_LOG_LEVEL_WARN
LV_USE_PRIVATE_API 1
LV_FONT_MONTSERRAT_8 0
LV_FONT_MONTSERRAT_10 0
LV_FONT_MONTSERRAT_12 0
LV_FONT_MONTSERRAT_14 0
LV_FONT_MONTSERRAT_16 0
LV_FONT_MONTSERRAT_18 0
LV_FONT_MONTSERRAT_20 0
LV_FONT_MONTSERRAT_22 0
LV_FONT_MONTSERRAT_24 0
LV_FONT_MONTSERRAT_26 0
LV_FONT_MONTSERRAT_28 0
LV_FONT_MONTSERRAT_30 0
LV_FONT_MONTSERRAT_32 0
LV_FONT_MONTSERRAT_34 0
LV_FONT_MONTSERRAT_36 0
LV_FONT_MONTSERRAT_38 0
LV_FONT_MONTSERRAT_40 0
LV_FONT_MONTSERRAT_42 0
LV_FONT_MONTSERRAT_44 0
LV_FONT_MONTSERRAT_46 0
LV_FONT_MONTSERRAT_48 0
LV_FONT_MONTSERRAT_28_COMPRESSED 0
LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0
LV_FONT_SIMSUN_14_CJK 0
LV_FONT_SIMSUN_16_CJK 0
LV_FONT_UNSCII_8 0
LV_FONT_UNSCII_16 0
#LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(bbx_font_32)
LV_FONT_DEFAULT &bbx_font_32
LV_WIDGETS_HAS_DEFAULT_VALUE 0
LV_USE_ANIMIMG 0
LV_USE_ARC 0
LV_USE_BAR 0
LV_USE_BUTTON 1
LV_USE_BUTTONMATRIX 1
LV_USE_CALENDAR 0
LV_USE_CANVAS 0
LV_USE_CHART 0
LV_USE_CHECKBOX 0
LV_USE_DROPDOWN 1
LV_USE_IMAGE 1
LV_USE_IMAGEBUTTON 0
LV_USE_KEYBOARD 1
LV_USE_LABEL 1
LV_LABEL_TEXT_SELECTION 0
LV_LABEL_LONG_TXT_HINT 0
LV_USE_LED 0
LV_USE_LINE 0
LV_USE_LIST 0
LV_USE_LOTTIE 0
LV_USE_MENU 0
LV_USE_MSGBOX 1
LV_USE_ROLLER 0
LV_USE_SCALE 0
LV_USE_SLIDER 0
LV_USE_SPAN 0
LV_USE_SPINBOX 0
LV_USE_SPINNER 0
LV_USE_SWITCH 0
LV_USE_TEXTAREA 1
LV_TEXTAREA_DEF_PWD_SHOW_TIME 0 /*ms*/
LV_USE_TABLE 0
LV_USE_TABVIEW 0
LV_USE_TILEVIEW 0
LV_USE_WIN 0
LV_USE_THEME_DEFAULT 0
LV_USE_THEME_SIMPLE 0
LV_USE_THEME_MONO 0
LV_USE_FLEX 1
LV_USE_GRID 0
LV_USE_LINUX_FBDEV 1
LV_LINUX_FBDEV_BSD 0
LV_LINUX_FBDEV_RENDER_MODE LV_DISPLAY_RENDER_MODE_PARTIAL
LV_USE_LINUX_DRM 0
LV_USE_LIBINPUT 1
LV_LIBINPUT_BSD 0
LV_LIBINPUT_XKB 1
LV_BUILD_EXAMPLES 0
LV_BUILD_DEMOS 0

1392
f0rmz/lv_conf.h Normal file

File diff suppressed because it is too large Load diff

908
f0rmz/main.c Normal file
View file

@ -0,0 +1,908 @@
/**
* Copyright 2025 Clayton Craft
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "command_line.h"
#include "config.h"
#include "../shared/backends.h"
#include "../shared/display.h"
#include "../shared/header.h"
#include "../shared/indev.h"
#include "../shared/keyboard.h"
#include "../shared/log.h"
#include "../shared/theme.h"
#include "../shared/themes.h"
#include "../shared/terminal.h"
#include "../squeek2lvgl/sq2lv.h"
#include "lvgl/lvgl.h"
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/reboot.h>
#define F0_PASSWORD_HIDDEN_DOTS "••••••••"
/**
* Static variables
*/
f0_cli_opts cli_opts;
f0_config_opts conf_opts;
bool is_alternate_theme = false;
bool is_keyboard_hidden = false;
static char **field_values = NULL;
int current_field_index = 0;
lv_obj_t *form_container = NULL;
lv_obj_t *form_textarea = NULL;
lv_obj_t *keyboard = NULL;
int32_t content_height_with_kb;
int32_t content_height_without_kb;
/**
* 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_alternate true if the alternate theme should be applied, false if the default theme should be applied
*/
static void set_theme(bool is_alternate);
/**
* Get the UI theme.
*
* @param is_alternate true if the alternate theme should be selected, false if the default theme should be selected
*/
static const bbx_theme * get_theme(bool is_alternate);
/**
* Show the intro screen.
*
*/
static void show_intro_screen(void);
/**
* Handle LV_EVENT_KEY events from the intro 'get started' button.
*
* @param event the event object
*/
static void get_started_btn_clicked_cb(lv_event_t *event);
/**
* Handle LV_EVENT_KEY events on intro screen.
*
* @param event the event object
*/
static void intro_key_cb(lv_event_t *event);
/**
* Show form screen with a field
*/
static void show_form_screen(void);
/**
* Handle LV_EVENT_CLICKED events from the form field submit.
*
* @param event the event object
*/
static void field_submit_cb(lv_event_t *event);
/**
* Handle LV_EVENT_CLICKED events from the form 'previous' button.
*
* @param event the event object
*/
static void prev_btn_clicked_cb(lv_event_t *event);
/**
* Handle LV_EVENT_CLICKED events from the form 'next' button.
*
* @param event the event object
*/
static void next_btn_clicked_cb(lv_event_t *event);
/**
* Validate a form field according to its requirements.
*
* @param field_index index of the field to validate
* @return true if field is valid, false otherwise
*/
static bool validate_field(int field_index);
/**
* Set visual validation error state on the current textarea.
*
* @param has_error true to show error styling, false to clear it
*/
static void set_field_validation_error(bool has_error);
/**
* Save current textarea content and validate the field.
*
* @return true if field is valid, false if validation failed
*/
static bool save_and_validate_current_field(void);
/**
* 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);
/**
* Handle LV_EVENT_CLICKED events from password visibility toggle button.
*
* @param event the event object
*/
static void toggle_password_btn_clicked_cb(lv_event_t *event);
/**
* Handle LV_EVENT_CLICKED events from password visibility toggle button in
* summary.
*
* @param event the event object
*/
static void toggle_password_summary_btn_clicked_cb(lv_event_t *event);
/**
* 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 confirmation events from the shutdown message box.
*
* @param event the event object
*/
static void shutdown_mbox_confirmed_cb(lv_event_t *event);
/**
* Handle declination events from the shutdown message box.
*
* @param event the event object
*/
static void shutdown_mbox_declined_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);
/**
* Show summary screen with all field values.
*/
static void show_summary_screen(void);
/**
* Handle LV_EVENT_CLICKED events from summary field items.
*
* @param event the event object
*/
static void summary_field_clicked_cb(lv_event_t *event);
/**
* Handle LV_EVENT_CLICKED events from finish button.
*
* @param event the event object
*/
static void finish_cb(lv_event_t *event);
/**
* Shuts down the device.
*/
static void shutdown(void);
/**
* Handle termination signals sent to the process.
*
* @param signum the signal's number
*/
static void sigaction_handler(int signum);
/**
* Restore the terminal and exit from the program with EXIT_FAILURE.
*/
static void exit_failure();
/**
* Static functions
*/
static void intro_key_cb(lv_event_t *event) {
uint32_t key = lv_indev_get_key(lv_indev_active());
if (key == LV_KEY_ENTER) {
get_started_btn_clicked_cb(event);
}
}
static void toggle_theme_btn_clicked_cb(lv_event_t *event) {
LV_UNUSED(event);
toggle_theme();
}
static void sigaction_handler(int signum) {
bbx_terminal_reset_current_terminal();
exit(signum);
}
static void exit_failure() {
bbx_terminal_reset_current_terminal();
exit(EXIT_FAILURE);
}
static void toggle_theme(void) {
is_alternate_theme = !is_alternate_theme;
set_theme(is_alternate_theme);
}
static void set_theme(bool is_alternate) {
bbx_theme_apply(get_theme(is_alternate));
}
static const bbx_theme * get_theme(bool is_alternate) {
return bbx_themes_themes[is_alternate ? conf_opts.theme.alternate_id : conf_opts.theme.default_id];
}
static void toggle_kb_btn_clicked_cb(lv_event_t *event) {
LV_UNUSED(event);
toggle_keyboard_hidden();
}
static void toggle_keyboard_hidden(void) {
is_keyboard_hidden = !is_keyboard_hidden;
set_keyboard_hidden(is_keyboard_hidden);
}
static void set_keyboard_hidden(bool is_hidden) {
if (!form_container) return;
lv_anim_t container_anim;
lv_anim_init(&container_anim);
lv_anim_set_var(&container_anim, form_container);
lv_anim_set_exec_cb(&container_anim, (lv_anim_exec_xcb_t) lv_obj_set_height);
lv_anim_set_path_cb(&container_anim, lv_anim_path_ease_out);
lv_anim_set_time(&container_anim, 500);
lv_anim_set_values(&container_anim,
is_hidden? content_height_with_kb : content_height_without_kb,
is_hidden? content_height_without_kb : content_height_with_kb);
lv_anim_start(&container_anim);
}
static void toggle_password_btn_clicked_cb(lv_event_t *event) {
lv_obj_t *btn = lv_event_get_target(event);
lv_obj_t *textarea = (lv_obj_t *)lv_obj_get_user_data(btn);
lv_obj_t *btn_label = lv_obj_get_child(btn, 0);
bool is_obscured = lv_textarea_get_password_mode(textarea);
lv_textarea_set_password_mode(textarea, !is_obscured);
lv_label_set_text(btn_label, is_obscured ? LV_SYMBOL_EYE_CLOSE : LV_SYMBOL_EYE_OPEN);
}
static void toggle_password_summary_btn_clicked_cb(lv_event_t *event) {
lv_obj_t *btn = lv_event_get_target(event);
lv_obj_t *value_label = (lv_obj_t *)lv_obj_get_user_data(btn);
lv_obj_t *btn_label = lv_obj_get_child(btn, 0);
const char *current_text = lv_label_get_text(value_label);
bool is_obscured = (strcmp(current_text, F0_PASSWORD_HIDDEN_DOTS) == 0);
if (is_obscured) {
/* Show actual password - need field index to get real value */
int field_index = (int)(intptr_t)lv_obj_get_user_data(value_label);
const char *real_value = field_values[field_index] ? field_values[field_index] : "";
lv_label_set_text(value_label, real_value);
lv_label_set_text(btn_label, LV_SYMBOL_EYE_CLOSE);
} else {
lv_label_set_text(value_label, F0_PASSWORD_HIDDEN_DOTS);
lv_label_set_text(btn_label, LV_SYMBOL_EYE_OPEN);
}
}
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);
}
static void shutdown_btn_clicked_cb(lv_event_t *event) {
LV_UNUSED(event);
lv_obj_t *mbox = lv_msgbox_create(NULL);
lv_msgbox_add_title(mbox, "Shutdown device?");
lv_obj_t *confirm_btn = lv_msgbox_add_footer_button(mbox, "Yes");
lv_obj_add_event_cb(confirm_btn, shutdown_mbox_confirmed_cb, LV_EVENT_CLICKED, NULL);
lv_obj_t *decline_btn = lv_msgbox_add_footer_button(mbox, "No");
lv_obj_add_event_cb(decline_btn, shutdown_mbox_declined_cb, LV_EVENT_CLICKED, NULL);
lv_obj_set_size(mbox, 400, LV_SIZE_CONTENT);
lv_obj_center(mbox);
}
static void shutdown_mbox_confirmed_cb(lv_event_t *event) {
LV_UNUSED(event);
shutdown();
}
static void shutdown_mbox_declined_cb(lv_event_t *event) {
/* Find the containing message box for the clicked button */
lv_obj_t *obj = lv_event_get_target(event);
while (obj && !lv_obj_check_type(obj, &lv_msgbox_class)) {
obj = lv_obj_get_parent(obj);
}
if (!obj) {
bbx_log(BBX_LOG_LEVEL_ERROR, "Could not find containing message box for clicked button");
return;
}
lv_msgbox_close(obj);
}
static void keyboard_value_changed_cb(lv_event_t *event) {
lv_obj_t *kb = lv_event_get_target(event);
uint16_t btn_id = lv_buttonmatrix_get_selected_button(kb);
if (btn_id == LV_BUTTONMATRIX_BUTTON_NONE) {
return;
}
if (sq2lv_is_layer_switcher(kb, btn_id)) {
sq2lv_switch_layer(kb, btn_id);
return;
}
lv_keyboard_def_event_cb(event);
}
static void keyboard_ready_cb(lv_event_t *event) {
field_submit_cb(event);
}
static void get_started_btn_clicked_cb(lv_event_t *event) {
LV_UNUSED(event);
current_field_index = 0;
show_form_screen();
}
static void field_submit_cb(lv_event_t *event) {
LV_UNUSED(event);
if (save_and_validate_current_field()) {
current_field_index++;
if (current_field_index >= conf_opts.num_fields) {
show_summary_screen();
} else {
show_form_screen();
}
}
}
static void prev_btn_clicked_cb(lv_event_t *event) {
LV_UNUSED(event);
if (current_field_index > 0 && save_and_validate_current_field()) {
current_field_index--;
show_form_screen();
}
}
static void next_btn_clicked_cb(lv_event_t *event) {
LV_UNUSED(event);
if (save_and_validate_current_field()) {
current_field_index++;
if (current_field_index >= conf_opts.num_fields) {
show_summary_screen();
} else {
show_form_screen();
}
}
}
static void summary_field_clicked_cb(lv_event_t *event) {
lv_obj_t *target = lv_event_get_target(event);
int field_index = (int)(intptr_t)lv_obj_get_user_data(target);
current_field_index = field_index;
show_form_screen();
}
static void finish_cb(lv_event_t *event) {
LV_UNUSED(event);
/* Output key=value pairs */
for (int i = 0; i < conf_opts.num_fields; i++) {
const f0_form_field_t *field = &conf_opts.fields[i];
const char *value = field_values[i] ? field_values[i] : "";
printf("%s=%s\n", field->name, value);
}
/* Clear the screen so that form data cannot leak via stale display buffers */
lv_obj_t *rect = lv_obj_create(lv_screen_active());
lv_obj_set_size(rect, LV_PCT(100), LV_PCT(100));
lv_obj_set_pos(rect, 0, 0);
lv_obj_set_style_bg_opa(rect, LV_OPA_COVER, LV_PART_MAIN);
lv_obj_set_style_bg_color(rect, lv_color_hex(get_theme(is_alternate_theme)->window.bg_color), LV_PART_MAIN);
lv_refr_now(lv_display_get_default()); /* Force the screen to be drawn */
/* Trigger SIGTERM to exit */
sigaction_handler(SIGTERM);
exit(0);
}
static bool validate_field(int field_index) {
if (field_index >= conf_opts.num_fields) return true;
const f0_form_field_t *field = &conf_opts.fields[field_index];
const char *value = field_values[field_index] ? field_values[field_index] : "";
// Required field validation
if (field->required && strlen(value) == 0) {
return false;
}
// Future validation rules here, e.g.:
// if (field->min_length > 0 && strlen(value) < field->min_length) return false;
return true;
}
static void set_field_validation_error(bool has_error) {
if (!form_textarea) return;
if (has_error) {
lv_obj_set_style_border_color(form_textarea, lv_color_hex(0xFF0000), LV_PART_MAIN);
lv_obj_set_style_border_width(form_textarea, 2, LV_PART_MAIN);
} else {
lv_obj_set_style_border_color(form_textarea, lv_color_hex(0x000000), LV_PART_MAIN);
lv_obj_set_style_border_width(form_textarea, 1, LV_PART_MAIN);
}
}
static bool save_and_validate_current_field() {
if (!form_textarea || !field_values) return true;
// Save current content
char *new_value = strdup(lv_textarea_get_text(form_textarea));
if (new_value) {
if (field_values[current_field_index]) {
free(field_values[current_field_index]);
}
field_values[current_field_index] = new_value;
}
// Validate and show/clear error
bool is_valid = validate_field(current_field_index);
set_field_validation_error(!is_valid);
return is_valid;
}
static void show_intro_screen(void) {
lv_obj_t *screen = lv_screen_active();
/* Header config */
bbx_header_config_t header_config;
bbx_header_init_config(&header_config);
/* No OSK needed on intro */
header_config.show_keyboard_toggle = false;
header_config.show_layout_dropdown = false;
bbx_header_widgets_t header_widgets;
lv_obj_t *header = bbx_header_create(screen, &header_config, &header_widgets);
lv_obj_add_flag(header, BBX_WIDGET_HEADER);
lv_theme_apply(header);
/* Attach callbacks */
lv_obj_add_event_cb(header_widgets.theme_toggle_btn, toggle_theme_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
/* Container for intro content */
lv_obj_t *container = lv_obj_create(screen);
lv_obj_set_size(container, LV_PCT(100), LV_PCT(100));
lv_obj_set_flex_flow(container, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(container, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_pad_all(container, 40, LV_PART_MAIN);
/* Title */
lv_obj_t *title = lv_label_create(container);
lv_label_set_text(title, conf_opts.intro.title);
lv_obj_set_style_text_align(title, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN);
lv_obj_set_style_pad_bottom(title, 20, LV_PART_MAIN);
/* Body */
lv_obj_t *body = lv_label_create(container);
lv_label_set_text(body, conf_opts.intro.body);
lv_label_set_long_mode(body, LV_LABEL_LONG_WRAP);
lv_obj_set_width(body, LV_PCT(80));
lv_obj_set_style_text_align(body, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN);
lv_obj_set_style_pad_bottom(body, 30, LV_PART_MAIN);
/* Get Started button */
lv_obj_t *btn = lv_button_create(container);
lv_obj_t *btn_label = lv_label_create(btn);
lv_label_set_text(btn_label, "Get Started");
lv_obj_center(btn_label);
lv_obj_add_event_cb(btn, get_started_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
/* Set up keyboard input for intro screen */
lv_group_t *intro_input_group = lv_group_create();
bbx_indev_set_keyboard_input_group(intro_input_group);
lv_group_add_obj(intro_input_group, btn);
lv_obj_add_event_cb(btn, intro_key_cb, LV_EVENT_KEY, NULL);
}
static void show_form_screen(void) {
if (current_field_index >= conf_opts.num_fields) {
bbx_log(BBX_LOG_LEVEL_VERBOSE, "Form complete");
return;
}
if (field_values == NULL) {
field_values = calloc(conf_opts.num_fields, sizeof(char*));
}
f0_form_field_t *field = &conf_opts.fields[current_field_index];
/* Clear screen */
lv_obj_clean(lv_screen_active());
/* Recreate header */
bbx_header_config_t header_config;
bbx_header_init_config(&header_config);
header_config.show_keyboard_toggle = true;
header_config.show_layout_dropdown = true;
header_config.dropdown_options = sq2lv_layout_short_names;
bbx_header_widgets_t header_widgets;
lv_obj_t *header = bbx_header_create(lv_screen_active(), &header_config, &header_widgets);
lv_obj_add_flag(header, BBX_WIDGET_HEADER);
lv_theme_apply(header);
/* Attach callbacks */
lv_obj_add_event_cb(header_widgets.theme_toggle_btn, toggle_theme_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
lv_obj_add_event_cb(header_widgets.keyboard_toggle_btn, toggle_kb_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
lv_obj_add_event_cb(header_widgets.layout_dropdown, layout_dropdown_value_changed_cb, LV_EVENT_VALUE_CHANGED, NULL);
lv_obj_add_event_cb(header_widgets.shutdown_btn, shutdown_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
/* Calculate keyboard dimensions and container heights */
lv_obj_update_layout(header);
const int32_t hor_res = lv_display_get_horizontal_resolution(lv_display_get_default());
const int32_t ver_res = lv_display_get_vertical_resolution(lv_display_get_default());
const int32_t keyboard_height = ver_res > hor_res ? ver_res / 2.5 : ver_res / 1.8;
content_height_without_kb = ver_res - lv_obj_get_height(header);
content_height_with_kb = content_height_without_kb - keyboard_height;
/* Form container - vertical layout */
form_container = lv_obj_create(lv_screen_active());
lv_obj_set_flex_flow(form_container, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(form_container, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_pad_all(form_container, 40, LV_PART_MAIN);
lv_obj_remove_flag(form_container, LV_OBJ_FLAG_SCROLLABLE);
/* Field label */
lv_obj_t *label = lv_label_create(form_container);
lv_label_set_text(label, field->label ? field->label : field->name);
lv_obj_set_style_pad_bottom(label, 20, LV_PART_MAIN);
/* Textarea container */
lv_obj_t *textarea_container = lv_obj_create(form_container);
lv_obj_set_size(textarea_container, LV_PCT(80), LV_SIZE_CONTENT);
lv_obj_set_flex_flow(textarea_container, LV_FLEX_FLOW_ROW);
/* Create textarea and restore content */
form_textarea = lv_textarea_create(textarea_container);
lv_textarea_set_one_line(form_textarea, true);
if (field->type == F0_FIELD_TYPE_PASSWORD) {
lv_textarea_set_password_mode(form_textarea, true);
lv_textarea_set_password_bullet(form_textarea, conf_opts.textarea.bullet);
}
lv_obj_add_event_cb(form_textarea, field_submit_cb, LV_EVENT_READY, NULL);
lv_obj_set_flex_grow(form_textarea, 1);
lv_obj_add_state(form_textarea, LV_STATE_FOCUSED);
/* Reveal / obscure password button */
if (field->type == F0_FIELD_TYPE_PASSWORD) {
lv_obj_update_layout(form_textarea);
const int32_t textarea_height = lv_obj_get_height(form_textarea);
lv_obj_t *toggle_pw_btn = lv_button_create(textarea_container);
lv_obj_set_size(toggle_pw_btn, textarea_height, textarea_height);
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_set_user_data(toggle_pw_btn, form_textarea);
lv_obj_add_event_cb(toggle_pw_btn, toggle_password_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
}
/* Restore saved content */
if (field_values[current_field_index]) {
lv_textarea_set_text(form_textarea, field_values[current_field_index]);
/* Prevent text from being scrolled off to the left of the textarea */
lv_obj_update_layout(form_textarea);
lv_obj_scroll_to_x(form_textarea, 0, LV_ANIM_OFF);
}
/* Navigation bar at bottom */
lv_obj_t *nav_container = lv_obj_create(lv_screen_active());
lv_obj_set_size(nav_container, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_flex_flow(nav_container, LV_FLEX_FLOW_ROW);
lv_obj_set_style_pad_all(nav_container, 10, LV_PART_MAIN);
/* Previous button */
lv_obj_t *prev_btn = lv_button_create(nav_container);
lv_obj_t *prev_label = lv_label_create(prev_btn);
lv_label_set_text(prev_label, "Previous");
lv_obj_center(prev_label);
lv_obj_add_event_cb(prev_btn, prev_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
if (current_field_index == 0) {
lv_obj_add_flag(prev_btn, LV_OBJ_FLAG_HIDDEN);
} else {
lv_obj_remove_flag(prev_btn, LV_OBJ_FLAG_HIDDEN);
}
/* Spacer to push Next to the right */
lv_obj_t *spacer = lv_obj_create(nav_container);
lv_obj_set_flex_grow(spacer, 1);
lv_obj_set_height(spacer, 0);
/* Next button */
lv_obj_t *next_btn = lv_button_create(nav_container);
lv_obj_t *next_label = lv_label_create(next_btn);
lv_label_set_text(next_label, current_field_index >= conf_opts.num_fields - 1 ? "Submit" : "Next");
lv_obj_center(next_label);
lv_obj_add_event_cb(next_btn, next_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
/* Update layout to get nav bar height */
lv_obj_update_layout(nav_container);
const int32_t nav_height = lv_obj_get_height(nav_container);
/* Adjust content heights for nav bar */
content_height_without_kb -= nav_height;
content_height_with_kb -= nav_height;
/* Update form container size to account for nav bar */
lv_obj_set_size(form_container, LV_PCT(100), is_keyboard_hidden ? content_height_without_kb : content_height_with_kb);
/* Create keyboard widget */
bbx_keyboard_config_t keyboard_config;
bbx_keyboard_init_config(&keyboard_config);
keyboard_config.layout_id = (int)conf_opts.keyboard.layout_id;
keyboard_config.height = keyboard_height;
keyboard_config.popovers = conf_opts.keyboard.popovers;
keyboard_config.value_changed_callback = keyboard_value_changed_cb;
keyboard_config.ready_callback = keyboard_ready_cb;
keyboard = bbx_keyboard_create(lv_screen_active(), form_textarea, &keyboard_config);
/* Configuring routing for physical keyboard input into the textarea */
lv_group_t *keyboard_input_group = lv_group_create();
bbx_indev_set_keyboard_input_group(keyboard_input_group);
lv_group_add_obj(keyboard_input_group, form_textarea);
}
static void show_summary_screen(void) {
/* Clear screen */
lv_obj_clean(lv_screen_active());
/* Header */
bbx_header_config_t header_config;
bbx_header_init_config(&header_config);
header_config.show_keyboard_toggle = false;
header_config.show_layout_dropdown = false;
bbx_header_widgets_t header_widgets;
lv_obj_t *header = bbx_header_create(lv_screen_active(), &header_config, &header_widgets);
lv_obj_add_flag(header, BBX_WIDGET_HEADER);
lv_theme_apply(header);
lv_obj_add_event_cb(header_widgets.theme_toggle_btn, toggle_theme_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
/* Summary container */
lv_obj_t *container = lv_obj_create(lv_screen_active());
lv_obj_set_size(container, LV_PCT(100), LV_PCT(80));
lv_obj_set_flex_flow(container, LV_FLEX_FLOW_COLUMN);
lv_obj_set_style_pad_all(container, 20, LV_PART_MAIN);
/* Title */
lv_obj_t *title = lv_label_create(container);
lv_label_set_text(title, "Summary");
lv_obj_set_style_pad_bottom(title, 20, LV_PART_MAIN);
/* Field list */
for (int i = 0; i < conf_opts.num_fields; i++) {
f0_form_field_t *field = &conf_opts.fields[i];
const char *value = field_values[i] ? field_values[i] : "";
lv_obj_t *item_btn = lv_button_create(container);
lv_obj_set_width(item_btn, LV_PCT(100));
lv_obj_set_user_data(item_btn, (void*)(intptr_t)i);
lv_obj_add_event_cb(item_btn, summary_field_clicked_cb, LV_EVENT_CLICKED, NULL);
lv_obj_t *item_container = lv_obj_create(item_btn);
lv_obj_set_flex_flow(item_container, LV_FLEX_FLOW_COLUMN);
lv_obj_set_width(item_container, LV_PCT(100));
lv_obj_add_flag(item_container, LV_OBJ_FLAG_EVENT_BUBBLE);
lv_obj_t *label = lv_label_create(item_container);
lv_label_set_text(label, field->label ? field->label : field->name);
lv_obj_set_style_text_decor(label, LV_TEXT_DECOR_UNDERLINE, LV_PART_MAIN);
lv_obj_t *value_label = lv_label_create(item_container);
if (strlen(value) > 0) {
if (field->type == F0_FIELD_TYPE_PASSWORD) {
lv_label_set_text(value_label, F0_PASSWORD_HIDDEN_DOTS);
/* Add toggle button for password */
lv_obj_t *toggle_btn = lv_button_create(item_container);
lv_obj_set_size(toggle_btn, 40, 30);
lv_obj_set_user_data(toggle_btn, value_label);
lv_obj_t *toggle_label = lv_label_create(toggle_btn);
lv_label_set_text(toggle_label, LV_SYMBOL_EYE_OPEN);
lv_obj_center(toggle_label);
lv_obj_add_event_cb(toggle_btn, toggle_password_summary_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
} else {
lv_label_set_text(value_label, value);
}
} else {
lv_label_set_text(value_label, "(empty)");
}
/* Save field index to obj to reference later in summary_field_click_cb */
lv_obj_set_user_data(item_container, (void*)(intptr_t)i);
lv_obj_set_user_data(label, (void*)(intptr_t)i);
lv_obj_set_user_data(value_label, (void*)(intptr_t)i);
}
/* Spacer for button positioning */
lv_obj_t *spacer = lv_obj_create(container);
lv_obj_set_height(spacer, 20);
lv_obj_set_width(spacer, 0);
/* Button container for centering */
lv_obj_t *button_container = lv_obj_create(container);
lv_obj_set_size(button_container, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_flex_flow(button_container, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(button_container, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
/* Finish button */
lv_obj_t *finish_btn = lv_button_create(button_container);
lv_obj_t *finish_label = lv_label_create(finish_btn);
lv_label_set_text(finish_label, "Finish");
lv_obj_center(finish_label);
lv_obj_add_event_cb(finish_btn, finish_cb, LV_EVENT_CLICKED, NULL);
/* Set up keyboard input for summary screen */
lv_group_t *summary_input_group = lv_group_create();
bbx_indev_set_keyboard_input_group(summary_input_group);
lv_group_add_obj(summary_input_group, finish_btn);
}
int main(int argc, char *argv[]) {
f0_cli_parse_opts(argc, argv, &cli_opts);
if (cli_opts.common.verbose) {
bbx_log_set_level(BBX_LOG_LEVEL_VERBOSE);
}
/* Parse config files */
f0_config_init_opts(&conf_opts);
f0_config_parse_file("/usr/share/f0rmz/f0rmz.conf", &conf_opts);
f0_config_parse_directory("/usr/share/f0rmz/f0rmz.conf.d", &conf_opts);
f0_config_parse_file("/etc/f0rmz.conf", &conf_opts);
f0_config_parse_directory("/etc/f0rmz.conf.d", &conf_opts);
f0_config_parse_file(cli_opts.config_file, &conf_opts);
/* Prepare current TTY and clean up on termination */
bbx_terminal_prepare_current_terminal(!conf_opts.quirks.terminal_prevent_graphics_mode, !conf_opts.quirks.terminal_allow_keyboard_input);
struct sigaction action;
memset(&action, 0, sizeof(action));
action.sa_handler = sigaction_handler;
sigaction(SIGINT, &action, NULL);
sigaction(SIGTERM, &action, NULL);
/* Initialize LVGL */
lv_init();
lv_log_register_print_cb(bbx_log_print_cb);
/* Populate display config */
bbx_display_config_t display_config = {
.hor_res = cli_opts.common.hor_res,
.ver_res = cli_opts.common.ver_res,
.x_offset = cli_opts.common.x_offset,
.y_offset = cli_opts.common.y_offset,
.dpi = cli_opts.common.dpi,
.fbdev_force_refresh = conf_opts.quirks.fbdev_force_refresh
};
/* Initialize display */
lv_display_t *disp = bbx_display_create(conf_opts.general.backend, &display_config);
if (!disp) {
exit_failure();
}
/* Prepare for routing physical keyboard input into the textarea */
lv_group_t *keyboard_input_group = lv_group_create();
bbx_indev_set_keyboard_input_group(keyboard_input_group);
/* Start input device monitor and auto-connect available devices */
bbx_indev_start_monitor_and_autoconnect(conf_opts.input.keyboard, conf_opts.input.pointer, conf_opts.input.touchscreen);
/* Hide the on-screen keyboard by default if a physical keyboard is connected */
if (conf_opts.keyboard.autohide && bbx_indev_is_keyboard_connected()) {
is_keyboard_hidden = true;
}
/* Prevent scrolling when keyboard is off-screen */
lv_obj_t *screen = lv_screen_active();
lv_theme_apply(screen);
lv_obj_set_flex_flow(screen, LV_FLEX_FLOW_COLUMN);
lv_obj_remove_flag(screen, LV_OBJ_FLAG_SCROLLABLE);
/* Initialise theme */
set_theme(is_alternate_theme);
/* Create header */
show_intro_screen();
/* Main loop */
while(1) {
uint32_t time_till_next = lv_timer_handler();
usleep(time_till_next * 1000);
}
return 0;
}

34
f0rmz/meson.build Normal file
View file

@ -0,0 +1,34 @@
# Copyright 2025 buffybox contributors
# SPDX-License-Identifier: GPL-3.0-or-later
f0rmz_sources = files(
'command_line.c',
'config.c',
'main.c',
'sq2lv_layouts.c'
)
f0rmz_dependencies = [
common_dependencies,
depinih,
depxkbcommon
]
f0rmz_args = []
deplibdrm = dependency('libdrm', required: get_option('with-drm'))
if deplibdrm.found()
f0rmz_dependencies += deplibdrm
f0rmz_args += '-DLV_USE_LINUX_DRM=1'
else
f0rmz_args += '-DLV_USE_LINUX_DRM=0'
endif
executable('f0rmz',
include_directories: common_include_dirs,
sources: f0rmz_sources + shared_sources + squeek2lvgl_sources + lvgl_sources + header_sources,
dependencies: f0rmz_dependencies,
c_args: f0rmz_args,
install: true,
install_tag: 'f0rmz'
)

949
f0rmz/sq2lv_layouts.c Normal file
View file

@ -0,0 +1,949 @@
/**
* Auto-generated with squeek2lvgl
**/
#include "sq2lv_layouts.h"
#include "../squeek2lvgl/sq2lv.h"
#define SQ2LV_SYMBOL_SHIFT "\xef\x8d\x9b"
/**
* Layout: US English - generated from us
**/
static const char * const name_us = "US English";
static const char * const short_name_us = "us";
/* Layer: Lowercase letters - generated from base */
static const int num_keys_lower_us = 44;
static const char * const keycaps_lower_us[] = { \
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "\n", \
"q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "\n", \
"a", "s", "d", "f", "g", "h", "j", "k", "l", "\n", \
SQ2LV_SYMBOL_SHIFT, "z", "x", "c", "v", "b", "n", "m", LV_SYMBOL_BACKSPACE, "\n", \
"123", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, ".", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_lower_us[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_MOD_INACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_lower_us = 0;
static const int * const modifier_idxs_lower_us = NULL;
static const int num_switchers_lower_us = 2;
static const int switcher_idxs_lower_us[] = { \
29, 38 \
};
static const int switcher_dests_lower_us[] = { \
1, 2 \
};
/* Layer: Uppercase letters - generated from upper */
static const int num_keys_upper_us = 44;
static const char * const keycaps_upper_us[] = { \
"!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "\n", \
"Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "\n", \
"A", "S", "D", "F", "G", "H", "J", "K", "L", "\n", \
SQ2LV_SYMBOL_SHIFT, "Z", "X", "C", "V", "B", "N", "M", LV_SYMBOL_BACKSPACE, "\n", \
"123", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, ".", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_upper_us[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_MOD_ACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_upper_us = 0;
static const int * const modifier_idxs_upper_us = NULL;
static const int num_switchers_upper_us = 2;
static const int switcher_idxs_upper_us[] = { \
29, 38 \
};
static const int switcher_dests_upper_us[] = { \
0, 2 \
};
/* Layer: Numbers / symbols - generated from numbers */
static const int num_keys_numbers_us = 36;
static const char * const keycaps_numbers_us[] = { \
"<hidden>", "\n", \
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "\n", \
"@", "#", "$", "%", "&", "-", "_", "+", "(", ")", "\n", \
"*/=", ",", "\"", "'", ":", ";", "!", "?", LV_SYMBOL_BACKSPACE, "\n", \
"ABC", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, ".", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_numbers_us[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_HIDDEN | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_numbers_us = 0;
static const int * const modifier_idxs_numbers_us = NULL;
static const int num_switchers_numbers_us = 2;
static const int switcher_idxs_numbers_us[] = { \
21, 30 \
};
static const int switcher_dests_numbers_us[] = { \
3, 0 \
};
/* Layer: Symbols - generated from symbols */
static const int num_keys_symbols_us = 36;
static const char * const keycaps_symbols_us[] = { \
"<hidden>", "\n", \
"~", "`", "|", "·", "", "π", "τ", "÷", "×", "", "\n", \
"©", "®", "£", "", "¥", "^", "°", "*", "{", "}", "\n", \
"123", "\\", "/", "<", ">", "=", "[", "]", LV_SYMBOL_BACKSPACE, "\n", \
"ABC", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, ".", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_symbols_us[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_HIDDEN | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_symbols_us = 0;
static const int * const modifier_idxs_symbols_us = NULL;
static const int num_switchers_symbols_us = 2;
static const int switcher_idxs_symbols_us[] = { \
21, 30 \
};
static const int switcher_dests_symbols_us[] = { \
2, 0 \
};
/* Layer array */
static const int num_layers_us = 4;
static const sq2lv_layer_t layers_us[] = {
{
.num_keys = num_keys_lower_us,
.keycaps = keycaps_lower_us,
.attributes = attributes_lower_us,
.num_modifiers = num_modifiers_lower_us,
.modifier_idxs = modifier_idxs_lower_us,
.num_switchers = num_switchers_lower_us,
.switcher_idxs = switcher_idxs_lower_us,
.switcher_dests = switcher_dests_lower_us
},
{
.num_keys = num_keys_upper_us,
.keycaps = keycaps_upper_us,
.attributes = attributes_upper_us,
.num_modifiers = num_modifiers_upper_us,
.modifier_idxs = modifier_idxs_upper_us,
.num_switchers = num_switchers_upper_us,
.switcher_idxs = switcher_idxs_upper_us,
.switcher_dests = switcher_dests_upper_us
},
{
.num_keys = num_keys_numbers_us,
.keycaps = keycaps_numbers_us,
.attributes = attributes_numbers_us,
.num_modifiers = num_modifiers_numbers_us,
.modifier_idxs = modifier_idxs_numbers_us,
.num_switchers = num_switchers_numbers_us,
.switcher_idxs = switcher_idxs_numbers_us,
.switcher_dests = switcher_dests_numbers_us
},
{
.num_keys = num_keys_symbols_us,
.keycaps = keycaps_symbols_us,
.attributes = attributes_symbols_us,
.num_modifiers = num_modifiers_symbols_us,
.modifier_idxs = modifier_idxs_symbols_us,
.num_switchers = num_switchers_symbols_us,
.switcher_idxs = switcher_idxs_symbols_us,
.switcher_dests = switcher_dests_symbols_us
}
};
/**
* Layout: Deutsch - generated from de
**/
static const char * const name_de = "Deutsch";
static const char * const short_name_de = "de";
/* Layer: Lowercase letters - generated from base */
static const int num_keys_lower_de = 46;
static const char * const keycaps_lower_de[] = { \
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "\n", \
"q", "w", "e", "r", "t", "z", "u", "i", "o", "p", "\n", \
"a", "s", "d", "f", "g", "h", "j", "k", "l", "\n", \
SQ2LV_SYMBOL_SHIFT, "y", "x", "c", "v", "b", "n", "m", LV_SYMBOL_BACKSPACE, "\n", \
"123", "äÄ", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, ",", ".", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_lower_de[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_MOD_INACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_MOD_INACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_lower_de = 0;
static const int * const modifier_idxs_lower_de = NULL;
static const int num_switchers_lower_de = 3;
static const int switcher_idxs_lower_de[] = { \
29, 38, 39 \
};
static const int switcher_dests_lower_de[] = { \
1, 2, 4 \
};
/* Layer: Uppercase letters - generated from upper */
static const int num_keys_upper_de = 46;
static const char * const keycaps_upper_de[] = { \
"!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "\n", \
"Q", "W", "E", "R", "T", "Z", "U", "I", "O", "P", "\n", \
"A", "S", "D", "F", "G", "H", "J", "K", "L", "\n", \
SQ2LV_SYMBOL_SHIFT, "Y", "X", "C", "V", "B", "N", "M", LV_SYMBOL_BACKSPACE, "\n", \
"123", "äÄ", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, "!", "?", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_upper_de[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_MOD_ACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_MOD_INACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_upper_de = 0;
static const int * const modifier_idxs_upper_de = NULL;
static const int num_switchers_upper_de = 3;
static const int switcher_idxs_upper_de[] = { \
29, 38, 39 \
};
static const int switcher_dests_upper_de[] = { \
0, 2, 4 \
};
/* Layer: Numbers / symbols - generated from numbers */
static const int num_keys_numbers_de = 38;
static const char * const keycaps_numbers_de[] = { \
"<hidden>", "\n", \
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "\n", \
"@", "#", "", "%", "&", "-", "_", "+", "(", ")", "\n", \
"*/=", ";", "\"", "'", ":", "=", "<", ">", LV_SYMBOL_BACKSPACE, "\n", \
"abc", "äÄ", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, ",", ".", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_numbers_de[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_HIDDEN | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_MOD_INACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_numbers_de = 0;
static const int * const modifier_idxs_numbers_de = NULL;
static const int num_switchers_numbers_de = 3;
static const int switcher_idxs_numbers_de[] = { \
21, 30, 31 \
};
static const int switcher_dests_numbers_de[] = { \
3, 0, 4 \
};
/* Layer: Symbols - generated from symbols */
static const int num_keys_symbols_de = 38;
static const char * const keycaps_symbols_de[] = { \
"<hidden>", "\n", \
"~", "`", "´", "|", "·", "", "µ", "÷", "×", "", "\n", \
"©", "®", "£", "$", "¥", "^", "°", "*", "{", "}", "\n", \
"123", "\\", "/", "§", "π", "τ", "[", "]", LV_SYMBOL_BACKSPACE, "\n", \
"abc", "äÄ", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, ",", ".", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_symbols_de[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_HIDDEN | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_MOD_INACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_symbols_de = 0;
static const int * const modifier_idxs_symbols_de = NULL;
static const int num_switchers_symbols_de = 3;
static const int switcher_idxs_symbols_de[] = { \
21, 30, 31 \
};
static const int switcher_dests_symbols_de[] = { \
2, 0, 4 \
};
/* Layer: Special characters - generated from eschars */
static const int num_keys_special_de = 38;
static const char * const keycaps_special_de[] = { \
"<hidden>", "\n", \
"ä", "è", "é", "ö", "ü", "Ä", "È", "É", "Ö", "Ü", "\n", \
"à", "â", "ê", "î", "ô", "À", "Â", "È", "Î", "Ô", "\n", \
"123", "«", "»", "ç", "Ç", "æ", "œ", "ß", LV_SYMBOL_BACKSPACE, "\n", \
"abc", "äÄ", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, "", "", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_special_de[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_HIDDEN | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_MOD_ACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_special_de = 0;
static const int * const modifier_idxs_special_de = NULL;
static const int num_switchers_special_de = 3;
static const int switcher_idxs_special_de[] = { \
21, 30, 31 \
};
static const int switcher_dests_special_de[] = { \
2, 0, 0 \
};
/* Layer array */
static const int num_layers_de = 5;
static const sq2lv_layer_t layers_de[] = {
{
.num_keys = num_keys_lower_de,
.keycaps = keycaps_lower_de,
.attributes = attributes_lower_de,
.num_modifiers = num_modifiers_lower_de,
.modifier_idxs = modifier_idxs_lower_de,
.num_switchers = num_switchers_lower_de,
.switcher_idxs = switcher_idxs_lower_de,
.switcher_dests = switcher_dests_lower_de
},
{
.num_keys = num_keys_upper_de,
.keycaps = keycaps_upper_de,
.attributes = attributes_upper_de,
.num_modifiers = num_modifiers_upper_de,
.modifier_idxs = modifier_idxs_upper_de,
.num_switchers = num_switchers_upper_de,
.switcher_idxs = switcher_idxs_upper_de,
.switcher_dests = switcher_dests_upper_de
},
{
.num_keys = num_keys_numbers_de,
.keycaps = keycaps_numbers_de,
.attributes = attributes_numbers_de,
.num_modifiers = num_modifiers_numbers_de,
.modifier_idxs = modifier_idxs_numbers_de,
.num_switchers = num_switchers_numbers_de,
.switcher_idxs = switcher_idxs_numbers_de,
.switcher_dests = switcher_dests_numbers_de
},
{
.num_keys = num_keys_symbols_de,
.keycaps = keycaps_symbols_de,
.attributes = attributes_symbols_de,
.num_modifiers = num_modifiers_symbols_de,
.modifier_idxs = modifier_idxs_symbols_de,
.num_switchers = num_switchers_symbols_de,
.switcher_idxs = switcher_idxs_symbols_de,
.switcher_dests = switcher_dests_symbols_de
},
{
.num_keys = num_keys_special_de,
.keycaps = keycaps_special_de,
.attributes = attributes_special_de,
.num_modifiers = num_modifiers_special_de,
.modifier_idxs = modifier_idxs_special_de,
.num_switchers = num_switchers_special_de,
.switcher_idxs = switcher_idxs_special_de,
.switcher_dests = switcher_dests_special_de
}
};
/**
* Layout: Español - generated from es
**/
static const char * const name_es = "Español";
static const char * const short_name_es = "es";
/* Layer: Lowercase letters - generated from base */
static const int num_keys_lower_es = 47;
static const char * const keycaps_lower_es[] = { \
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "\n", \
"q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "\n", \
"a", "s", "d", "f", "g", "h", "j", "k", "l", "ñ", "\n", \
SQ2LV_SYMBOL_SHIFT, "z", "x", "c", "v", "b", "n", "m", LV_SYMBOL_BACKSPACE, "\n", \
"123", "áÁ", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, "?", ".", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_lower_es[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_MOD_INACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_MOD_INACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_lower_es = 0;
static const int * const modifier_idxs_lower_es = NULL;
static const int num_switchers_lower_es = 3;
static const int switcher_idxs_lower_es[] = { \
30, 39, 40 \
};
static const int switcher_dests_lower_es[] = { \
1, 2, 4 \
};
/* Layer: Uppercase letters - generated from upper */
static const int num_keys_upper_es = 47;
static const char * const keycaps_upper_es[] = { \
"!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "\n", \
"Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "\n", \
"A", "S", "D", "F", "G", "H", "J", "K", "L", "Ñ", "\n", \
SQ2LV_SYMBOL_SHIFT, "Z", "X", "C", "V", "B", "N", "M", LV_SYMBOL_BACKSPACE, "\n", \
"123", "áÁ", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, "¿", ".", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_upper_es[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_MOD_ACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_MOD_INACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_upper_es = 0;
static const int * const modifier_idxs_upper_es = NULL;
static const int num_switchers_upper_es = 3;
static const int switcher_idxs_upper_es[] = { \
30, 39, 40 \
};
static const int switcher_dests_upper_es[] = { \
0, 2, 4 \
};
/* Layer: Numbers / symbols - generated from numbers */
static const int num_keys_numbers_es = 38;
static const char * const keycaps_numbers_es[] = { \
"<hidden>", "\n", \
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "\n", \
"@", "#", "", "%", "&", "-", "_", "+", "(", ")", "\n", \
"*/=", ",", "\"", "'", ":", ";", "!", "=", LV_SYMBOL_BACKSPACE, "\n", \
"abc", "áÁ", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, "?", ".", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_numbers_es[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_HIDDEN | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_MOD_INACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_numbers_es = 0;
static const int * const modifier_idxs_numbers_es = NULL;
static const int num_switchers_numbers_es = 3;
static const int switcher_idxs_numbers_es[] = { \
21, 30, 31 \
};
static const int switcher_dests_numbers_es[] = { \
3, 0, 4 \
};
/* Layer: Symbols - generated from symbols */
static const int num_keys_symbols_es = 38;
static const char * const keycaps_symbols_es[] = { \
"<hidden>", "\n", \
"~", "`", "|", "·", "", "π", "τ", "÷", "×", "", "\n", \
"©", "®", "£", "$", "¥", "^", "°", "*", "{", "}", "\n", \
"123", "\\", "/", "<", ">", "=", "[", "]", LV_SYMBOL_BACKSPACE, "\n", \
"abc", "áÁ", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, "?", ".", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_symbols_es[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_HIDDEN | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_MOD_INACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_symbols_es = 0;
static const int * const modifier_idxs_symbols_es = NULL;
static const int num_switchers_symbols_es = 3;
static const int switcher_idxs_symbols_es[] = { \
21, 30, 31 \
};
static const int switcher_dests_symbols_es[] = { \
2, 0, 4 \
};
/* Layer: Special characters - generated from eschars */
static const int num_keys_special_es = 38;
static const char * const keycaps_special_es[] = { \
"<hidden>", "\n", \
"á", "é", "í", "ó", "ú", "Á", "É", "Í", "Ó", "Ú", "\n", \
"à", "è", "ì", "ò", "ù", "À", "È", "Ì", "Ò", "Ù", "\n", \
"123", "ü", "ç", "ï", "Ü", "Ç", "Ï", "¡", LV_SYMBOL_BACKSPACE, "\n", \
"abc", "áÁ", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, "«", "»", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_special_es[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_HIDDEN | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_MOD_ACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_special_es = 0;
static const int * const modifier_idxs_special_es = NULL;
static const int num_switchers_special_es = 3;
static const int switcher_idxs_special_es[] = { \
21, 30, 31 \
};
static const int switcher_dests_special_es[] = { \
2, 0, 0 \
};
/* Layer array */
static const int num_layers_es = 5;
static const sq2lv_layer_t layers_es[] = {
{
.num_keys = num_keys_lower_es,
.keycaps = keycaps_lower_es,
.attributes = attributes_lower_es,
.num_modifiers = num_modifiers_lower_es,
.modifier_idxs = modifier_idxs_lower_es,
.num_switchers = num_switchers_lower_es,
.switcher_idxs = switcher_idxs_lower_es,
.switcher_dests = switcher_dests_lower_es
},
{
.num_keys = num_keys_upper_es,
.keycaps = keycaps_upper_es,
.attributes = attributes_upper_es,
.num_modifiers = num_modifiers_upper_es,
.modifier_idxs = modifier_idxs_upper_es,
.num_switchers = num_switchers_upper_es,
.switcher_idxs = switcher_idxs_upper_es,
.switcher_dests = switcher_dests_upper_es
},
{
.num_keys = num_keys_numbers_es,
.keycaps = keycaps_numbers_es,
.attributes = attributes_numbers_es,
.num_modifiers = num_modifiers_numbers_es,
.modifier_idxs = modifier_idxs_numbers_es,
.num_switchers = num_switchers_numbers_es,
.switcher_idxs = switcher_idxs_numbers_es,
.switcher_dests = switcher_dests_numbers_es
},
{
.num_keys = num_keys_symbols_es,
.keycaps = keycaps_symbols_es,
.attributes = attributes_symbols_es,
.num_modifiers = num_modifiers_symbols_es,
.modifier_idxs = modifier_idxs_symbols_es,
.num_switchers = num_switchers_symbols_es,
.switcher_idxs = switcher_idxs_symbols_es,
.switcher_dests = switcher_dests_symbols_es
},
{
.num_keys = num_keys_special_es,
.keycaps = keycaps_special_es,
.attributes = attributes_special_es,
.num_modifiers = num_modifiers_special_es,
.modifier_idxs = modifier_idxs_special_es,
.num_switchers = num_switchers_special_es,
.switcher_idxs = switcher_idxs_special_es,
.switcher_dests = switcher_dests_special_es
}
};
/**
* Layout: Français - generated from fr
**/
static const char * const name_fr = "Français";
static const char * const short_name_fr = "fr";
/* Layer: Lowercase letters - generated from base */
static const int num_keys_lower_fr = 45;
static const char * const keycaps_lower_fr[] = { \
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "\n", \
"a", "z", "e", "r", "t", "y", "u", "i", "o", "p", "\n", \
"q", "s", "d", "f", "g", "h", "j", "k", "l", "m", "\n", \
SQ2LV_SYMBOL_SHIFT, "w", "x", "c", "v", "b", "n", ".", LV_SYMBOL_BACKSPACE, "\n", \
"123", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, "âÂ", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_lower_fr[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_MOD_INACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, SQ2LV_CTRL_MOD_INACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_lower_fr = 0;
static const int * const modifier_idxs_lower_fr = NULL;
static const int num_switchers_lower_fr = 3;
static const int switcher_idxs_lower_fr[] = { \
30, 39, 43 \
};
static const int switcher_dests_lower_fr[] = { \
1, 2, 4 \
};
/* Layer: Uppercase letters - generated from upper */
static const int num_keys_upper_fr = 45;
static const char * const keycaps_upper_fr[] = { \
"!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "\n", \
"A", "Z", "E", "R", "T", "Y", "U", "I", "O", "P", "\n", \
"Q", "S", "D", "F", "G", "H", "J", "K", "L", "M", "\n", \
SQ2LV_SYMBOL_SHIFT, "W", "X", "C", "V", "B", "N", ",", LV_SYMBOL_BACKSPACE, "\n", \
"123", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, "âÂ", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_upper_fr[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_MOD_ACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, SQ2LV_CTRL_MOD_INACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_upper_fr = 0;
static const int * const modifier_idxs_upper_fr = NULL;
static const int num_switchers_upper_fr = 3;
static const int switcher_idxs_upper_fr[] = { \
30, 39, 43 \
};
static const int switcher_dests_upper_fr[] = { \
0, 2, 4 \
};
/* Layer: Numbers / symbols - generated from numbers */
static const int num_keys_numbers_fr = 36;
static const char * const keycaps_numbers_fr[] = { \
"<hidden>", "\n", \
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "\n", \
"@", "#", "", "%", "&", "-", "_", "+", "(", ")", "\n", \
"*/=", ",", "\"", "'", ":", ";", "!", "?", LV_SYMBOL_BACKSPACE, "\n", \
"abc", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, "âÂ", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_numbers_fr[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_HIDDEN | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, SQ2LV_CTRL_MOD_INACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_numbers_fr = 0;
static const int * const modifier_idxs_numbers_fr = NULL;
static const int num_switchers_numbers_fr = 3;
static const int switcher_idxs_numbers_fr[] = { \
21, 30, 34 \
};
static const int switcher_dests_numbers_fr[] = { \
3, 0, 4 \
};
/* Layer: Symbols - generated from symbols */
static const int num_keys_symbols_fr = 36;
static const char * const keycaps_symbols_fr[] = { \
"<hidden>", "\n", \
"~", "`", "|", "·", "", "π", "τ", "÷", "×", "", "\n", \
"©", "®", "£", "$", "¥", "^", "°", "*", "{", "}", "\n", \
"123", "\\", "/", "<", ">", "=", "[", "]", LV_SYMBOL_BACKSPACE, "\n", \
"abc", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, "âÂ", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_symbols_fr[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_HIDDEN | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, SQ2LV_CTRL_MOD_INACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_symbols_fr = 0;
static const int * const modifier_idxs_symbols_fr = NULL;
static const int num_switchers_symbols_fr = 3;
static const int switcher_idxs_symbols_fr[] = { \
21, 30, 34 \
};
static const int switcher_dests_symbols_fr[] = { \
2, 0, 4 \
};
/* Layer: Special characters - generated from eschars */
static const int num_keys_special_fr = 36;
static const char * const keycaps_special_fr[] = { \
"<hidden>", "\n", \
"à", "â", "ç", "é", "è", "ê", "î", "ô", "ù", "û", "\n", \
"À", "Â", "Ç", "É", "È", "Ê", "Î", "Ô", "Ù", "Û", "\n", \
"123", "æ", "œ", "ä", "ë", "ï", "ö", "ü", LV_SYMBOL_BACKSPACE, "\n", \
"abc", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, "âÂ", LV_SYMBOL_OK, "" \
};
static const lv_buttonmatrix_ctrl_t attributes_special_fr[] = { \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_HIDDEN | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, LV_BUTTONMATRIX_CTRL_POPOVER | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 2, SQ2LV_CTRL_NON_CHAR | 3, \
SQ2LV_CTRL_NON_CHAR | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 2, 7, SQ2LV_CTRL_NON_CHAR | 2, SQ2LV_CTRL_MOD_ACTIVE | LV_BUTTONMATRIX_CTRL_NO_REPEAT | 3, SQ2LV_CTRL_NON_CHAR | 3 \
};
static const int num_modifiers_special_fr = 0;
static const int * const modifier_idxs_special_fr = NULL;
static const int num_switchers_special_fr = 3;
static const int switcher_idxs_special_fr[] = { \
21, 30, 34 \
};
static const int switcher_dests_special_fr[] = { \
2, 0, 0 \
};
/* Layer array */
static const int num_layers_fr = 5;
static const sq2lv_layer_t layers_fr[] = {
{
.num_keys = num_keys_lower_fr,
.keycaps = keycaps_lower_fr,
.attributes = attributes_lower_fr,
.num_modifiers = num_modifiers_lower_fr,
.modifier_idxs = modifier_idxs_lower_fr,
.num_switchers = num_switchers_lower_fr,
.switcher_idxs = switcher_idxs_lower_fr,
.switcher_dests = switcher_dests_lower_fr
},
{
.num_keys = num_keys_upper_fr,
.keycaps = keycaps_upper_fr,
.attributes = attributes_upper_fr,
.num_modifiers = num_modifiers_upper_fr,
.modifier_idxs = modifier_idxs_upper_fr,
.num_switchers = num_switchers_upper_fr,
.switcher_idxs = switcher_idxs_upper_fr,
.switcher_dests = switcher_dests_upper_fr
},
{
.num_keys = num_keys_numbers_fr,
.keycaps = keycaps_numbers_fr,
.attributes = attributes_numbers_fr,
.num_modifiers = num_modifiers_numbers_fr,
.modifier_idxs = modifier_idxs_numbers_fr,
.num_switchers = num_switchers_numbers_fr,
.switcher_idxs = switcher_idxs_numbers_fr,
.switcher_dests = switcher_dests_numbers_fr
},
{
.num_keys = num_keys_symbols_fr,
.keycaps = keycaps_symbols_fr,
.attributes = attributes_symbols_fr,
.num_modifiers = num_modifiers_symbols_fr,
.modifier_idxs = modifier_idxs_symbols_fr,
.num_switchers = num_switchers_symbols_fr,
.switcher_idxs = switcher_idxs_symbols_fr,
.switcher_dests = switcher_dests_symbols_fr
},
{
.num_keys = num_keys_special_fr,
.keycaps = keycaps_special_fr,
.attributes = attributes_special_fr,
.num_modifiers = num_modifiers_special_fr,
.modifier_idxs = modifier_idxs_special_fr,
.num_switchers = num_switchers_special_fr,
.switcher_idxs = switcher_idxs_special_fr,
.switcher_dests = switcher_dests_special_fr
}
};
/**
* Public interface
**/
const int sq2lv_num_layouts = 4;
const sq2lv_layout_t sq2lv_layouts[] = {
/* US English */
{
.name = name_us,
.short_name = short_name_us,
.num_layers = num_layers_us,
.layers = layers_us
},
/* Deutsch */
{
.name = name_de,
.short_name = short_name_de,
.num_layers = num_layers_de,
.layers = layers_de
},
/* Español */
{
.name = name_es,
.short_name = short_name_es,
.num_layers = num_layers_es,
.layers = layers_es
},
/* Français */
{
.name = name_fr,
.short_name = short_name_fr,
.num_layers = num_layers_fr,
.layers = layers_fr
}
};
const char * const sq2lv_layout_names =
"US English" "\n"
"Deutsch" "\n"
"Español" "\n"
"Français";
const char * const sq2lv_layout_short_names =
"us" "\n"
"de" "\n"
"es" "\n"
"fr";

61
f0rmz/sq2lv_layouts.h Normal file
View file

@ -0,0 +1,61 @@
/**
* Auto-generated with squeek2lvgl
**/
#ifndef SQ2LV_LAYOUTS_H
#define SQ2LV_LAYOUTS_H
#include "lvgl/lvgl.h"
#define SQ2LV_SCANCODES_ENABLED 0
/* Layout IDs, values can be used as indexes into the sq2lv_layouts array */
typedef enum {
SQ2LV_LAYOUT_NONE = -1,
SQ2LV_LAYOUT_US = 0,
SQ2LV_LAYOUT_DE = 1,
SQ2LV_LAYOUT_ES = 2,
SQ2LV_LAYOUT_FR = 3
} sq2lv_layout_id_t;
/* Layer type */
typedef struct {
/* Number of keys */
const int num_keys;
/* Key caps */
const char * const * const keycaps;
/* Key attributes */
const lv_buttonmatrix_ctrl_t * const attributes;
/* Number of modifier keys */
const int num_modifiers;
/* Button indexes of modifier keys */
const int * const modifier_idxs;
/* Number of buttons that trigger a layer switch */
const int num_switchers;
/* Button indexes that trigger a layer switch */
const int * const switcher_idxs;
/* Indexes of layers to jump to when triggering layer switch buttons */
const int * const switcher_dests;
} sq2lv_layer_t;
/* Layout type */
typedef struct {
/* Layout name */
const char * const name;
/* Layout short name */
const char * const short_name;
/* Total number of layers */
const int num_layers;
/* Layers array */
const sq2lv_layer_t * const layers;
} sq2lv_layout_t;
/* Layouts */
extern const int sq2lv_num_layouts;
extern const sq2lv_layout_t sq2lv_layouts[];
/* Layout names (suitable for use in lv_dropdown_t) */
extern const char * const sq2lv_layout_names;
extern const char * const sq2lv_layout_short_names;
#endif /* SQ2LV_LAYOUTS_H */

View file

@ -22,15 +22,22 @@ endif
common_include_dirs = include_directories('.')
shared_sources = files(
'shared/backends.c',
'shared/cursor/cursor.c',
'shared/cli_common.c',
'shared/display.c',
'shared/fonts/font_32.c',
'shared/config.c',
'shared/indev.c',
'shared/keyboard.c',
'shared/log.c',
'shared/terminal.c',
'shared/theme.c',
'shared/themes.c'
)
header_sources = files('shared/header.c')
squeek2lvgl_sources = files(
'squeek2lvgl/sq2lv.c'
)
@ -47,6 +54,7 @@ common_dependencies = [
subdir('unl0kr')
subdir('buffyboard')
subdir('f0rmz')
if get_option('man')
subdir('man')

View file

@ -15,7 +15,7 @@
* Public interface
*/
const char *ul_backends_backends[] = {
const char *bbx_backends_backends[] = {
#if LV_USE_LINUX_FBDEV
"fbdev",
#endif /* LV_USE_LINUX_FBDEV */
@ -25,13 +25,13 @@ const char *ul_backends_backends[] = {
NULL
};
ul_backends_backend_id_t ul_backends_find_backend_with_name(const char *name) {
for (int i = 0; ul_backends_backends[i] != NULL; ++i) {
if (strcmp(ul_backends_backends[i], name) == 0) {
bbx_backends_backend_id_t bbx_backends_find_backend_with_name(const char *name) {
for (int i = 0; bbx_backends_backends[i] != NULL; ++i) {
if (strcmp(bbx_backends_backends[i], name) == 0) {
bbx_log(BBX_LOG_LEVEL_VERBOSE, "Found backend: %s\n", name);
return i;
}
}
bbx_log(BBX_LOG_LEVEL_WARNING, "Backend %s not found\n", name);
return UL_BACKENDS_BACKEND_NONE;
return BBX_BACKENDS_BACKEND_NONE;
}

40
shared/backends.h Normal file
View file

@ -0,0 +1,40 @@
/**
* Copyright 2022 Eugenio Paolantonio (g7)
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef BBX_BACKENDS_H
#define BBX_BACKENDS_H
#include "lvgl/lvgl.h"
/**
* Backend identifiers
*
* Only BBX_BACKENDS_BACKEND_NONE should have an explicit value assigned
*/
typedef enum {
BBX_BACKENDS_BACKEND_NONE = -1,
#if LV_USE_LINUX_FBDEV
BBX_BACKENDS_BACKEND_FBDEV,
#endif /* LV_USE_LINUX_FBDEV */
#if LV_USE_LINUX_DRM
BBX_BACKENDS_BACKEND_DRM,
#endif /* LV_USE_LINUX_DRM */
} bbx_backends_backend_id_t;
/**
* Actual backends
*/
extern const char *bbx_backends_backends[];
/**
* Find the first backend with a given name.
*
* @param name backend name
* @return ID of the first matching backend or BBX_BACKENDS_BACKEND_NONE if no backend matched
*/
bbx_backends_backend_id_t bbx_backends_find_backend_with_name(const char *name);
#endif /* BBX_BACKENDS_H */

52
shared/cli_common.c Normal file
View file

@ -0,0 +1,52 @@
/**
* Copyright 2025 buffybox contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "cli_common.h"
#include "log.h"
#include <stdio.h>
#include <stdlib.h>
#ifndef PROJECT_VERSION
#define PROJECT_VERSION "?" /* Real version injected by meson during build */
#endif
void bbx_cli_init_common_opts(bbx_cli_common_opts *opts) {
opts->hor_res = -1;
opts->ver_res = -1;
opts->x_offset = 0;
opts->y_offset = 0;
opts->dpi = 0;
opts->verbose = false;
}
int bbx_cli_parse_geometry(const char *optarg, bbx_cli_common_opts *opts) {
/* Try parsing with offset first: NxM@X,Y */
if (sscanf(optarg, "%ix%i@%i,%i", &(opts->hor_res), &(opts->ver_res),
&(opts->x_offset), &(opts->y_offset)) == 4) {
return 0;
}
/* Try parsing without offset: NxM */
if (sscanf(optarg, "%ix%i", &(opts->hor_res), &(opts->ver_res)) == 2) {
return 0;
}
bbx_log(BBX_LOG_LEVEL_ERROR, "Invalid geometry argument \"%s\"", optarg);
return -1;
}
int bbx_cli_parse_dpi(const char *optarg, bbx_cli_common_opts *opts) {
if (sscanf(optarg, "%i", &(opts->dpi)) != 1) {
bbx_log(BBX_LOG_LEVEL_ERROR, "Invalid dpi argument \"%s\"", optarg);
return -1;
}
return 0;
}
void bbx_cli_print_version_and_exit(const char *program_name) {
fprintf(stderr, "%s %s\n", program_name, PROJECT_VERSION);
exit(0);
}

58
shared/cli_common.h Normal file
View file

@ -0,0 +1,58 @@
/**
* Copyright 2025 buffybox contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef BBX_CLI_COMMON_H
#define BBX_CLI_COMMON_H
#include <stdbool.h>
/**
* Common CLI options shared across buffybox tools
*/
typedef struct {
/* Display geometry */
int hor_res;
int ver_res;
int x_offset;
int y_offset;
/* DPI override */
int dpi;
/* Verbose logging */
bool verbose;
} bbx_cli_common_opts;
/**
* Initialize common CLI options with default values.
*
* @param opts pointer to the options struct
*/
void bbx_cli_init_common_opts(bbx_cli_common_opts *opts);
/**
* Parse geometry argument in format "NxM[@X,Y]".
*
* @param optarg the argument string
* @param opts pointer to options struct to populate
* @return 0 on success, -1 on failure
*/
int bbx_cli_parse_geometry(const char *optarg, bbx_cli_common_opts *opts);
/**
* Parse DPI argument.
*
* @param optarg the argument string
* @param opts pointer to options struct to populate
* @return 0 on success, -1 on failure
*/
int bbx_cli_parse_dpi(const char *optarg, bbx_cli_common_opts *opts);
/**
* Print version information and exit.
*
* @param program_name name of the program
*/
void bbx_cli_print_version_and_exit(const char *program_name);
#endif /* BBX_CLI_COMMON_H */

91
shared/display.c Normal file
View file

@ -0,0 +1,91 @@
/**
* Copyright 2025 buffybox contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "display.h"
#include "log.h"
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
lv_display_t *bbx_display_create(bbx_backends_backend_id_t backend_id, bbx_display_config_t *config) {
lv_display_t *disp = NULL;
switch (backend_id) {
#if LV_USE_LINUX_FBDEV
case BBX_BACKENDS_BACKEND_FBDEV:
bbx_log(BBX_LOG_LEVEL_VERBOSE, "Using framebuffer backend");
disp = lv_linux_fbdev_create();
if (!disp) {
bbx_log(BBX_LOG_LEVEL_ERROR, "Failed to create framebuffer display");
return NULL;
}
if (access("/dev/fb0", F_OK) != 0) {
bbx_log(BBX_LOG_LEVEL_ERROR, "/dev/fb0 is not available");
return NULL;
}
lv_linux_fbdev_set_file(disp, "/dev/fb0");
if (config && config->fbdev_force_refresh) {
lv_linux_fbdev_set_force_refresh(disp, true);
}
break;
#endif /* LV_USE_LINUX_FBDEV */
#if LV_USE_LINUX_DRM
case BBX_BACKENDS_BACKEND_DRM:
bbx_log(BBX_LOG_LEVEL_VERBOSE, "Using DRM backend");
disp = lv_linux_drm_create();
if (!disp) {
bbx_log(BBX_LOG_LEVEL_ERROR, "Failed to create DRM display");
return NULL;
}
char drm_path[16];
bool found = false;
for (int i = 0; i < 9; i++) {
sprintf(drm_path, "/dev/dri/card%d", i);
if (access(drm_path, F_OK) == 0) {
found = true;
break;
}
}
if (!found) {
bbx_log(BBX_LOG_LEVEL_ERROR, "/dev/dri/card* are not available");
return NULL;
}
lv_linux_drm_set_file(disp, drm_path, -1);
break;
#endif /* LV_USE_LINUX_DRM */
default:
bbx_log(BBX_LOG_LEVEL_ERROR, "Unable to find suitable backend");
return NULL;
}
/* Apply configuration overrides if provided */
if (config) {
/* Set display offset */
lv_display_set_offset(disp, config->x_offset, config->y_offset);
/* Override resolution if specified */
if (config->hor_res > 0 || config->ver_res > 0) {
lv_display_set_physical_resolution(disp,
lv_display_get_horizontal_resolution(disp),
lv_display_get_vertical_resolution(disp));
lv_display_set_resolution(disp, config->hor_res, config->ver_res);
}
/* Override DPI if specified */
if (config->dpi > 0) {
lv_display_set_dpi(disp, config->dpi);
}
}
return disp;
}

37
shared/display.h Normal file
View file

@ -0,0 +1,37 @@
/**
* Copyright 2025 buffybox contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef BBX_DISPLAY_H
#define BBX_DISPLAY_H
#include "backends.h"
#include "lvgl/lvgl.h"
/**
* Display configuration options
*/
typedef struct {
/* Display resolution override */
int hor_res;
int ver_res;
/* Display offset */
int x_offset;
int y_offset;
/* DPI override */
int dpi;
/* Framebuffer force refresh quirk */
bool fbdev_force_refresh;
} bbx_display_config_t;
/**
* Initialize LVGL display with the specified backend and configuration.
*
* @param backend_id the backend to use
* @param config display configuration options
* @return initialized display or NULL on failure
*/
lv_display_t *bbx_display_create(bbx_backends_backend_id_t backend_id, bbx_display_config_t *config);
#endif /* BBX_DISPLAY_H */

88
shared/header.c Normal file
View file

@ -0,0 +1,88 @@
/**
* Copyright 2025 buffybox contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "header.h"
void bbx_header_init_config(bbx_header_config_t *config) {
config->show_theme_toggle = true;
config->show_keyboard_toggle = true;
config->show_layout_dropdown = true;
config->show_shutdown_button = true;
config->dropdown_options = "Option 1\nOption 2\nOption 3";
config->dropdown_width = 90;
config->theme_symbol = LV_SYMBOL_SETTINGS;
config->keyboard_symbol = LV_SYMBOL_KEYBOARD;
config->shutdown_symbol = LV_SYMBOL_POWER;
}
lv_obj_t *bbx_header_create(lv_obj_t *parent, bbx_header_config_t *config, bbx_header_widgets_t *widgets) {
lv_memzero(widgets, sizeof(bbx_header_widgets_t));
/* Create header flexbox */
lv_obj_t *header = lv_obj_create(parent);
widgets->header = header;
/* Theme toggle button */
if (config->show_theme_toggle) {
lv_obj_t *btn = lv_button_create(header);
widgets->theme_toggle_btn = btn;
lv_obj_t *label = lv_label_create(btn);
lv_label_set_text(label, config->theme_symbol);
lv_obj_center(label);
}
/* Keyboard toggle button */
if (config->show_keyboard_toggle) {
lv_obj_t *btn = lv_button_create(header);
widgets->keyboard_toggle_btn = btn;
lv_obj_t *label = lv_label_create(btn);
lv_label_set_text(label, config->keyboard_symbol);
lv_obj_center(label);
}
/* Layout dropdown */
if (config->show_layout_dropdown) {
lv_obj_t *dropdown = lv_dropdown_create(header);
widgets->layout_dropdown = dropdown;
lv_dropdown_set_options(dropdown, config->dropdown_options);
lv_obj_set_width(dropdown, config->dropdown_width);
}
/* Spacer */
lv_obj_t *spacer = lv_obj_create(header);
lv_obj_set_height(spacer, 0);
lv_obj_set_flex_grow(spacer, 1);
/* Shutdown button */
if (config->show_shutdown_button) {
lv_obj_t *btn = lv_button_create(header);
widgets->shutdown_btn = btn;
lv_obj_t *label = lv_label_create(btn);
lv_label_set_text(label, config->shutdown_symbol);
lv_obj_center(label);
}
/* Size buttons to match dropdown height */
if (widgets->layout_dropdown) {
lv_obj_update_layout(widgets->layout_dropdown);
const int32_t dropdown_height = lv_obj_get_height(widgets->layout_dropdown);
if (widgets->theme_toggle_btn) {
lv_obj_set_size(widgets->theme_toggle_btn, dropdown_height, dropdown_height);
}
if (widgets->keyboard_toggle_btn) {
lv_obj_set_size(widgets->keyboard_toggle_btn, dropdown_height, dropdown_height);
}
if (widgets->shutdown_btn) {
lv_obj_set_size(widgets->shutdown_btn, dropdown_height, dropdown_height);
}
}
return header;
}

60
shared/header.h Normal file
View file

@ -0,0 +1,60 @@
/**
* Copyright 2025 buffybox contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef BBX_HEADER_H
#define BBX_HEADER_H
#include "lvgl/lvgl.h"
#include <stdbool.h>
/**
* Header configuration options
*/
typedef struct {
/* Which elements to include */
bool show_theme_toggle;
bool show_keyboard_toggle;
bool show_layout_dropdown;
bool show_shutdown_button;
/* Dropdown options (if enabled) */
const char *dropdown_options;
int dropdown_width;
/* Button symbols */
const char *theme_symbol;
const char *keyboard_symbol;
const char *shutdown_symbol;
} bbx_header_config_t;
/**
* Header widget references for attaching callbacks
*/
typedef struct {
lv_obj_t *header;
lv_obj_t *theme_toggle_btn;
lv_obj_t *keyboard_toggle_btn;
lv_obj_t *layout_dropdown;
lv_obj_t *shutdown_btn;
} bbx_header_widgets_t;
/**
* Create a header bar with configurable elements.
*
* @param parent parent object (usually screen)
* @param config header configuration
* @param widgets output struct for widget references
* @return header object
*/
lv_obj_t *bbx_header_create(lv_obj_t *parent, bbx_header_config_t *config, bbx_header_widgets_t *widgets);
/**
* Initialize header config with default values.
*
* @param config config struct to initialize
*/
void bbx_header_init_config(bbx_header_config_t *config);
#endif /* BBX_HEADER_H */

59
shared/keyboard.c Normal file
View file

@ -0,0 +1,59 @@
/**
* Copyright 2025 buffybox contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "keyboard.h"
#include "theme.h"
#include "../squeek2lvgl/sq2lv.h"
void bbx_keyboard_init_config(bbx_keyboard_config_t *config) {
config->mode = LV_KEYBOARD_MODE_TEXT_LOWER;
config->layout_id = 0; /* Default to first layout */
config->popovers = false;
config->height = -1; /* Auto-calculate */
config->value_changed_callback = NULL;
config->ready_callback = NULL;
}
lv_obj_t *bbx_keyboard_create(lv_obj_t *parent, lv_obj_t *textarea, bbx_keyboard_config_t *config) {
lv_obj_t *keyboard = lv_keyboard_create(parent);
lv_keyboard_set_mode(keyboard, config->mode);
lv_keyboard_set_textarea(keyboard, textarea);
/* Remove default event callback and add custom ones */
uint32_t num_events = lv_obj_get_event_count(keyboard);
for(uint32_t i = 0; i < num_events; ++i) {
if(lv_event_dsc_get_cb(lv_obj_get_event_dsc(keyboard, i)) == lv_keyboard_def_event_cb) {
lv_obj_remove_event(keyboard, i);
break;
}
}
if (config->value_changed_callback) {
lv_obj_add_event_cb(keyboard, config->value_changed_callback, LV_EVENT_VALUE_CHANGED, NULL);
}
if (config->ready_callback) {
lv_obj_add_event_cb(keyboard, config->ready_callback, LV_EVENT_READY, NULL);
}
/* Set size */
if (config->height > 0) {
lv_obj_set_size(keyboard, LV_PCT(100), config->height);
}
/* Apply theme preparation */
bbx_theme_prepare_keyboard(keyboard);
/* Set layout */
sq2lv_switch_layout(keyboard, config->layout_id);
/* Enable popovers if requested */
if (config->popovers) {
lv_keyboard_set_popovers(keyboard, true);
}
return keyboard;
}

19
shared/keyboard.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef BBX_KEYBOARD_H
#define BBX_KEYBOARD_H
#include "lvgl/lvgl.h"
#include <stdbool.h>
typedef struct {
lv_keyboard_mode_t mode;
int layout_id;
bool popovers;
int32_t height;
lv_event_cb_t value_changed_callback;
lv_event_cb_t ready_callback;
} bbx_keyboard_config_t;
lv_obj_t *bbx_keyboard_create(lv_obj_t *parent, lv_obj_t *textarea, bbx_keyboard_config_t *config);
void bbx_keyboard_init_config(bbx_keyboard_config_t *config);
#endif /* BBX_KEYBOARD_H */

View file

@ -30,7 +30,7 @@ static int original_kb_mode = -1;
* Public functions
*/
void ul_terminal_prepare_current_terminal(bool enable_graphics_mode, bool disable_keyboard_input) {
void bbx_terminal_prepare_current_terminal(bool enable_graphics_mode, bool disable_keyboard_input) {
/* Exit early if there is nothing to do */
if (!enable_graphics_mode && !disable_keyboard_input) {
return;
@ -66,7 +66,7 @@ void ul_terminal_prepare_current_terminal(bool enable_graphics_mode, bool disabl
}
}
void ul_terminal_reset_current_terminal(void) {
void bbx_terminal_reset_current_terminal(void) {
/* If we haven't previously opened the current terminal, exit */
if (current_fd < 0) {
bbx_log(BBX_LOG_LEVEL_WARNING, "Could not reset current terminal");

View file

@ -4,8 +4,8 @@
*/
#ifndef UL_TERMINAL_H
#define UL_TERMINAL_H
#ifndef BBX_TERMINAL_H
#define BBX_TERMINAL_H
#include <stdbool.h>
@ -15,11 +15,11 @@
* @param enable_graphics_mode if true, switch terminal into graphics mode (hides command prompt)
* @param disable_keyboard_input if true, disable terminal keyboard input (hides entered text)
*/
void ul_terminal_prepare_current_terminal(bool enable_graphics_mode, bool disable_keyboard_input);
void bbx_terminal_prepare_current_terminal(bool enable_graphics_mode, bool disable_keyboard_input);
/**
* Reset the current TTY to text output.
*/
void ul_terminal_reset_current_terminal(void);
void bbx_terminal_reset_current_terminal(void);
#endif /* UL_TERMINAL_H */
#endif /* BBX_TERMINAL_H */

View file

@ -230,6 +230,10 @@ static void apply_theme_cb(lv_theme_t *theme, lv_obj_t *obj) {
if (lv_obj_has_flag(obj, BBX_WIDGET_HEADER)) {
lv_obj_add_style(obj, &(styles.header), 0);
#if LV_USE_FLEX
lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW);
lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT);
#endif
return;
}

View file

@ -1,40 +0,0 @@
/**
* Copyright 2022 Eugenio Paolantonio (g7)
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef UL_BACKENDS_H
#define UL_BACKENDS_H
#include "lvgl/lvgl.h"
/**
* Backend identifiers
*
* Only UL_BACKENDS_BACKEND_NONE should have an explicit value assigned
*/
typedef enum {
UL_BACKENDS_BACKEND_NONE = -1,
#if LV_USE_LINUX_FBDEV
UL_BACKENDS_BACKEND_FBDEV,
#endif /* LV_USE_LINUX_FBDEV */
#if LV_USE_LINUX_DRM
UL_BACKENDS_BACKEND_DRM,
#endif /* LV_USE_LINUX_DRM */
} ul_backends_backend_id_t;
/**
* Actual backends
*/
extern const char *ul_backends_backends[];
/**
* Find the first backend with a given name.
*
* @param name backend name
* @return ID of the first matching backend or UL_BACKENDS_BACKEND_NONE if no backend matched
*/
ul_backends_backend_id_t ul_backends_find_backend_with_name(const char *name);
#endif /* UL_BACKENDS_H */

View file

@ -38,16 +38,11 @@ static void print_usage();
*/
static void init_opts(ul_cli_opts *opts) {
bbx_cli_init_common_opts(&opts->common);
opts->num_config_files = 0;
opts->config_files = NULL;
opts->message = NULL;
opts->hor_res = -1;
opts->ver_res = -1;
opts->x_offset = 0;
opts->y_offset = 0;
opts->dpi = 0;
opts->newline = true;
opts->verbose = false;
}
static void print_usage() {
@ -115,16 +110,12 @@ void ul_cli_parse_opts(int argc, char *argv[], ul_cli_opts *opts) {
opts->num_config_files++;
break;
case 'g':
if (sscanf(optarg, "%ix%i@%i,%i", &(opts->hor_res), &(opts->ver_res), &(opts->x_offset), &(opts->y_offset)) != 4) {
if (sscanf(optarg, "%ix%i", &(opts->hor_res), &(opts->ver_res)) != 2) {
bbx_log(BBX_LOG_LEVEL_ERROR, "Invalid geometry argument \"%s\"\n", optarg);
if (bbx_cli_parse_geometry(optarg, &opts->common) != 0) {
exit(EXIT_FAILURE);
}
}
break;
case 'd':
if (sscanf(optarg, "%i", &(opts->dpi)) != 1) {
bbx_log(BBX_LOG_LEVEL_ERROR, "Invalid dpi argument \"%s\"\n", optarg);
if (bbx_cli_parse_dpi(optarg, &opts->common) != 0) {
exit(EXIT_FAILURE);
}
break;
@ -135,11 +126,11 @@ void ul_cli_parse_opts(int argc, char *argv[], ul_cli_opts *opts) {
opts->newline = false;
break;
case 'v':
opts->verbose = true;
opts->common.verbose = true;
break;
case 'V':
fprintf(stderr, "unl0kr %s\n", PROJECT_VERSION);
exit(0);
bbx_cli_print_version_and_exit("unl0kr");
break;
default:
print_usage();
exit(EXIT_FAILURE);

View file

@ -7,32 +7,23 @@
#ifndef UL_COMMAND_LINE_H
#define UL_COMMAND_LINE_H
#include "../shared/cli_common.h"
#include <stdbool.h>
/**
* Options parsed from command line arguments
*/
typedef struct {
/* Common cli options */
bbx_cli_common_opts common;
/* Number of config files */
int num_config_files;
/* Paths of config file */
const char **config_files;
/* Message for a user */
const char *message;
/* Horizontal display resolution */
int hor_res;
/* Vertical display resolution */
int ver_res;
/* Horizontal display offset */
int x_offset;
/* Vertical display offset */
int y_offset;
/* DPI */
int dpi;
/* If true, append a newline character to a password */
bool newline;
/* Verbose mode. If true, provide more detailed logging output on STDERR. */
bool verbose;
} ul_cli_opts;
/**

View file

@ -46,8 +46,8 @@ static int parsing_handler(void* user_data, const char* section, const char* key
return 1;
}
} else if (strcmp(key, "backend") == 0) {
ul_backends_backend_id_t id = ul_backends_find_backend_with_name(value);
if (id != UL_BACKENDS_BACKEND_NONE) {
bbx_backends_backend_id_t id = bbx_backends_find_backend_with_name(value);
if (id != BBX_BACKENDS_BACKEND_NONE) {
opts->general.backend = id;
return 1;
}
@ -139,7 +139,7 @@ static int parsing_handler(void* user_data, const char* section, const char* key
void ul_config_init_opts(ul_config_opts *opts) {
opts->general.animations = false;
opts->general.backend = ul_backends_backends[0] == NULL ? UL_BACKENDS_BACKEND_NONE : 0;
opts->general.backend = bbx_backends_backends[0] == NULL ? BBX_BACKENDS_BACKEND_NONE : 0;
opts->general.timeout = 0;
opts->keyboard.autohide = true;
opts->keyboard.layout_id = SQ2LV_LAYOUT_US;

View file

@ -7,8 +7,8 @@
#ifndef UL_CONFIG_H
#define UL_CONFIG_H
#include "backends.h"
#include "../shared/backends.h"
#include "../shared/themes.h"
#include "sq2lv_layouts.h"
@ -23,7 +23,7 @@ typedef struct {
/* If true, use animations */
bool animations;
/* Backend to use */
ul_backends_backend_id_t backend;
bbx_backends_backend_id_t backend;
/* Timeout (in seconds) - once elapsed, the device will shutdown. 0 (default) to disable */
uint16_t timeout;
} ul_config_opts_general;

View file

@ -4,14 +4,17 @@
*/
#include "backends.h"
#include "command_line.h"
#include "config.h"
#include "unl0kr.h"
#include "terminal.h"
#include "../shared/backends.h"
#include "../shared/display.h"
#include "../shared/header.h"
#include "../shared/indev.h"
#include "../shared/keyboard.h"
#include "../shared/log.h"
#include "../shared/terminal.h"
#include "../shared/theme.h"
#include "../shared/themes.h"
#include "../squeek2lvgl/sq2lv.h"
@ -372,12 +375,12 @@ static void shutdown(void) {
static void sigaction_handler(int signum) {
LV_UNUSED(signum);
ul_terminal_reset_current_terminal();
bbx_terminal_reset_current_terminal();
exit(0);
}
static void exit_failure() {
ul_terminal_reset_current_terminal();
bbx_terminal_reset_current_terminal();
exit(EXIT_FAILURE);
}
@ -391,7 +394,7 @@ int main(int argc, char *argv[]) {
ul_cli_parse_opts(argc, argv, &cli_opts);
/* Set up log level */
if (cli_opts.verbose) {
if (cli_opts.common.verbose) {
bbx_log_set_level(BBX_LOG_LEVEL_VERBOSE);
}
@ -414,7 +417,7 @@ int main(int argc, char *argv[]) {
ul_config_parse_files(cli_opts.config_files, cli_opts.num_config_files, &conf_opts);
/* Prepare current TTY and clean up on termination */
ul_terminal_prepare_current_terminal(!conf_opts.quirks.terminal_prevent_graphics_mode, !conf_opts.quirks.terminal_allow_keyboard_input);
bbx_terminal_prepare_current_terminal(!conf_opts.quirks.terminal_prevent_graphics_mode, !conf_opts.quirks.terminal_allow_keyboard_input);
struct sigaction action;
memset(&action, 0, sizeof(action));
action.sa_handler = sigaction_handler;
@ -425,61 +428,21 @@ int main(int argc, char *argv[]) {
lv_init();
lv_log_register_print_cb(bbx_log_print_cb);
/* Initialise display */
lv_display_t *disp = NULL;
switch (conf_opts.general.backend) {
#if LV_USE_LINUX_FBDEV
case UL_BACKENDS_BACKEND_FBDEV:
bbx_log(BBX_LOG_LEVEL_VERBOSE, "Using framebuffer backend");
disp = lv_linux_fbdev_create();
if (access("/dev/fb0", F_OK) != 0) {
bbx_log(BBX_LOG_LEVEL_ERROR, "/dev/fb0 is not available");
/* Populate display config */
bbx_display_config_t display_config = {
.hor_res = cli_opts.common.hor_res,
.ver_res = cli_opts.common.ver_res,
.x_offset = cli_opts.common.x_offset,
.y_offset = cli_opts.common.y_offset,
.dpi = cli_opts.common.dpi,
.fbdev_force_refresh = conf_opts.quirks.fbdev_force_refresh
};
/* Initialize display */
lv_display_t *disp = bbx_display_create(conf_opts.general.backend, &display_config);
if (!disp) {
exit_failure();
}
lv_linux_fbdev_set_file(disp, "/dev/fb0");
if (conf_opts.quirks.fbdev_force_refresh) {
lv_linux_fbdev_set_force_refresh(disp, true);
}
break;
#endif /* LV_USE_LINUX_FBDEV */
#if LV_USE_LINUX_DRM
case UL_BACKENDS_BACKEND_DRM:
bbx_log(BBX_LOG_LEVEL_VERBOSE, "Using DRM backend");
disp = lv_linux_drm_create();
char drm_path[16];
bool found = false;
for (int i = 0; i < 9; i++) {
sprintf(drm_path, "/dev/dri/card%d", i);
if (access(drm_path, F_OK) == 0) {
found = true;
break;
}
}
if (!found) {
bbx_log(BBX_LOG_LEVEL_ERROR, "/dev/dri/card* are not available");
exit_failure();
}
lv_linux_drm_set_file(disp, drm_path, -1);
break;
#endif /* LV_USE_LINUX_DRM */
default:
bbx_log(BBX_LOG_LEVEL_ERROR, "Unable to find suitable backend");
exit_failure();
}
/* Override display properties with command line options if necessary */
lv_display_set_offset(disp, cli_opts.x_offset, cli_opts.y_offset);
if (cli_opts.hor_res > 0 || cli_opts.ver_res > 0) {
lv_display_set_physical_resolution(disp, lv_display_get_horizontal_resolution(disp), lv_display_get_vertical_resolution(disp));
lv_display_set_resolution(disp, cli_opts.hor_res, cli_opts.ver_res);
}
if (cli_opts.dpi > 0) {
lv_display_set_dpi(disp, cli_opts.dpi);
}
/* Prepare for routing physical keyboard input into the textarea */
lv_group_t *keyboard_input_group = lv_group_create();
@ -507,50 +470,25 @@ int main(int argc, char *argv[]) {
lv_obj_set_flex_flow(screen, LV_FLEX_FLOW_COLUMN);
lv_obj_remove_flag(screen, LV_OBJ_FLAG_SCROLLABLE);
/* Header flexbox */
lv_obj_t *header = lv_obj_create(screen);
/* Configure header */
bbx_header_config_t header_config;
bbx_header_init_config(&header_config);
header_config.theme_symbol = UL_SYMBOL_ADJUST;
header_config.dropdown_options = sq2lv_layout_short_names;
bbx_header_widgets_t header_widgets;
lv_obj_t *header = bbx_header_create(screen, &header_config, &header_widgets);
lv_obj_add_flag(header, BBX_WIDGET_HEADER);
lv_theme_apply(header); /* Force re-apply theme after setting flag so that the widget can be identified */
lv_obj_set_flex_flow(header, LV_FLEX_FLOW_ROW);
lv_obj_set_size(header, LV_PCT(100), LV_SIZE_CONTENT);
/* Theme switcher button */
lv_obj_t *toggle_theme_btn = lv_button_create(header);
lv_obj_add_event_cb(toggle_theme_btn, toggle_theme_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
lv_obj_t *toggle_theme_btn_label = lv_label_create(toggle_theme_btn);
lv_label_set_text(toggle_theme_btn_label, UL_SYMBOL_ADJUST);
lv_obj_center(toggle_theme_btn_label);
/* Add theme toggle to distinguish this widget type */
lv_obj_add_flag(header, BBX_WIDGET_HEADER);
lv_theme_apply(header);
/* Show / hide keyboard button */
lv_obj_t *toggle_kb_btn = lv_button_create(header);
lv_obj_add_event_cb(toggle_kb_btn, toggle_kb_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
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(header);
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_width(layout_dropdown, 90);
/* Spacer */
lv_obj_t *spacer = lv_obj_create(header);
lv_obj_set_height(spacer, 0);
lv_obj_set_flex_grow(spacer, 1);
/* Shutdown button */
lv_obj_t *shutdown_btn = lv_button_create(header);
lv_obj_add_event_cb(shutdown_btn, shutdown_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
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);
lv_obj_update_layout(layout_dropdown);
const int32_t dropwdown_height = lv_obj_get_height(layout_dropdown);
lv_obj_set_size(toggle_theme_btn, dropwdown_height, dropwdown_height);
lv_obj_set_size(toggle_kb_btn, dropwdown_height, dropwdown_height);
lv_obj_set_size(shutdown_btn, dropwdown_height, dropwdown_height);
/* Attach callbacks */
lv_obj_add_event_cb(header_widgets.theme_toggle_btn, toggle_theme_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
lv_obj_add_event_cb(header_widgets.keyboard_toggle_btn, toggle_kb_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
lv_obj_add_event_cb(header_widgets.layout_dropdown, layout_dropdown_value_changed_cb, LV_EVENT_VALUE_CHANGED, NULL);
lv_obj_add_event_cb(header_widgets.shutdown_btn, shutdown_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
lv_obj_update_layout(header);
content_height_without_kb = ver_res - lv_obj_get_height(header);
@ -633,30 +571,22 @@ int main(int argc, char *argv[]) {
lv_obj_set_style_pad_bottom(container, is_keyboard_hidden? content_pad_bottom_without_kb : content_pad_bottom_with_kb, LV_PART_MAIN);
/* Keyboard (after textarea / label so that key popovers are not drawn over) */
keyboard = lv_keyboard_create(screen);
lv_keyboard_set_mode(keyboard, LV_KEYBOARD_MODE_TEXT_LOWER);
lv_keyboard_set_textarea(keyboard, textarea);
uint32_t num_keyboard_events = lv_obj_get_event_count(keyboard);
for(uint32_t i = 0; i < num_keyboard_events; ++i) {
if(lv_event_dsc_get_cb(lv_obj_get_event_dsc(keyboard, i)) == lv_keyboard_def_event_cb) {
lv_obj_remove_event(keyboard, i);
break;
}
}
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);
lv_obj_set_size(keyboard, LV_PCT(100), keyboard_height);
bbx_theme_prepare_keyboard(keyboard);
bbx_keyboard_config_t keyboard_config;
bbx_keyboard_init_config(&keyboard_config);
keyboard_config.layout_id = (int)conf_opts.keyboard.layout_id;
keyboard_config.height = keyboard_height;
keyboard_config.popovers = conf_opts.keyboard.popovers;
keyboard_config.value_changed_callback = keyboard_value_changed_cb;
keyboard_config.ready_callback = keyboard_ready_cb;
keyboard = bbx_keyboard_create(screen, textarea, &keyboard_config);
/* 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) {
lv_keyboard_set_popovers(keyboard, true);
}
lv_dropdown_set_selected(header_widgets.layout_dropdown, conf_opts.keyboard.layout_id);
/* Periodically run timer / task handler */
uint32_t timeout = conf_opts.general.timeout * 1000; /* ms */

View file

@ -2,12 +2,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later
unl0kr_sources = files(
'backends.c',
'command_line.c',
'config.c',
'main.c',
'sq2lv_layouts.c',
'terminal.c'
)
unl0kr_dependencies = [
@ -27,7 +25,7 @@ endif
executable('unl0kr',
include_directories: common_include_dirs,
sources: unl0kr_sources + shared_sources + squeek2lvgl_sources + lvgl_sources,
sources: unl0kr_sources + shared_sources + squeek2lvgl_sources + lvgl_sources + header_sources,
dependencies: unl0kr_dependencies,
c_args: unl0kr_args,
install: true,