From d5f4138b2d2ee777fe06835cd6646c489b59d967 Mon Sep 17 00:00:00 2001 From: John Hernandez <129467592+H3rnand3zzz@users.noreply.github.com> Date: Mon, 13 Nov 2023 12:40:27 +0100 Subject: [PATCH] Add `ALT`+`UP`/`DOWN`/`mouse wheel` scroll support Before the change, the only way to scroll was usage of page up/down, it allowed to scroll only by skipping pages, which was not smooth. --- docs/profanity.1 | 6 +++++ src/command/cmd_defs.c | 15 +++++++++++ src/command/cmd_funcs.c | 9 +++++++ src/command/cmd_funcs.h | 1 + src/config/preferences.c | 3 +++ src/config/preferences.h | 1 + src/config/theme.c | 1 + src/ui/console.c | 10 ++++++++ src/ui/inputwin.c | 49 ++++++++++++++++++++++++++++++++++-- src/ui/inputwin.h | 1 + src/ui/ui.h | 1 + src/ui/window.c | 46 ++++++++++++++++++++------------- src/ui/window.h | 5 ++-- tests/unittests/ui/stub_ui.c | 9 +++++++ 14 files changed, 136 insertions(+), 21 deletions(-) diff --git a/docs/profanity.1 b/docs/profanity.1 index 8590da59a2..ffbc789639 100755 --- a/docs/profanity.1 +++ b/docs/profanity.1 @@ -71,6 +71,12 @@ Page the occupants or roster panel up. .BI ALT+PAGEDOWN Page the occupants or roster panel down. .TP +.BI ALT+UP " or " ALT+WHEEL UP +Scroll up. +.TP +.BI ALT+DOWN " or " ALT+WHEEL DOWN +Scroll down. +.TP .BI ALT+a Jump to the next unread window. .TP diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index fecb197510..d15cf69d0a 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -1279,6 +1279,21 @@ static const struct cmd_t command_defs[] = { { "down", "Move the main window down the screen." }) }, + { CMD_PREAMBLE("/mouse", + parse_args, 0, 1, &cons_mouse_setting) + CMD_MAINFUNC(cmd_mouse_scroll) + CMD_TAGS( + CMD_TAG_UI) + CMD_SYN( + "/mouse on", + "/mouse off") + CMD_DESC( + "Mouse scroll controls.") + CMD_ARGS( + { "on", "Activate mouse scroll." }, + { "off", "Deactivate mouse scroll." }) + }, + { CMD_PREAMBLE("/statusbar", parse_args, 1, 3, &cons_statusbar_setting) CMD_MAINFUNC(cmd_statusbar) diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index 48790e8839..aef911593c 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -81,6 +81,7 @@ #include "tools/bookmark_ignore.h" #include "tools/editor.h" #include "plugins/plugins.h" +#include "ui/inputwin.h" #include "ui/ui.h" #include "ui/window_list.h" #include "xmpp/avatar.h" @@ -6151,6 +6152,14 @@ cmd_mainwin(ProfWin* window, const char* const command, gchar** args) return TRUE; } +gboolean +cmd_mouse_scroll(ProfWin* window, const char* const command, gchar** args) +{ + _cmd_set_boolean_preference(args[0], "Mouse wheel scroll", PREF_MOUSE); + inp_update_mouse_prefs(); + return TRUE; +} + gboolean cmd_statusbar(ProfWin* window, const char* const command, gchar** args) { diff --git a/src/command/cmd_funcs.h b/src/command/cmd_funcs.h index 234febecbf..ac1933bd66 100644 --- a/src/command/cmd_funcs.h +++ b/src/command/cmd_funcs.h @@ -157,6 +157,7 @@ gboolean cmd_inpblock(ProfWin* window, const char* const command, gchar** args); gboolean cmd_titlebar(ProfWin* window, const char* const command, gchar** args); gboolean cmd_titlebar_show_hide(ProfWin* window, const char* const command, gchar** args); gboolean cmd_mainwin(ProfWin* window, const char* const command, gchar** args); +gboolean cmd_mouse_scroll(ProfWin* window, const char* const command, gchar** args); gboolean cmd_statusbar(ProfWin* window, const char* const command, gchar** args); gboolean cmd_inputwin(ProfWin* window, const char* const command, gchar** args); gboolean cmd_script(ProfWin* window, const char* const command, gchar** args); diff --git a/src/config/preferences.c b/src/config/preferences.c index a80e53211e..ab7907d4b9 100644 --- a/src/config/preferences.c +++ b/src/config/preferences.c @@ -1792,6 +1792,7 @@ _get_group(preference_t pref) case PREF_OUTGOING_STAMP: case PREF_INCOMING_STAMP: case PREF_MOOD: + case PREF_MOUSE: return PREF_GROUP_UI; case PREF_STATES: case PREF_OUTTYPE: @@ -1992,6 +1993,8 @@ _get_key(preference_t pref) return "shared"; case PREF_PRESENCE: return "presence"; + case PREF_MOUSE: + return "mouse"; case PREF_WRAP: return "wrap"; case PREF_TIME_CONSOLE: diff --git a/src/config/preferences.h b/src/config/preferences.h index a8fb3f4691..a070649dca 100644 --- a/src/config/preferences.h +++ b/src/config/preferences.h @@ -95,6 +95,7 @@ typedef enum { PREF_ROSTER_PRIVATE, PREF_MUC_PRIVILEGES, PREF_PRESENCE, + PREF_MOUSE, PREF_WRAP, PREF_TIME_CONSOLE, PREF_TIME_CHAT, diff --git a/src/config/theme.c b/src/config/theme.c index 5fc393ed11..0a42b8930a 100644 --- a/src/config/theme.c +++ b/src/config/theme.c @@ -323,6 +323,7 @@ _load_preferences(void) _set_boolean_preference("roster.rooms", PREF_ROSTER_ROOMS); _set_boolean_preference("privileges", PREF_MUC_PRIVILEGES); _set_boolean_preference("presence", PREF_PRESENCE); + _set_boolean_preference("mouse", PREF_MOUSE); _set_boolean_preference("intype", PREF_INTYPE); _set_boolean_preference("enc.warn", PREF_ENC_WARN); _set_boolean_preference("tls.show", PREF_TLS_SHOW); diff --git a/src/ui/console.c b/src/ui/console.c index 370fa5bb93..26ba1344cb 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -1466,6 +1466,15 @@ cons_time_setting(void) cons_show("Time vCard (/time) : %s", pref_time_vcard); } +void +cons_mouse_setting(void) +{ + if (prefs_get_boolean(PREF_VERCHECK)) + cons_show("Mouse scrolling (/mouse) : ON"); + else + cons_show("Mouse scrolling (/mouse) : OFF"); +} + void cons_vercheck_setting(void) { @@ -1674,6 +1683,7 @@ cons_show_ui_prefs(void) cons_time_setting(); cons_resource_setting(); cons_vercheck_setting(); + cons_mouse_setting(); cons_console_setting(); cons_occupants_setting(); cons_roster_setting(); diff --git a/src/ui/inputwin.c b/src/ui/inputwin.c index 3966daca65..0379d5045e 100644 --- a/src/ui/inputwin.c +++ b/src/ui/inputwin.c @@ -136,6 +136,9 @@ static int _inp_rl_subwin_pageup_handler(int count, int key); static int _inp_rl_subwin_pagedown_handler(int count, int key); static int _inp_rl_startup_hook(void); static int _inp_rl_down_arrow_handler(int count, int key); +static int _no_op(int count, int key); +static int _inp_rl_scroll_impl(int count, int key); +static int _inp_rl_scroll_trampoline(int count, int key); static int _inp_rl_send_to_editor(int count, int key); static int _inp_rl_print_newline_symbol(int count, int key); @@ -554,6 +557,8 @@ _inp_rl_startup_hook(void) rl_bind_key('\t', _inp_rl_tab_handler); rl_bind_keyseq("\\e[Z", _inp_rl_shift_tab_handler); + rl_bind_keyseq("\\e[1;3A", _inp_rl_scroll_trampoline); // alt + scroll/arrow up + rl_bind_keyseq("\\e[1;3B", _inp_rl_scroll_trampoline); // alt + scroll/arrow down rl_bind_keyseq("\\e[1;5B", _inp_rl_down_arrow_handler); // ctrl+arrow down rl_bind_keyseq("\\eOb", _inp_rl_down_arrow_handler); @@ -571,6 +576,8 @@ _inp_rl_startup_hook(void) rl_read_init_file(inputrc); } + inp_update_mouse_prefs(); + return 0; } @@ -906,7 +913,7 @@ static int _inp_rl_win_pageup_handler(int count, int key) { ProfWin* current = wins_get_current(); - win_page_up(current); + win_page_up(current, 0); return 0; } @@ -914,7 +921,7 @@ static int _inp_rl_win_pagedown_handler(int count, int key) { ProfWin* current = wins_get_current(); - win_page_down(current); + win_page_down(current, 0); return 0; } @@ -934,6 +941,44 @@ _inp_rl_subwin_pagedown_handler(int count, int key) return 0; } +static int +_no_op(int count, int key) +{ + return 0; +} + +static int (*_inp_rl_scroll_fp)(int count, int key) = _no_op; + +void +inp_update_mouse_prefs(void) +{ + if (prefs_get_boolean(PREF_MOUSE)) + _inp_rl_scroll_fp = _inp_rl_scroll_impl; + else + _inp_rl_scroll_fp = _no_op; +} + +static int +_inp_rl_scroll_trampoline(int count, int key) +{ + return _inp_rl_scroll_fp(count, key); +} + +static int +_inp_rl_scroll_impl(int count, int key) +{ + ProfWin* window = wins_get_current(); + + if (key == 'B') { + // mouse wheel down + win_page_down(window, 4); + } else if (key == 'A') { + // mouse wheel up + win_page_up(window, 4); + } + return 0; +} + static int _inp_rl_down_arrow_handler(int count, int key) { diff --git a/src/ui/inputwin.h b/src/ui/inputwin.h index 3aefcc0a77..9b8fa03ea0 100644 --- a/src/ui/inputwin.h +++ b/src/ui/inputwin.h @@ -46,5 +46,6 @@ void inp_win_resize(void); void inp_put_back(void); char* inp_get_password(void); char* inp_get_line(void); +void inp_update_mouse_prefs(void); #endif diff --git a/src/ui/ui.h b/src/ui/ui.h index 2c2d2d7e33..d58997287a 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -311,6 +311,7 @@ void cons_tray_setting(void); void cons_splash_setting(void); void cons_titlebar_setting(void); void cons_vercheck_setting(void); +void cons_mouse_setting(void); void cons_occupants_setting(void); void cons_roster_setting(void); void cons_presence_setting(void); diff --git a/src/ui/window.c b/src/ui/window.c index 348bfeaa61..e3dff37780 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -623,17 +623,20 @@ win_free(ProfWin* window) } void -win_page_up(ProfWin* window) +win_page_up(ProfWin* window, int scroll_size) { _reached_bottom_of_database = FALSE; int rows = getmaxy(stdscr); - int y = getcury(window->layout->win); + int total_rows = getcury(window->layout->win); int page_space = rows - 4; int* page_start = &(window->layout->y_pos); + int page_start_initial = *page_start; + if (scroll_size == 0) + scroll_size = page_space; - *page_start -= page_space; + *page_start -= scroll_size; - if (*page_start == -page_space && window->type == WIN_CHAT) { + if (*page_start == -scroll_size && window->type == WIN_CHAT) { ProfChatWin* chatwin = (ProfChatWin*)window; ProfBuffEntry* first_entry = buffer_size(window->layout->buffer) != 0 ? buffer_get_entry(window->layout->buffer, 0) : NULL; @@ -655,27 +658,33 @@ win_page_up(ProfWin* window) *page_start = 0; window->layout->paged = 1; - win_update_virtual(window); + // update only if position has changed + if (page_start_initial != *page_start) { + win_update_virtual(window); + } // switch off page if last line and space line visible - if ((y) - *page_start == page_space) { + if ((total_rows) - *page_start == page_space) { window->layout->paged = 0; } } void -win_page_down(ProfWin* window) +win_page_down(ProfWin* window, int scroll_size) { _reached_top_of_database = FALSE; int rows = getmaxy(stdscr); - int y = getcury(window->layout->win); - int page_space = rows - 4; int* page_start = &(window->layout->y_pos); + int total_rows = getcury(window->layout->win); + int page_space = rows - 4; + int page_start_initial = *page_start; + if (scroll_size == 0) + scroll_size = page_space; - *page_start += page_space; + *page_start += scroll_size; // Scrolled down after reaching the bottom of the page - if ((*page_start == y || (*page_start == page_space && *page_start >= y)) && window->type == WIN_CHAT) { + if ((*page_start == total_rows || (*page_start == page_space && *page_start >= total_rows)) && window->type == WIN_CHAT) { int bf_size = buffer_size(window->layout->buffer); if (bf_size > 0) { auto_gchar gchar* start = g_date_time_format_iso8601(buffer_get_entry(window->layout->buffer, bf_size - 1)->time); @@ -691,18 +700,21 @@ win_page_down(ProfWin* window) } // only got half a screen, show full screen - if ((y - (*page_start)) < page_space) - *page_start = y - page_space; + if ((total_rows - (*page_start)) < page_space) + *page_start = total_rows - page_space; // went past end, show full screen - else if (*page_start >= y) - *page_start = y - page_space - 1; + else if (*page_start >= total_rows) + *page_start = total_rows - page_space - 1; window->layout->paged = 1; - win_update_virtual(window); + // update only if position has changed + if (page_start_initial != *page_start) { + win_update_virtual(window); + } // switch off page if last line and space line visible - if ((y) - *page_start == page_space) { + if ((total_rows) - *page_start == page_space) { window->layout->paged = 0; } } diff --git a/src/ui/window.h b/src/ui/window.h index 9bbbf8c48f..a3791a7225 100644 --- a/src/ui/window.h +++ b/src/ui/window.h @@ -83,13 +83,14 @@ int win_roster_cols(void); int win_occpuants_cols(void); void win_sub_print(WINDOW* win, char* msg, gboolean newline, gboolean wrap, int indent); void win_sub_newline_lazy(WINDOW* win); +void win_mouse(ProfWin* current, const wint_t ch, const int result); void win_mark_received(ProfWin* window, const char* const id); void win_update_entry_message(ProfWin* window, const char* const id, const char* const message); gboolean win_has_active_subwin(ProfWin* window); -void win_page_up(ProfWin* window); -void win_page_down(ProfWin* window); +void win_page_up(ProfWin* window, int scroll_size); +void win_page_down(ProfWin* window, int scroll_size); void win_sub_page_down(ProfWin* window); void win_sub_page_up(ProfWin* window); diff --git a/tests/unittests/ui/stub_ui.c b/tests/unittests/ui/stub_ui.c index f45f6b070f..cad157d603 100644 --- a/tests/unittests/ui/stub_ui.c +++ b/tests/unittests/ui/stub_ui.c @@ -684,6 +684,11 @@ inp_nonblocking(gboolean reset) { } +void +inp_update_mouse_prefs(void) +{ +} + void ui_inp_history_append(char* inp) { @@ -1009,6 +1014,10 @@ cons_vercheck_setting(void) { } void +cons_mouse_setting(void) +{ +} +void cons_resource_setting(void) { }