diff --git a/CHANGELOG.md b/CHANGELOG.md index 3703703..f290759 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ If a change only affects particular applications, they are listed in parentheses - fix: Do not hang if graphics backend is not available (!57, thanks @vstoiakin) - fix!(unl0kr): Disable software rotation due to regressed performance (!56) - feat(buffyboard): Rotate the keyboard according to /sys/class/graphics/fbcon/rotate by default (!60, thanks @vstoiakin) +- fix(buffyboard): Prevent overlap of the keyboard and the terminal (!58, thanks @vstoiakin) +- feat(buffyboard): Add a handler for SIGUSR1 to redraw the keyboard (!58, thanks @vstoiakin) ## 3.3.0 (2025-04-15) diff --git a/buffyboard/buffyboard.conf b/buffyboard/buffyboard.conf index 1d51fad..9f77241 100644 --- a/buffyboard/buffyboard.conf +++ b/buffyboard/buffyboard.conf @@ -7,3 +7,4 @@ default=breezy-light #[quirks] #fbdev_force_refresh=true +#ignore_unused_terminals=false diff --git a/buffyboard/buffyboard.service.in b/buffyboard/buffyboard.service.in index 333f6b0..a3e2109 100644 --- a/buffyboard/buffyboard.service.in +++ b/buffyboard/buffyboard.service.in @@ -1,5 +1,6 @@ [Unit] Documentation=https://gitlab.postmarketos.org/postmarketOS/buffybox +After=getty.target [Service] ExecStart=@bindir@/buffyboard @@ -36,3 +37,6 @@ SystemCallArchitectures=native SystemCallFilter=@system-service SystemCallFilter=~@privileged SystemCallFilter=~@resources + +[Install] +WantedBy=multi-user.target diff --git a/buffyboard/config.c b/buffyboard/config.c index 81373aa..939e9d1 100644 --- a/buffyboard/config.c +++ b/buffyboard/config.c @@ -63,6 +63,10 @@ static int parsing_handler(void* user_data, const char* section, const char* key if (bbx_config_parse_bool(value, &(opts->quirks.fbdev_force_refresh))) { return 1; } + } else if (strcmp(key, "ignore_unused_terminals") == 0) { + if (bbx_config_parse_bool(value, &(opts->quirks.ignore_unused_terminals))) { + return 1; + } } } @@ -80,6 +84,7 @@ void bb_config_init_opts(bb_config_opts *opts) { opts->input.pointer = true; opts->input.touchscreen = true; opts->quirks.fbdev_force_refresh = false; + opts->quirks.ignore_unused_terminals = true; } void bb_config_parse_directory(const char *path, bb_config_opts *opts) { diff --git a/buffyboard/config.h b/buffyboard/config.h index d319a4f..2a64006 100644 --- a/buffyboard/config.h +++ b/buffyboard/config.h @@ -35,6 +35,8 @@ typedef struct { typedef struct { /* If true and using the framebuffer backend, force a refresh on every draw operation */ bool fbdev_force_refresh; + /* If true, do not automatically update the layout of new terminals and wait for SIGUSR1 */ + bool ignore_unused_terminals; } bb_config_opts_quirks; /** diff --git a/buffyboard/getty-buffyboard.conf b/buffyboard/getty-buffyboard.conf new file mode 100644 index 0000000..d7bd8bd --- /dev/null +++ b/buffyboard/getty-buffyboard.conf @@ -0,0 +1,3 @@ +[Service] +ExecStartPost=-/usr/bin/kill -s SIGUSR1 buffyboard +StandardError=journal diff --git a/buffyboard/main.c b/buffyboard/main.c index c8f4c67..3e692af 100644 --- a/buffyboard/main.c +++ b/buffyboard/main.c @@ -19,13 +19,14 @@ #include "../shared/themes.h" #include "../squeek2lvgl/sq2lv.h" -#include +#include +#include +#include #include #include #include #include -#include /** @@ -35,37 +36,19 @@ bb_cli_opts cli_opts; bb_config_opts conf_opts; -static bool resize_terminals = false; static lv_obj_t *keyboard = NULL; - +static sig_atomic_t redraw_requested = false; /** * Static prototypes */ /** - * Compute the denominator of the keyboard height factor. The keyboard height is calculated - * by dividing the display height by the denominator. - * - * @param width display width - * @param height display height - * @return denominator - */ -static int keyboard_height_denominator(int32_t width, int32_t height); - -/** - * Handle termination signals sent to the process. + * Handle signals sent to the process. * * @param signum the signal's number */ -static void sigaction_handler(int signum); - -/** - * Callback for the terminal resizing timer. - * - * @param timer the timer object - */ -static void terminal_resize_timer_cb(lv_timer_t *timer); +static void signal_handler(int signum); /** * Handle LV_EVENT_VALUE_CHANGED events from the keyboard widget. @@ -93,25 +76,16 @@ static void pop_checked_modifier_keys(void); * Static functions */ -static int keyboard_height_denominator(int32_t width, int32_t height) { - return (height > width) ? 3 : 2; -} - -static void sigaction_handler(int signum) { - LV_UNUSED(signum); - if (resize_terminals) { - bb_terminal_reset_all(); +static void signal_handler(int signum) { + if (signum == SIGUSR1) { + redraw_requested = true; + return; } + + bb_terminal_reset_all(); exit(0); } -static void terminal_resize_timer_cb(lv_timer_t *timer) { - LV_UNUSED(timer); - if (resize_terminals) { - bb_terminal_shrink_current(); - } -} - static void keyboard_value_changed_cb(lv_event_t *event) { lv_obj_t *kb = lv_event_get_target(event); @@ -196,23 +170,9 @@ int main(int argc, char *argv[]) { bb_config_parse_directory("/etc/buffyboard.conf.d", &conf_opts); bb_config_parse_files(cli_opts.config_files, cli_opts.num_config_files, &conf_opts); - /* Prepare for terminal resizing and reset */ - resize_terminals = bb_terminal_init(2.0f / 3.0f); - if (resize_terminals) { - /* Clean up on termination */ - struct sigaction action; - lv_memset(&action, 0, sizeof(action)); - action.sa_handler = sigaction_handler; - sigaction(SIGINT, &action, NULL); - sigaction(SIGTERM, &action, NULL); - - /* Resize current terminal */ - bb_terminal_shrink_current(); - } - /* Set up uinput device */ if (!bb_uinput_device_init(sq2lv_unique_scancodes, sq2lv_num_unique_scancodes)) { - return 1; + return EXIT_FAILURE; } /* Initialise LVGL and set up logging callback */ @@ -223,17 +183,19 @@ int main(int argc, char *argv[]) { lv_display_t *disp = lv_linux_fbdev_create(); if (access("/dev/fb0", F_OK) != 0) { bbx_log(BBX_LOG_LEVEL_ERROR, "/dev/fb0 is not available"); - sigaction_handler(SIGTERM); + return 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); } + lv_display_set_physical_resolution(disp, + lv_display_get_horizontal_resolution(disp), + 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_physical_resolution(disp, lv_display_get_horizontal_resolution(disp), lv_display_get_vertical_resolution(disp)); + if (cli_opts.hor_res > 0 && cli_opts.ver_res > 0) { lv_display_set_resolution(disp, cli_opts.hor_res, cli_opts.ver_res); } if (cli_opts.dpi > 0) { @@ -241,27 +203,29 @@ int main(int argc, char *argv[]) { } /* Set up display rotation */ - int32_t hor_res_phys = lv_display_get_horizontal_resolution(disp); - int32_t ver_res_phys = lv_display_get_vertical_resolution(disp); - lv_display_set_physical_resolution(disp, hor_res_phys, ver_res_phys); lv_display_set_rotation(disp, cli_opts.rotation); + + const int32_t hor_res = lv_display_get_horizontal_resolution(disp); + const int32_t ver_res = lv_display_get_vertical_resolution(disp); + const int32_t keyboard_height = ver_res > hor_res ? ver_res / 3 : ver_res / 2; + const int32_t tty_height = ver_res - keyboard_height; + switch (cli_opts.rotation) { - case LV_DISPLAY_ROTATION_0: - case LV_DISPLAY_ROTATION_180: { - int32_t denom = keyboard_height_denominator(hor_res_phys, ver_res_phys); - lv_display_set_resolution(disp, hor_res_phys, ver_res_phys / denom); - lv_display_set_offset(disp, 0, (cli_opts.rotation == LV_DISPLAY_ROTATION_0) ? (denom - 1) * ver_res_phys / denom : 0); - break; - } - case LV_DISPLAY_ROTATION_90: - case LV_DISPLAY_ROTATION_270: { - int32_t denom = keyboard_height_denominator(ver_res_phys, hor_res_phys); - lv_display_set_resolution(disp, hor_res_phys / denom, ver_res_phys); - lv_display_set_offset(disp, 0, (cli_opts.rotation == LV_DISPLAY_ROTATION_90) ? (denom - 1) * hor_res_phys / denom : 0); - break; - } + case LV_DISPLAY_ROTATION_0: + case LV_DISPLAY_ROTATION_180: + lv_display_set_resolution(disp, hor_res, keyboard_height); + lv_display_set_offset(disp, 0, cli_opts.rotation == LV_DISPLAY_ROTATION_0? tty_height : 0); + break; + case LV_DISPLAY_ROTATION_90: + case LV_DISPLAY_ROTATION_270: + lv_display_set_resolution(disp, keyboard_height, hor_res); + lv_display_set_offset(disp, cli_opts.rotation == LV_DISPLAY_ROTATION_90? tty_height : 0, 0); + break; } + /* Prepare for terminal resizing and reset */ + bb_terminal_init(tty_height - 8, hor_res, ver_res); + /* Start input device monitor and auto-connect available devices */ bbx_indev_start_monitor_and_autoconnect(false, conf_opts.input.pointer, conf_opts.input.touchscreen); @@ -286,13 +250,89 @@ int main(int argc, char *argv[]) { /* Apply default keyboard layout */ sq2lv_switch_layout(keyboard, SQ2LV_LAYOUT_TERMINAL_US); - /* Start timer for periodically resizing terminals */ - lv_timer_create(terminal_resize_timer_cb, 1000, NULL); + /* Open the file to track virtual terminals */ + int fd_tty = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (fd_tty < 0) { + perror("Can't open /sys/class/tty/tty0/active"); + return EXIT_FAILURE; + } + + int fd_epoll = epoll_create1(EPOLL_CLOEXEC); + if (fd_epoll == -1) { + perror("epoll_create1() is failed"); + return EXIT_FAILURE; + } + + struct epoll_event event; + event.events = EPOLLIN|EPOLLET; + event.data.fd = fd_tty; + + int r = epoll_ctl(fd_epoll, EPOLL_CTL_ADD, fd_tty, &event); + if (r == -1) { + perror("epoll_ctl() is failed"); + return EXIT_FAILURE; + } + + /* Set signal handlers */ + struct sigaction action; + action.sa_handler = signal_handler; + action.sa_flags = 0; + sigfillset(&action.sa_mask); + sigaction(SIGINT, &action, NULL); + sigaction(SIGTERM, &action, NULL); + + action.sa_flags = SA_RESTART; + sigemptyset(&action.sa_mask); + sigaction(SIGUSR1, &action, NULL); + + sigset_t sigmask; + sigemptyset(&sigmask); + sigaddset(&sigmask, SIGUSR1); + + sigprocmask(SIG_BLOCK, &sigmask, NULL); + + sigemptyset(&sigmask); /* Periodically run timer / task handler */ while(1) { uint32_t time_till_next = lv_timer_handler(); - usleep(time_till_next * 1000); + + int r = epoll_pwait(fd_epoll, &event, 1, time_till_next, &sigmask); + if (r == 0) + continue; + if (r < 0) { + if (errno != EINTR) { + perror("epoll_wait() is failed"); + return EXIT_FAILURE; + } + if (!redraw_requested) + continue; + redraw_requested = false; + } else if (conf_opts.quirks.ignore_unused_terminals) { + lseek(fd_tty, 0, SEEK_SET); + + char buffer[8]; + ssize_t size = read(fd_tty, buffer, sizeof(buffer)); + if (size <= 0) { + bbx_log(BBX_LOG_LEVEL_WARNING, "Can't read /sys/class/tty/tty0/active"); + continue; + } + buffer[size] = 0; + + unsigned int tty; + if (sscanf(buffer, "tty%u", &tty) != 1) { + bbx_log(BBX_LOG_LEVEL_WARNING, "Unexpected value of /sys/class/tty/tty0/active"); + continue; + } + + if (!bb_terminal_is_busy(tty)) { + bbx_log(BBX_LOG_LEVEL_VERBOSE, "Terminal %u isn't used, skip automatic update.", tty); + continue; + } + } + + bb_terminal_shrink_current(); + lv_obj_invalidate(keyboard); } return 0; diff --git a/buffyboard/meson.build b/buffyboard/meson.build index 40f18c1..0e2b0eb 100644 --- a/buffyboard/meson.build +++ b/buffyboard/meson.build @@ -40,4 +40,10 @@ if depsystemd.found() install_dir: system_unit_dir, install_tag: 'buffyboard' ) + + install_data('getty-buffyboard.conf', + rename: 'buffyboard.conf', + install_dir: system_unit_dir / 'getty@.service.d', + install_tag: 'buffyboard' + ) endif diff --git a/buffyboard/terminal.c b/buffyboard/terminal.c index 889f1da..d964d30 100644 --- a/buffyboard/terminal.c +++ b/buffyboard/terminal.c @@ -3,16 +3,14 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ - #include "terminal.h" -#include #include -#include +#include #include -#include #include +#include #include #include @@ -22,260 +20,121 @@ * Static variables */ -static int current_fd = -1; -static int current_vt = -1; -static bool resized_vts[MAX_NR_CONSOLES]; -static float height_factor = 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); - -/** - * Get the currently active virtual terminal. - * - * @return number of the active VT (e.g. 7 for /dev/tty7) - */ -static int get_active_terminal(void); - -/** - * Retrieve a terminal's size. - * - * @param fd TTY file descriptor - * @param size pointer to winsize struct for writing the size into - * @return true if the operation was successful, false otherwise. On failure, errno will be set - * to the value set by the failed system call. - */ -static bool get_terminal_size(int fd, struct winsize *size); - -/** - * Update a terminal's size. - * - * @param fd TTY file descriptor - * @param size pointer to winsize struct for reading the new size from - * @return true if the operation was successful, false otherwise. On failure, errno will be set - * to the value set by the failed system call. - */ -static bool set_terminal_size(int fd, struct winsize *size); - -/** - * Shrink the height of a terminal by the current factor. - * - * @param fd TTY file descriptor - * @return true if the operation was successful, false otherwise - */ -static bool shrink_terminal(int fd); - -/** - * Reset the height of a terminal to the maximum. - * - * @param fd TTY file descriptor - * @param size pointer to winsize struct for writing the final size into - * @return true if the operation was successful, false otherwise - */ -static bool reset_terminal(int fd, struct winsize *size); - - -/** - * Static functions - */ - -static bool reopen_current_terminal(void) { - close_current_terminal(); - - current_fd = open("/dev/tty0", O_RDWR | O_NOCTTY); - if (current_fd < 0) { - perror("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; -} - -static int get_active_terminal(void) { - struct vt_stat stat; - if (ioctl(current_fd, VT_GETSTATE, &stat) != 0) { - perror("Could not retrieve current termimal state"); - return -1; - } - return stat.v_active; -} - -static bool get_terminal_size(int fd, struct winsize *size) { - if (ioctl(fd, TIOCGWINSZ, size) != 0) { - int errsv = errno; - perror("Could not retrieve current terminal size"); - errno = errsv; - return false; - } - return true; -} - -static bool set_terminal_size(int fd, struct winsize *size) { - if (ioctl(fd, TIOCSWINSZ, size) != 0) { - int errsv = errno; - perror("Could not update current terminal size"); - errno = errsv; - return false; - } - return true; -} - -static bool shrink_terminal(int fd) { - struct winsize size = { 0, 0, 0, 0 }; - - if (!reset_terminal(fd, &size)) { - perror("Could not shrink terminal size"); - return false; - } - - size.ws_row = floor((float)size.ws_row * height_factor); - if (!set_terminal_size(fd, &size)) { - perror("Could not shrink terminal size"); - return false; - } - - return true; -} - -static bool reset_terminal(int fd, struct winsize *size) { - if (!get_terminal_size(fd, size)) { - perror("Could not reset terminal size"); - return false; - } - - /* Test-resize by two rows. If the terminal is already maximised, this will fail and we can exit early. */ - size->ws_row += 2; - if (!set_terminal_size(fd, size)) { - bool is_max = (errno == EINVAL); - size->ws_row -= 2; - return is_max; - } - - size->ws_row = floor((float)size->ws_row / height_factor); - if (!set_terminal_size(fd, size)) { - if (errno != EINVAL) { - perror("Could not reset terminal size"); - return false; - } - - /* Size too large. Reduce by one row until it fits. */ - do { - size->ws_row -= 1; - } while (size->ws_row > 0 && !set_terminal_size(fd, size) && errno == EINVAL); - - if (errno != EINVAL || size->ws_row == 0) { - perror("Could not reset terminal size"); - return false; - } - } else { - /* Size fits but may not max out available space. Increase by one row until it doesn't fit anymore. */ - do { - size->ws_row += 1; - } while (set_terminal_size(fd, size)); - - if (errno != EINVAL) { - perror("Could not reset terminal size"); - return false; - } - - size->ws_row -= 1; - } - - return true; -} +static int32_t _tty_size; +static int32_t _h_display_size; +static int32_t _v_display_size; /** * Public functions */ -bool bb_terminal_init(float factor) { - if (!reopen_current_terminal()) { - perror("Could not prepare for terminal resizing"); +void bb_terminal_init(int32_t tty_size, int32_t h_display_size, int32_t v_display_size) { + _tty_size = tty_size; + _h_display_size = h_display_size; + _v_display_size = v_display_size; +} + +void bb_terminal_shrink_current() { + int fd = open("/dev/tty0", O_RDONLY|O_NOCTTY); + if (fd < 0) + return; + + /* KDFONTOP returns EINVAL if we are not in the text mode, + so we can skip this check */ +/* + int mode; + if (ioctl(fd, KDGETMODE, &mode) != 0) + goto end; + + if (mode != KD_TEXT) + goto end; +*/ + struct console_font_op cfo = { + .op = KD_FONT_OP_GET, + .width = UINT_MAX, + .height = UINT_MAX, + .charcount = UINT_MAX, + .data = NULL + }; + if (ioctl(fd, KDFONTOP, &cfo) != 0) + goto end; + + struct winsize size; + size.ws_row = _tty_size / cfo.height; + size.ws_col = _h_display_size / cfo.width; + ioctl(fd, TIOCSWINSZ, &size); +end: + close(fd); +} + +void bb_terminal_reset_all() { + int fd = open("/dev/tty0", O_RDONLY|O_NOCTTY); + if (fd < 0) + return; + + struct vt_stat state; + if (ioctl(fd, VT_GETSTATE, &state) != 0) { + close(fd); + return; + } + + close(fd); + + char buffer[sizeof("/dev/tty") + 2]; + unsigned short mask = state.v_state >> 1; + unsigned int tty = 1; + + for (; mask; mask >>= 1, tty++) { + if (mask & 0x01) { + sprintf(buffer, "/dev/tty%u", tty); + int tty_fd = open(buffer, O_RDONLY|O_NOCTTY); + if (tty_fd < 0) + continue; + + /* KDFONTOP returns EINVAL if we are not in the text mode, + so we can skip this check */ +/* + int mode; + if (ioctl(tty_fd, KDGETMODE, &mode) != 0) + goto end; + + if (mode != KD_TEXT) + goto end; +*/ + struct console_font_op cfo = { + .op = KD_FONT_OP_GET, + .width = UINT_MAX, + .height = UINT_MAX, + .charcount = UINT_MAX, + .data = NULL + }; + if (ioctl(tty_fd, KDFONTOP, &cfo) != 0) + goto end; + + struct winsize size; + size.ws_row = _v_display_size / cfo.height; + size.ws_col = _h_display_size / cfo.width; + ioctl(tty_fd, TIOCSWINSZ, &size); +end: + close(tty_fd); + } + } +} + +bool bb_terminal_is_busy(unsigned int tty) { + /* We can use any other terminal than `tty` here. */ + int fd = open(tty == 1? "/dev/tty2" : "/dev/tty1", O_RDONLY|O_NOCTTY); + if (fd < 0) return false; - } - current_vt = get_active_terminal(); - if (current_vt < 0) { - perror("Could not prepare for terminal resizing"); + struct vt_stat state; + int r = ioctl(fd, VT_GETSTATE, &state); + + close(fd); + + if (r != 0) return false; - } - height_factor = factor; - return true; -} - -void bb_terminal_shrink_current(void) { - int active_vt = get_active_terminal(); - if (active_vt < 0) { - perror("Could not resize current terminal"); - return; - } - - if (active_vt < 0 || active_vt > MAX_NR_CONSOLES - 1) { - perror("Could not resize current terminal, index is out of bounds"); - return; - } - - if (resized_vts[active_vt - 1]) { - return; /* Already resized */ - } - - if (active_vt != current_vt) { - if (!reopen_current_terminal()) { - perror("Could not resize current terminal"); - return; - } - current_vt = active_vt; - } - - if (!shrink_terminal(current_fd)) { - perror("Could not resize current terminal"); - return; - } - - resized_vts[current_vt - 1] = true; -} - -void bb_terminal_reset_all(void) { - char device[16]; - struct winsize size = { 0, 0, 0, 0 }; - - for (int i = 0; i < MAX_NR_CONSOLES; ++i) { - if (!resized_vts[i]) { - continue; - } - - snprintf(device, 16, "/dev/tty%d", i + 1); - int fd = open(device, O_RDWR | O_NOCTTY); - if (fd < 0) { - perror("Could not reset TTY, unable to open TTY"); - continue; - } - - reset_terminal(fd, &size); - } + return (state.v_state >> tty) & 0x01; } diff --git a/buffyboard/terminal.h b/buffyboard/terminal.h index 78dbd6d..b45be24 100644 --- a/buffyboard/terminal.h +++ b/buffyboard/terminal.h @@ -8,24 +8,30 @@ #define BB_TERMINAL_H #include +#include /** - * Prepare for resizing terminals by opening the current one. + * Prepare for resizing terminals. * - * @param factor factor (between 0 and 1) by which to adapt terminal sizes - * @return true if the operation was successful, false otherwise. No other bb_terminal_* functions - * must be called if false is returned. + * @param tty_size vertical size of the tty area in pixels + * @param h_display_size horizontal resolution of the display in pixels + * @param v_display_size vertical resolution of the display in pixels */ -bool bb_terminal_init(float factor); +void bb_terminal_init(int32_t tty_size, int32_t h_display_size, int32_t v_display_size); /** - * Shrink the height of the active terminal by the current factor. + * Shrink the height of the active terminal. */ -void bb_terminal_shrink_current(void); +void bb_terminal_shrink_current(); /** - * Re-maximise the height of all previously resized terminals. + * Re-maximise the size of all active terminals. */ -void bb_terminal_reset_all(void); +void bb_terminal_reset_all(); + +/** + * Check whether the terminal is opened by some process + */ +bool bb_terminal_is_busy(unsigned int tty); #endif /* BB_TERMINAL_H */ diff --git a/man/buffyboard.1.scd b/man/buffyboard.1.scd index dac7662..93c931b 100644 --- a/man/buffyboard.1.scd +++ b/man/buffyboard.1.scd @@ -52,6 +52,15 @@ result. *-V, --version* Print the unl0kr version and exit. +# NOTES + +Some terminal commands, like _clear_ or _setfont_, can erase the keyboard or brake the layout of the terminal. In this case you should send a signal to Buffyboard or switch to another terminal to update the screen: + +``` +setfont solar24x32;/usr/bin/kill -s SIGUSR1 buffyboard +setfont solar24x32;chvt $((`fgconsole`+1));chvt $((`fgconsole`-1)) +``` + # EXAMPLES *Execute Buffyboard using the default config* diff --git a/man/buffyboard.conf.5.scd b/man/buffyboard.conf.5.scd index 7af9d37..f9db834 100644 --- a/man/buffyboard.conf.5.scd +++ b/man/buffyboard.conf.5.scd @@ -45,6 +45,17 @@ for and, if found, merged in the following order: after every draw operation. This has a negative performance impact. Default: false. +*ignore_unused_terminals* = + If true, buffyboard won't automatically update the layout of a new terminal and + draw the keyboard, if the terminal is not opened by any process. In this case + SIGUSR1 should be sent to buffyboard to update the layout. This quirk was introduced to resolve a race between buffyboard and systemd-logind according to the following scenario: + - A user switches to a new virtual terminal + - Buffyboard opens the terminal and changes the number of rows + - systemd-logind sees that the terminal is opened by some other process and don't start getty@.service + + The race is resolved by enabling this option and installing a drop-in file + for getty@.service that sends SIGUSR1 to buffyboard. Default: true. + # SEE ALSO *buffyboard*(1)