Commit 1cf303f60c35
tarball2 files changed+55-20
@@ -1,8 +1,11 @@
11
//! Launch context. A window goes to the output and tag the user was on when22
//! its launch began, found by matching its process or an ancestor against3
-//! the programs monolith spawned.3
+//! the programs monolith spawned, then against processes that own a mapped4
+//! window, and last the focus at map time.45
6
+use crate::state::State;57
use monolith_layout::{OutputId, TagId};8
+use smithay::reexports::wayland_server::Resource;69
use std::time::{Duration, Instant};710
811
const KEEP: Duration = Duration::from_secs(120);@@ -29,14 +32,55 @@ impl Launches {
2932
}3033
3134
pub fn find(&self, pid: u32) -> Option<(Option<OutputId>, TagId)> {32
- let mut pid = pid;33
- for _ in 0..32 {34
- if let Some(l) = self.0.iter().find(|l| l.pid == pid) {35
- return Some((l.output, l.tag));36
- }37
- pid = parent(pid).filter(|&p| p > 1)?;35
+ lineage(pid).find_map(|pid| {36
+ let l = self.0.iter().find(|l| l.pid == pid)?;37
+ Some((l.output, l.tag))38
+ })39
+ }40
+}41
+42
+/// `pid` and its ancestors, nearest first.43
+fn lineage(pid: u32) -> impl Iterator<Item = u32> {44
+ std::iter::successors(Some(pid), |&pid| parent(pid).filter(|&p| p > 1)).take(32)45
+}46
+47
+impl State {48
+ /// Where the window of process `pid` belongs. A program monolith spawned49
+ /// comes first, then the nearest ancestor owning a mapped window, which50
+ /// includes `pid` itself for its second window, then the focus now.51
+ pub fn launch_of(&self, pid: Option<u32>) -> (Option<OutputId>, TagId) {52
+ let Some(pid) = pid else {53
+ return self.launch_context();54
+ };55
+ if let Some(found) = self.services.launches.find(pid) {56
+ return found;57
+ }58
+ let owners: Vec<(u32, OutputId, TagId)> = self59
+ .wm60
+ .iter()61
+ .filter_map(|(id, s)| {62
+ let w = self.wm.layout.window(id)?;63
+ if w.scratchpad.is_some() || w.sticky {64
+ return None;65
+ }66
+ Some((self.window_pid(&s.window)?, w.output?, w.tag))67
+ })68
+ .collect();69
+ lineage(pid)70
+ .find_map(|p| owners.iter().find(|o| o.0 == p))71
+ .map(|&(_, output, tag)| (Some(output), tag))72
+ .unwrap_or_else(|| self.launch_context())73
+ }74
+75
+ pub fn window_pid(&self, window: &smithay::desktop::Window) -> Option<u32> {76
+ match window.x11_surface() {77
+ Some(x) => x.pid(),78
+ None => window79
+ .toplevel()80
+ .and_then(|t| t.wl_surface().client())81
+ .and_then(|c| c.get_credentials(&self.core.display).ok())82
+ .map(|c| c.pid as u32),3883
}39
- None4084
}4185
}4286
@@ -8,7 +8,6 @@ use smithay::backend::renderer::utils::{import_surface_tree, with_renderer_surfa
88
use smithay::desktop::Window;99
use smithay::reexports::calloop::timer::{TimeoutAction, Timer};1010
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel::State as XdgState;11
-use smithay::reexports::wayland_server::Resource;1211
use smithay::reexports::wayland_server::protocol::wl_output::WlOutput;1312
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;1413
use smithay::utils::{Logical, Point, Rectangle, Serial};@@ -22,15 +21,7 @@ impl State {
2221
pub fn map_window(&mut self, window: Window, float: Option<Rectangle<i32, Logical>>) {2322
let (app_id, title) = identity(&window);2423
let rule = self.settings.config.placement(&app_id, &title);25
- let pid = match window.x11_surface() {26
- Some(x) => x.pid(),27
- None => window28
- .toplevel()29
- .and_then(|t| t.wl_surface().client())30
- .and_then(|c| c.get_credentials(&self.core.display).ok())31
- .map(|c| c.pid as u32),32
- };33
- let launch = pid.and_then(|pid| self.services.launches.find(pid));24
+ let launch = self.launch_of(self.window_pid(&window));3425
let (fullscreen, fullscreen_output) = requested_fullscreen(&window);3526
let output = rule3627
.output@@ -43,10 +34,10 @@ impl State {
4334
.map(|(id, _)| id)4435
})4536
.or(fullscreen_output.and_then(|o| self.layout_output(&o)))46
- .or(launch.and_then(|l| l.0));37
+ .or(launch.0);4738
let tag = match rule.tag.as_deref() {4839
Some(t) => Some(self.wm.layout.tag(t)),49
- None => launch.map(|l| l.1),40
+ None => (output == launch.0).then_some(launch.1),5041
};5142
let float = float.map(|r| {5243
Rect::new(