mirror of
https://github.com/rust-windowing/winit.git
synced 2026-08-31 05:40:04 -04:00
On X11, don't require XSETTINGS
We could fail to setup property watcher and fail to start, thus
don't require XSETTINGS to work.
Fixes: df8805c0 (On X11, reload DPI on _XSETTINGS_SETTINGS)
This commit is contained in:
@@ -38,11 +38,13 @@ impl XConnection {
|
|||||||
// Retrieve DPI from Xft.dpi property
|
// Retrieve DPI from Xft.dpi property
|
||||||
pub fn get_xft_dpi(&self) -> Option<f64> {
|
pub fn get_xft_dpi(&self) -> Option<f64> {
|
||||||
// Try to get it from XSETTINGS first.
|
// Try to get it from XSETTINGS first.
|
||||||
match self.xsettings_dpi() {
|
if let Some(xsettings_screen) = self.xsettings_screen() {
|
||||||
Ok(Some(dpi)) => return Some(dpi),
|
match self.xsettings_dpi(xsettings_screen) {
|
||||||
Ok(None) => {}
|
Ok(Some(dpi)) => return Some(dpi),
|
||||||
Err(err) => {
|
Ok(None) => {}
|
||||||
log::warn!("failed to fetch XSettings: {err}");
|
Err(err) => {
|
||||||
|
log::warn!("failed to fetch XSettings: {err}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ pub(crate) struct XConnection {
|
|||||||
randr_version: (u32, u32),
|
randr_version: (u32, u32),
|
||||||
|
|
||||||
/// Atom for the XSettings screen.
|
/// Atom for the XSettings screen.
|
||||||
xsettings_screen: xproto::Atom,
|
xsettings_screen: Option<xproto::Atom>,
|
||||||
|
|
||||||
pub latest_error: Mutex<Option<XError>>,
|
pub latest_error: Mutex<Option<XError>>,
|
||||||
pub cursor_cache: Mutex<HashMap<Option<CursorIcon>, ffi::Cursor>>,
|
pub cursor_cache: Mutex<HashMap<Option<CursorIcon>, ffi::Cursor>>,
|
||||||
@@ -108,21 +108,6 @@ impl XConnection {
|
|||||||
// Get the default screen.
|
// Get the default screen.
|
||||||
let default_screen = unsafe { (xlib.XDefaultScreen)(display) } as usize;
|
let default_screen = unsafe { (xlib.XDefaultScreen)(display) } as usize;
|
||||||
|
|
||||||
// Fetch the _XSETTINGS_S[screen number] atom.
|
|
||||||
let xsettings_screen = xcb
|
|
||||||
.intern_atom(false, format!("_XSETTINGS_S{}", default_screen).as_bytes())
|
|
||||||
.map_err(|e| XNotSupported::XcbConversionError(Arc::new(e)))?;
|
|
||||||
|
|
||||||
// Fetch the other atoms.
|
|
||||||
let atoms = Atoms::new(&xcb)
|
|
||||||
.map_err(|e| XNotSupported::XcbConversionError(Arc::new(e)))?
|
|
||||||
.reply()
|
|
||||||
.map_err(|e| XNotSupported::XcbConversionError(Arc::new(e)))?;
|
|
||||||
let xsettings_screen = xsettings_screen
|
|
||||||
.reply()
|
|
||||||
.map_err(|e| XNotSupported::XcbConversionError(Arc::new(e)))?
|
|
||||||
.atom;
|
|
||||||
|
|
||||||
// Load the database.
|
// Load the database.
|
||||||
let database = resource_manager::new_from_default(&xcb)
|
let database = resource_manager::new_from_default(&xcb)
|
||||||
.map_err(|e| XNotSupported::XcbConversionError(Arc::new(e)))?;
|
.map_err(|e| XNotSupported::XcbConversionError(Arc::new(e)))?;
|
||||||
@@ -134,23 +119,16 @@ impl XConnection {
|
|||||||
.reply()
|
.reply()
|
||||||
.expect("failed to query XRandR version");
|
.expect("failed to query XRandR version");
|
||||||
|
|
||||||
// Get PropertyNotify events from the XSETTINGS window.
|
let xsettings_screen = Self::new_xsettings_screen(&xcb, default_screen);
|
||||||
// TODO: The XSETTINGS window here can change. In the future, listen for DestroyNotify on this window
|
if xsettings_screen.is_none() {
|
||||||
// in order to accomodate for a changed window here.
|
log::warn!("error setting XSETTINGS; Xft options won't reload automatically")
|
||||||
let selector_window = xcb
|
}
|
||||||
.get_selection_owner(xsettings_screen)
|
|
||||||
|
// Fetch atoms.
|
||||||
|
let atoms = Atoms::new(&xcb)
|
||||||
.map_err(|e| XNotSupported::XcbConversionError(Arc::new(e)))?
|
.map_err(|e| XNotSupported::XcbConversionError(Arc::new(e)))?
|
||||||
.reply()
|
.reply()
|
||||||
.map_err(|e| XNotSupported::XcbConversionError(Arc::new(e)))?
|
.map_err(|e| XNotSupported::XcbConversionError(Arc::new(e)))?;
|
||||||
.owner;
|
|
||||||
xcb.change_window_attributes(
|
|
||||||
selector_window,
|
|
||||||
&xproto::ChangeWindowAttributesAux::new()
|
|
||||||
.event_mask(xproto::EventMask::PROPERTY_CHANGE),
|
|
||||||
)
|
|
||||||
.map_err(|e| XNotSupported::XcbConversionError(Arc::new(e)))?
|
|
||||||
.check()
|
|
||||||
.map_err(|e| XNotSupported::XcbConversionError(Arc::new(e)))?;
|
|
||||||
|
|
||||||
Ok(XConnection {
|
Ok(XConnection {
|
||||||
xlib,
|
xlib,
|
||||||
@@ -170,6 +148,37 @@ impl XConnection {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn new_xsettings_screen(xcb: &XCBConnection, default_screen: usize) -> Option<xproto::Atom> {
|
||||||
|
// Fetch the _XSETTINGS_S[screen number] atom.
|
||||||
|
let xsettings_screen = xcb
|
||||||
|
.intern_atom(false, format!("_XSETTINGS_S{}", default_screen).as_bytes())
|
||||||
|
.ok()?
|
||||||
|
.reply()
|
||||||
|
.ok()?
|
||||||
|
.atom;
|
||||||
|
|
||||||
|
// Get PropertyNotify events from the XSETTINGS window.
|
||||||
|
// TODO: The XSETTINGS window here can change. In the future, listen for DestroyNotify on this window
|
||||||
|
// in order to accomodate for a changed window here.
|
||||||
|
let selector_window = xcb
|
||||||
|
.get_selection_owner(xsettings_screen)
|
||||||
|
.ok()?
|
||||||
|
.reply()
|
||||||
|
.ok()?
|
||||||
|
.owner;
|
||||||
|
|
||||||
|
xcb.change_window_attributes(
|
||||||
|
selector_window,
|
||||||
|
&xproto::ChangeWindowAttributesAux::new()
|
||||||
|
.event_mask(xproto::EventMask::PROPERTY_CHANGE),
|
||||||
|
)
|
||||||
|
.ok()?
|
||||||
|
.check()
|
||||||
|
.ok()?;
|
||||||
|
|
||||||
|
Some(xsettings_screen)
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks whether an error has been triggered by the previous function calls.
|
/// Checks whether an error has been triggered by the previous function calls.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn check_errors(&self) -> Result<(), XError> {
|
pub fn check_errors(&self) -> Result<(), XError> {
|
||||||
@@ -258,7 +267,7 @@ impl XConnection {
|
|||||||
|
|
||||||
/// Get the atom for Xsettings.
|
/// Get the atom for Xsettings.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn xsettings_screen(&self) -> u32 {
|
pub fn xsettings_screen(&self) -> Option<xproto::Atom> {
|
||||||
self.xsettings_screen
|
self.xsettings_screen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
//!
|
//!
|
||||||
//! [here]: https://github.com/derat/xsettingsd
|
//! [here]: https://github.com/derat/xsettingsd
|
||||||
|
|
||||||
use super::{atoms::*, XConnection};
|
|
||||||
|
|
||||||
use x11rb::protocol::xproto::ConnectionExt;
|
|
||||||
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
|
|
||||||
|
use x11rb::protocol::xproto::{self, ConnectionExt};
|
||||||
|
|
||||||
|
use super::{atoms::*, XConnection};
|
||||||
|
|
||||||
type Result<T> = core::result::Result<T, ParserError>;
|
type Result<T> = core::result::Result<T, ParserError>;
|
||||||
|
|
||||||
const DPI_NAME: &[u8] = b"Xft/DPI";
|
const DPI_NAME: &[u8] = b"Xft/DPI";
|
||||||
@@ -20,13 +20,16 @@ const BIG_ENDIAN: u8 = b'B';
|
|||||||
|
|
||||||
impl XConnection {
|
impl XConnection {
|
||||||
/// Get the DPI from XSettings.
|
/// Get the DPI from XSettings.
|
||||||
pub(crate) fn xsettings_dpi(&self) -> core::result::Result<Option<f64>, super::X11Error> {
|
pub(crate) fn xsettings_dpi(
|
||||||
|
&self,
|
||||||
|
xsettings_screen: xproto::Atom,
|
||||||
|
) -> core::result::Result<Option<f64>, super::X11Error> {
|
||||||
let atoms = self.atoms();
|
let atoms = self.atoms();
|
||||||
|
|
||||||
// Get the current owner of the screen's settings.
|
// Get the current owner of the screen's settings.
|
||||||
let owner = self
|
let owner = self
|
||||||
.xcb_connection()
|
.xcb_connection()
|
||||||
.get_selection_owner(self.xsettings_screen())?
|
.get_selection_owner(xsettings_screen)?
|
||||||
.reply()?;
|
.reply()?;
|
||||||
|
|
||||||
// Read the _XSETTINGS_SETTINGS property.
|
// Read the _XSETTINGS_SETTINGS property.
|
||||||
|
|||||||
Reference in New Issue
Block a user