Justering/expand/marginaler, hover-popup med peek, appikon
All checks were successful
check / check (push) Successful in 1m37s
All checks were successful
check / check (push) Successful in 1m37s
- Ny layoutmodell: alignment (center/start/end längs kanten), expand (ö eller täck hela kanten) och tre marginaler — A från kanten, B/C i början/slutet av kanten. Funkar för alla fyra positionerna. - Settings → Layout har en ritad illustration (cairo) som visar vad A/B/C betyder för vald position och uppdateras live. - Fönsterlistan för grupper kan öppnas vid hover (group_popup) och stängs när pekaren lämnar den; hover på en rad kan peeka (alla andra fönster tonas ner via Wayfires alpha-plugin) eller fokusera fönstret (list_hover: peek/focus/none). - Appikon (assets/waydock.svg) + .desktop-fil; installeras av install.sh och används av settings-fönstret. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
108
src/menu.rs
108
src/menu.rs
@@ -11,7 +11,7 @@ use gtk4::glib;
|
||||
use gtk4::prelude::*;
|
||||
use log::warn;
|
||||
|
||||
use crate::config::{self, MenuItem};
|
||||
use crate::config::{self, GroupPopup, ListHover, MenuItem};
|
||||
use crate::dock::{Ctx, Item};
|
||||
use crate::icons;
|
||||
use crate::settings;
|
||||
@@ -232,12 +232,56 @@ pub fn popup_item_menu(ctx: &Rc<Ctx>, item: &Rc<Item>, anchor: >k::Button) {
|
||||
popover.popup();
|
||||
}
|
||||
|
||||
/// Vänsterklick på grupp med flera fönster: lista fönstren.
|
||||
/// Tona ner alla andra fönster än det hovrade (peek). Returnerar id:n
|
||||
/// som dimmats så de kan återställas.
|
||||
fn peek_apply(hovered: &crate::toplevel::ToplevelInfo) -> Vec<i64> {
|
||||
let Some(views) = wayfire_ipc::list_views() else {
|
||||
return Vec::new();
|
||||
};
|
||||
let hovered_id = views
|
||||
.iter()
|
||||
.find(|v| {
|
||||
v["app-id"].as_str() == Some(hovered.app_id.as_str())
|
||||
&& v["title"].as_str() == Some(hovered.title.as_str())
|
||||
})
|
||||
.and_then(|v| v["id"].as_i64());
|
||||
let mut dimmed = Vec::new();
|
||||
for v in &views {
|
||||
if v["role"].as_str() != Some("toplevel")
|
||||
|| !v["mapped"].as_bool().unwrap_or(false)
|
||||
|| v["minimized"].as_bool().unwrap_or(false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let Some(id) = v["id"].as_i64() else { continue };
|
||||
if Some(id) != hovered_id {
|
||||
wayfire_ipc::set_view_alpha(id, 0.15);
|
||||
dimmed.push(id);
|
||||
}
|
||||
}
|
||||
dimmed
|
||||
}
|
||||
|
||||
fn peek_restore(dimmed: &[i64]) {
|
||||
for id in dimmed {
|
||||
wayfire_ipc::set_view_alpha(*id, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Vänsterklick (eller hover) på grupp med flera fönster: lista fönstren.
|
||||
pub fn popup_group_list(ctx: &Rc<Ctx>, item: &Rc<Item>, anchor: >k::Button) {
|
||||
let popover = gtk::Popover::new();
|
||||
popover.add_css_class("waydock-menu");
|
||||
let list = gtk::Box::new(gtk::Orientation::Vertical, 2);
|
||||
|
||||
let (list_hover, hover_mode) = {
|
||||
let b = &ctx.cfg.borrow().behavior;
|
||||
(b.list_hover.clone(), b.group_popup == GroupPopup::Hover)
|
||||
};
|
||||
let peek_possible = list_hover == ListHover::Peek && wayfire_ipc::available();
|
||||
// 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 {
|
||||
let row = gtk::Button::new();
|
||||
row.add_css_class("flat");
|
||||
@@ -250,16 +294,76 @@ pub fn popup_group_list(ctx: &Rc<Ctx>, item: &Rc<Item>, anchor: >k::Button) {
|
||||
let ctx2 = ctx.clone();
|
||||
let w2 = w.clone();
|
||||
let pop2 = popover.clone();
|
||||
let dimmed2 = dimmed.clone();
|
||||
row.connect_clicked(move |_| {
|
||||
peek_restore(&dimmed2.borrow());
|
||||
dimmed2.borrow_mut().clear();
|
||||
if let Some(s) = ctx2.service.borrow().as_ref() {
|
||||
s.activate(&w2);
|
||||
}
|
||||
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();
|
||||
mc.connect_enter(move |_, _, _| {
|
||||
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();
|
||||
mc.connect_enter(move |_, _, _| {
|
||||
if let Some(s) = ctx3.service.borrow().as_ref() {
|
||||
s.activate(&w3);
|
||||
}
|
||||
});
|
||||
row.add_controller(mc);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
list.append(&row);
|
||||
}
|
||||
popover.set_child(Some(&list));
|
||||
popover.set_parent(anchor);
|
||||
|
||||
// säkerhetsnät: återställ peek när popovern stängs
|
||||
{
|
||||
let dimmed5 = dimmed.clone();
|
||||
popover.connect_closed(move |_| {
|
||||
peek_restore(&dimmed5.borrow());
|
||||
dimmed5.borrow_mut().clear();
|
||||
});
|
||||
}
|
||||
|
||||
// i hover-läge: stäng listan när pekaren lämnar den
|
||||
if hover_mode {
|
||||
let mc = gtk::EventControllerMotion::new();
|
||||
let pop3 = popover.clone();
|
||||
mc.connect_leave(move |ctl| {
|
||||
let pop4 = pop3.clone();
|
||||
let ctl2 = ctl.clone();
|
||||
glib::timeout_add_local_once(std::time::Duration::from_millis(400), move || {
|
||||
if !ctl2.contains_pointer() {
|
||||
pop4.popdown();
|
||||
}
|
||||
});
|
||||
});
|
||||
popover.add_controller(mc);
|
||||
}
|
||||
|
||||
autodispose(&popover);
|
||||
popover.popup();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user