Use the new scrollbar settings
This commit is contained in:
parent
1e13050fda
commit
03537ee902
3 changed files with 61 additions and 69 deletions
|
|
@ -158,12 +158,9 @@ typedef struct {
|
|||
double width, gap, hitbox_expansion;
|
||||
} ScrollbarGeometry;
|
||||
|
||||
static ScrollbarGeometry calculate_scrollbar_geometry(Window *w);
|
||||
static ScrollbarHitType get_scrollbar_hit_type(Window *w, double mouse_x, double mouse_y);
|
||||
static bool handle_scrollbar_mouse(Window *w, int button, MouseAction action, int modifiers);
|
||||
static void handle_scrollbar_drag(Window *w, double mouse_y);
|
||||
static void end_drag(Window *w);
|
||||
static void update_scrollbar_hover_state(Window *w, bool hovering);
|
||||
// }}}
|
||||
|
||||
static Window*
|
||||
|
|
@ -178,6 +175,19 @@ window_for_id(id_type window_id) {
|
|||
return window_for_window_id(window_id);
|
||||
}
|
||||
|
||||
static void
|
||||
update_scrollbar_hover_state(Window *w, bool hovering) {
|
||||
if (!w) return;
|
||||
bool changed = w->scrollbar.is_hovering != hovering;
|
||||
w->scrollbar.is_hovering = hovering;
|
||||
|
||||
if (changed && global_state.callback_os_window) {
|
||||
global_state.callback_os_window->needs_render = true;
|
||||
request_tick_callback();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
send_mouse_leave_event_if_needed(id_type currently_over_window, int modifiers) {
|
||||
if (global_state.mouse_hover_in_window != currently_over_window && global_state.mouse_hover_in_window) {
|
||||
|
|
@ -819,12 +829,13 @@ validate_scrollbar_state(Window *w) {
|
|||
static ScrollbarGeometry
|
||||
calculate_scrollbar_geometry(Window *w) {
|
||||
ScrollbarGeometry geom = {0};
|
||||
if (!w) return geom;
|
||||
if (!w || !w->render_data.screen) return geom;
|
||||
|
||||
WindowGeometry *g = &w->render_data.geometry;
|
||||
geom.width = OPT(scrollbar_width);
|
||||
geom.gap = OPT(scrollbar_gap);
|
||||
geom.hitbox_expansion = OPT(scrollbar_hitbox_expansion);
|
||||
unsigned cell_width = w->render_data.screen->cell_size.width;
|
||||
geom.width = OPT(scrollbar.width) * cell_width;
|
||||
geom.gap = OPT(scrollbar.gap) * cell_width;
|
||||
geom.hitbox_expansion = OPT(scrollbar.hitbox_expansion) * cell_width;
|
||||
|
||||
double right_edge = g->right + g->spaces.right;
|
||||
geom.left = right_edge - geom.gap - geom.width - geom.hitbox_expansion;
|
||||
|
|
@ -835,18 +846,6 @@ calculate_scrollbar_geometry(Window *w) {
|
|||
return geom;
|
||||
}
|
||||
|
||||
static void
|
||||
update_scrollbar_hover_state(Window *w, bool hovering) {
|
||||
if (!w) return;
|
||||
bool changed = w->scrollbar.is_hovering != hovering;
|
||||
w->scrollbar.is_hovering = hovering;
|
||||
|
||||
if (changed && OPT(scrollbar_autohide) && global_state.callback_os_window) {
|
||||
global_state.callback_os_window->needs_render = true;
|
||||
request_tick_callback();
|
||||
}
|
||||
}
|
||||
|
||||
static ScrollbarHitType
|
||||
get_scrollbar_hit_type(Window *w, double mouse_x, double mouse_y) {
|
||||
if (!w || !validate_scrollbar_state(w)) return SCROLLBAR_HIT_NONE;
|
||||
|
|
@ -861,7 +860,8 @@ get_scrollbar_hit_type(Window *w, double mouse_x, double mouse_y) {
|
|||
OSWindow *os_window = global_state.callback_os_window;
|
||||
if (!os_window) return SCROLLBAR_HIT_TRACK;
|
||||
double mouse_window_fraction = mouse_y / os_window->viewport_height;
|
||||
double hitbox_expansion_fraction = (double)OPT(scrollbar_hitbox_expansion) / os_window->viewport_height;
|
||||
unsigned cell_width = w->render_data.screen->cell_size.width;
|
||||
double hitbox_expansion_fraction = (double)(OPT(scrollbar.hitbox_expansion) * cell_width) / os_window->viewport_height;
|
||||
|
||||
if (mouse_window_fraction >= (w->scrollbar.thumb_top - hitbox_expansion_fraction) &&
|
||||
mouse_window_fraction <= (w->scrollbar.thumb_bottom + hitbox_expansion_fraction)) {
|
||||
|
|
@ -877,7 +877,7 @@ handle_scrollbar_track_click(Window *w, double mouse_y) {
|
|||
Screen *screen = w->render_data.screen;
|
||||
if (!validate_scrollbar_state(w)) return;
|
||||
|
||||
if (OPT(scrollbar_track_behavior) == SCROLLBAR_TRACK_JUMP) {
|
||||
if (OPT(scrollbar.track_behavior) == SCROLLBAR_TRACK_JUMP) {
|
||||
ScrollbarGeometry geom = calculate_scrollbar_geometry(w);
|
||||
double scrollbar_height = geom.bottom - geom.top;
|
||||
double mouse_pane_fraction = (mouse_y - geom.top) / scrollbar_height;
|
||||
|
|
@ -908,7 +908,7 @@ start_scrollbar_drag(Window *w, double mouse_y) {
|
|||
|
||||
static bool
|
||||
handle_scrollbar_mouse(Window *w, int button, MouseAction action, int modifiers UNUSED) {
|
||||
if (!w || !OPT(scrollbar_interactive) || !global_state.callback_os_window) return false;
|
||||
if (!w || !OPT(scrollbar.interactive) || !global_state.callback_os_window) return false;
|
||||
|
||||
double mouse_x = global_state.callback_os_window->mouse_x;
|
||||
double mouse_y = global_state.callback_os_window->mouse_y;
|
||||
|
|
@ -952,17 +952,15 @@ handle_scrollbar_mouse(Window *w, int button, MouseAction action, int modifiers
|
|||
|
||||
static void
|
||||
handle_scrollbar_drag(Window *w, double mouse_y) {
|
||||
if (!w || !w->scrollbar.is_dragging) return;
|
||||
|
||||
if (!w || !w->scrollbar.is_dragging || !validate_scrollbar_state(w)) return;
|
||||
Screen *screen = w->render_data.screen;
|
||||
if (!validate_scrollbar_state(w)) return;
|
||||
|
||||
ScrollbarGeometry geom = calculate_scrollbar_geometry(w);
|
||||
double scrollbar_height = geom.bottom - geom.top;
|
||||
double mouse_pane_fraction = (mouse_y - geom.top) / scrollbar_height;
|
||||
double delta_y = mouse_pane_fraction - w->scrollbar.drag_start_y;
|
||||
double visible_fraction = (double)screen->lines / (screen->lines + screen->historybuf->count);
|
||||
double min_thumb_height_fraction = (double)OPT(scrollbar_min_thumb_height) / scrollbar_height;
|
||||
unsigned cell_height = screen->cell_size.height;
|
||||
double min_thumb_height_fraction = ((double)OPT(scrollbar.min_handle_height) * cell_height) / scrollbar_height;
|
||||
double thumb_height = MAX(min_thumb_height_fraction, visible_fraction);
|
||||
double available_space = 1.0 - thumb_height;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "colors.h"
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "text-cache.h"
|
||||
#include "window_logo.h"
|
||||
#include "srgb_gamma.h"
|
||||
#include "uniforms_generated.h"
|
||||
|
|
@ -740,11 +741,18 @@ draw_visual_bell(const UIRenderData *ui) {
|
|||
}
|
||||
|
||||
static bool
|
||||
has_scrollbar(Screen *screen) {
|
||||
return OPT(scrollbar_opacity) > 0 && screen->linebuf == screen->main_linebuf && screen->historybuf->count > 0;
|
||||
has_scrollbar(Window *w, Screen *screen) {
|
||||
if (screen->linebuf != screen->main_linebuf || !screen->historybuf->count) return false;
|
||||
switch (OPT(scrollbar.visible_when)) {
|
||||
case SCROLLBAR_NEVER: return false;
|
||||
case SCROLLBAR_ALWAYS: return true;
|
||||
case SCROLLBAR_ON_SCROLLED: return screen->scrolled_by > 0;
|
||||
case SCROLLBAR_ON_HOVERED: return w->scrollbar.is_hovering;
|
||||
case SCROLLBAR_ON_SCROLL_AND_HOVER: return screen->scrolled_by > 0 && w->scrollbar.is_hovering;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static unsigned
|
||||
render_a_bar(const UIRenderData *ui, WindowBarData *bar, PyObject *title, bool along_bottom) {
|
||||
unsigned border_width = (unsigned)ceil(thickness_as_float(ui->os_window, 1));
|
||||
|
|
@ -876,32 +884,28 @@ set_color_uniform_with_opacity(color_type color, float opacity) {
|
|||
glUniform4f(tint_program_layout.uniforms.tint_color, r, g, b, opacity);
|
||||
}
|
||||
|
||||
static color_type
|
||||
scrollbar_color(Screen *screen, unsigned val) {
|
||||
switch (val & 0xff) {
|
||||
case 0: return colorprofile_to_color(screen->color_profile, screen->color_profile->overridden.default_fg, screen->color_profile->configured.default_fg).rgb;
|
||||
case 1: return colorprofile_to_color(screen->color_profile, screen->color_profile->overridden.highlight_bg, screen->color_profile->configured.highlight_fg).rgb;
|
||||
default: return val >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
draw_scrollbar(const UIRenderData *ui) {
|
||||
if (!has_scrollbar(ui->screen)) return;
|
||||
Screen *screen = ui->screen;
|
||||
Window *window = ui->window;
|
||||
if (!window) return;
|
||||
if (!window || !screen || !has_scrollbar(window, screen)) return;
|
||||
|
||||
color_type bar_color;
|
||||
unsigned int val = OPT(scrollbar_color);
|
||||
switch (val & 0xff) {
|
||||
case 0: bar_color = colorprofile_to_color(screen->color_profile, screen->color_profile->overridden.default_fg, screen->color_profile->configured.default_fg).rgb; break;
|
||||
case 1: bar_color = colorprofile_to_color(screen->color_profile, screen->color_profile->overridden.highlight_fg, screen->color_profile->configured.highlight_fg).rgb; break;
|
||||
default: bar_color = val >> 8; break;
|
||||
}
|
||||
|
||||
// Division by zero is safe here because has_scrollbar() ensures historybuf->count > 0
|
||||
float bar_frac = (float)screen->scrolled_by / (float)screen->historybuf->count;
|
||||
|
||||
if (OPT(scrollbar_autohide) && !window->scrollbar.is_hovering && screen->scrolled_by == 0) return;
|
||||
|
||||
float opacity = OPT(scrollbar_opacity);
|
||||
float track_opacity = OPT(scrollbar_track_opacity);
|
||||
|
||||
GLsizei scrollbar_width_px = OPT(scrollbar_width);
|
||||
GLsizei scrollbar_gap_px = OPT(scrollbar_gap);
|
||||
unsigned int scrollbar_radius = OPT(scrollbar_radius);
|
||||
color_type bar_color = scrollbar_color(screen, OPT(scrollbar.color)), track_color = scrollbar_color(screen, OPT(scrollbar.track_color));
|
||||
float bar_frac = (float)screen->scrolled_by / MAX(1u, (float)screen->historybuf->count);
|
||||
float opacity = OPT(scrollbar.opacity);
|
||||
float track_opacity = window->scrollbar.is_hovering ? OPT(scrollbar.track_hover_opacity) : OPT(scrollbar.track_opacity);
|
||||
GLsizei scrollbar_width_px = (GLsizei)(OPT(scrollbar.width) * ui->cell_width);
|
||||
GLsizei scrollbar_gap_px = (GLsizei)(OPT(scrollbar.gap) * ui->cell_width);
|
||||
unsigned scrollbar_radius = (unsigned)(OPT(scrollbar.radius) * ui->cell_width);
|
||||
|
||||
// Calculate window boundaries including padding
|
||||
GLsizei window_right_edge = ui->screen_left + ui->screen_width + window->render_data.geometry.spaces.right;
|
||||
|
|
@ -915,7 +919,7 @@ draw_scrollbar(const UIRenderData *ui) {
|
|||
|
||||
// Calculate thumb size and position
|
||||
float visible_fraction = (float)screen->lines / (float)(screen->lines + screen->historybuf->count);
|
||||
float min_thumb_height_fraction = (float)OPT(scrollbar_min_thumb_height) / (float)window_height;
|
||||
float min_thumb_height_fraction = (OPT(scrollbar.min_handle_height) * ui->cell_height) / (float)window_height;
|
||||
float thumb_height_fraction = MAX(min_thumb_height_fraction, visible_fraction);
|
||||
|
||||
// Convert to OpenGL coordinates (range -1.0 to 1.0, total span = 2.0)
|
||||
|
|
@ -940,10 +944,12 @@ draw_scrollbar(const UIRenderData *ui) {
|
|||
);
|
||||
|
||||
// Draw scrollbar track (background)
|
||||
bind_program(TINT_PROGRAM);
|
||||
set_color_uniform_with_opacity(bar_color, track_opacity);
|
||||
glUniform4f(tint_program_layout.uniforms.edges, -1.f, 1.f, 1.f, -1.f);
|
||||
draw_quad(true, 0);
|
||||
if (track_opacity > 0) {
|
||||
bind_program(TINT_PROGRAM);
|
||||
set_color_uniform_with_opacity(track_color, track_opacity);
|
||||
glUniform4f(tint_program_layout.uniforms.edges, -1.f, 1.f, 1.f, -1.f);
|
||||
draw_quad(true, 0);
|
||||
}
|
||||
|
||||
// Draw scrollbar thumb (handle)
|
||||
if (scrollbar_radius > 0) {
|
||||
|
|
@ -1023,7 +1029,7 @@ draw_window_logo(const UIRenderData *ui) {
|
|||
|
||||
bool
|
||||
screen_needs_rendering_in_layers(OSWindow *os_window, Window *w, Screen *screen) {
|
||||
const bool has_ui = has_visual_bell(screen) || has_scrollbar(screen) || has_hyperlink_target(os_window, w, screen) || has_window_number(w, screen);
|
||||
const bool has_ui = has_visual_bell(screen) || has_scrollbar(w, screen) || has_hyperlink_target(os_window, w, screen) || has_window_number(w, screen);
|
||||
GraphicsManager *grman = screen->paused_rendering.expires_at && screen->paused_rendering.grman ? screen->paused_rendering.grman : screen->grman;
|
||||
return has_ui || (w && w->window_logo.id) || grman_has_images(grman);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,18 +80,6 @@ typedef struct Options {
|
|||
ScrollbarVisibilityPolicy visible_when;
|
||||
} scrollbar;
|
||||
|
||||
bool scrollbar_interactive;
|
||||
float scrollbar_opacity;
|
||||
float scrollbar_track_opacity;
|
||||
color_type scrollbar_color;
|
||||
unsigned int scrollbar_width;
|
||||
unsigned int scrollbar_gap;
|
||||
unsigned int scrollbar_min_thumb_height;
|
||||
unsigned int scrollbar_hitbox_expansion;
|
||||
unsigned int scrollbar_radius;
|
||||
bool scrollbar_autohide;
|
||||
ScrollbarTrackBehavior scrollbar_track_behavior;
|
||||
|
||||
float text_contrast, text_gamma_adjustment;
|
||||
bool text_old_gamma;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue