aboutsummaryrefslogtreecommitdiff
path: root/src/niri.rs
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-05-05 10:19:47 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2024-05-05 10:19:47 +0400
commit65b9c74f624b4a78c2247135bf1a96dcac0bd009 (patch)
treed4b960d3aac247df759ada124a2ffa050ae8ee9f /src/niri.rs
parent2dff67447082f3c000b7eb68b4826f5b3db7397b (diff)
downloadniri-65b9c74f624b4a78c2247135bf1a96dcac0bd009.tar.gz
niri-65b9c74f624b4a78c2247135bf1a96dcac0bd009.tar.bz2
niri-65b9c74f624b4a78c2247135bf1a96dcac0bd009.zip
Implement niri msg output
Diffstat (limited to 'src/niri.rs')
-rw-r--r--src/niri.rs161
1 files changed, 115 insertions, 46 deletions
diff --git a/src/niri.rs b/src/niri.rs
index b1e2d917..b6bfb84d 100644
--- a/src/niri.rs
+++ b/src/niri.rs
@@ -138,6 +138,13 @@ const FRAME_CALLBACK_THROTTLE: Option<Duration> = Some(Duration::from_millis(995
pub struct Niri {
pub config: Rc<RefCell<Config>>,
+ /// Output config from the config file.
+ ///
+ /// This does not include transient output config changes done via IPC. It is only used when
+ /// reloading the config from disk to determine if the output configuration should be reloaded
+ /// (and transient changes dropped).
+ pub config_file_output_config: Vec<niri_config::Output>,
+
pub event_loop: LoopHandle<'static, State>,
pub scheduler: Scheduler<()>,
pub stop_signal: LoopSignal,
@@ -858,6 +865,7 @@ impl State {
let mut reload_xkb = None;
let mut libinput_config_changed = false;
let mut output_config_changed = false;
+ let mut preserved_output_config = None;
let mut window_rules_changed = false;
let mut debug_config_changed = false;
let mut shaders_changed = false;
@@ -894,8 +902,15 @@ impl State {
libinput_config_changed = true;
}
- if config.outputs != old_config.outputs {
+ if config.outputs != self.niri.config_file_output_config {
output_config_changed = true;
+ self.niri
+ .config_file_output_config
+ .clone_from(&config.outputs);
+ } else {
+ // Output config did not change from the last disk load, so we need to preserve the
+ // transient changes.
+ preserved_output_config = Some(mem::take(&mut old_config.outputs));
}
if config.binds != old_config.binds {
@@ -926,6 +941,10 @@ impl State {
*old_config = config;
+ if let Some(outputs) = preserved_output_config {
+ old_config.outputs = outputs;
+ }
+
// Release the borrow.
drop(old_config);
@@ -945,51 +964,7 @@ impl State {
}
if output_config_changed {
- let mut resized_outputs = vec![];
- for output in self.niri.global_space.outputs() {
- let name = output.name();
- let config = self.niri.config.borrow_mut();
- let config = config.outputs.iter().find(|o| o.name == name);
-
- let scale = config.map(|c| c.scale).unwrap_or_else(|| {
- let size_mm = output.physical_properties().size;
- let resolution = output.current_mode().unwrap().size;
- guess_monitor_scale(size_mm, resolution)
- });
- let scale = scale.clamp(1., 10.).ceil() as i32;
-
- let mut transform = config
- .map(|c| ipc_transform_to_smithay(c.transform))
- .unwrap_or(Transform::Normal);
- // FIXME: fix winit damage on other transforms.
- if name == "winit" {
- transform = Transform::Flipped180;
- }
-
- if output.current_scale().integer_scale() != scale
- || output.current_transform() != transform
- {
- output.change_current_state(
- None,
- Some(transform),
- Some(output::Scale::Integer(scale)),
- None,
- );
- self.niri.ipc_outputs_changed = true;
- resized_outputs.push(output.clone());
- }
- }
- for output in resized_outputs {
- self.niri.output_resized(&output);
- }
-
- self.backend.on_output_config_changed(&mut self.niri);
-
- self.niri.reposition_outputs(None);
-
- if let Some(touch) = self.niri.seat.get_touch() {
- touch.cancel(self);
- }
+ self.reload_output_config();
}
if debug_config_changed {
@@ -1032,6 +1007,98 @@ impl State {
self.niri.queue_redraw_all();
}
+ fn reload_output_config(&mut self) {
+ let mut resized_outputs = vec![];
+ for output in self.niri.global_space.outputs() {
+ let name = output.name();
+ let config = self.niri.config.borrow_mut();
+ let config = config.outputs.iter().find(|o| o.name == name);
+
+ let scale = config.map(|c| c.scale).unwrap_or_else(|| {
+ let size_mm = output.physical_properties().size;
+ let resolution = output.current_mode().unwrap().size;
+ guess_monitor_scale(size_mm, resolution)
+ });
+ let scale = scale.clamp(1., 10.).ceil() as i32;
+
+ let mut transform = config
+ .map(|c| ipc_transform_to_smithay(c.transform))
+ .unwrap_or(Transform::Normal);
+ // FIXME: fix winit damage on other transforms.
+ if name == "winit" {
+ transform = Transform::Flipped180;
+ }
+
+ if output.current_scale().integer_scale() != scale
+ || output.current_transform() != transform
+ {
+ output.change_current_state(
+ None,
+ Some(transform),
+ Some(output::Scale::Integer(scale)),
+ None,
+ );
+ self.niri.ipc_outputs_changed = true;
+ resized_outputs.push(output.clone());
+ }
+ }
+ for output in resized_outputs {
+ self.niri.output_resized(&output);
+ }
+
+ self.backend.on_output_config_changed(&mut self.niri);
+
+ self.niri.reposition_outputs(None);
+
+ if let Some(touch) = self.niri.seat.get_touch() {
+ touch.cancel(self);
+ }
+ }
+
+ pub fn apply_transient_output_config(&mut self, name: &str, action: niri_ipc::OutputAction) {
+ {
+ let mut config = self.niri.config.borrow_mut();
+ let config = if let Some(config) = config.outputs.iter_mut().find(|o| o.name == name) {
+ config
+ } else {
+ config.outputs.push(niri_config::Output {
+ name: String::from(name),
+ ..Default::default()
+ });
+ config.outputs.last_mut().unwrap()
+ };
+
+ match action {
+ niri_ipc::OutputAction::Off => config.off = true,
+ niri_ipc::OutputAction::On => config.off = false,
+ niri_ipc::OutputAction::Mode { mode } => {
+ config.mode = match mode {
+ niri_ipc::ModeToSet::Automatic => None,
+ niri_ipc::ModeToSet::Specific(mode) => Some(mode),
+ }
+ }
+ niri_ipc::OutputAction::Scale { scale } => config.scale = scale,
+ niri_ipc::OutputAction::Transform { transform } => config.transform = transform,
+ niri_ipc::OutputAction::Position { position } => {
+ config.position = match position {
+ niri_ipc::PositionToSet::Automatic => None,
+ niri_ipc::PositionToSet::Specific(position) => {
+ Some(niri_config::Position {
+ x: position.x,
+ y: position.y,
+ })
+ }
+ }
+ }
+ niri_ipc::OutputAction::Vrr { enable } => {
+ config.variable_refresh_rate = enable;
+ }
+ }
+ }
+
+ self.reload_output_config();
+ }
+
pub fn refresh_ipc_outputs(&mut self) {
if !self.niri.ipc_outputs_changed {
return;
@@ -1175,6 +1242,7 @@ impl Niri {
let display_handle = display.handle();
let config_ = config.borrow();
+ let config_file_output_config = config_.outputs.clone();
let layout = Layout::new(&config_);
@@ -1353,6 +1421,7 @@ impl Niri {
drop(config_);
Self {
config,
+ config_file_output_config,
event_loop,
scheduler,