diff --git a/src/state.rs b/src/state.rs index 39772323..2492ff5e 100644 --- a/src/state.rs +++ b/src/state.rs @@ -53,6 +53,7 @@ use smithay::{ compositor::{CompositorClientState, CompositorState}, data_device::DataDeviceState, dmabuf::{DmabufFeedback, DmabufState}, + fractional_scale::{with_fractional_scale, FractionalScaleManagerState}, keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitState, output::OutputManagerState, presentation::PresentationState, @@ -113,6 +114,7 @@ pub struct Common { pub compositor_state: CompositorState, pub data_device_state: DataDeviceState, pub dmabuf_state: DmabufState, + pub fractional_scale_state: FractionalScaleManagerState, pub keyboard_shortcuts_inhibit_state: KeyboardShortcutsInhibitState, pub output_state: OutputManagerState, pub output_configuration_state: OutputConfigurationState, @@ -244,6 +246,7 @@ impl State { let compositor_state = CompositorState::new::(dh); let data_device_state = DataDeviceState::new::(dh); let dmabuf_state = DmabufState::new(); + let fractional_scale_state = FractionalScaleManagerState::new::(dh); let keyboard_shortcuts_inhibit_state = KeyboardShortcutsInhibitState::new::(dh); let output_state = OutputManagerState::new_with_xdg_output::(dh); let output_configuration_state = OutputConfigurationState::new(dh, |_| true); @@ -292,6 +295,7 @@ impl State { compositor_state, data_device_state, dmabuf_state, + fractional_scale_state, screencopy_state, shm_state, seat_state, @@ -450,7 +454,7 @@ impl Common { if outputs_for_element.contains(&output) { let window = mapped.active_window(); window.with_surfaces(|surface, states| { - update_surface_primary_scanout_output( + let primary_scanout_output = update_surface_primary_scanout_output( surface, output, states, @@ -468,6 +472,12 @@ impl Common { } }, ); + if let Some(output) = primary_scanout_output { + with_fractional_scale(states, |fraction_scale| { + fraction_scale + .set_preferred_scale(output.current_scale().fractional_scale()); + }); + } }); window.send_frame(output, time, throttle, surface_primary_scanout_output); if let Some(feedback) = window @@ -504,13 +514,19 @@ impl Common { self.shell.override_redirect_windows.iter().for_each(|or| { if let Some(wl_surface) = or.wl_surface() { with_surfaces_surface_tree(&wl_surface, |surface, states| { - update_surface_primary_scanout_output( + let primary_scanout_output = update_surface_primary_scanout_output( surface, output, states, render_element_states, default_primary_scanout_output_compare, ); + if let Some(output) = primary_scanout_output { + with_fractional_scale(states, |fraction_scale| { + fraction_scale + .set_preferred_scale(output.current_scale().fractional_scale()); + }); + } }); send_frames_surface_tree( &wl_surface, @@ -542,13 +558,19 @@ impl Common { let map = smithay::desktop::layer_map_for_output(output); for layer_surface in map.layers() { layer_surface.with_surfaces(|surface, states| { - update_surface_primary_scanout_output( + let primary_scanout_output = update_surface_primary_scanout_output( surface, output, states, render_element_states, default_primary_scanout_output_compare, ); + if let Some(output) = primary_scanout_output { + with_fractional_scale(states, |fraction_scale| { + fraction_scale + .set_preferred_scale(output.current_scale().fractional_scale()); + }); + } }); layer_surface.send_frame(output, time, throttle, surface_primary_scanout_output); if let Some(feedback) = diff --git a/src/wayland/handlers/fractional_scale.rs b/src/wayland/handlers/fractional_scale.rs new file mode 100644 index 00000000..54b1eaf7 --- /dev/null +++ b/src/wayland/handlers/fractional_scale.rs @@ -0,0 +1,60 @@ +use crate::{state::State, utils::prelude::SeatExt}; +use smithay::{ + delegate_fractional_scale, + desktop::utils::surface_primary_scanout_output, + reexports::wayland_server::protocol::wl_surface::WlSurface, + wayland::{ + compositor::{get_parent, with_states}, + fractional_scale::{with_fractional_scale, FractionalScaleHandler}, + }, +}; + +impl FractionalScaleHandler for State { + fn new_fractional_scale(&mut self, surface: WlSurface) { + // Here we can set the initial fractional scale + // + // First we look if the surface already has a primary scan-out output, if not + // we test if the surface is a subsurface and try to use the primary scan-out output + // of the root surface. If the root also has no primary scan-out output we just try + // to use the first output of the toplevel. + // If the surface is the root we also try to use the first output of the toplevel. + // + // If all the above tests do not lead to a output we just use the active output + // of the last active seat (which will also be the output a toplevel will + // initially be placed on) + let mut root = surface.clone(); + while let Some(parent) = get_parent(&root) { + root = parent; + } + + with_states(&surface, |states| { + let output = surface_primary_scanout_output(&surface, states) + .or_else(|| { + if root != surface { + with_states(&root, |states| { + surface_primary_scanout_output(&root, states).or_else(|| { + self.common + .shell + .visible_outputs_for_surface(&surface) + .next() + }) + }) + } else { + self.common + .shell + .visible_outputs_for_surface(&surface) + .next() + } + }) + .unwrap_or_else(|| { + let seat = self.common.last_active_seat(); + seat.active_output() + }); + with_fractional_scale(states, |fractional_scale| { + fractional_scale.set_preferred_scale(output.current_scale().fractional_scale()); + }); + }); + } +} + +delegate_fractional_scale!(State); diff --git a/src/wayland/handlers/mod.rs b/src/wayland/handlers/mod.rs index 56e4a9be..098b6e4b 100644 --- a/src/wayland/handlers/mod.rs +++ b/src/wayland/handlers/mod.rs @@ -5,6 +5,7 @@ pub mod compositor; pub mod data_device; pub mod decoration; pub mod dmabuf; +pub mod fractional_scale; pub mod keyboard_shortcuts_inhibit; pub mod layer_shell; pub mod output;