1
0
Fork 0
forked from wry/wry

config: add toplevel-tag window criteria

This commit is contained in:
Julian Orth 2025-05-01 17:31:42 +02:00
parent 5f1268cada
commit 6d3d4dcabb
15 changed files with 106 additions and 8 deletions

View file

@ -1990,6 +1990,7 @@ impl ConfigProxyHandler {
match *field {
WindowCriterionStringField::Title => mgr.title(needle),
WindowCriterionStringField::AppId => mgr.app_id(needle),
WindowCriterionStringField::Tag => mgr.tag(needle),
}
}
WindowCriterionIpc::Types(t) => mgr.kind(*t),

View file

@ -18,7 +18,7 @@ use {
tlmm_just_mapped::TlmMatchJustMapped,
tlmm_kind::TlmMatchKind,
tlmm_seat_focus::TlmMatchSeatFocus,
tlmm_string::{TlmMatchAppId, TlmMatchTitle},
tlmm_string::{TlmMatchAppId, TlmMatchTag, TlmMatchTitle},
tlmm_urgent::TlmMatchUrgent,
tlmm_visible::TlmMatchVisible,
},
@ -51,6 +51,7 @@ bitflags! {
TL_CHANGED_SEAT_FOCI = 1 << 7,
TL_CHANGED_FULLSCREEN = 1 << 8,
TL_CHANGED_JUST_MAPPED = 1 << 9,
TL_CHANGED_TAG = 1 << 10,
}
type TlmFixedRootMatcher<T> = FixedRootMatcher<ToplevelData, T>;
@ -76,6 +77,7 @@ pub struct RootMatchers {
kinds: TlmRootMatcherMap<TlmMatchKind>,
clients: CopyHashMap<CritMatcherId, Weak<TlmMatchClient>>,
title: TlmRootMatcherMap<TlmMatchTitle>,
tag: TlmRootMatcherMap<TlmMatchTag>,
app_id: TlmRootMatcherMap<TlmMatchAppId>,
seat_foci: TlmRootMatcherMap<TlmMatchSeatFocus>,
}
@ -205,6 +207,7 @@ impl TlMatcherManager {
conditional!(TL_CHANGED_TITLE, title);
conditional!(TL_CHANGED_APP_ID, app_id);
conditional!(TL_CHANGED_SEAT_FOCI, seat_foci);
conditional!(TL_CHANGED_TAG, tag);
fixed_conditional!(TL_CHANGED_FLOATING, floating);
fixed_conditional!(TL_CHANGED_VISIBLE, visible);
fixed_conditional!(TL_CHANGED_URGENT, urgent);
@ -277,6 +280,7 @@ impl TlMatcherManager {
conditional!(TL_CHANGED_TITLE, title);
conditional!(TL_CHANGED_APP_ID, app_id);
conditional!(TL_CHANGED_SEAT_FOCI, seat_foci);
conditional!(TL_CHANGED_TAG, tag);
fixed_conditional!(TL_CHANGED_FLOATING, floating);
fixed_conditional!(TL_CHANGED_VISIBLE, visible);
fixed_conditional!(TL_CHANGED_URGENT, urgent);
@ -299,6 +303,10 @@ impl TlMatcherManager {
self.root(TlmMatchAppId::new(string))
}
pub fn tag(&self, string: CritLiteralOrRegex) -> Rc<TlmUpstreamNode> {
self.root(TlmMatchTag::new(string))
}
pub fn floating(&self) -> Rc<TlmUpstreamNode> {
self.floating[true].clone()
}

View file

@ -3,16 +3,18 @@ use crate::{
crit_matchers::critm_string::{CritMatchString, StringAccess},
tlm::{RootMatchers, TlmRootMatcherMap},
},
tree::ToplevelData,
tree::{ToplevelData, ToplevelType},
};
pub type TlmMatchString<T> = CritMatchString<ToplevelData, T>;
pub type TlmMatchTitle = TlmMatchString<TitleAccess>;
pub type TlmMatchAppId = TlmMatchString<AppIdAccess>;
pub type TlmMatchTag = TlmMatchString<TagAccess>;
pub struct TitleAccess;
pub struct AppIdAccess;
pub struct TagAccess;
impl StringAccess<ToplevelData> for TitleAccess {
fn with_string(data: &ToplevelData, f: impl FnOnce(&str) -> bool) -> bool {
@ -33,3 +35,16 @@ impl StringAccess<ToplevelData> for AppIdAccess {
&roots.app_id
}
}
impl StringAccess<ToplevelData> for TagAccess {
fn with_string(data: &ToplevelData, f: impl FnOnce(&str) -> bool) -> bool {
if let ToplevelType::XdgToplevel(data) = &data.kind {
return f(&data.tag.borrow());
}
false
}
fn nodes(roots: &RootMatchers) -> &TlmRootMatcherMap<TlmMatchString<Self>> {
&roots.tag
}
}

View file

@ -92,6 +92,11 @@ pub enum Decoration {
Server,
}
#[derive(Debug)]
pub struct XdgToplevelToplevelData {
pub tag: RefCell<String>,
}
pub struct XdgToplevel {
pub id: XdgToplevelId,
pub state: Rc<State>,
@ -112,6 +117,7 @@ pub struct XdgToplevel {
is_mapped: Cell<bool>,
dialog: CloneCell<Option<Rc<XdgDialogV1>>>,
extents_set: Cell<bool>,
pub data: Rc<XdgToplevelToplevelData>,
}
impl Debug for XdgToplevel {
@ -135,6 +141,9 @@ impl XdgToplevel {
}
let state = &surface.surface.client.state;
let node_id = state.node_ids.next();
let data = Rc::new(XdgToplevelToplevelData {
tag: Default::default(),
});
Self {
id,
state: state.clone(),
@ -154,7 +163,7 @@ impl XdgToplevel {
state,
String::new(),
Some(surface.surface.client.clone()),
ToplevelType::XdgToplevel,
ToplevelType::XdgToplevel(data.clone()),
node_id,
slf,
),
@ -162,6 +171,7 @@ impl XdgToplevel {
is_mapped: Cell::new(false),
dialog: Default::default(),
extents_set: Cell::new(false),
data,
}
}

View file

@ -1,9 +1,11 @@
use {
crate::{
client::{Client, ClientError},
criteria::tlm::TL_CHANGED_TAG,
globals::{Global, GlobalName},
leaks::Tracker,
object::{Object, Version},
tree::ToplevelNodeBase,
wire::{XdgToplevelTagManagerV1Id, xdg_toplevel_tag_manager_v1::*},
},
std::rc::Rc,
@ -72,9 +74,17 @@ impl XdgToplevelTagManagerV1RequestHandler for XdgToplevelTagManagerV1 {
fn set_toplevel_tag(
&self,
_req: SetToplevelTag<'_>,
req: SetToplevelTag<'_>,
_slf: &Rc<Self>,
) -> Result<(), Self::Error> {
let tl = self.client.lookup(req.toplevel)?;
let tag = &mut *tl.data.tag.borrow_mut();
if tag == req.tag {
return Ok(());
}
tag.clear();
tag.push_str(req.tag);
tl.tl_data().property_changed(TL_CHANGED_TAG);
Ok(())
}

View file

@ -16,7 +16,7 @@ use {
jay_screencast::JayScreencast,
jay_toplevel::JayToplevel,
wl_seat::{NodeSeatState, SeatId, collect_kb_foci, collect_kb_foci2},
wl_surface::WlSurface,
wl_surface::{WlSurface, xdg_surface::xdg_toplevel::XdgToplevelToplevelData},
},
rect::Rect,
state::State,
@ -277,7 +277,7 @@ impl ToplevelOpt {
pub enum ToplevelType {
Container,
Placeholder,
XdgToplevel,
XdgToplevel(Rc<XdgToplevelToplevelData>),
XWindow,
}
@ -286,7 +286,7 @@ impl ToplevelType {
match self {
ToplevelType::Container => window::CONTAINER,
ToplevelType::Placeholder => window::PLACEHOLDER,
ToplevelType::XdgToplevel => window::XDG_TOPLEVEL,
ToplevelType::XdgToplevel { .. } => window::XDG_TOPLEVEL,
ToplevelType::XWindow => window::X_WINDOW,
}
}