mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 22:01:31 +11:00
Make with_x11_visual take ID instead of a pointer
At the moment, the with_x11_visual function takes a pointer and immediately dereferences it to get the visual info inside. As it is safe to pass a null pointer to this function, it is unsound. This commit replaces the pointer parameter with a visual ID, and then uses that ID to look up the actual visual under the X11 setup. As this is what was already practically happening before, this change shouldn't cause any performance downgrades. This is a breaking change, but it's done in the name of soundness so it should be okay. It should be trivial for end users to accommodate it, as it's just a matter of getting the visual ID from the pointer to the visual before passing it in. Signed-off-by: John Nunley <dev@notgull.net>
This commit is contained in:
parent
8100a6a584
commit
584aab4cd0
|
@ -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** `RedrawEventsCleared` removed ([#2900](https://github.com/rust-windowing/winit/issues/2900))
|
||||||
- **Breaking** `MainEventsCleared` 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))
|
- 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
|
# 0.29.0-beta.0
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use std::ptr;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
event_loop::{EventLoopBuilder, EventLoopWindowTarget},
|
event_loop::{EventLoopBuilder, EventLoopWindowTarget},
|
||||||
monitor::MonitorHandle,
|
monitor::MonitorHandle,
|
||||||
|
@ -7,7 +5,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::dpi::Size;
|
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};
|
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 =
|
pub type XlibErrorHook =
|
||||||
Box<dyn Fn(*mut std::ffi::c_void, *mut std::ffi::c_void) -> bool + Send + Sync>;
|
Box<dyn Fn(*mut std::ffi::c_void, *mut std::ffi::c_void) -> bool + Send + Sync>;
|
||||||
|
|
||||||
|
/// A unique identifer for an X11 visual.
|
||||||
|
pub type XVisualID = u32;
|
||||||
|
|
||||||
/// Hook to winit's xlib error handling callback.
|
/// Hook to winit's xlib error handling callback.
|
||||||
///
|
///
|
||||||
/// This method is provided as a safe way to handle the errors comming from X11
|
/// 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.
|
/// Additional methods on [`WindowBuilder`] that are specific to X11.
|
||||||
pub trait WindowBuilderExtX11 {
|
pub trait WindowBuilderExtX11 {
|
||||||
fn with_x11_visual<T>(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;
|
fn with_x11_screen(self, screen_id: i32) -> Self;
|
||||||
|
|
||||||
|
@ -120,11 +122,8 @@ pub trait WindowBuilderExtX11 {
|
||||||
|
|
||||||
impl WindowBuilderExtX11 for WindowBuilder {
|
impl WindowBuilderExtX11 for WindowBuilder {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn with_x11_visual<T>(mut self, visual_infos: *const T) -> Self {
|
fn with_x11_visual(mut self, visual_id: XVisualID) -> Self {
|
||||||
{
|
self.platform_specific.visual_id = Some(visual_id);
|
||||||
self.platform_specific.visual_infos =
|
|
||||||
Some(unsafe { ptr::read(visual_infos as *const XVisualInfo) });
|
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ use std::time::Duration;
|
||||||
#[cfg(x11_platform)]
|
#[cfg(x11_platform)]
|
||||||
pub use self::x11::XNotSupported;
|
pub use self::x11::XNotSupported;
|
||||||
#[cfg(x11_platform)]
|
#[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)]
|
#[cfg(x11_platform)]
|
||||||
use crate::platform::x11::XlibErrorHook;
|
use crate::platform::x11::XlibErrorHook;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -96,7 +96,7 @@ pub struct PlatformSpecificWindowBuilderAttributes {
|
||||||
pub name: Option<ApplicationName>,
|
pub name: Option<ApplicationName>,
|
||||||
pub activation_token: Option<ActivationToken>,
|
pub activation_token: Option<ActivationToken>,
|
||||||
#[cfg(x11_platform)]
|
#[cfg(x11_platform)]
|
||||||
pub visual_infos: Option<XVisualInfo>,
|
pub visual_id: Option<x11rb::protocol::xproto::Visualid>,
|
||||||
#[cfg(x11_platform)]
|
#[cfg(x11_platform)]
|
||||||
pub screen_id: Option<i32>,
|
pub screen_id: Option<i32>,
|
||||||
#[cfg(x11_platform)]
|
#[cfg(x11_platform)]
|
||||||
|
@ -113,7 +113,7 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
|
||||||
name: None,
|
name: None,
|
||||||
activation_token: None,
|
activation_token: None,
|
||||||
#[cfg(x11_platform)]
|
#[cfg(x11_platform)]
|
||||||
visual_infos: None,
|
visual_id: None,
|
||||||
#[cfg(x11_platform)]
|
#[cfg(x11_platform)]
|
||||||
screen_id: None,
|
screen_id: None,
|
||||||
#[cfg(x11_platform)]
|
#[cfg(x11_platform)]
|
||||||
|
|
|
@ -886,6 +886,9 @@ pub enum X11Error {
|
||||||
|
|
||||||
/// Got an invalid activation token.
|
/// Got an invalid activation token.
|
||||||
InvalidActivationToken(Vec<u8>),
|
InvalidActivationToken(Vec<u8>),
|
||||||
|
|
||||||
|
/// Could not find a matching X11 visual for this visualid
|
||||||
|
NoSuchVisual(xproto::Visualid),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for X11Error {
|
impl fmt::Display for X11Error {
|
||||||
|
@ -902,6 +905,13 @@ impl fmt::Display for X11Error {
|
||||||
"Invalid activation token: {}",
|
"Invalid activation token: {}",
|
||||||
std::str::from_utf8(s).unwrap_or("<invalid utf8>")
|
std::str::from_utf8(s).unwrap_or("<invalid utf8>")
|
||||||
),
|
),
|
||||||
|
X11Error::NoSuchVisual(visualid) => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"Could not find a matching X11 visual for ID `{:x}`",
|
||||||
|
visualid
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,30 +214,45 @@ impl UnownedWindow {
|
||||||
None => xconn.default_screen_index() as c_int,
|
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
|
// creating
|
||||||
let (visual, depth, require_colormap) = match pl_attribs.visual_infos {
|
let (visualtype, depth, require_colormap) = match pl_attribs.visual_id {
|
||||||
Some(vi) => (vi.visualid as _, vi.depth as _, false),
|
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 => {
|
None if window_attrs.transparent => {
|
||||||
// Find a suitable visual, true color with 32 bits of depth.
|
// Find a suitable visual, true color with 32 bits of depth.
|
||||||
xconn.xcb_connection().setup().roots
|
all_visuals
|
||||||
.iter()
|
.find_map(|(visual, depth)| {
|
||||||
.flat_map(|root| &root.allowed_depths)
|
(visual.class == xproto::VisualClass::TRUE_COLOR)
|
||||||
.filter(|depth| depth.depth == 32)
|
.then_some((Some(visual), depth, true))
|
||||||
.flat_map(|depth| depth.visuals.iter().map(move |visual| (visual, depth.depth)))
|
|
||||||
.find(|(visual, _)| {
|
|
||||||
visual.class == xproto::VisualClass::TRUE_COLOR
|
|
||||||
})
|
})
|
||||||
.map_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
debug!("Could not set transparency, because XMatchVisualInfo returned zero for the required parameters");
|
debug!("Could not set transparency, because XMatchVisualInfo returned zero for the required parameters");
|
||||||
(x11rb::COPY_FROM_PARENT as _, x11rb::COPY_FROM_PARENT as _, false)
|
(None as _, x11rb::COPY_FROM_PARENT as _, false)
|
||||||
}, |(visual, depth)| (visual.visual_id, depth, true))
|
})
|
||||||
}
|
}
|
||||||
_ => (
|
_ => (None, x11rb::COPY_FROM_PARENT as _, false),
|
||||||
x11rb::COPY_FROM_PARENT as _,
|
|
||||||
x11rb::COPY_FROM_PARENT as _,
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
let visual = visualtype.map_or(x11rb::COPY_FROM_PARENT, |v| v.visual_id);
|
||||||
|
|
||||||
let window_attributes = {
|
let window_attributes = {
|
||||||
use xproto::EventMask;
|
use xproto::EventMask;
|
||||||
|
@ -260,8 +275,8 @@ impl UnownedWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a colormap if needed.
|
// Add a colormap if needed.
|
||||||
let colormap_visual = match pl_attribs.visual_infos {
|
let colormap_visual = match pl_attribs.visual_id {
|
||||||
Some(vi) => Some(vi.visualid as u32),
|
Some(vi) => Some(vi),
|
||||||
None if require_colormap => Some(visual),
|
None if require_colormap => Some(visual),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue