17
README.md
17
README.md
@@ -56,23 +56,34 @@ Below is a summary of contributions upstreamed thus far.
|
||||
|
||||
# Usage
|
||||
|
||||
For an overview of available command line options, run unl0kr with the `-h` or `--help` argument.
|
||||
A man page is planned to be added with #6. For the time being, you can get an overview of available command line options by running unl0kr with the `-h` or `--help` argument.
|
||||
|
||||
```
|
||||
$ unl0kr --help
|
||||
Usage: unl0kr [OPTION]
|
||||
|
||||
Mandatory arguments to long options are mandatory for short options too.
|
||||
-g, --geometry=NxM Force a display size of N horizontal times M vertical pixels
|
||||
-c, --config=PATH Locaton of the main config file. Defaults to
|
||||
/etc/unl0kr.conf.
|
||||
-C, --config-override Location of the config override file. Values in
|
||||
this file override values for the same keys in the
|
||||
main config file. If specified multiple times, the
|
||||
values from consecutive files will be merged in
|
||||
order.
|
||||
-g, --geometry=NxM Force a display size of N horizontal times M
|
||||
vertical pixels
|
||||
-h, --help Print this message and exit
|
||||
-v, --verbose Enable more detailed logging output on STDERR
|
||||
-V, --version Print the unl0kr version and exit
|
||||
```
|
||||
|
||||
For an example configuration file, see [unl0kr.conf].
|
||||
|
||||
# Development
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [inih]
|
||||
- [lvgl] (git submodule / linked statically)
|
||||
- [lv_drivers] (git submodule / linked statically)
|
||||
- [squeek2lvgl] (git submodule / linked statically)
|
||||
@@ -172,6 +183,7 @@ The [FontAwesome] font is licensed under the Open Font License version 1.1.
|
||||
[feat(msgbox): omit title label unless needed]: https://github.com/lvgl/lvgl/pull/2539
|
||||
[fix(btnmatrix): make ORed values work correctly with lv_btnmatrix_has_btn_ctrl]: https://github.com/lvgl/lvgl/pull/2571
|
||||
[fix(examples) don't compile assets unless needed]: https://github.com/lvgl/lvgl/pull/2523
|
||||
[inih]: https://github.com/benhoyt/inih
|
||||
[libinput]: https://gitlab.freedesktop.org/libinput/libinput
|
||||
[libxkbcommon]: https://github.com/xkbcommon/libxkbcommon
|
||||
[lv_drivers]: https://github.com/lvgl/lv_drivers
|
||||
@@ -183,5 +195,6 @@ The [FontAwesome] font is licensed under the Open Font License version 1.1.
|
||||
[osk-sdl]: https://gitlab.com/postmarketOS/osk-sdl
|
||||
[squeek2lvgl]: https://gitlab.com/cherrypicker/squeek2lvgl
|
||||
[squeekboard layouts]: https://gitlab.gnome.org/World/Phosh/squeekboard/-/tree/master/data/keyboards
|
||||
[unl0kr.conf]: ./unl0kr.conf
|
||||
[v1 milestone]: https://gitlab.com/cherrypicker/unl0kr/-/milestones/1
|
||||
[wiki]: https://gitlab.com/cherrypicker/unl0kr/-/wikis/home
|
||||
|
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "command_line.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "unl0kr.h"
|
||||
|
||||
#include <getopt.h>
|
||||
@@ -32,7 +33,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialise a command line options struct with default values.
|
||||
* Initialise a command line options struct with default values and exit on failure.
|
||||
*
|
||||
* @param opts pointer to the options struct
|
||||
*/
|
||||
@@ -49,6 +50,15 @@ static void print_usage();
|
||||
*/
|
||||
|
||||
static void init_opts(ul_cli_opts *opts) {
|
||||
opts->num_config_files = 1;
|
||||
|
||||
opts->config_files = malloc(sizeof(char *));
|
||||
if (!opts->config_files) {
|
||||
ul_log(UL_LOG_LEVEL_ERROR, "Could not allocate memory for config file paths");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
opts->config_files[0] = "/etc/unl0kr.conf";
|
||||
|
||||
opts->hor_res = -1;
|
||||
opts->ver_res = -1;
|
||||
opts->verbose = false;
|
||||
@@ -56,13 +66,23 @@ static void init_opts(ul_cli_opts *opts) {
|
||||
|
||||
static void print_usage() {
|
||||
fprintf(stderr,
|
||||
/*-------------------------------- 78 CHARS --------------------------------*/
|
||||
"Usage: unl0kr [OPTION]\n"
|
||||
"\n"
|
||||
"Mandatory arguments to long options are mandatory for short options too.\n"
|
||||
" -g, --geometry=NxM Force a display size of N horizontal times M vertical pixels\n"
|
||||
" -c, --config=PATH Locaton of the main config file. Defaults to\n"
|
||||
" /etc/unl0kr.conf.\n"
|
||||
" -C, --config-override Location of the config override file. Values in\n"
|
||||
" this file override values for the same keys in the\n"
|
||||
" main config file. If specified multiple times, the\n"
|
||||
" values from consecutive files will be merged in\n"
|
||||
" order.\n"
|
||||
" -g, --geometry=NxM Force a display size of N horizontal times M\n"
|
||||
" vertical pixels\n"
|
||||
" -h, --help Print this message and exit\n"
|
||||
" -v, --verbose Enable more detailed logging output on STDERR\n"
|
||||
" -V, --version Print the unl0kr version and exit\n");
|
||||
/*-------------------------------- 78 CHARS --------------------------------*/
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +94,8 @@ void ul_cli_parse_opts(int argc, char *argv[], ul_cli_opts *opts) {
|
||||
init_opts(opts);
|
||||
|
||||
struct option long_opts[] = {
|
||||
{ "config", required_argument, NULL, 'c' },
|
||||
{ "config-override", required_argument, NULL, 'C' },
|
||||
{ "geometry", required_argument, NULL, 'g' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "verbose", no_argument, NULL, 'v' },
|
||||
@@ -83,11 +105,23 @@ void ul_cli_parse_opts(int argc, char *argv[], ul_cli_opts *opts) {
|
||||
|
||||
int opt, index = 0;
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "g:hvV", long_opts, &index)) != -1) {
|
||||
while ((opt = getopt_long(argc, argv, "c:C:g:hvV", long_opts, &index)) != -1) {
|
||||
switch (opt) {
|
||||
case 'c':
|
||||
opts->config_files[0] = optarg;
|
||||
break;
|
||||
case 'C':
|
||||
opts->config_files = realloc(opts->config_files, (opts->num_config_files + 1) * sizeof(char *));
|
||||
if (!opts->config_files) {
|
||||
ul_log(UL_LOG_LEVEL_ERROR, "Could not allocate memory for config file paths");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
opts->config_files[opts->num_config_files] = optarg;
|
||||
opts->num_config_files++;
|
||||
break;
|
||||
case 'g':
|
||||
if (sscanf(optarg, "%ix%i", &(opts->hor_res), &(opts->ver_res)) != 2) {
|
||||
fprintf(stderr, "Error: invalid geometry argument \"%s\"\n", optarg);
|
||||
ul_log(UL_LOG_LEVEL_ERROR, "Invalid geometry argument \"%s\"\n", optarg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
|
@@ -27,6 +27,10 @@
|
||||
* Options parsed from command line arguments
|
||||
*/
|
||||
typedef struct {
|
||||
/* 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 */
|
||||
|
144
config.c
Normal file
144
config.c
Normal file
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* Copyright 2021 Johannes Marbach
|
||||
*
|
||||
* This file is part of unl0kr, hereafter referred to as the program.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#include <ini.h>
|
||||
|
||||
#include "squeek2lvgl/sq2lv.h"
|
||||
|
||||
|
||||
/**
|
||||
* Static prototypes
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialise a config options struct with default values.
|
||||
*
|
||||
* @param opts pointer to the options struct
|
||||
*/
|
||||
static void init_opts(ul_config_opts *opts);
|
||||
|
||||
/**
|
||||
* Parse options from a configuration file.
|
||||
*
|
||||
* @param path path to configuration file
|
||||
* @param opts pointer for writing the parsed options into
|
||||
*/
|
||||
static void parse_file(const char *path, ul_config_opts *opts);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Attempt to parse a boolean value.
|
||||
*
|
||||
* @param value string to parse
|
||||
* @param result pointer to write result into if parsing is successful
|
||||
* @return true on success, false otherwise
|
||||
*/
|
||||
static bool parse_bool(const char *value, bool *result);
|
||||
|
||||
|
||||
/**
|
||||
* Static functions
|
||||
*/
|
||||
|
||||
static void init_opts(ul_config_opts *opts) {
|
||||
opts->general.animations = false;
|
||||
opts->textarea.obscured = true;
|
||||
opts->keyboard.layout_id = SQ2LV_LAYOUT_US;
|
||||
opts->keyboard.popovers = false;
|
||||
}
|
||||
|
||||
static void parse_file(const char *path, ul_config_opts *opts) {
|
||||
if (ini_parse(path, parsing_handler, opts) != 0) {
|
||||
ul_log(UL_LOG_LEVEL_ERROR, "Ignoring invalid config file %s", path);
|
||||
}
|
||||
}
|
||||
|
||||
static int parsing_handler(void* user_data, const char* section, const char* key, const char* value) {
|
||||
ul_config_opts *opts = (ul_config_opts *)user_data;
|
||||
|
||||
if (strcmp(section, "general") == 0) {
|
||||
if (strcmp(key, "animations") == 0) {
|
||||
if (parse_bool(value, &(opts->general.animations))) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else if (strcmp(section, "textarea") == 0) {
|
||||
if (strcmp(key, "obscured") == 0) {
|
||||
if (parse_bool(value, &(opts->textarea.obscured))) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else if (strcmp(section, "keyboard") == 0) {
|
||||
if (strcmp(key, "popovers") == 0) {
|
||||
if (parse_bool(value, &(opts->keyboard.popovers))) {
|
||||
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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ul_log(UL_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 (e.g. file not found) */
|
||||
}
|
||||
|
||||
static bool parse_bool(const char *value, bool *result) {
|
||||
if (strcmp(value, "true") == 0) {
|
||||
*result = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strcmp(value, "false") == 0) {
|
||||
*result = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Public functions
|
||||
*/
|
||||
|
||||
void ul_config_parse(const char **files, int num_files, ul_config_opts *opts) {
|
||||
init_opts(opts);
|
||||
for (int i = 0; i < num_files; ++i) {
|
||||
parse_file(files[i], opts);
|
||||
}
|
||||
}
|
75
config.h
Normal file
75
config.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Copyright 2021 Johannes Marbach
|
||||
*
|
||||
* This file is part of unl0kr, hereafter referred to as the program.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UL_CONFIG_H
|
||||
#define UL_CONFIG_H
|
||||
|
||||
#include "sq2lv_layouts.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* General options
|
||||
*/
|
||||
typedef struct {
|
||||
/* If true, use animations */
|
||||
bool animations;
|
||||
} ul_config_opts_general;
|
||||
|
||||
/**
|
||||
* Options related to the password textarea
|
||||
*/
|
||||
typedef struct {
|
||||
/* If true, disguise the entered text with dots */
|
||||
bool obscured;
|
||||
} ul_config_opts_textarea;
|
||||
|
||||
/**
|
||||
* Options related to the keyboard
|
||||
*/
|
||||
typedef struct {
|
||||
/* Keyboard layout */
|
||||
sq2lv_layout_id_t layout_id;
|
||||
/* If true, display key popovers on press */
|
||||
bool popovers;
|
||||
} ul_config_opts_keyboard;
|
||||
|
||||
/**
|
||||
* Options parsed from config file(s)
|
||||
*/
|
||||
typedef struct {
|
||||
/* General options */
|
||||
ul_config_opts_general general;
|
||||
/* Options related to the password textarea */
|
||||
ul_config_opts_textarea textarea;
|
||||
/* Options related to the keyboard */
|
||||
ul_config_opts_keyboard keyboard;
|
||||
} ul_config_opts;
|
||||
|
||||
/**
|
||||
* Parse options from 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 ul_config_parse(const char **files, int num_files, ul_config_opts *opts);
|
||||
|
||||
#endif /* UL_CONFIG_H */
|
66
main.c
66
main.c
@@ -19,6 +19,7 @@
|
||||
|
||||
|
||||
#include "command_line.h"
|
||||
#include "config.h"
|
||||
#include "indev.h"
|
||||
#include "log.h"
|
||||
#include "unl0kr.h"
|
||||
@@ -50,8 +51,11 @@ LV_FONT_DECLARE(montserrat_extended_32);
|
||||
* Static variables
|
||||
*/
|
||||
|
||||
ul_cli_opts cli_opts;
|
||||
ul_config_opts conf_opts;
|
||||
|
||||
bool is_dark_theme = false;
|
||||
bool is_password_hidden = true;
|
||||
bool is_password_obscured = true;
|
||||
bool is_keyboard_hidden = false;
|
||||
|
||||
lv_obj_t *keyboard = NULL;
|
||||
@@ -92,14 +96,14 @@ static void toggle_pw_btn_clicked_cb(lv_event_t *event);
|
||||
/**
|
||||
* Toggle between showing and hiding the password.
|
||||
*/
|
||||
static void toggle_password_hidden(void);
|
||||
static void toggle_password_obscured(void);
|
||||
|
||||
/**
|
||||
* Show / hide the password.
|
||||
*
|
||||
* @param is_hidden true if the password should be hidden, false if it should be shown
|
||||
*/
|
||||
static void set_password_hidden(bool is_hidden);
|
||||
static void set_password_obscured(bool is_obscured);
|
||||
|
||||
/**
|
||||
* Handle LV_EVENT_CLICKED events from the show/hide keyboard toggle button.
|
||||
@@ -196,17 +200,17 @@ static void set_theme(bool is_dark) {
|
||||
}
|
||||
|
||||
static void toggle_pw_btn_clicked_cb(lv_event_t *event) {
|
||||
toggle_password_hidden();
|
||||
toggle_password_obscured();
|
||||
}
|
||||
|
||||
static void toggle_password_hidden(void) {
|
||||
is_password_hidden = !is_password_hidden;
|
||||
set_password_hidden(is_password_hidden);
|
||||
static void toggle_password_obscured(void) {
|
||||
is_password_obscured = !is_password_obscured;
|
||||
set_password_obscured(is_password_obscured);
|
||||
}
|
||||
|
||||
static void set_password_hidden(bool is_hidden) {
|
||||
static void set_password_obscured(bool is_obscured) {
|
||||
lv_obj_t *textarea = lv_keyboard_get_textarea(keyboard);
|
||||
lv_textarea_set_password_mode(textarea, is_hidden);
|
||||
lv_textarea_set_password_mode(textarea, is_obscured);
|
||||
}
|
||||
|
||||
static void toggle_kb_btn_clicked_cb(lv_event_t *event) {
|
||||
@@ -219,6 +223,11 @@ static void toggle_keyboard_hidden(void) {
|
||||
}
|
||||
|
||||
static void set_keyboard_hidden(bool is_hidden) {
|
||||
if (!conf_opts.general.animations) {
|
||||
lv_obj_set_y(keyboard, is_hidden ? lv_obj_get_height(keyboard) : 0);
|
||||
return;
|
||||
}
|
||||
|
||||
lv_anim_t keyboard_anim;
|
||||
lv_anim_init(&keyboard_anim);
|
||||
lv_anim_set_var(&keyboard_anim, keyboard);
|
||||
@@ -330,25 +339,19 @@ static void keyboard_ready_cb(lv_event_t *event) {
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
/* Parse command line options */
|
||||
ul_cli_opts opts;
|
||||
ul_cli_parse_opts(argc, argv, &opts);
|
||||
|
||||
/* Parse config file */
|
||||
ul_config_opts config;
|
||||
ul_config_init(&config);
|
||||
ul_config_parse(opts.config, &config);
|
||||
|
||||
printf("anim %d, pops %d, layout %d\n", config.animations, config.popovers, config.layout_id);
|
||||
exit(1);
|
||||
ul_cli_parse_opts(argc, argv, &cli_opts);
|
||||
|
||||
/* Set up log level */
|
||||
if (opts.verbose) {
|
||||
if (cli_opts.verbose) {
|
||||
ul_log_set_level(UL_LOG_LEVEL_VERBOSE);
|
||||
}
|
||||
|
||||
/* Announce ourselves */
|
||||
ul_log(UL_LOG_LEVEL_VERBOSE, "unl0kr %s", UL_VERSION);
|
||||
|
||||
/* Parse config files */
|
||||
ul_config_parse(cli_opts.config_files, cli_opts.num_config_files, &conf_opts);
|
||||
|
||||
/* Initialise LVGL and set up logging callback */
|
||||
lv_init();
|
||||
lv_log_register_print_cb(ul_log_print_cb);
|
||||
@@ -360,11 +363,11 @@ exit(1);
|
||||
fbdev_get_sizes(&hor_res, &ver_res);
|
||||
|
||||
/* Override display size with command line options if necessary */
|
||||
if (opts.hor_res > 0) {
|
||||
hor_res = LV_MIN(hor_res, opts.hor_res);
|
||||
if (cli_opts.hor_res > 0) {
|
||||
hor_res = LV_MIN(hor_res, cli_opts.hor_res);
|
||||
}
|
||||
if (opts.ver_res > 0) {
|
||||
ver_res = LV_MIN(ver_res, opts.ver_res);
|
||||
if (cli_opts.ver_res > 0) {
|
||||
ver_res = LV_MIN(ver_res, cli_opts.ver_res);
|
||||
}
|
||||
|
||||
/* Prepare display buffer */
|
||||
@@ -461,7 +464,7 @@ exit(1);
|
||||
/* Route physical keyboard input into textarea */
|
||||
ul_indev_set_up_textarea_for_keyboard_input(textarea);
|
||||
|
||||
/* Show / hide password button */
|
||||
/* Reveal / obscure password button */
|
||||
lv_obj_t *toggle_pw_btn = lv_btn_create(lv_scr_act());
|
||||
lv_obj_align(toggle_pw_btn, LV_ALIGN_CENTER, (hor_res - 60 > 512 ? 512 : hor_res - 60) / 2 + 32, ver_res / 2 - keyboard_height - 3 * row_height / 2);
|
||||
lv_obj_set_size(toggle_pw_btn, 64, 64);
|
||||
@@ -488,7 +491,6 @@ exit(1);
|
||||
keyboard = lv_keyboard_create(lv_scr_act());
|
||||
lv_keyboard_set_mode(keyboard, LV_KEYBOARD_MODE_TEXT_LOWER);
|
||||
lv_keyboard_set_textarea(keyboard, textarea);
|
||||
// lv_btnmatrix_set_popovers(keyboard, true);
|
||||
lv_obj_remove_event_cb(keyboard, lv_keyboard_def_event_cb);
|
||||
lv_obj_add_event_cb(keyboard, keyboard_draw_part_begin_cb, LV_EVENT_DRAW_PART_BEGIN, NULL);
|
||||
lv_obj_add_event_cb(keyboard, keyboard_value_changed_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
@@ -497,9 +499,15 @@ exit(1);
|
||||
lv_obj_set_size(keyboard, hor_res, keyboard_height);
|
||||
lv_obj_add_style(keyboard, &style_text_normal, 0);
|
||||
|
||||
/* Apply defaults */
|
||||
sq2lv_switch_layout(keyboard, 0);
|
||||
set_password_hidden(is_password_hidden);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* Run lvgl in "tickless" mode */
|
||||
while(1) {
|
||||
|
@@ -28,6 +28,7 @@ add_project_arguments('-DUL_VERSION="@0@"'.format(meson.project_version()), lang
|
||||
|
||||
unl0kr_sources = [
|
||||
'command_line.c',
|
||||
'config.c',
|
||||
'cursor.c',
|
||||
'indev.c',
|
||||
'log.c',
|
||||
@@ -49,7 +50,8 @@ executable(
|
||||
sources: unl0kr_sources + squeek2lvgl_sources + lvgl_sources + lv_drivers_sources,
|
||||
include_directories: ['lvgl', 'lv_drivers'],
|
||||
dependencies: [
|
||||
dependency('xkbcommon'),
|
||||
dependency('inih'),
|
||||
dependency('libinput'),
|
||||
dependency('xkbcommon')
|
||||
]
|
||||
)
|
||||
|
9
unl0kr.conf
Normal file
9
unl0kr.conf
Normal file
@@ -0,0 +1,9 @@
|
||||
[general]
|
||||
animations=true
|
||||
|
||||
[textarea]
|
||||
obscured=true
|
||||
|
||||
[keyboard]
|
||||
popovers=true
|
||||
layout=de
|
Reference in New Issue
Block a user