From 756b91cd087c68c1997f1d43f0f6b428fa12112c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toma=C5=BE=20Hribernik?= Date: Sat, 7 Oct 2023 13:10:03 +0200 Subject: [PATCH] Add force_reverse_video_selection config This config option allows selection to behave similarly as the cursor does when force_reverse_video_cursor config option is set to true. With this new config set to true, selected text's foreground and background colors are swapped. Addresses issue #3440 --- config/src/config.rs | 3 ++ wezterm-gui/src/termwindow/render/mod.rs | 8 +++- .../src/termwindow/render/screen_line.rs | 47 ++++++++++++++++++- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/config/src/config.rs b/config/src/config.rs index 19d5b9c81..f4c46493f 100644 --- a/config/src/config.rs +++ b/config/src/config.rs @@ -599,6 +599,9 @@ pub struct Config { #[dynamic(default)] pub force_reverse_video_cursor: bool, + #[dynamic(default)] + pub force_reverse_video_selection: bool, + /// Specifies the default cursor style. various escape sequences /// can override the default style in different situations (eg: /// an editor can change it depending on the mode), but this value diff --git a/wezterm-gui/src/termwindow/render/mod.rs b/wezterm-gui/src/termwindow/render/mod.rs index b4266e9f2..fe21c8875 100644 --- a/wezterm-gui/src/termwindow/render/mod.rs +++ b/wezterm-gui/src/termwindow/render/mod.rs @@ -579,11 +579,15 @@ impl crate::TermWindow { visibility, ) { // Selected text overrides colors - (true, _, _, CursorVisibility::Hidden) => ( + (true, _, _, CursorVisibility::Hidden) => if self.config.force_reverse_video_selection {( + params.bg_color, + params.fg_color, + params.cursor_bg, + )} else {( params.selection_fg.when_fully_transparent(params.fg_color), params.selection_bg, params.cursor_bg, - ), + )}, // block Cursor cell overrides colors ( _, diff --git a/wezterm-gui/src/termwindow/render/screen_line.rs b/wezterm-gui/src/termwindow/render/screen_line.rs index b7d4daa4f..6a639dfef 100644 --- a/wezterm-gui/src/termwindow/render/screen_line.rs +++ b/wezterm-gui/src/termwindow/render/screen_line.rs @@ -11,6 +11,7 @@ use config::{HsbTransform, TextStyle}; use std::ops::Range; use std::rc::Rc; use std::time::Instant; +use std::cmp::{max, min}; use termwiz::cell::{unicode_column_width, Blink}; use termwiz::color::LinearRgba; use wezterm_bidi::Direction; @@ -288,17 +289,61 @@ impl crate::TermWindow { let selection_pixel_range = if !params.selection.is_empty() { let start = params.left_pixel_x + (params.selection.start as f32 * cell_width); let width = (params.selection.end - params.selection.start) as f32 * cell_width; + + // When using reverse video, we draw the selection rectangle with + // text foreground as its color + let selection_color = if self.config.force_reverse_video_selection { + params.foreground + } else { + params.selection_bg + }; + let mut quad = self .filled_rectangle( layers, 0, euclid::rect(start, params.top_pixel_y, width, cell_height), - params.selection_bg, + selection_color, ) .context("filled_rectangle")?; quad.set_hsv(hsv); + // When using reverse video selection, we also draw a selection + // rectangle for each item with a different foreground color than + // the default one + if self.config.force_reverse_video_selection { + for item in shaped.iter() { + let cluster = &item.cluster; + + if !item.fg_color.eq(¶ms.foreground) { + // Calculate the number of item's cells actually inside + // the selection + let left = max(cluster.first_cell_idx, params.selection.start); + let right = min(cluster.first_cell_idx + cluster.width, params.selection.end); + + // Only draw a rectangle for items with selected cells + if right > left { + // log::error!("Drawing A rectangle {} {}", left, right); + let mut quad = self + .filled_rectangle( + layers, + 0, + euclid::rect( + params.left_pixel_x + (left as f32 * cell_width), + params.top_pixel_y, + (right - left) as f32 * cell_width, + cell_height + ), + item.fg_color, + ) + .context("filled_rectangle")?; + quad.set_hsv(hsv); + } + } + } + } + start..start + width } else { 0.0..0.0