From 266e25a9ff33d00df894d2c8408e68ae0fa9ade1 Mon Sep 17 00:00:00 2001 From: claude Date: Sun, 30 Aug 2026 00:55:11 +0200 Subject: [PATCH] =?UTF-8?q?Fixa=20d=C3=B6tt=20v=C3=A4nsterklick=20+=20sett?= =?UTF-8?q?ing=20f=C3=B6r=20skroll=20p=C3=A5=20ej=20startad=20app?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vänsterklick nådde ALDRIG fram: GtkButtons interna klickgest claimar knapp 1 före vår GestureClick, så released-callbacken avfyrades bara för mitt/höger. Primäraktionen går nu via knappens clicked-signal (gesten hanterar bara knapp 2/3). Därmed funkar fokus/minimera, grupplista-vid-klick och start av pinnade appar. Ny setting behavior.scroll_stopped (none|launch): vad skroll gör på en app utan fönster — som du bad om, eget beteende för ej startade appar. Co-Authored-By: Claude Fable 5 --- doc/usage.md | 1 + src/config.rs | 10 ++++++++++ src/dock.rs | 36 ++++++++++++++++++++++++++++++------ src/settings.rs | 9 ++++++++- 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/doc/usage.md b/doc/usage.md index 3eec5c6..fe73501 100644 --- a/doc/usage.md +++ b/doc/usage.md @@ -79,6 +79,7 @@ inställningar; "Återställ skärmen till globalt" tar bort dem. "group_apps": true, "tooltips": true, "urgent_pulse": true, + "scroll_stopped": "none", // none | launch — skroll på app som inte är igång "group_popup": "click", // click | hover — hur fönsterlistan öppnas "list_hover": "peek" // peek (visa bara det fönstret, tona ner andra) // | focus (fokusera vid hover) | none diff --git a/src/config.rs b/src/config.rs index 0b60136..9467050 100644 --- a/src/config.rs +++ b/src/config.rs @@ -45,6 +45,14 @@ pub enum GroupPopup { Hover, } +/// Vad skroll gör på en app som inte är igång (pinnad, 0 fönster). +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "snake_case")] +pub enum ScrollStopped { + None, + Launch, +} + /// Vad som händer när man hovrar en rad i fönsterlistan. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "snake_case")] @@ -181,6 +189,7 @@ pub struct Behavior { pub urgent_pulse: bool, pub group_popup: GroupPopup, pub list_hover: ListHover, + pub scroll_stopped: ScrollStopped, } impl Default for Behavior { fn default() -> Self { @@ -193,6 +202,7 @@ impl Default for Behavior { urgent_pulse: true, group_popup: GroupPopup::Click, list_hover: ListHover::Peek, + scroll_stopped: ScrollStopped::None, } } } diff --git a/src/dock.rs b/src/dock.rs index 0bbe0a2..5fd1520 100644 --- a/src/dock.rs +++ b/src/dock.rs @@ -17,7 +17,7 @@ use log::{debug, info}; use crate::config::{ Alignment, AutohideMode, ClickAction, Config, GroupPopup, Layer as CfgLayer, - MiddleClick, Position, ScrollAction, SharedConfig, + MiddleClick, Position, ScrollAction, ScrollStopped, SharedConfig, }; use crate::icons::{self, AppMeta}; use crate::menu; @@ -679,7 +679,19 @@ fn build_item_widget(ctx: &Rc, connector: &str, item: Rc) -> gtk::But }); } - // klick: vänster/mitt/höger + // vänsterklick: via knappens egna clicked-signal — GtkButtons interna + // gest claimar vänsterknappen, så en egen GestureClick för knapp 1 + // avfyras aldrig (buggen som gjorde vänsterklick dött) + { + let ctx = ctx.clone(); + let item = item.clone(); + let conn2 = connector.to_string(); + btn.connect_clicked(move |btn| { + let live = live_item(&ctx, &conn2, &item); + primary_action(&ctx, &conn2, &live, btn); + }); + } + // mitt- och högerklick via egen gest let click = gtk::GestureClick::new(); click.set_button(0); { @@ -688,10 +700,13 @@ fn build_item_widget(ctx: &Rc, connector: &str, item: Rc) -> gtk::But let btn2 = btn.clone(); let conn2 = connector.to_string(); click.connect_released(move |gesture, _, _, _| { + let button = gesture.current_button(); + if button != 2 && button != 3 { + return; // vänsterklick sköts av knappen själv + } gesture.set_state(gtk::EventSequenceState::Claimed); let live = live_item(&ctx, &conn2, &item); - match gesture.current_button() { - 1 => primary_action(&ctx, &conn2, &live, &btn2), + match button { 2 => middle_action(&ctx, &conn2, &live), 3 => menu::popup_item_menu(&ctx, &live, &btn2), _ => {} @@ -743,8 +758,17 @@ fn build_item_widget(ctx: &Rc, connector: &str, item: Rc) -> gtk::But step(dy); return glib::Propagation::Stop; } - if ctx.cfg.borrow().for_output(&conn2).behavior.scroll == ScrollAction::CycleWindows { - let live = live_item(&ctx, &conn2, &item); + let behavior = ctx.cfg.borrow().for_output(&conn2).behavior; + let live = live_item(&ctx, &conn2, &item); + if live.windows.is_empty() { + // egen setting för appar som inte är igång + if behavior.scroll_stopped == ScrollStopped::Launch { + icons::launch(&live.meta); + return glib::Propagation::Stop; + } + return glib::Propagation::Proceed; + } + if behavior.scroll == ScrollAction::CycleWindows { cycle_windows(&ctx, &live, dy > 0.0); glib::Propagation::Stop } else { diff --git a/src/settings.rs b/src/settings.rs index 8c8f45b..da3797d 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -15,7 +15,7 @@ use log::warn; use crate::config::{ self, Alignment, AutohideMode, ClickAction, GroupPopup, HotspotAction, IndicatorStyle, - Layer, ListHover, MenuItem, MiddleClick, Position, ScrollAction, + Layer, ListHover, MenuItem, MiddleClick, Position, ScrollAction, ScrollStopped, }; use crate::dock::Ctx; @@ -541,6 +541,13 @@ fn build_behavior_page(ctx: &Rc) -> gtk::ScrolledWindow { row(&list, "Skroll", &dropdown(ctx, &["Växla fönster", "Inget"], scroll_idx, |c, i| { c.behavior.scroll = if i == 1 { ScrollAction::None } else { ScrollAction::CycleWindows }; })); + let ss_idx = match b.scroll_stopped { + ScrollStopped::None => 0, + ScrollStopped::Launch => 1, + }; + row(&list, "Skroll på ej startad app", &dropdown(ctx, &["Gör inget", "Starta appen"], ss_idx, |c, i| { + c.behavior.scroll_stopped = if i == 1 { ScrollStopped::Launch } else { ScrollStopped::None }; + })); heading(&list, "Gruppering & popup"); row(&list, "Gruppera appar", &switch(ctx, b.group_apps, |c, v| c.behavior.group_apps = v));