diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2023-09-30 11:33:02 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2023-09-30 11:33:02 +0400 |
| commit | 21737abbfdb78698e323c0a9490759b427370a74 (patch) | |
| tree | 37b702f5fbdebedfef99490b1b5be92d7c7b9597 /src/niri.rs | |
| parent | a413f3e91d3538cc16d82880129732df7e31ec86 (diff) | |
| download | niri-21737abbfdb78698e323c0a9490759b427370a74.tar.gz niri-21737abbfdb78698e323c0a9490759b427370a74.tar.bz2 niri-21737abbfdb78698e323c0a9490759b427370a74.zip | |
Make output position configurable
Implements https://github.com/YaLTeR/niri/issues/14
Diffstat (limited to 'src/niri.rs')
| -rw-r--r-- | src/niri.rs | 70 |
1 files changed, 61 insertions, 9 deletions
diff --git a/src/niri.rs b/src/niri.rs index 6f152a00..48761702 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -74,7 +74,7 @@ use crate::dbus::mutter_display_config::DisplayConfig; use crate::dbus::mutter_screen_cast::{self, ScreenCast, ToNiriMsg}; use crate::dbus::mutter_service_channel::ServiceChannel; use crate::frame_clock::FrameClock; -use crate::layout::{MonitorRenderElement, MonitorSet}; +use crate::layout::{output_size, MonitorRenderElement, MonitorSet}; use crate::pw_utils::{Cast, PipeWire}; use crate::utils::{center, get_monotonic_time, load_default_cursor, make_screenshot_path}; @@ -668,15 +668,67 @@ impl Niri { pub fn add_output(&mut self, output: Output, refresh_interval: Option<Duration>) { let global = output.create_global::<State>(&self.display_handle); - let x = self - .global_space - .outputs() - .map(|output| self.global_space.output_geometry(output).unwrap()) - .map(|geom| geom.loc.x + geom.size.w) - .max() - .unwrap_or(0); + let name = output.name(); + let config = self + .config + .borrow() + .outputs + .iter() + .find(|o| o.name == name) + .cloned() + .unwrap_or_default(); + + let size = output_size(&output); + let position = config + .position + .map(|pos| Point::from((pos.x, pos.y))) + .filter(|pos| { + // Ensure that the requested position does not overlap any existing output. + let target_geom = Rectangle::from_loc_and_size(*pos, size); + + let overlap = self + .global_space + .outputs() + .map(|output| self.global_space.output_geometry(output).unwrap()) + .find(|geom| geom.overlaps(target_geom)); + + if let Some(overlap) = overlap { + warn!( + "new output {name} at x={} y={} sized {}x{} \ + overlaps an existing output at x={} y={} sized {}x{}, \ + falling back to automatic placement", + pos.x, + pos.y, + size.w, + size.h, + overlap.loc.x, + overlap.loc.y, + overlap.size.w, + overlap.size.h, + ); + + false + } else { + true + } + }) + .unwrap_or_else(|| { + let x = self + .global_space + .outputs() + .map(|output| self.global_space.output_geometry(output).unwrap()) + .map(|geom| geom.loc.x + geom.size.w) + .max() + .unwrap_or(0); + + Point::from((x, 0)) + }); - self.global_space.map_output(&output, (x, 0)); + debug!( + "putting new output {name} at x={} y={}", + position.x, position.y + ); + self.global_space.map_output(&output, position); self.monitor_set.add_output(output.clone()); let state = OutputState { |
