mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-26 03:36:32 +11:00
Fix X11 memory leak and remove mio-misc (#1987)
* Fix X11 memory leak and remove mio-misc I also fixed a couple of clippy lints. Fixes #1984 * Send the redraw event before waking up the main event * Use .map instead of a match, and remove comments saved by git * Remove unnecessary pub keywords on `WakeSender` in x11/mod.rs
This commit is contained in:
parent
125ee0b446
commit
9e72396709
3 changed files with 45 additions and 38 deletions
|
@ -18,7 +18,7 @@ targets = ["i686-pc-windows-msvc", "x86_64-pc-windows-msvc", "i686-unknown-linux
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["x11", "wayland"]
|
default = ["x11", "wayland"]
|
||||||
x11 = ["x11-dl", "mio", "mio-misc", "percent-encoding", "parking_lot"]
|
x11 = ["x11-dl", "mio", "percent-encoding", "parking_lot"]
|
||||||
wayland = ["wayland-client", "wayland-protocols", "sctk"]
|
wayland = ["wayland-client", "wayland-protocols", "sctk"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -87,7 +87,6 @@ wayland-client = { version = "0.29", features = [ "dlopen"], optional = true }
|
||||||
wayland-protocols = { version = "0.29", features = [ "staging_protocols"], optional = true }
|
wayland-protocols = { version = "0.29", features = [ "staging_protocols"], optional = true }
|
||||||
sctk = { package = "smithay-client-toolkit", version = "0.15.0", optional = true }
|
sctk = { package = "smithay-client-toolkit", version = "0.15.0", optional = true }
|
||||||
mio = { version = "0.7", features = ["os-ext"], optional = true }
|
mio = { version = "0.7", features = ["os-ext"], optional = true }
|
||||||
mio-misc = { version = "1.0", optional = true }
|
|
||||||
x11-dl = { version = "2.18.5", optional = true }
|
x11-dl = { version = "2.18.5", optional = true }
|
||||||
percent-encoding = { version = "2.0", optional = true }
|
percent-encoding = { version = "2.0", optional = true }
|
||||||
parking_lot = { version = "0.11.0", optional = true }
|
parking_lot = { version = "0.11.0", optional = true }
|
||||||
|
|
|
@ -32,7 +32,7 @@ use std::{
|
||||||
ptr,
|
ptr,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
slice,
|
slice,
|
||||||
sync::mpsc::Receiver,
|
sync::mpsc::{Receiver, Sender},
|
||||||
sync::{mpsc, Arc, Weak},
|
sync::{mpsc, Arc, Weak},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
@ -41,12 +41,6 @@ use libc::{self, setlocale, LC_CTYPE};
|
||||||
|
|
||||||
use mio::{unix::SourceFd, Events, Interest, Poll, Token, Waker};
|
use mio::{unix::SourceFd, Events, Interest, Poll, Token, Waker};
|
||||||
|
|
||||||
use mio_misc::{
|
|
||||||
channel::{channel, SendError, Sender},
|
|
||||||
queue::NotificationQueue,
|
|
||||||
NotificationId,
|
|
||||||
};
|
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
dnd::{Dnd, DndState},
|
dnd::{Dnd, DndState},
|
||||||
event_processor::EventProcessor,
|
event_processor::EventProcessor,
|
||||||
|
@ -64,6 +58,11 @@ use crate::{
|
||||||
const X_TOKEN: Token = Token(0);
|
const X_TOKEN: Token = Token(0);
|
||||||
const USER_REDRAW_TOKEN: Token = Token(1);
|
const USER_REDRAW_TOKEN: Token = Token(1);
|
||||||
|
|
||||||
|
struct WakeSender<T> {
|
||||||
|
sender: Sender<T>,
|
||||||
|
waker: Arc<Waker>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct EventLoopWindowTarget<T> {
|
pub struct EventLoopWindowTarget<T> {
|
||||||
xconn: Arc<XConnection>,
|
xconn: Arc<XConnection>,
|
||||||
wm_delete_window: ffi::Atom,
|
wm_delete_window: ffi::Atom,
|
||||||
|
@ -72,27 +71,30 @@ pub struct EventLoopWindowTarget<T> {
|
||||||
root: ffi::Window,
|
root: ffi::Window,
|
||||||
ime: RefCell<Ime>,
|
ime: RefCell<Ime>,
|
||||||
windows: RefCell<HashMap<WindowId, Weak<UnownedWindow>>>,
|
windows: RefCell<HashMap<WindowId, Weak<UnownedWindow>>>,
|
||||||
redraw_sender: Sender<WindowId>,
|
redraw_sender: WakeSender<WindowId>,
|
||||||
_marker: ::std::marker::PhantomData<T>,
|
_marker: ::std::marker::PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EventLoop<T: 'static> {
|
pub struct EventLoop<T: 'static> {
|
||||||
poll: Poll,
|
poll: Poll,
|
||||||
|
waker: Arc<Waker>,
|
||||||
event_processor: EventProcessor<T>,
|
event_processor: EventProcessor<T>,
|
||||||
redraw_channel: Receiver<WindowId>,
|
redraw_channel: Receiver<WindowId>,
|
||||||
user_channel: Receiver<T>,
|
user_channel: Receiver<T>, //waker.wake needs to be called whenever something gets sent
|
||||||
user_sender: Sender<T>,
|
user_sender: Sender<T>,
|
||||||
target: Rc<RootELW<T>>,
|
target: Rc<RootELW<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EventLoopProxy<T: 'static> {
|
pub struct EventLoopProxy<T: 'static> {
|
||||||
user_sender: Sender<T>,
|
user_sender: Sender<T>,
|
||||||
|
waker: Arc<Waker>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: 'static> Clone for EventLoopProxy<T> {
|
impl<T: 'static> Clone for EventLoopProxy<T> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
EventLoopProxy {
|
EventLoopProxy {
|
||||||
user_sender: self.user_sender.clone(),
|
user_sender: self.user_sender.clone(),
|
||||||
|
waker: self.waker.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -185,15 +187,13 @@ impl<T: 'static> EventLoop<T> {
|
||||||
|
|
||||||
let poll = Poll::new().unwrap();
|
let poll = Poll::new().unwrap();
|
||||||
let waker = Arc::new(Waker::new(poll.registry(), USER_REDRAW_TOKEN).unwrap());
|
let waker = Arc::new(Waker::new(poll.registry(), USER_REDRAW_TOKEN).unwrap());
|
||||||
let queue = Arc::new(NotificationQueue::new(waker));
|
|
||||||
|
|
||||||
poll.registry()
|
poll.registry()
|
||||||
.register(&mut SourceFd(&xconn.x11_fd), X_TOKEN, Interest::READABLE)
|
.register(&mut SourceFd(&xconn.x11_fd), X_TOKEN, Interest::READABLE)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let (user_sender, user_channel) = channel(queue.clone(), NotificationId::gen_next());
|
let (user_sender, user_channel) = std::sync::mpsc::channel();
|
||||||
|
let (redraw_sender, redraw_channel) = std::sync::mpsc::channel();
|
||||||
let (redraw_sender, redraw_channel) = channel(queue, NotificationId::gen_next());
|
|
||||||
|
|
||||||
let target = Rc::new(RootELW {
|
let target = Rc::new(RootELW {
|
||||||
p: super::EventLoopWindowTarget::X(EventLoopWindowTarget {
|
p: super::EventLoopWindowTarget::X(EventLoopWindowTarget {
|
||||||
|
@ -205,7 +205,10 @@ impl<T: 'static> EventLoop<T> {
|
||||||
xconn,
|
xconn,
|
||||||
wm_delete_window,
|
wm_delete_window,
|
||||||
net_wm_ping,
|
net_wm_ping,
|
||||||
redraw_sender,
|
redraw_sender: WakeSender {
|
||||||
|
sender: redraw_sender, // not used again so no clone
|
||||||
|
waker: waker.clone(),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
_marker: ::std::marker::PhantomData,
|
_marker: ::std::marker::PhantomData,
|
||||||
});
|
});
|
||||||
|
@ -233,21 +236,21 @@ impl<T: 'static> EventLoop<T> {
|
||||||
|
|
||||||
event_processor.init_device(ffi::XIAllDevices);
|
event_processor.init_device(ffi::XIAllDevices);
|
||||||
|
|
||||||
let result = EventLoop {
|
EventLoop {
|
||||||
poll,
|
poll,
|
||||||
|
waker,
|
||||||
|
event_processor,
|
||||||
redraw_channel,
|
redraw_channel,
|
||||||
user_channel,
|
user_channel,
|
||||||
user_sender,
|
user_sender,
|
||||||
event_processor,
|
|
||||||
target,
|
target,
|
||||||
};
|
}
|
||||||
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_proxy(&self) -> EventLoopProxy<T> {
|
pub fn create_proxy(&self) -> EventLoopProxy<T> {
|
||||||
EventLoopProxy {
|
EventLoopProxy {
|
||||||
user_sender: self.user_sender.clone(),
|
user_sender: self.user_sender.clone(),
|
||||||
|
waker: self.waker.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,7 +395,6 @@ impl<T: 'static> EventLoop<T> {
|
||||||
{
|
{
|
||||||
let target = &self.target;
|
let target = &self.target;
|
||||||
let mut xev = MaybeUninit::uninit();
|
let mut xev = MaybeUninit::uninit();
|
||||||
|
|
||||||
let wt = get_xtarget(&self.target);
|
let wt = get_xtarget(&self.target);
|
||||||
|
|
||||||
while unsafe { self.event_processor.poll_one_event(xev.as_mut_ptr()) } {
|
while unsafe { self.event_processor.poll_one_event(xev.as_mut_ptr()) } {
|
||||||
|
@ -407,7 +409,8 @@ impl<T: 'static> EventLoop<T> {
|
||||||
super::WindowId::X(wid),
|
super::WindowId::X(wid),
|
||||||
)) = event
|
)) = event
|
||||||
{
|
{
|
||||||
wt.redraw_sender.send(wid).unwrap();
|
wt.redraw_sender.sender.send(wid).unwrap();
|
||||||
|
wt.redraw_sender.waker.wake().unwrap();
|
||||||
} else {
|
} else {
|
||||||
callback(event, window_target, control_flow);
|
callback(event, window_target, control_flow);
|
||||||
}
|
}
|
||||||
|
@ -436,13 +439,10 @@ impl<T> EventLoopWindowTarget<T> {
|
||||||
|
|
||||||
impl<T: 'static> EventLoopProxy<T> {
|
impl<T: 'static> EventLoopProxy<T> {
|
||||||
pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed<T>> {
|
pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed<T>> {
|
||||||
self.user_sender.send(event).map_err(|e| {
|
self.user_sender
|
||||||
EventLoopClosed(if let SendError::Disconnected(x) = e {
|
.send(event)
|
||||||
x
|
.map_err(|e| EventLoopClosed(e.0))
|
||||||
} else {
|
.map(|_| self.waker.wake().unwrap())
|
||||||
unreachable!()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,7 +520,7 @@ impl Window {
|
||||||
attribs: WindowAttributes,
|
attribs: WindowAttributes,
|
||||||
pl_attribs: PlatformSpecificWindowBuilderAttributes,
|
pl_attribs: PlatformSpecificWindowBuilderAttributes,
|
||||||
) -> Result<Self, RootOsError> {
|
) -> Result<Self, RootOsError> {
|
||||||
let window = Arc::new(UnownedWindow::new(&event_loop, attribs, pl_attribs)?);
|
let window = Arc::new(UnownedWindow::new(event_loop, attribs, pl_attribs)?);
|
||||||
event_loop
|
event_loop
|
||||||
.windows
|
.windows
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
|
|
|
@ -11,7 +11,6 @@ use std::{
|
||||||
use x11_dl::xlib::TrueColor;
|
use x11_dl::xlib::TrueColor;
|
||||||
|
|
||||||
use libc;
|
use libc;
|
||||||
use mio_misc::channel::Sender;
|
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -26,7 +25,9 @@ use crate::{
|
||||||
window::{CursorIcon, Fullscreen, Icon, UserAttentionType, WindowAttributes},
|
window::{CursorIcon, Fullscreen, Icon, UserAttentionType, WindowAttributes},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{ffi, util, EventLoopWindowTarget, ImeSender, WindowId, XConnection, XError};
|
use super::{
|
||||||
|
ffi, util, EventLoopWindowTarget, ImeSender, WakeSender, WindowId, XConnection, XError,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SharedState {
|
pub struct SharedState {
|
||||||
|
@ -104,7 +105,7 @@ pub struct UnownedWindow {
|
||||||
cursor_visible: Mutex<bool>,
|
cursor_visible: Mutex<bool>,
|
||||||
ime_sender: Mutex<ImeSender>,
|
ime_sender: Mutex<ImeSender>,
|
||||||
pub shared_state: Mutex<SharedState>,
|
pub shared_state: Mutex<SharedState>,
|
||||||
redraw_sender: Sender<WindowId>,
|
redraw_sender: WakeSender<WindowId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UnownedWindow {
|
impl UnownedWindow {
|
||||||
|
@ -274,7 +275,10 @@ impl UnownedWindow {
|
||||||
cursor_visible: Mutex::new(true),
|
cursor_visible: Mutex::new(true),
|
||||||
ime_sender: Mutex::new(event_loop.ime_sender.clone()),
|
ime_sender: Mutex::new(event_loop.ime_sender.clone()),
|
||||||
shared_state: SharedState::new(guessed_monitor, window_attrs.visible),
|
shared_state: SharedState::new(guessed_monitor, window_attrs.visible),
|
||||||
redraw_sender: event_loop.redraw_sender.clone(),
|
redraw_sender: WakeSender {
|
||||||
|
waker: event_loop.redraw_sender.waker.clone(),
|
||||||
|
sender: event_loop.redraw_sender.sender.clone(),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Title must be set before mapping. Some tiling window managers (i.e. i3) use the window
|
// Title must be set before mapping. Some tiling window managers (i.e. i3) use the window
|
||||||
|
@ -1102,7 +1106,7 @@ impl UnownedWindow {
|
||||||
|
|
||||||
fn update_normal_hints<F>(&self, callback: F) -> Result<(), XError>
|
fn update_normal_hints<F>(&self, callback: F) -> Result<(), XError>
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut util::NormalHints<'_>) -> (),
|
F: FnOnce(&mut util::NormalHints<'_>),
|
||||||
{
|
{
|
||||||
let mut normal_hints = self.xconn.get_normal_hints(self.xwindow)?;
|
let mut normal_hints = self.xconn.get_normal_hints(self.xwindow)?;
|
||||||
callback(&mut normal_hints);
|
callback(&mut normal_hints);
|
||||||
|
@ -1183,7 +1187,7 @@ impl UnownedWindow {
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let window_size = Some(Size::from(self.inner_size()));
|
let window_size = Some(Size::from(self.inner_size()));
|
||||||
(window_size.clone(), window_size)
|
(window_size, window_size)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.set_maximizable_inner(resizable).queue();
|
self.set_maximizable_inner(resizable).queue();
|
||||||
|
@ -1445,7 +1449,11 @@ impl UnownedWindow {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn request_redraw(&self) {
|
pub fn request_redraw(&self) {
|
||||||
self.redraw_sender.send(WindowId(self.xwindow)).unwrap();
|
self.redraw_sender
|
||||||
|
.sender
|
||||||
|
.send(WindowId(self.xwindow))
|
||||||
|
.unwrap();
|
||||||
|
self.redraw_sender.waker.wake().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
Loading…
Add table
Reference in a new issue