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:
Davester47 2021-08-24 03:38:56 -07:00 committed by GitHub
parent 125ee0b446
commit 9e72396709
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 38 deletions

View file

@ -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 }

View file

@ -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()

View file

@ -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]