This commit is contained in:
2026-08-07 20:33:33 +09:00
parent 3166c12448
commit 349f49e496
6 changed files with 90 additions and 97 deletions
+10
View File
@@ -251,6 +251,16 @@ in
interrupt_message = true;
};
settings.tui.status_line = [
"model-with-reasoning"
"context-remaining"
"used-tokens"
"total-input-tokens"
"total-output-tokens"
"five-hour-limit"
"weekly-limit"
];
projects."/home/moons/dotfiles".trust_level = "trusted";
};
+1 -1
View File
@@ -110,7 +110,7 @@ in
"Mod+V" = {
action.spawn = [
"vicinae"
"vicinae://launch/clipboard/history?toggle=true"
"vicinae://launch/clipboard/history"
];
hotkey-overlay.title = "Clipboard History";
};
@@ -28,13 +28,11 @@ diff --git a/src/shell/bar/widgets/taskbar_widget.cpp b/src/shell/bar/widgets/ta
// Integer centering; optional odd spare pixel on the end side (right/bottom).
[[nodiscard]] float centeredOffset(float extent, float content, float inset = 0.0F, bool oddSpareOnEnd = true) {
const float inner = std::max(0.0F, extent - inset * 2.0F);
@@ -373,6 +386,12 @@ void TaskbarWidget::activateOrLaunchPinned(const TaskModel& task) {
@@ -373,6 +386,10 @@ void TaskbarWidget::activateOrLaunchPinned(const TaskModel& task) {
return;
}
+ const std::string overviewAppId =
+ !task.appId.empty() ? task.appId : (!task.desktopEntryId.empty() ? task.desktopEntryId : task.idLower);
+ if (launchTaskbarOverview(overviewAppId)) {
+ if (!windows[0].appId.empty() && launchTaskbarOverview(windows[0].appId)) {
+ return;
+ }
+
@@ -24,6 +24,7 @@ rustPlatform.buildRustPackage rec {
patches = [
./patches/window-overview.patch
./patches/niri-backend.patch
./patches/niri-hold-release.patch
];
cargoHash = "sha256-KBLgtS8ULrmsOf6BN5SlkVQyXB12utvr/KonnKnCTCM=";
@@ -0,0 +1,69 @@
diff --git a/src/shell.rs b/src/shell.rs
index 54fc2f0..dee4def 100644
--- a/src/shell.rs
+++ b/src/shell.rs
@@ -83,2 +83 @@ struct State {
- /// We've painted at least one frame with the modifier genuinely held; gates the
- /// confirm-on-release so the launching chord's tail can't trigger it.
+ /// A rendered hold after sources arrived, enabling immediate confirmation on release.
@@ -85,0 +85,2 @@ struct State {
+ /// A release received before source enumeration completes, to confirm after render.
+ pending_release: bool,
@@ -179,0 +181 @@ pub fn run(app: App, t0: Instant) -> anyhow::Result<()> {
+ pending_release: false,
@@ -205,5 +207,2 @@ impl State {
- // Record that we've shown at least one frame with the modifier held; this
- // gates confirm-on-release (see `reconcile`).
- if self.armed && self.any_armed_held() {
- self.armed_rendered = true;
- }
+ // Record a frame with the modifier held after source enumeration completes.
+ let armed_held = self.armed && self.any_armed_held();
@@ -234,0 +234,7 @@ impl State {
+ if armed_held && self.app.release_ready() {
+ self.armed_rendered = true;
+ self.pending_release = false;
+ } else if self.pending_release && self.app.release_ready() {
+ self.pending_release = false;
+ self.app.confirm_release();
+ }
@@ -485,2 +491,2 @@ impl State {
- // Confirm on release — but only after we've painted a frame with the
- // modifier genuinely held, so the launching chord's tail can't fire it.
+ // Confirm on release. Before the UI is ready, latch the edge and consume it
+ // only after `run_ui` has received sources and the frame has rendered.
@@ -488,2 +494,12 @@ impl State {
- if self.armed && self.armed_rendered && self.prev_held && !held {
- self.app.confirm_release();
+ // A new hold represents a new switching gesture, so do not consume a
+ // release that belonged to an earlier gesture.
+ if held {
+ self.pending_release = false;
+ }
+ if self.armed && self.prev_held && !held {
+ if self.armed_rendered && self.app.release_ready() {
+ self.pending_release = false;
+ self.app.confirm_release();
+ } else {
+ self.pending_release = true;
+ }
diff --git a/src/ui.rs b/src/ui.rs
index c821d66..854f6ad 100644
--- a/src/ui.rs
+++ b/src/ui.rs
@@ -854,0 +855 @@ pub struct App {
+ sources_received: bool,
@@ -899,0 +901 @@ impl App {
+ sources_received: false,
@@ -1008 +1010,4 @@ impl App {
- Msg::Sources(s) => self.sources = s,
+ Msg::Sources(s) => {
+ self.sources = s;
+ self.sources_received = true;
+ }
@@ -1080,0 +1086,5 @@ impl App {
+ /// True once `run_ui` has received the initial source enumeration.
+ pub fn release_ready(&self) -> bool {
+ self.sources_received
+ }
+
@@ -176,7 +176,7 @@
- // behind are hidden (a client can't move them; this hides them instead).
@@ -716 +795 @@
- c[3] = c[3].max(0.96);
+ c[3] = 0.5;
+ c[3] = c[3].max(0.88);
@@ -734 +813,5 @@
- self.selected = if n > 1 { 1 } else { 0 };
+ self.selected = if n > 1 {
@@ -231,7 +231,7 @@
+ );
@@ -1048,0 +1167 @@
+ let selected = *i == self.selected;
@@ -1062,9 +1181,3 @@
@@ -1062,9 +1181 @@
- rect.size() * (0.86 + 0.14 * ease),
- );
- self.paint_expose_tile(
@@ -241,96 +241,11 @@
- *i == self.selected,
- resp.hovered(),
- ease,
+ rect.size()
+ * (0.86 + 0.14 * ease)
+ * if selected { 1.04 } else { 1.0 },
+ rect.size() * (0.86 + 0.14 * ease),
@@ -1071,0 +1185 @@
+ self.paint_expose_tile(ui, s, scaled, selected, resp.hovered(), ease);
@@ -1077,0 +1192,8 @@
+ ui.painter().text(
+ egui::pos2(full_area.right(), full_area.top()),
+ egui::Align2::RIGHT_TOP,
+ format!("− {:.0}% +", self.overview_scale * 100.0),
+ egui::FontId::proportional(14.0),
+ self.theme.text_dim,
+ );
+
@@ -1107 +1229,14 @@
@@ -1107 +1229,3 @@
- let white = egui::Color32::WHITE.gamma_multiply(a);
+ let accent = if s.is_window {
+ t.window_accent
+ } else {
+ t.screen_accent
+ };
+ let content_alpha = if selected || hovered { 1.0 } else { 0.55 };
+ let white = egui::Color32::WHITE.gamma_multiply(a * content_alpha);
+ if selected {
+ p.rect_filled(
+ rect.expand(8.0),
+ radius + 8.0,
+ fade(accent).gamma_multiply(0.35),
+ let white = egui::Color32::WHITE.gamma_multiply(
+ a * if selected || hovered { 1.0 } else { 0.7 },
+ );
+ }
@@ -1127,0 +1263,7 @@
+ if !selected && !hovered {
+ p.rect_filled(
+ rect,
+ radius,
+ egui::Color32::from_black_alpha(72).gamma_multiply(a),
+ );
+ }
@@ -1136 +1278,5 @@
- egui::Color32::from_black_alpha(160).gamma_multiply(a),
+ if selected {
+ fade(accent).gamma_multiply(0.9)
+ } else {
+ egui::Color32::from_black_alpha(160).gamma_multiply(a)
+ },
@@ -1175,9 +1321,22 @@
- let accent = if s.is_window {
- t.window_accent
- } else {
- t.screen_accent
- };
- let (sw, col) = if selected {
- (3.0, accent)
- } else if hovered {
- (2.0, accent)
+ if selected {
+ p.rect_stroke(
+ rect.expand(4.0),
+ radius + 4.0,
+ egui::Stroke::new(3.0, fade(egui::Color32::WHITE)),
+ egui::StrokeKind::Inside,
+ );
+ p.rect_stroke(
+ rect,
+ radius,
+ egui::Stroke::new(6.0, fade(accent)),
+ egui::StrokeKind::Inside,
+ );
+ let marker = egui::pos2(rect.right() - 18.0, rect.top() + 18.0);
+ p.circle_filled(marker, 13.0, fade(accent));
+ p.text(
+ marker,
+ egui::Align2::CENTER_CENTER,
+ "✓",
+ egui::FontId::proportional(18.0),
+ fade(egui::Color32::WHITE),
+ );
@@ -1185,8 +1344,7 @@
- (1.0, t.thumb)
- };
- p.rect_stroke(
- rect,
- radius,
- egui::Stroke::new(sw, fade(col)),
- egui::StrokeKind::Inside,
- );
+ p.rect_stroke(
+ rect,
+ radius,
+ egui::Stroke::new(if hovered { 2.0 } else { 1.0 }, fade(accent)),
+ egui::StrokeKind::Inside,
+ );
+ }