diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c273213..ae43fda9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ And please only add new entries to the top of this list, right below the `# Unre - **Breaking** `RedrawEventsCleared` removed ([#2900](https://github.com/rust-windowing/winit/issues/2900)) - **Breaking** `MainEventsCleared` removed ([#2900](https://github.com/rust-windowing/winit/issues/2900)) - Added `AboutToWait` event which is emitted when the event loop is about to block and wait for new events ([#2900](https://github.com/rust-windowing/winit/issues/2900)) +- **Breaking:** `with_x11_visual` now takes the visual ID instead of the bare pointer. # 0.29.0-beta.0 diff --git a/src/platform/x11.rs b/src/platform/x11.rs index 7d81546f..95b2534a 100644 --- a/src/platform/x11.rs +++ b/src/platform/x11.rs @@ -1,5 +1,3 @@ -use std::ptr; - use crate::{ event_loop::{EventLoopBuilder, EventLoopWindowTarget}, monitor::MonitorHandle, @@ -7,7 +5,7 @@ use crate::{ }; use crate::dpi::Size; -use crate::platform_impl::{x11::ffi::XVisualInfo, ApplicationName, Backend, XLIB_ERROR_HOOKS}; +use crate::platform_impl::{ApplicationName, Backend, XLIB_ERROR_HOOKS}; pub use crate::platform_impl::{x11::util::WindowType as XWindowType, XNotSupported}; @@ -19,6 +17,9 @@ pub use crate::platform_impl::{x11::util::WindowType as XWindowType, XNotSupport pub type XlibErrorHook = Box bool + Send + Sync>; +/// A unique identifer for an X11 visual. +pub type XVisualID = u32; + /// Hook to winit's xlib error handling callback. /// /// This method is provided as a safe way to handle the errors comming from X11 @@ -84,7 +85,8 @@ impl WindowExtX11 for Window {} /// Additional methods on [`WindowBuilder`] that are specific to X11. pub trait WindowBuilderExtX11 { - fn with_x11_visual(self, visual_infos: *const T) -> Self; + /// Create this window with a specific X11 visual. + fn with_x11_visual(self, visual_id: XVisualID) -> Self; fn with_x11_screen(self, screen_id: i32) -> Self; @@ -120,11 +122,8 @@ pub trait WindowBuilderExtX11 { impl WindowBuilderExtX11 for WindowBuilder { #[inline] - fn with_x11_visual(mut self, visual_infos: *const T) -> Self { - { - self.platform_specific.visual_infos = - Some(unsafe { ptr::read(visual_infos as *const XVisualInfo) }); - } + fn with_x11_visual(mut self, visual_id: XVisualID) -> Self { + self.platform_specific.visual_id = Some(visual_id); self } diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 52947896..dedc3c51 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -24,7 +24,7 @@ use std::time::Duration; #[cfg(x11_platform)] pub use self::x11::XNotSupported; #[cfg(x11_platform)] -use self::x11::{ffi::XVisualInfo, util::WindowType as XWindowType, X11Error, XConnection, XError}; +use self::x11::{util::WindowType as XWindowType, X11Error, XConnection, XError}; #[cfg(x11_platform)] use crate::platform::x11::XlibErrorHook; use crate::{ @@ -96,7 +96,7 @@ pub struct PlatformSpecificWindowBuilderAttributes { pub name: Option, pub activation_token: Option, #[cfg(x11_platform)] - pub visual_infos: Option, + pub visual_id: Option, #[cfg(x11_platform)] pub screen_id: Option, #[cfg(x11_platform)] @@ -113,7 +113,7 @@ impl Default for PlatformSpecificWindowBuilderAttributes { name: None, activation_token: None, #[cfg(x11_platform)] - visual_infos: None, + visual_id: None, #[cfg(x11_platform)] screen_id: None, #[cfg(x11_platform)] diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 718a5c32..0746c42d 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -886,6 +886,9 @@ pub enum X11Error { /// Got an invalid activation token. InvalidActivationToken(Vec), + + /// Could not find a matching X11 visual for this visualid + NoSuchVisual(xproto::Visualid), } impl fmt::Display for X11Error { @@ -902,6 +905,13 @@ impl fmt::Display for X11Error { "Invalid activation token: {}", std::str::from_utf8(s).unwrap_or("") ), + X11Error::NoSuchVisual(visualid) => { + write!( + f, + "Could not find a matching X11 visual for ID `{:x}`", + visualid + ) + } } } } diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index fd00bd64..d44fa4fa 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -214,30 +214,45 @@ impl UnownedWindow { None => xconn.default_screen_index() as c_int, }; + // An iterator over all of the visuals combined with their depths. + let mut all_visuals = xconn + .xcb_connection() + .setup() + .roots + .iter() + .flat_map(|root| &root.allowed_depths) + .flat_map(|depth| { + depth + .visuals + .iter() + .map(move |visual| (visual, depth.depth)) + }); + // creating - let (visual, depth, require_colormap) = match pl_attribs.visual_infos { - Some(vi) => (vi.visualid as _, vi.depth as _, false), + let (visualtype, depth, require_colormap) = match pl_attribs.visual_id { + Some(vi) => { + // Find this specific visual. + let (visualtype, depth) = all_visuals + .find(|(visual, _)| visual.visual_id == vi) + .ok_or_else(|| os_error!(OsError::XError(X11Error::NoSuchVisual(vi).into())))?; + + (Some(visualtype), depth, true) + } None if window_attrs.transparent => { // Find a suitable visual, true color with 32 bits of depth. - xconn.xcb_connection().setup().roots - .iter() - .flat_map(|root| &root.allowed_depths) - .filter(|depth| depth.depth == 32) - .flat_map(|depth| depth.visuals.iter().map(move |visual| (visual, depth.depth))) - .find(|(visual, _)| { - visual.class == xproto::VisualClass::TRUE_COLOR + all_visuals + .find_map(|(visual, depth)| { + (visual.class == xproto::VisualClass::TRUE_COLOR) + .then_some((Some(visual), depth, true)) }) - .map_or_else(|| { + .unwrap_or_else(|| { debug!("Could not set transparency, because XMatchVisualInfo returned zero for the required parameters"); - (x11rb::COPY_FROM_PARENT as _, x11rb::COPY_FROM_PARENT as _, false) - }, |(visual, depth)| (visual.visual_id, depth, true)) + (None as _, x11rb::COPY_FROM_PARENT as _, false) + }) } - _ => ( - x11rb::COPY_FROM_PARENT as _, - x11rb::COPY_FROM_PARENT as _, - false, - ), + _ => (None, x11rb::COPY_FROM_PARENT as _, false), }; + let visual = visualtype.map_or(x11rb::COPY_FROM_PARENT, |v| v.visual_id); let window_attributes = { use xproto::EventMask; @@ -260,8 +275,8 @@ impl UnownedWindow { } // Add a colormap if needed. - let colormap_visual = match pl_attribs.visual_infos { - Some(vi) => Some(vi.visualid as u32), + let colormap_visual = match pl_attribs.visual_id { + Some(vi) => Some(vi), None if require_colormap => Some(visual), _ => None, };