config: add auto-focus window rule
This commit is contained in:
parent
51e752992f
commit
b1ca98b488
12 changed files with 114 additions and 10 deletions
|
|
@ -8,6 +8,7 @@ use {
|
|||
config::handler::ConfigProxyHandler,
|
||||
ifs::wl_seat::SeatId,
|
||||
state::State,
|
||||
tree::ToplevelData,
|
||||
utils::{
|
||||
clonecell::CloneCell, numcell::NumCell, ptr_ext::PtrExt,
|
||||
toplevel_identifier::ToplevelIdentifier, unlink_on_drop::UnlinkOnDrop, xrd::xrd,
|
||||
|
|
@ -161,6 +162,13 @@ impl ConfigProxy {
|
|||
handler.windows_to_tl_id.remove(&win);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn auto_focus(&self, data: &ToplevelData) -> bool {
|
||||
let Some(handler) = self.handler.get() else {
|
||||
return true;
|
||||
};
|
||||
handler.auto_focus(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ConfigProxy {
|
||||
|
|
@ -224,6 +232,7 @@ impl ConfigProxy {
|
|||
window_matcher_cache: Default::default(),
|
||||
window_matcher_leafs: Default::default(),
|
||||
window_matcher_std_kinds: state.tl_matcher_manager.kind(window::CLIENT_WINDOW),
|
||||
window_matcher_no_auto_focus: Default::default(),
|
||||
});
|
||||
let init_msg = bincode_ops()
|
||||
.serialize(&InitMessage::V1(V1InitMessage {}))
|
||||
|
|
|
|||
|
|
@ -124,6 +124,8 @@ pub(super) struct ConfigProxyHandler {
|
|||
pub window_matcher_cache: CriterionCache<WindowCriterionIpc, ToplevelData>,
|
||||
pub window_matcher_leafs: CopyHashMap<WindowMatcher, Rc<TlmLeafMatcher>>,
|
||||
pub window_matcher_std_kinds: Rc<TlmUpstreamNode>,
|
||||
pub window_matcher_no_auto_focus:
|
||||
CopyHashMap<WindowMatcher, Rc<CachedCriterion<WindowCriterionIpc, ToplevelData>>>,
|
||||
}
|
||||
|
||||
pub struct Pollable {
|
||||
|
|
@ -2027,6 +2029,7 @@ impl ConfigProxyHandler {
|
|||
fn handle_destroy_window_matcher(&self, matcher: WindowMatcher) {
|
||||
self.window_matchers.remove(&matcher);
|
||||
self.window_matcher_leafs.remove(&matcher);
|
||||
self.window_matcher_no_auto_focus.remove(&matcher);
|
||||
}
|
||||
|
||||
fn handle_enable_window_matcher_events(
|
||||
|
|
@ -2056,6 +2059,20 @@ impl ConfigProxyHandler {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_set_window_matcher_auto_focus(
|
||||
&self,
|
||||
matcher: WindowMatcher,
|
||||
auto_focus: bool,
|
||||
) -> Result<(), CphError> {
|
||||
if auto_focus {
|
||||
self.window_matcher_no_auto_focus.remove(&matcher);
|
||||
} else {
|
||||
let m = self.get_window_matcher(matcher)?;
|
||||
self.window_matcher_no_auto_focus.set(matcher, m);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn spaces_change(&self) {
|
||||
struct V;
|
||||
impl NodeVisitorBase for V {
|
||||
|
|
@ -2861,9 +2878,24 @@ impl ConfigProxyHandler {
|
|||
ClientMessage::EnableWindowMatcherEvents { matcher } => self
|
||||
.handle_enable_window_matcher_events(matcher)
|
||||
.wrn("enable_window_matcher_events")?,
|
||||
ClientMessage::SetWindowMatcherAutoFocus {
|
||||
matcher,
|
||||
auto_focus,
|
||||
} => self
|
||||
.handle_set_window_matcher_auto_focus(matcher, auto_focus)
|
||||
.wrn("set_window_matcher_auto_focus")?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn auto_focus(&self, data: &ToplevelData) -> bool {
|
||||
for matcher in self.window_matcher_no_auto_focus.lock().values() {
|
||||
if matcher.node.pull(data) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
|
|
|
|||
23
src/state.rs
23
src/state.rs
|
|
@ -665,11 +665,7 @@ impl State {
|
|||
pub fn map_tiled(self: &Rc<Self>, node: Rc<dyn ToplevelNode>) {
|
||||
let seat = self.seat_queue.last();
|
||||
self.do_map_tiled(seat.as_deref(), node.clone());
|
||||
if node.node_visible() {
|
||||
if let Some(seat) = seat {
|
||||
node.node_do_focus(&seat, Direction::Unspecified);
|
||||
}
|
||||
}
|
||||
self.focus_after_map(node, seat.as_deref());
|
||||
}
|
||||
|
||||
fn do_map_tiled(self: &Rc<Self>, seat: Option<&Rc<WlSeatGlobal>>, node: Rc<dyn ToplevelNode>) {
|
||||
|
|
@ -739,11 +735,22 @@ impl State {
|
|||
Rect::new_sized(x1, y1, width, height).unwrap()
|
||||
};
|
||||
FloatNode::new(self, workspace, position, node.clone());
|
||||
if node.node_visible() {
|
||||
if let Some(seat) = self.seat_queue.last() {
|
||||
node.node_do_focus(&seat, Direction::Unspecified);
|
||||
self.focus_after_map(node, self.seat_queue.last().as_deref());
|
||||
}
|
||||
|
||||
fn focus_after_map(&self, node: Rc<dyn ToplevelNode>, seat: Option<&Rc<WlSeatGlobal>>) {
|
||||
if !node.node_visible() {
|
||||
return;
|
||||
}
|
||||
let Some(seat) = seat else {
|
||||
return;
|
||||
};
|
||||
if let Some(config) = self.config.get() {
|
||||
if !config.auto_focus(node.tl_data()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
node.node_do_focus(&seat, Direction::Unspecified);
|
||||
}
|
||||
|
||||
pub fn show_workspace(&self, seat: &Rc<WlSeatGlobal>, name: &str) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue