From 00b5d8359912e897f4c5539be45926e782b3f92e Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Thu, 27 Jan 2022 20:03:10 +0100 Subject: [PATCH] Avoid TTY cursor blinking Fixes: #26 --- main.c | 30 +++++++++++++--- meson.build | 1 + terminal.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++ terminal.h | 34 ++++++++++++++++++ 4 files changed, 161 insertions(+), 4 deletions(-) create mode 100644 terminal.c create mode 100644 terminal.h diff --git a/main.c b/main.c index 517f102..2b11485 100644 --- a/main.c +++ b/main.c @@ -23,6 +23,7 @@ #include "indev.h" #include "log.h" #include "unl0kr.h" +#include "terminal.h" #include "theme.h" #include "themes.h" @@ -32,6 +33,7 @@ #include "squeek2lvgl/sq2lv.h" +#include #include #include #include @@ -170,7 +172,14 @@ static void textarea_ready_cb(lv_event_t *event); * * @param textarea the textarea widget */ -static void finish(lv_obj_t *textarea); +static void print_password_and_exit(lv_obj_t *textarea); + +/** + * Handle termination signals sent to the process. + * + * @param signum the signal's number + */ +static void sigaction_handler(int signum); /** @@ -280,15 +289,20 @@ static void keyboard_value_changed_cb(lv_event_t *event) { } static void keyboard_ready_cb(lv_event_t *event) { - finish(lv_keyboard_get_textarea(lv_event_get_target(event))); + print_password_and_exit(lv_keyboard_get_textarea(lv_event_get_target(event))); } static void textarea_ready_cb(lv_event_t *event) { - finish(lv_event_get_target(event)); + print_password_and_exit(lv_event_get_target(event)); } -static void finish(lv_obj_t *textarea) { +static void print_password_and_exit(lv_obj_t *textarea) { printf("%s\n", lv_textarea_get_text(textarea)); + sigaction_handler(SIGTERM); +} + +static void sigaction_handler(int signum) { + ul_terminal_reset_current_terminal(); exit(0); } @@ -312,6 +326,14 @@ int main(int argc, char *argv[]) { /* Parse config files */ ul_config_parse(cli_opts.config_files, cli_opts.num_config_files, &conf_opts); + /* Prepare current TTY and clean up on termination */ + ul_terminal_prepare_current_terminal(); + struct sigaction action; + memset(&action, 0, sizeof(action)); + action.sa_handler = sigaction_handler; + sigaction(SIGINT, &action, NULL); + sigaction(SIGTERM, &action, NULL); + /* Initialise LVGL and set up logging callback */ lv_init(); lv_log_register_print_cb(ul_log_print_cb); diff --git a/meson.build b/meson.build index 44488bb..9beb47a 100644 --- a/meson.build +++ b/meson.build @@ -35,6 +35,7 @@ unl0kr_sources = [ 'log.c', 'main.c', 'sq2lv_layouts.c', + 'terminal.c', 'theme.c', 'themes.c' ] diff --git a/terminal.c b/terminal.c new file mode 100644 index 0000000..d07b3bb --- /dev/null +++ b/terminal.c @@ -0,0 +1,100 @@ +/** + * 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 . + */ + + +#include "terminal.h" + +#include "log.h" + +#include +#include +#include + +#include + +#include + + +/** + * Static variables + */ + +static int current_fd = -1; + + +/** + * Static prototypes + */ + +/** + * Close the current file descriptor and reopen /dev/tty0. + * + * @return true if opening was successful, false otherwise + */ +static bool reopen_current_terminal(void); + +/** + * Close the current file descriptor. + */ +static void close_current_terminal(void); + + +/** + * Static functions + */ + +static bool reopen_current_terminal(void) { + close_current_terminal(); + + current_fd = open("/dev/tty0", O_RDWR); + if (current_fd < 0) { + ul_log(UL_LOG_LEVEL_WARNING, "Could not open /dev/tty0"); + return false; + } + + return true; +} + +static void close_current_terminal(void) { + if (current_fd < 0) { + return; + } + + close(current_fd); + current_fd = -1; +} + + +/** + * Public functions + */ + +void ul_terminal_prepare_current_terminal(void) { + reopen_current_terminal(); + if (current_fd < 0 || ioctl(current_fd, KDSETMODE, KD_GRAPHICS) != 0) { + ul_log(UL_LOG_LEVEL_WARNING, "Could not set current terminal to graphics mode"); + } +} + +void ul_terminal_reset_current_terminal(void) { + if (current_fd < 0 || ioctl(current_fd, KDSETMODE, KD_TEXT) != 0) { + ul_log(UL_LOG_LEVEL_WARNING, "Could not reset current terminal to text mode"); + } + close_current_terminal(); +} diff --git a/terminal.h b/terminal.h new file mode 100644 index 0000000..d7d1764 --- /dev/null +++ b/terminal.h @@ -0,0 +1,34 @@ +/** + * 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 . + */ + + +#ifndef UL_TERMINAL_H +#define UL_TERMINAL_H + +/** + * Prepare the current TTY for graphics output. + */ +void ul_terminal_prepare_current_terminal(void); + +/** + * Reset the current TTY to text output. + */ +void ul_terminal_reset_current_terminal(void); + +#endif /* UL_TERMINAL_H */