Skroll-stegning i fönsterlistan + klick/launch-debugloggar
All checks were successful
check / check (push) Successful in 1m34s
All checks were successful
check / check (push) Successful in 1m34s
Med en grupps lista öppen stegar skroll (på gruppikonen eller över listan) markeringen mellan raderna — markerad rad får accentbakgrund och triggar samma förhandsvisning som hover (peek/fokus enligt list_hover). Funkar i både hover- och klickläge; utan öppen lista beter sig skroll som förut (cykla fönster). Watchdogen räknar stegning som aktivitet så listan inte stängs mitt i. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
166
src/menu.rs
166
src/menu.rs
@@ -18,6 +18,13 @@ use crate::settings;
|
||||
use crate::toplevel::ToplevelInfo;
|
||||
use crate::wayfire_ipc;
|
||||
|
||||
/// Handle till en öppen fönsterlista: gruppikonen skroll-stegar via denna.
|
||||
pub struct GroupList {
|
||||
pub key: String,
|
||||
pub connector: String,
|
||||
pub step: Rc<dyn Fn(f64)>,
|
||||
}
|
||||
|
||||
/// Målet för den senast öppnade ikon-menyn (actions läser härifrån).
|
||||
pub struct MenuTarget {
|
||||
pub key: String,
|
||||
@@ -343,7 +350,10 @@ pub fn popup_group_list(ctx: &Rc<Ctx>, item: &Rc<Item>, anchor: >k::Button) {
|
||||
// fönster som tonats ner av peek — återställs vid radbyte/stängning
|
||||
let dimmed: Rc<std::cell::RefCell<Vec<i64>>> = Rc::new(std::cell::RefCell::new(Vec::new()));
|
||||
|
||||
for w in &item.windows {
|
||||
// bygg raderna först, koppla handlers efteråt (select behöver alla)
|
||||
let windows: Rc<Vec<crate::toplevel::ToplevelInfo>> = Rc::new(item.windows.clone());
|
||||
let mut rows_vec = Vec::new();
|
||||
for w in windows.iter() {
|
||||
let row = gtk::Button::new();
|
||||
row.add_css_class("flat");
|
||||
let title = if w.title.is_empty() { item.meta.display_name.clone() } else { w.title.clone() };
|
||||
@@ -352,6 +362,68 @@ pub fn popup_group_list(ctx: &Rc<Ctx>, item: &Rc<Item>, anchor: >k::Button) {
|
||||
label.set_max_width_chars(40);
|
||||
label.set_halign(gtk::Align::Start);
|
||||
row.set_child(Some(&label));
|
||||
list.append(&row);
|
||||
rows_vec.push(row);
|
||||
}
|
||||
let rows: Rc<Vec<gtk::Button>> = Rc::new(rows_vec);
|
||||
|
||||
// markera rad idx: visuell markering + förhandsvisning (peek/fokus)
|
||||
let selected = Rc::new(std::cell::Cell::new(None::<usize>));
|
||||
let select: Rc<dyn Fn(usize)> = Rc::new({
|
||||
let rows = rows.clone();
|
||||
let windows = windows.clone();
|
||||
let dimmed = dimmed.clone();
|
||||
let selected = selected.clone();
|
||||
let list_hover = list_hover.clone();
|
||||
let ctx2 = ctx.clone();
|
||||
move |idx: usize| {
|
||||
for (i, r) in rows.iter().enumerate() {
|
||||
if i == idx {
|
||||
r.add_css_class("selected");
|
||||
} else {
|
||||
r.remove_css_class("selected");
|
||||
}
|
||||
}
|
||||
selected.set(Some(idx));
|
||||
let w = &windows[idx];
|
||||
match list_hover {
|
||||
ListHover::Peek if peek_possible => {
|
||||
peek_restore(&dimmed.borrow());
|
||||
*dimmed.borrow_mut() = peek_apply(w);
|
||||
}
|
||||
ListHover::Focus => {
|
||||
if let Some(s) = ctx2.service.borrow().as_ref() {
|
||||
s.activate(w);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// skroll-stegning (från gruppikonen eller över listan)
|
||||
let step: Rc<dyn Fn(f64)> = Rc::new({
|
||||
let select = select.clone();
|
||||
let selected = selected.clone();
|
||||
let n = windows.len();
|
||||
move |dy: f64| {
|
||||
if n == 0 {
|
||||
return;
|
||||
}
|
||||
let next = match selected.get() {
|
||||
None => {
|
||||
if dy > 0.0 { 0 } else { n - 1 }
|
||||
}
|
||||
Some(i) => {
|
||||
if dy > 0.0 { (i + 1) % n } else { (i + n - 1) % n }
|
||||
}
|
||||
};
|
||||
select(next);
|
||||
}
|
||||
});
|
||||
|
||||
// per rad: klick aktiverar; hover markerar (efter armering)
|
||||
for (i, (row, w)) in rows.iter().zip(windows.iter()).enumerate() {
|
||||
let ctx2 = ctx.clone();
|
||||
let w2 = w.clone();
|
||||
let pop2 = popover.clone();
|
||||
@@ -364,47 +436,47 @@ pub fn popup_group_list(ctx: &Rc<Ctx>, item: &Rc<Item>, anchor: >k::Button) {
|
||||
}
|
||||
pop2.popdown();
|
||||
});
|
||||
|
||||
// hover-effekt per rad: peek eller fokus
|
||||
match list_hover {
|
||||
ListHover::Peek if peek_possible => {
|
||||
let mc = gtk::EventControllerMotion::new();
|
||||
let w3 = w.clone();
|
||||
let dimmed3 = dimmed.clone();
|
||||
let armed3 = armed.clone();
|
||||
mc.connect_enter(move |_, _, _| {
|
||||
if !armed3.get() {
|
||||
return;
|
||||
}
|
||||
peek_restore(&dimmed3.borrow());
|
||||
*dimmed3.borrow_mut() = peek_apply(&w3);
|
||||
});
|
||||
let dimmed4 = dimmed.clone();
|
||||
mc.connect_leave(move |_| {
|
||||
peek_restore(&dimmed4.borrow());
|
||||
dimmed4.borrow_mut().clear();
|
||||
});
|
||||
row.add_controller(mc);
|
||||
}
|
||||
ListHover::Focus => {
|
||||
let mc = gtk::EventControllerMotion::new();
|
||||
let ctx3 = ctx.clone();
|
||||
let w3 = w.clone();
|
||||
let armed3 = armed.clone();
|
||||
mc.connect_enter(move |_, _, _| {
|
||||
if !armed3.get() {
|
||||
return;
|
||||
}
|
||||
if let Some(s) = ctx3.service.borrow().as_ref() {
|
||||
s.activate(&w3);
|
||||
}
|
||||
});
|
||||
row.add_controller(mc);
|
||||
}
|
||||
_ => {}
|
||||
if list_hover != ListHover::None {
|
||||
let mc = gtk::EventControllerMotion::new();
|
||||
let select2 = select.clone();
|
||||
let armed2 = armed.clone();
|
||||
mc.connect_enter(move |_, _, _| {
|
||||
if armed2.get() {
|
||||
select2(i);
|
||||
}
|
||||
});
|
||||
row.add_controller(mc);
|
||||
}
|
||||
list.append(&row);
|
||||
}
|
||||
|
||||
// skroll över själva listan stegar också
|
||||
{
|
||||
let sc = gtk::EventControllerScroll::new(gtk::EventControllerScrollFlags::VERTICAL);
|
||||
let step2 = step.clone();
|
||||
sc.connect_scroll(move |_, _, dy| {
|
||||
step2(dy);
|
||||
glib::Propagation::Stop
|
||||
});
|
||||
popover.add_controller(sc);
|
||||
}
|
||||
|
||||
// registrera handlet så gruppikonens skroll når stegningen
|
||||
*ctx.group_list.borrow_mut() = Some(GroupList {
|
||||
key: item.meta.key.clone(),
|
||||
connector: connector.clone(),
|
||||
step: step.clone(),
|
||||
});
|
||||
{
|
||||
let ctx2 = ctx.clone();
|
||||
let key = item.meta.key.clone();
|
||||
popover.connect_closed(move |_| {
|
||||
let mut gl = ctx2.group_list.borrow_mut();
|
||||
if gl.as_ref().map(|h| h.key == key).unwrap_or(false) {
|
||||
*gl = None;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
popover.set_child(Some(&list));
|
||||
popover.set_parent(anchor);
|
||||
|
||||
@@ -437,13 +509,19 @@ pub fn popup_group_list(ctx: &Rc<Ctx>, item: &Rc<Item>, anchor: >k::Button) {
|
||||
}
|
||||
popover.add_controller(mc.clone());
|
||||
|
||||
// watchdog: om pekaren aldrig ens når listan, stäng efter en stund
|
||||
// watchdog: om pekaren aldrig når listan OCH ingen skroll-stegning
|
||||
// sker, stäng efter en stund (upprepas; aktivitet = markerad rad)
|
||||
{
|
||||
let pop3 = popover.clone();
|
||||
glib::timeout_add_local_once(std::time::Duration::from_millis(1500), move || {
|
||||
if !mc.contains_pointer() {
|
||||
pop3.popdown();
|
||||
let selected2 = selected.clone();
|
||||
let last_seen = std::cell::Cell::new(selected.get());
|
||||
glib::timeout_add_local(std::time::Duration::from_millis(1500), move || {
|
||||
if mc.contains_pointer() || selected2.get() != last_seen.get() {
|
||||
last_seen.set(selected2.get());
|
||||
return glib::ControlFlow::Continue;
|
||||
}
|
||||
pop3.popdown();
|
||||
glib::ControlFlow::Break
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user