Skip to content

Commit

Permalink
xwayland: Add descaling option
Browse files Browse the repository at this point in the history
  • Loading branch information
Drakulix committed Sep 2, 2024
1 parent c9220a7 commit 971c28d
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 2 deletions.
3 changes: 3 additions & 0 deletions cosmic-comp-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ pub struct CosmicCompConfig {
pub autotile_behavior: TileBehavior,
/// Active hint enabled
pub active_hint: bool,
/// Let X11 applications scale themselves
pub descale_xwayland: bool,
}

impl Default for CosmicCompConfig {
Expand All @@ -48,6 +50,7 @@ impl Default for CosmicCompConfig {
autotile: Default::default(),
autotile_behavior: Default::default(),
active_hint: true,
descale_xwayland: false,
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,13 @@ fn config_changed(config: cosmic_config::Config, keys: Vec<String>, state: &mut
state.common.update_config();
}
}
"descale_xwayland" => {
let new = get_config::<bool>(&config, "descale_xwayland");
if new != state.common.config.cosmic_conf.descale_xwayland {
state.common.config.cosmic_conf.descale_xwayland = new;
state.common.update_xwayland_scale();
}
}
_ => {}
}
}
Expand Down
12 changes: 12 additions & 0 deletions src/shell/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3422,6 +3422,18 @@ impl Shell {

output_presentation_feedback
}

pub fn mapped(&self) -> impl Iterator<Item = &CosmicMapped> {
self.workspaces.iter().flat_map(|(_, set)| {
set.sticky_layer
.mapped()
.chain(set.minimized_windows.iter().map(|m| &m.window))
.chain(set.workspaces.iter().flat_map(|w| {
w.mapped()
.chain(w.minimized_windows.iter().map(|m| &m.window))
}))
})
}
}

fn workspace_set_idx(
Expand Down
4 changes: 4 additions & 0 deletions src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ pub struct Common {
pub xdg_activation_state: XdgActivationState,
pub xdg_foreign_state: XdgForeignState,
pub workspace_state: WorkspaceState<State>,
pub xwayland_scale: Option<i32>,
pub xwayland_state: Option<XWaylandState>,
pub xwayland_shell_state: XWaylandShellState,
}
Expand Down Expand Up @@ -354,6 +355,8 @@ impl BackendData {
self.schedule_render(&output);
}

loop_handle.insert_idle(|state| state.common.update_xwayland_scale());

Ok(())
}

Expand Down Expand Up @@ -615,6 +618,7 @@ impl State {
xdg_activation_state,
xdg_foreign_state,
workspace_state,
xwayland_scale: None,
xwayland_state: None,
xwayland_shell_state,
},
Expand Down
74 changes: 72 additions & 2 deletions src/xwayland.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::{
use smithay::{
backend::drm::DrmNode,
desktop::space::SpaceElement,
reexports::x11rb::protocol::xproto::Window as X11Window,
reexports::{wayland_server::Client, x11rb::protocol::xproto::Window as X11Window},
utils::{Logical, Point, Rectangle, Size, SERIAL_COUNTER},
wayland::{
selection::{
Expand All @@ -33,13 +33,14 @@ use smithay::{
},
xwayland::{
xwm::{Reorder, X11Relatable, XwmId},
X11Surface, X11Wm, XWayland, XWaylandEvent, XwmHandler,
X11Surface, X11Wm, XWayland, XWaylandClientData, XWaylandEvent, XwmHandler,
},
};
use tracing::{error, trace, warn};

#[derive(Debug)]
pub struct XWaylandState {
pub client: Client,
pub xwm: Option<X11Wm>,
pub display: u32,
}
Expand Down Expand Up @@ -80,6 +81,7 @@ impl State {
display_number,
} => {
data.common.xwayland_state = Some(XWaylandState {
client: client.clone(),
xwm: None,
display: display_number,
});
Expand Down Expand Up @@ -114,6 +116,8 @@ impl State {
let xwayland_state = data.common.xwayland_state.as_mut().unwrap();
xwayland_state.xwm = Some(wm);
data.notify_ready();

data.common.update_xwayland_scale();
}
XWaylandEvent::Error => {
if let Some(mut xwayland_state) = data.common.xwayland_state.take() {
Expand Down Expand Up @@ -242,6 +246,72 @@ impl Common {
}
}
}

pub fn update_xwayland_scale(&mut self) {
let new_scale = if self.config.cosmic_conf.descale_xwayland {
let shell = self.shell.read().unwrap();
shell
.outputs()
.map(|o| o.current_scale().integer_scale())
.max()
.unwrap_or(1) as i32
} else {
1
};

// compare with current scale
if Some(new_scale) != self.xwayland_scale {
if let Some(xwayland) = self.xwayland_state.as_mut() {
// backup geometries
let geometries = self
.shell
.read()
.unwrap()
.mapped()
.flat_map(|m| m.windows().map(|(s, _)| s))
.filter_map(|s| s.0.x11_surface().map(|x| (x.clone(), x.geometry())))
.collect::<Vec<_>>();

// update xorg dpi
if let Some(xwm) = xwayland.xwm.as_mut() {
let dpi = new_scale.abs() * 96 * 1024;
if let Err(err) = xwm.set_xsettings(
[
("Xft/DPI".into(), dpi.into()),
("Gdk/UnscaledDPI".into(), (dpi / new_scale).into()),
("Gdk/WindowScalingFactor".into(), new_scale.into()),
]
.into_iter(),
) {
warn!(wm_id = ?xwm.id(), ?err, "Failed to update XSETTINGS.");
}
}

// update client scale
xwayland
.client
.get_data::<XWaylandClientData>()
.unwrap()
.compositor_state
.set_client_scale(new_scale as u32);

// update wl/xdg_outputs
for output in self.shell.read().unwrap().outputs() {
output.change_current_state(None, None, None, None);
}

// update geometries
for (surface, geometry) in geometries.iter() {
if let Err(err) = surface.configure(*geometry) {
warn!(?err, surface = ?surface.window_id(), "Failed to update geometry after scale change");
}
}
self.update_x11_stacking_order();

self.xwayland_scale = Some(new_scale);
}
}
}
}

impl XwmHandler for State {
Expand Down

0 comments on commit 971c28d

Please sign in to comment.