From 36291cd1ccf71ba710a28ab7e96e066b7e2f4138 Mon Sep 17 00:00:00 2001 From: Daniel Hammer Date: Mon, 26 Oct 2026 16:03:33 +0100 Subject: [PATCH] fix: make Settings app scrollbar draggable --- programs/src/settings/main.cpp | 55 +++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/programs/src/settings/main.cpp b/programs/src/settings/main.cpp index e3aed19..f5f50e8 100644 --- a/programs/src/settings/main.cpp +++ b/programs/src/settings/main.cpp @@ -103,6 +103,9 @@ static mtk::TextInputState g_search = {}; static bool g_search_focus = false; static bool g_grid_focus = false; static int g_scroll = 0; +static bool g_sb_hover = false; // pointer over the scrollbar track +static bool g_sb_dragging = false; // dragging the scrollbar thumb +static int g_sb_drag_offset = 0; // grab point within the thumb static int g_selected = -1; // index into g_placed (a tile), keyboard focus static int g_hover_tile = -1; // index into g_placed static int g_hover_cat = CAT_NONE; @@ -458,6 +461,18 @@ static void relayout() { if (g_hover_tile >= g_placed_count) g_hover_tile = -1; } +// The scrollbar spans the whole pane right of the sidebar. Both rects are +// empty when the content fits. +static void scrollbar_rects(Rect& track, Rect& thumb) { + Rect body = body_rect(); + track = {0, 0, 0, 0}; + thumb = {0, 0, 0, 0}; + if (!mtk::scrollbar_needed(g_content_h, body.h)) return; + Rect view = {SIDEBAR_W, 0, g_win.width - SIDEBAR_W, body.h}; + track = mtk::scrollbar_track_rect(view); + thumb = mtk::scrollbar_thumb_rect(track, g_content_h, body.h, g_scroll); +} + static Rect placed_on_screen(int i) { Rect r = g_placed[i].r; r.y -= g_scroll; @@ -681,13 +696,9 @@ static void draw_body(Canvas& c, const mtk::Theme& theme) { theme.text_muted); } - Rect body = body_rect(); - if (mtk::scrollbar_needed(g_content_h, body.h)) { - Rect view = {SIDEBAR_W, 0, g_win.width - SIDEBAR_W, body.h}; - Rect track = mtk::scrollbar_track_rect(view); - Rect thumb = mtk::scrollbar_thumb_rect(track, g_content_h, body.h, g_scroll); - mtk::draw_scrollbar(c, track, thumb, false, false, theme); - } + Rect track, thumb; + scrollbar_rects(track, thumb); + mtk::draw_scrollbar(c, track, thumb, g_sb_hover, g_sb_dragging, theme); } static void draw_header(Canvas& c, const mtk::Theme& theme) { @@ -883,6 +894,36 @@ static void handle_mouse(const montauk::abi::WinEvent& ev) { relayout(); } + // Scrollbar: drag the thumb, or click the track to jump there and drag. + Rect track, thumb; + scrollbar_rects(track, thumb); + bool scrollable = !track.empty() && !thumb.empty(); + if (g_sb_dragging && (!(buttons & 1) || !scrollable)) g_sb_dragging = false; + if (g_sb_dragging) { + g_scroll = mtk::scrollbar_offset_from_thumb_top(track, g_content_h, body_rect().h, + thumb.h, g_mouse_y - g_sb_drag_offset); + relayout(); + g_hover_tile = -1; + return; + } + g_sb_hover = scrollable && track.contains(g_mouse_x, g_mouse_y); + if (g_sb_hover) { + g_hover_tile = -1; + g_hover_cat = CAT_NONE; + if (!pressed) return; + g_search_focus = false; + g_sb_dragging = true; + if (thumb.contains(g_mouse_x, g_mouse_y)) { + g_sb_drag_offset = g_mouse_y - thumb.y; + } else { + g_sb_drag_offset = thumb.h / 2; + g_scroll = mtk::scrollbar_offset_from_thumb_top(track, g_content_h, body_rect().h, + thumb.h, g_mouse_y - g_sb_drag_offset); + relayout(); + } + return; + } + g_hover_tile = tile_at(g_mouse_x, g_mouse_y); g_hover_cat = g_mouse_x < SIDEBAR_W ? sidebar_category_at(g_mouse_x, g_mouse_y) : CAT_NONE;