mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-24 02:46:33 +11:00
Replace std::mem::uninitialized
with MaybeUninit
(#1027)
* Replace `std::mem::uninitialized` with `MaybeUninit` * Avoid undefined behavior when using `MaybeUninit` * Restore unused `PointerState` fields as internally public * Zero-initialize some struct values in Xlib FFI calls * Reform usage of `MaybeUninit` in Xlib FFI * Prefer safe zero-initialization using `Default`, when possible * Zero-initialize integers and floats using `0` or `0.0` * Use `MaybeUninit::uninit` for large byte buffers and union types * Use `MaybeUninit::uninit` when the resulting value is ignored
This commit is contained in:
parent
17b8310517
commit
7daf146801
9 changed files with 186 additions and 126 deletions
|
@ -1,6 +1,6 @@
|
||||||
#![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
|
#![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
|
||||||
|
|
||||||
use std::{collections::VecDeque, env, ffi::CStr, fmt, mem, os::raw::*, sync::Arc};
|
use std::{collections::VecDeque, env, ffi::CStr, fmt, mem::MaybeUninit, os::raw::*, sync::Arc};
|
||||||
|
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use smithay_client_toolkit::reexports::client::ConnectError;
|
use smithay_client_toolkit::reexports::client::ConnectError;
|
||||||
|
@ -410,14 +410,16 @@ unsafe extern "C" fn x_error_callback(
|
||||||
) -> c_int {
|
) -> c_int {
|
||||||
let xconn_lock = X11_BACKEND.lock();
|
let xconn_lock = X11_BACKEND.lock();
|
||||||
if let Ok(ref xconn) = *xconn_lock {
|
if let Ok(ref xconn) = *xconn_lock {
|
||||||
let mut buf: [c_char; 1024] = mem::uninitialized();
|
// `assume_init` is safe here because the array consists of `MaybeUninit` values,
|
||||||
|
// which do not require initialization.
|
||||||
|
let mut buf: [MaybeUninit<c_char>; 1024] = MaybeUninit::uninit().assume_init();
|
||||||
(xconn.xlib.XGetErrorText)(
|
(xconn.xlib.XGetErrorText)(
|
||||||
display,
|
display,
|
||||||
(*event).error_code as c_int,
|
(*event).error_code as c_int,
|
||||||
buf.as_mut_ptr(),
|
buf.as_mut_ptr() as *mut c_char,
|
||||||
buf.len() as c_int,
|
buf.len() as c_int,
|
||||||
);
|
);
|
||||||
let description = CStr::from_ptr(buf.as_ptr()).to_string_lossy();
|
let description = CStr::from_ptr(buf.as_ptr() as *const c_char).to_string_lossy();
|
||||||
|
|
||||||
let error = XError {
|
let error = XError {
|
||||||
description: description.into_owned(),
|
description: description.into_owned(),
|
||||||
|
|
|
@ -20,7 +20,7 @@ use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::{HashMap, HashSet, VecDeque},
|
collections::{HashMap, HashSet, VecDeque},
|
||||||
ffi::CStr,
|
ffi::CStr,
|
||||||
mem,
|
mem::{self, MaybeUninit},
|
||||||
ops::Deref,
|
ops::Deref,
|
||||||
os::raw::*,
|
os::raw::*,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
|
@ -100,22 +100,21 @@ impl<T: 'static> EventLoop<T> {
|
||||||
.expect("Failed to query XRandR extension");
|
.expect("Failed to query XRandR extension");
|
||||||
|
|
||||||
let xi2ext = unsafe {
|
let xi2ext = unsafe {
|
||||||
let mut result = XExtension {
|
let mut ext = XExtension::default();
|
||||||
opcode: mem::uninitialized(),
|
|
||||||
first_event_id: mem::uninitialized(),
|
|
||||||
first_error_id: mem::uninitialized(),
|
|
||||||
};
|
|
||||||
let res = (xconn.xlib.XQueryExtension)(
|
let res = (xconn.xlib.XQueryExtension)(
|
||||||
xconn.display,
|
xconn.display,
|
||||||
b"XInputExtension\0".as_ptr() as *const c_char,
|
b"XInputExtension\0".as_ptr() as *const c_char,
|
||||||
&mut result.opcode as *mut c_int,
|
&mut ext.opcode,
|
||||||
&mut result.first_event_id as *mut c_int,
|
&mut ext.first_event_id,
|
||||||
&mut result.first_error_id as *mut c_int,
|
&mut ext.first_error_id,
|
||||||
);
|
);
|
||||||
|
|
||||||
if res == ffi::False {
|
if res == ffi::False {
|
||||||
panic!("X server missing XInput extension");
|
panic!("X server missing XInput extension");
|
||||||
}
|
}
|
||||||
result
|
|
||||||
|
ext
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -204,8 +203,9 @@ impl<T: 'static> EventLoop<T> {
|
||||||
move |evt, &mut ()| {
|
move |evt, &mut ()| {
|
||||||
if evt.readiness.is_readable() {
|
if evt.readiness.is_readable() {
|
||||||
// process all pending events
|
// process all pending events
|
||||||
let mut xev = unsafe { mem::uninitialized() };
|
let mut xev = MaybeUninit::uninit();
|
||||||
while unsafe { processor.poll_one_event(&mut xev) } {
|
while unsafe { processor.poll_one_event(xev.as_mut_ptr()) } {
|
||||||
|
let mut xev = unsafe { xev.assume_init() };
|
||||||
processor.process_event(&mut xev, &mut callback);
|
processor.process_event(&mut xev, &mut callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -401,9 +401,10 @@ struct DeviceInfo<'a> {
|
||||||
impl<'a> DeviceInfo<'a> {
|
impl<'a> DeviceInfo<'a> {
|
||||||
fn get(xconn: &'a XConnection, device: c_int) -> Option<Self> {
|
fn get(xconn: &'a XConnection, device: c_int) -> Option<Self> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut count = mem::uninitialized();
|
let mut count = 0;
|
||||||
let info = (xconn.xinput2.XIQueryDevice)(xconn.display, device, &mut count);
|
let info = (xconn.xinput2.XIQueryDevice)(xconn.display, device, &mut count);
|
||||||
xconn.check_errors().ok().and_then(|_| {
|
xconn.check_errors().ok()?;
|
||||||
|
|
||||||
if info.is_null() || count == 0 {
|
if info.is_null() || count == 0 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
@ -413,7 +414,6 @@ impl<'a> DeviceInfo<'a> {
|
||||||
count: count as usize,
|
count: count as usize,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -518,7 +518,7 @@ impl<'a> Drop for GenericEventCookie<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
struct XExtension {
|
struct XExtension {
|
||||||
opcode: c_int,
|
opcode: c_int,
|
||||||
first_event_id: c_int,
|
first_event_id: c_int,
|
||||||
|
|
|
@ -30,13 +30,17 @@ impl XConnection {
|
||||||
event_mask: Option<c_long>,
|
event_mask: Option<c_long>,
|
||||||
data: ClientMsgPayload,
|
data: ClientMsgPayload,
|
||||||
) -> Flusher<'_> {
|
) -> Flusher<'_> {
|
||||||
let mut event: ffi::XClientMessageEvent = unsafe { mem::uninitialized() };
|
let event = ffi::XClientMessageEvent {
|
||||||
event.type_ = ffi::ClientMessage;
|
type_: ffi::ClientMessage,
|
||||||
event.display = self.display;
|
display: self.display,
|
||||||
event.window = window;
|
window,
|
||||||
event.message_type = message_type;
|
message_type,
|
||||||
event.format = c_long::FORMAT as c_int;
|
format: c_long::FORMAT as c_int,
|
||||||
event.data = unsafe { mem::transmute(data) };
|
data: unsafe { mem::transmute(data) },
|
||||||
|
// These fields are ignored by `XSendEvent`
|
||||||
|
serial: 0,
|
||||||
|
send_event: 0,
|
||||||
|
};
|
||||||
self.send_event(target_window, event_mask, event)
|
self.send_event(target_window, event_mask, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,12 +58,17 @@ impl XConnection {
|
||||||
let format = T::FORMAT;
|
let format = T::FORMAT;
|
||||||
let size_of_t = mem::size_of::<T>();
|
let size_of_t = mem::size_of::<T>();
|
||||||
debug_assert_eq!(size_of_t, format.get_actual_size());
|
debug_assert_eq!(size_of_t, format.get_actual_size());
|
||||||
let mut event: ffi::XClientMessageEvent = unsafe { mem::uninitialized() };
|
let mut event = ffi::XClientMessageEvent {
|
||||||
event.type_ = ffi::ClientMessage;
|
type_: ffi::ClientMessage,
|
||||||
event.display = self.display;
|
display: self.display,
|
||||||
event.window = window;
|
window,
|
||||||
event.message_type = message_type;
|
message_type,
|
||||||
event.format = format as c_int;
|
format: format as c_int,
|
||||||
|
data: ffi::ClientMessageData::new(),
|
||||||
|
// These fields are ignored by `XSendEvent`
|
||||||
|
serial: 0,
|
||||||
|
send_event: 0,
|
||||||
|
};
|
||||||
|
|
||||||
let t_per_payload = format.get_payload_size() / size_of_t;
|
let t_per_payload = format.get_payload_size() / size_of_t;
|
||||||
assert!(t_per_payload > 0);
|
assert!(t_per_payload > 0);
|
||||||
|
|
|
@ -41,14 +41,14 @@ impl AaRect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Default)]
|
||||||
pub struct TranslatedCoords {
|
pub struct TranslatedCoords {
|
||||||
pub x_rel_root: c_int,
|
pub x_rel_root: c_int,
|
||||||
pub y_rel_root: c_int,
|
pub y_rel_root: c_int,
|
||||||
pub child: ffi::Window,
|
pub child: ffi::Window,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Geometry {
|
pub struct Geometry {
|
||||||
pub root: ffi::Window,
|
pub root: ffi::Window,
|
||||||
// If you want positions relative to the root window, use translate_coords.
|
// If you want positions relative to the root window, use translate_coords.
|
||||||
|
@ -183,7 +183,8 @@ impl XConnection {
|
||||||
window: ffi::Window,
|
window: ffi::Window,
|
||||||
root: ffi::Window,
|
root: ffi::Window,
|
||||||
) -> Result<TranslatedCoords, XError> {
|
) -> Result<TranslatedCoords, XError> {
|
||||||
let mut translated_coords: TranslatedCoords = unsafe { mem::uninitialized() };
|
let mut coords = TranslatedCoords::default();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
(self.xlib.XTranslateCoordinates)(
|
(self.xlib.XTranslateCoordinates)(
|
||||||
self.display,
|
self.display,
|
||||||
|
@ -191,18 +192,20 @@ impl XConnection {
|
||||||
root,
|
root,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
&mut translated_coords.x_rel_root,
|
&mut coords.x_rel_root,
|
||||||
&mut translated_coords.y_rel_root,
|
&mut coords.y_rel_root,
|
||||||
&mut translated_coords.child,
|
&mut coords.child,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
//println!("XTranslateCoordinates coords:{:?}", translated_coords);
|
|
||||||
self.check_errors().map(|_| translated_coords)
|
self.check_errors()?;
|
||||||
|
Ok(coords)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is adequate for inner_size
|
// This is adequate for inner_size
|
||||||
pub fn get_geometry(&self, window: ffi::Window) -> Result<Geometry, XError> {
|
pub fn get_geometry(&self, window: ffi::Window) -> Result<Geometry, XError> {
|
||||||
let mut geometry: Geometry = unsafe { mem::uninitialized() };
|
let mut geometry = Geometry::default();
|
||||||
|
|
||||||
let _status = unsafe {
|
let _status = unsafe {
|
||||||
(self.xlib.XGetGeometry)(
|
(self.xlib.XGetGeometry)(
|
||||||
self.display,
|
self.display,
|
||||||
|
@ -216,8 +219,9 @@ impl XConnection {
|
||||||
&mut geometry.depth,
|
&mut geometry.depth,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
//println!("XGetGeometry geo:{:?}", geometry);
|
|
||||||
self.check_errors().map(|_| geometry)
|
self.check_errors()?;
|
||||||
|
Ok(geometry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_frame_extents(&self, window: ffi::Window) -> Option<FrameExtents> {
|
fn get_frame_extents(&self, window: ffi::Window) -> Option<FrameExtents> {
|
||||||
|
@ -264,10 +268,10 @@ impl XConnection {
|
||||||
|
|
||||||
fn get_parent_window(&self, window: ffi::Window) -> Result<ffi::Window, XError> {
|
fn get_parent_window(&self, window: ffi::Window) -> Result<ffi::Window, XError> {
|
||||||
let parent = unsafe {
|
let parent = unsafe {
|
||||||
let mut root: ffi::Window = mem::uninitialized();
|
let mut root = 0;
|
||||||
let mut parent: ffi::Window = mem::uninitialized();
|
let mut parent = 0;
|
||||||
let mut children: *mut ffi::Window = ptr::null_mut();
|
let mut children: *mut ffi::Window = ptr::null_mut();
|
||||||
let mut nchildren: c_uint = mem::uninitialized();
|
let mut nchildren = 0;
|
||||||
|
|
||||||
// What's filled into `parent` if `window` is the root window?
|
// What's filled into `parent` if `window` is the root window?
|
||||||
let _status = (self.xlib.XQueryTree)(
|
let _status = (self.xlib.XQueryTree)(
|
||||||
|
|
|
@ -317,13 +317,13 @@ impl XConnection {
|
||||||
|
|
||||||
pub fn get_normal_hints(&self, window: ffi::Window) -> Result<NormalHints<'_>, XError> {
|
pub fn get_normal_hints(&self, window: ffi::Window) -> Result<NormalHints<'_>, XError> {
|
||||||
let size_hints = self.alloc_size_hints();
|
let size_hints = self.alloc_size_hints();
|
||||||
let mut supplied_by_user: c_long = unsafe { mem::uninitialized() };
|
let mut supplied_by_user = MaybeUninit::uninit();
|
||||||
unsafe {
|
unsafe {
|
||||||
(self.xlib.XGetWMNormalHints)(
|
(self.xlib.XGetWMNormalHints)(
|
||||||
self.display,
|
self.display,
|
||||||
window,
|
window,
|
||||||
size_hints.ptr,
|
size_hints.ptr,
|
||||||
&mut supplied_by_user,
|
supplied_by_user.as_mut_ptr(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
self.check_errors().map(|_| NormalHints { size_hints })
|
self.check_errors().map(|_| NormalHints { size_hints })
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::str;
|
use std::{slice, str};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::event::ModifiersState;
|
use crate::event::ModifiersState;
|
||||||
|
@ -23,18 +23,19 @@ impl From<ffi::XIModifierState> for ModifiersState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: Some of these fields are not used, but may be of use in the future.
|
||||||
pub struct PointerState<'a> {
|
pub struct PointerState<'a> {
|
||||||
xconn: &'a XConnection,
|
xconn: &'a XConnection,
|
||||||
root: ffi::Window,
|
pub root: ffi::Window,
|
||||||
child: ffi::Window,
|
pub child: ffi::Window,
|
||||||
pub root_x: c_double,
|
pub root_x: c_double,
|
||||||
pub root_y: c_double,
|
pub root_y: c_double,
|
||||||
win_x: c_double,
|
pub win_x: c_double,
|
||||||
win_y: c_double,
|
pub win_y: c_double,
|
||||||
buttons: ffi::XIButtonState,
|
buttons: ffi::XIButtonState,
|
||||||
modifiers: ffi::XIModifierState,
|
modifiers: ffi::XIModifierState,
|
||||||
group: ffi::XIGroupState,
|
pub group: ffi::XIGroupState,
|
||||||
relative_to_window: bool,
|
pub relative_to_window: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PointerState<'a> {
|
impl<'a> PointerState<'a> {
|
||||||
|
@ -93,29 +94,46 @@ impl XConnection {
|
||||||
device_id: c_int,
|
device_id: c_int,
|
||||||
) -> Result<PointerState<'_>, XError> {
|
) -> Result<PointerState<'_>, XError> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut pointer_state: PointerState<'_> = mem::uninitialized();
|
let mut root = 0;
|
||||||
pointer_state.xconn = self;
|
let mut child = 0;
|
||||||
pointer_state.relative_to_window = (self.xinput2.XIQueryPointer)(
|
let mut root_x = 0.0;
|
||||||
|
let mut root_y = 0.0;
|
||||||
|
let mut win_x = 0.0;
|
||||||
|
let mut win_y = 0.0;
|
||||||
|
let mut buttons = Default::default();
|
||||||
|
let mut modifiers = Default::default();
|
||||||
|
let mut group = Default::default();
|
||||||
|
|
||||||
|
let relative_to_window = (self.xinput2.XIQueryPointer)(
|
||||||
self.display,
|
self.display,
|
||||||
device_id,
|
device_id,
|
||||||
window,
|
window,
|
||||||
&mut pointer_state.root,
|
&mut root,
|
||||||
&mut pointer_state.child,
|
&mut child,
|
||||||
&mut pointer_state.root_x,
|
&mut root_x,
|
||||||
&mut pointer_state.root_y,
|
&mut root_y,
|
||||||
&mut pointer_state.win_x,
|
&mut win_x,
|
||||||
&mut pointer_state.win_y,
|
&mut win_y,
|
||||||
&mut pointer_state.buttons,
|
&mut buttons,
|
||||||
&mut pointer_state.modifiers,
|
&mut modifiers,
|
||||||
&mut pointer_state.group,
|
&mut group,
|
||||||
) == ffi::True;
|
) == ffi::True;
|
||||||
if let Err(err) = self.check_errors() {
|
|
||||||
// Running the destrutor would be bad news for us...
|
self.check_errors()?;
|
||||||
mem::forget(pointer_state);
|
|
||||||
Err(err)
|
Ok(PointerState {
|
||||||
} else {
|
xconn: self,
|
||||||
Ok(pointer_state)
|
root,
|
||||||
}
|
child,
|
||||||
|
root_x,
|
||||||
|
root_y,
|
||||||
|
win_x,
|
||||||
|
win_y,
|
||||||
|
buttons,
|
||||||
|
modifiers,
|
||||||
|
group,
|
||||||
|
relative_to_window,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +141,8 @@ impl XConnection {
|
||||||
&self,
|
&self,
|
||||||
ic: ffi::XIC,
|
ic: ffi::XIC,
|
||||||
key_event: &mut ffi::XKeyEvent,
|
key_event: &mut ffi::XKeyEvent,
|
||||||
buffer: &mut [u8],
|
buffer: *mut u8,
|
||||||
|
size: usize,
|
||||||
) -> (ffi::KeySym, ffi::Status, c_int) {
|
) -> (ffi::KeySym, ffi::Status, c_int) {
|
||||||
let mut keysym: ffi::KeySym = 0;
|
let mut keysym: ffi::KeySym = 0;
|
||||||
let mut status: ffi::Status = 0;
|
let mut status: ffi::Status = 0;
|
||||||
|
@ -131,8 +150,8 @@ impl XConnection {
|
||||||
(self.xlib.Xutf8LookupString)(
|
(self.xlib.Xutf8LookupString)(
|
||||||
ic,
|
ic,
|
||||||
key_event,
|
key_event,
|
||||||
buffer.as_mut_ptr() as *mut c_char,
|
buffer as *mut c_char,
|
||||||
buffer.len() as c_int,
|
size as c_int,
|
||||||
&mut keysym,
|
&mut keysym,
|
||||||
&mut status,
|
&mut status,
|
||||||
)
|
)
|
||||||
|
@ -141,21 +160,28 @@ impl XConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lookup_utf8(&self, ic: ffi::XIC, key_event: &mut ffi::XKeyEvent) -> String {
|
pub fn lookup_utf8(&self, ic: ffi::XIC, key_event: &mut ffi::XKeyEvent) -> String {
|
||||||
let mut buffer: [u8; TEXT_BUFFER_SIZE] = unsafe { mem::uninitialized() };
|
// `assume_init` is safe here because the array consists of `MaybeUninit` values,
|
||||||
let (_, status, count) = self.lookup_utf8_inner(ic, key_event, &mut buffer);
|
// which do not require initialization.
|
||||||
// The buffer overflowed, so we'll make a new one on the heap.
|
let mut buffer: [MaybeUninit<u8>; TEXT_BUFFER_SIZE] =
|
||||||
if status == ffi::XBufferOverflow {
|
unsafe { MaybeUninit::uninit().assume_init() };
|
||||||
let mut buffer = Vec::with_capacity(count as usize);
|
// If the buffer overflows, we'll make a new one on the heap.
|
||||||
unsafe { buffer.set_len(count as usize) };
|
let mut vec;
|
||||||
let (_, _, new_count) = self.lookup_utf8_inner(ic, key_event, &mut buffer);
|
|
||||||
|
let (_, status, count) =
|
||||||
|
self.lookup_utf8_inner(ic, key_event, buffer.as_mut_ptr() as *mut u8, buffer.len());
|
||||||
|
|
||||||
|
let bytes = if status == ffi::XBufferOverflow {
|
||||||
|
vec = Vec::with_capacity(count as usize);
|
||||||
|
let (_, _, new_count) =
|
||||||
|
self.lookup_utf8_inner(ic, key_event, vec.as_mut_ptr(), vec.capacity());
|
||||||
debug_assert_eq!(count, new_count);
|
debug_assert_eq!(count, new_count);
|
||||||
str::from_utf8(&buffer[..count as usize])
|
|
||||||
.unwrap_or("")
|
unsafe { vec.set_len(count as usize) };
|
||||||
.to_string()
|
&vec[..count as usize]
|
||||||
} else {
|
} else {
|
||||||
str::from_utf8(&buffer[..count as usize])
|
unsafe { slice::from_raw_parts(buffer.as_ptr() as *const u8, count as usize) }
|
||||||
.unwrap_or("")
|
};
|
||||||
.to_string()
|
|
||||||
}
|
str::from_utf8(bytes).unwrap_or("").to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,12 @@ pub use self::{
|
||||||
randr::*, window_property::*, wm::*,
|
randr::*, window_property::*, wm::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::{mem, ops::BitAnd, os::raw::*, ptr};
|
use std::{
|
||||||
|
mem::{self, MaybeUninit},
|
||||||
|
ops::BitAnd,
|
||||||
|
os::raw::*,
|
||||||
|
ptr,
|
||||||
|
};
|
||||||
|
|
||||||
use super::{ffi, XConnection, XError};
|
use super::{ffi, XConnection, XError};
|
||||||
|
|
||||||
|
|
|
@ -43,13 +43,14 @@ impl XConnection {
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
|
|
||||||
let mut done = false;
|
let mut done = false;
|
||||||
|
let mut actual_type = 0;
|
||||||
|
let mut actual_format = 0;
|
||||||
|
let mut quantity_returned = 0;
|
||||||
|
let mut bytes_after = 0;
|
||||||
|
let mut buf: *mut c_uchar = ptr::null_mut();
|
||||||
|
|
||||||
while !done {
|
while !done {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut actual_type: ffi::Atom = mem::uninitialized();
|
|
||||||
let mut actual_format: c_int = mem::uninitialized();
|
|
||||||
let mut quantity_returned: c_ulong = mem::uninitialized();
|
|
||||||
let mut bytes_after: c_ulong = mem::uninitialized();
|
|
||||||
let mut buf: *mut c_uchar = ptr::null_mut();
|
|
||||||
(self.xlib.XGetWindowProperty)(
|
(self.xlib.XGetWindowProperty)(
|
||||||
self.display,
|
self.display,
|
||||||
window,
|
window,
|
||||||
|
|
|
@ -1,4 +1,14 @@
|
||||||
use std::{cmp, collections::HashSet, env, ffi::CString, mem, os::raw::*, path::Path, sync::Arc};
|
use std::{
|
||||||
|
cmp,
|
||||||
|
collections::HashSet,
|
||||||
|
env,
|
||||||
|
ffi::CString,
|
||||||
|
mem::{self, MaybeUninit},
|
||||||
|
os::raw::*,
|
||||||
|
path::Path,
|
||||||
|
ptr, slice,
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
use libc;
|
use libc;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
@ -410,11 +420,11 @@ impl UnownedWindow {
|
||||||
unsafe {
|
unsafe {
|
||||||
// XSetInputFocus generates an error if the window is not visible, so we wait
|
// XSetInputFocus generates an error if the window is not visible, so we wait
|
||||||
// until we receive VisibilityNotify.
|
// until we receive VisibilityNotify.
|
||||||
let mut event = mem::uninitialized();
|
let mut event = MaybeUninit::uninit();
|
||||||
(xconn.xlib.XIfEvent)(
|
(xconn.xlib.XIfEvent)(
|
||||||
// This will flush the request buffer IF it blocks.
|
// This will flush the request buffer IF it blocks.
|
||||||
xconn.display,
|
xconn.display,
|
||||||
&mut event as *mut ffi::XEvent,
|
event.as_mut_ptr(),
|
||||||
Some(visibility_predicate),
|
Some(visibility_predicate),
|
||||||
window.xwindow as _,
|
window.xwindow as _,
|
||||||
);
|
);
|
||||||
|
@ -449,19 +459,22 @@ impl UnownedWindow {
|
||||||
let pid_atom = unsafe { self.xconn.get_atom_unchecked(b"_NET_WM_PID\0") };
|
let pid_atom = unsafe { self.xconn.get_atom_unchecked(b"_NET_WM_PID\0") };
|
||||||
let client_machine_atom = unsafe { self.xconn.get_atom_unchecked(b"WM_CLIENT_MACHINE\0") };
|
let client_machine_atom = unsafe { self.xconn.get_atom_unchecked(b"WM_CLIENT_MACHINE\0") };
|
||||||
unsafe {
|
unsafe {
|
||||||
let (hostname, hostname_length) = {
|
|
||||||
// 64 would suffice for Linux, but 256 will be enough everywhere (as per SUSv2). For instance, this is
|
// 64 would suffice for Linux, but 256 will be enough everywhere (as per SUSv2). For instance, this is
|
||||||
// the limit defined by OpenBSD.
|
// the limit defined by OpenBSD.
|
||||||
const MAXHOSTNAMELEN: usize = 256;
|
const MAXHOSTNAMELEN: usize = 256;
|
||||||
let mut hostname: [c_char; MAXHOSTNAMELEN] = mem::uninitialized();
|
// `assume_init` is safe here because the array consists of `MaybeUninit` values,
|
||||||
let status = libc::gethostname(hostname.as_mut_ptr(), hostname.len());
|
// which do not require initialization.
|
||||||
|
let mut buffer: [MaybeUninit<c_char>; MAXHOSTNAMELEN] =
|
||||||
|
MaybeUninit::uninit().assume_init();
|
||||||
|
let status = libc::gethostname(buffer.as_mut_ptr() as *mut c_char, buffer.len());
|
||||||
if status != 0 {
|
if status != 0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
hostname[MAXHOSTNAMELEN - 1] = '\0' as c_char; // a little extra safety
|
ptr::write(buffer[MAXHOSTNAMELEN - 1].as_mut_ptr() as *mut u8, b'\0'); // a little extra safety
|
||||||
let hostname_length = libc::strlen(hostname.as_ptr());
|
let hostname_length = libc::strlen(buffer.as_ptr() as *const c_char);
|
||||||
(hostname, hostname_length as usize)
|
|
||||||
};
|
let hostname = slice::from_raw_parts(buffer.as_ptr() as *const c_char, hostname_length);
|
||||||
|
|
||||||
self.xconn
|
self.xconn
|
||||||
.change_property(
|
.change_property(
|
||||||
self.xwindow,
|
self.xwindow,
|
||||||
|
@ -1134,13 +1147,13 @@ impl UnownedWindow {
|
||||||
let cursor = unsafe {
|
let cursor = unsafe {
|
||||||
// We don't care about this color, since it only fills bytes
|
// We don't care about this color, since it only fills bytes
|
||||||
// in the pixmap which are not 0 in the mask.
|
// in the pixmap which are not 0 in the mask.
|
||||||
let dummy_color: ffi::XColor = mem::uninitialized();
|
let mut dummy_color = MaybeUninit::uninit();
|
||||||
let cursor = (self.xconn.xlib.XCreatePixmapCursor)(
|
let cursor = (self.xconn.xlib.XCreatePixmapCursor)(
|
||||||
self.xconn.display,
|
self.xconn.display,
|
||||||
pixmap,
|
pixmap,
|
||||||
pixmap,
|
pixmap,
|
||||||
&dummy_color as *const _ as *mut _,
|
dummy_color.as_mut_ptr(),
|
||||||
&dummy_color as *const _ as *mut _,
|
dummy_color.as_mut_ptr(),
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Reference in a new issue