xwm: Set xcursor variables in Xresources db

This commit is contained in:
Victoria Brekenfeld 2026-01-09 18:34:51 +01:00 committed by Victoria Brekenfeld
parent 612ff2f523
commit e6a3a3a9c9
4 changed files with 97 additions and 30 deletions

View file

@ -180,8 +180,10 @@ impl Config {
let cosmic_comp_config =
CosmicCompConfig::get_entry(&config).unwrap_or_else(|(errs, c)| {
for err in errs {
error!(?err, "");
if cfg!(debug_assertions) {
for err in errs {
warn!(?err, "");
}
}
c
});
@ -189,6 +191,11 @@ impl Config {
// Listen for updates to the toolkit config
if let Ok(tk_config) = cosmic_config::Config::new("com.system76.CosmicTk", 1) {
fn handle_new_toolkit_config(config: CosmicTk, state: &mut State) {
if cosmic::icon_theme::default() != config.icon_theme {
cosmic::icon_theme::set_default(config.icon_theme.clone());
state.common.update_xwayland_settings();
}
let mut workspace_guard = state.common.workspace_state.update();
state.common.shell.write().update_toolkit(
config,
@ -197,19 +204,32 @@ impl Config {
);
}
if let Ok(config) = CosmicTk::get_entry(&tk_config) {
let _ = loop_handle.insert_idle(move |state| {
handle_new_toolkit_config(config, state);
});
}
let config = CosmicTk::get_entry(&tk_config).unwrap_or_else(|(errs, c)| {
if cfg!(debug_assertions) {
for err in errs {
warn!(?err, "");
}
}
c
});
let _ = loop_handle.insert_idle(move |state| {
handle_new_toolkit_config(config, state);
});
match cosmic_config::calloop::ConfigWatchSource::new(&tk_config) {
Ok(source) => {
if let Err(err) =
loop_handle.insert_source(source, |(config, _keys), (), state| {
if let Ok(config) = CosmicTk::get_entry(&config) {
handle_new_toolkit_config(config, state);
}
let config =
CosmicTk::get_entry(&config).unwrap_or_else(|(errs, c)| {
if cfg!(debug_assertions) {
for err in errs {
warn!(?err, "");
}
}
c
});
handle_new_toolkit_config(config, state);
})
{
warn!(?err, "Failed to watch com.system76.CosmicTk config");
@ -879,7 +899,7 @@ fn config_changed(config: cosmic_config::Config, keys: Vec<String>, state: &mut
let new = get_config::<XwaylandDescaling>(&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();
state.common.update_xwayland_settings();
}
}
"xwayland_eavesdropping" => {

View file

@ -4711,10 +4711,6 @@ impl Shell {
xdg_activation_state: &XdgActivationState,
workspace_state: &mut WorkspaceUpdateGuard<'_, State>,
) {
if cosmic::icon_theme::default() != toolkit.icon_theme {
cosmic::icon_theme::set_default(toolkit.icon_theme.clone());
}
let mut container = cosmic::config::COSMIC_TK.write().unwrap();
if *container != toolkit {
*container = toolkit;

View file

@ -579,7 +579,7 @@ impl LockedBackend<'_> {
loop_handle.insert_idle(move |state| {
state.update_inhibitor_locks();
state.common.update_xwayland_scale();
state.common.update_xwayland_settings();
state.common.update_xwayland_primary_output();
});

View file

@ -1,4 +1,10 @@
use std::{ffi::OsString, os::unix::io::OwnedFd, process::Stdio};
use std::{
ffi::OsString,
io::Write,
os::unix::io::OwnedFd,
process::Stdio,
sync::mpsc::{self, Receiver, Sender},
};
use crate::{
backend::render::cursor::{Cursor, load_cursor_env, load_cursor_theme},
@ -64,6 +70,39 @@ pub struct XWaylandState {
pub last_modifier_state: Option<ModifiersState>,
pub clipboard_selection_dirty: Option<Vec<String>>,
pub primary_selection_dirty: Option<Vec<String>>,
pub xrdb_thread: Sender<(String, u32)>,
}
fn xrdb_thread(rx: Receiver<(String, u32)>, display: u32) {
while let Ok((cursor_theme, cursor_size)) = rx.recv() {
if let Ok(mut child) = std::process::Command::new("xrdb")
.arg("-merge")
.env("DISPLAY", format!(":{}", display))
.stdin(Stdio::piped())
.spawn()
{
let resources = format!(
"Xcursor.theme: {}\nXcursor.size: {}\n",
cursor_theme, cursor_size,
);
if let Some(mut stdin) = child.stdin.take() {
if let Err(err) = stdin.write_all(resources.as_bytes()) {
warn!("Failed to update xresources: {}", err);
}
}
match child.wait() {
Ok(code) if code.success() => {}
Ok(code) => {
warn!("xrdb failed with code: {}", code);
}
Err(err) => {
warn!("Failed to wait for child: {}", err);
}
}
} else {
warn!("`xrdb` not found, cannot update Xresources.");
}
}
}
impl State {
@ -101,6 +140,9 @@ impl State {
x11_socket,
display_number,
} => {
let (tx, rx) = mpsc::channel();
std::thread::spawn(move || xrdb_thread(rx, display_number));
data.common.xwayland_state = Some(XWaylandState {
client: client.clone(),
xwm: None,
@ -110,6 +152,7 @@ impl State {
last_modifier_state: None,
clipboard_selection_dirty: None,
primary_selection_dirty: None,
xrdb_thread: tx,
});
let wm = match X11Wm::start_wm(
@ -130,7 +173,7 @@ impl State {
xwayland_state.reload_cursor(1.);
data.notify_ready();
data.common.update_xwayland_scale();
data.common.update_xwayland_settings();
data.common.update_xwayland_primary_output();
}
XWaylandEvent::Error => {
@ -594,7 +637,7 @@ impl Common {
}
}
pub fn update_xwayland_scale(&mut self) {
pub fn update_xwayland_settings(&mut self) {
let new_scale = match self.config.cosmic_conf.descale_xwayland {
XwaylandDescaling::Disabled => 1.,
XwaylandDescaling::Enabled => {
@ -619,10 +662,11 @@ impl Common {
val
}
};
let (_, cursor_size) = load_cursor_env();
// compare with current scale
if Some(new_scale) != self.xwayland_scale {
if let Some(xwayland) = self.xwayland_state.as_mut() {
if let Some(xwayland) = self.xwayland_state.as_mut() {
let geometries = if Some(new_scale) != self.xwayland_scale {
// backup geometries
let geometries = self
.shell
@ -632,8 +676,6 @@ impl Common {
.filter_map(|s| s.0.x11_surface().map(|x| (x.clone(), x.geometry())))
.collect::<Vec<_>>();
let (_, cursor_size) = load_cursor_env();
// update xorg dpi
if let Some(xwm) = xwayland.xwm.as_mut() {
let base = 96. * 1024.;
@ -644,10 +686,6 @@ impl Common {
if let Err(err) = xwm.set_xsettings(
[
("Xft/DPI".into(), (dpi.round() as i32).into()),
(
"Xcursor/size".into(),
((new_scale * cursor_size as f64).round() as i32).into(),
),
(
"Gdk/UnscaledDPI".into(),
(unscaled_dpi.round() as i32).into(),
@ -667,9 +705,22 @@ impl Common {
}
}
// update cursor
xwayland.reload_cursor(new_scale);
Some(geometries)
} else {
None
};
if let Err(_) = xwayland.xrdb_thread.send((
cosmic::icon_theme::default(),
(new_scale * cursor_size as f64).round() as u32,
)) {
warn!("xrdb thread died");
}
// update cursor
xwayland.reload_cursor(new_scale);
if let Some(geometries) = geometries {
// update client scale
xwayland
.client
@ -1192,7 +1243,7 @@ impl XwmHandler for State {
output_name.as_deref().is_some_and(|o| o == output.name());
}
self.common.output_configuration_state.update();
self.common.update_xwayland_scale();
self.common.update_xwayland_settings();
self.common
.config
.write_outputs(self.common.output_configuration_state.outputs());