X11: Fix request_redraw not waking the event loop (#1756)

This commit is contained in:
Murarth 2020-11-05 16:42:03 -07:00 committed by GitHub
parent 3a077ff211
commit 45e4fd6ec1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 38 deletions

View file

@ -9,6 +9,7 @@
- On Windows, fix use after free crash during window destruction.
- On Web, fix `WindowEvent::ReceivedCharacter` never being sent on key input.
- On macOS, fix compilation when targeting aarch64
- On X11, fix `Window::request_redraw` not waking the event loop.
# 0.23.0 (2020-10-02)

View file

@ -24,7 +24,7 @@ pub use self::{
use std::{
cell::RefCell,
collections::{HashMap, HashSet},
collections::HashMap,
ffi::CStr,
mem::{self, MaybeUninit},
ops::Deref,
@ -32,7 +32,7 @@ use std::{
ptr,
rc::Rc,
slice,
sync::{mpsc, Arc, Mutex, Weak},
sync::{mpsc, Arc, Weak},
time::{Duration, Instant},
};
@ -58,6 +58,7 @@ use crate::{
const X_TOKEN: Token = Token(0);
const USER_TOKEN: Token = Token(1);
const REDRAW_TOKEN: Token = Token(2);
pub struct EventLoopWindowTarget<T> {
xconn: Arc<XConnection>,
@ -67,13 +68,14 @@ pub struct EventLoopWindowTarget<T> {
root: ffi::Window,
ime: RefCell<Ime>,
windows: RefCell<HashMap<WindowId, Weak<UnownedWindow>>>,
pending_redraws: Arc<Mutex<HashSet<WindowId>>>,
redraw_sender: Sender<WindowId>,
_marker: ::std::marker::PhantomData<T>,
}
pub struct EventLoop<T: 'static> {
poll: Poll,
event_processor: EventProcessor<T>,
redraw_channel: Receiver<WindowId>,
user_channel: Receiver<T>,
user_sender: Sender<T>,
target: Rc<RootELW<T>>,
@ -174,32 +176,16 @@ impl<T: 'static> EventLoop<T> {
xconn.update_cached_wm_info(root);
let pending_redraws: Arc<Mutex<HashSet<WindowId>>> = Default::default();
let mut mod_keymap = ModifierKeymap::new();
mod_keymap.reset_from_x_connection(&xconn);
let target = Rc::new(RootELW {
p: super::EventLoopWindowTarget::X(EventLoopWindowTarget {
ime,
root,
windows: Default::default(),
_marker: ::std::marker::PhantomData,
ime_sender,
xconn,
wm_delete_window,
net_wm_ping,
pending_redraws: pending_redraws.clone(),
}),
_marker: ::std::marker::PhantomData,
});
let poll = Poll::new().unwrap();
let (user_sender, user_channel) = channel();
let (redraw_sender, redraw_channel) = channel();
poll.register(
&EventedFd(&get_xtarget(&target).xconn.x11_fd),
&EventedFd(&xconn.x11_fd),
X_TOKEN,
Ready::readable(),
PollOpt::level(),
@ -214,6 +200,29 @@ impl<T: 'static> EventLoop<T> {
)
.unwrap();
poll.register(
&redraw_channel,
REDRAW_TOKEN,
Ready::readable(),
PollOpt::level(),
)
.unwrap();
let target = Rc::new(RootELW {
p: super::EventLoopWindowTarget::X(EventLoopWindowTarget {
ime,
root,
windows: Default::default(),
_marker: ::std::marker::PhantomData,
ime_sender,
xconn,
wm_delete_window,
net_wm_ping,
redraw_sender,
}),
_marker: ::std::marker::PhantomData,
});
let event_processor = EventProcessor {
target: target.clone(),
dnd,
@ -239,6 +248,7 @@ impl<T: 'static> EventLoop<T> {
let result = EventLoop {
poll,
redraw_channel,
user_channel,
user_sender,
event_processor,
@ -277,8 +287,6 @@ impl<T: 'static> EventLoop<T> {
// Process all pending events
self.drain_events(&mut callback, &mut control_flow);
let wt = get_xtarget(&self.target);
// Empty the user event buffer
{
while let Ok(event) = self.user_channel.try_recv() {
@ -301,12 +309,10 @@ impl<T: 'static> EventLoop<T> {
}
// Empty the redraw requests
{
// Release the lock to prevent deadlock
let windows: Vec<_> = wt.pending_redraws.lock().unwrap().drain().collect();
for wid in windows {
while let Ok(window_id) = self.redraw_channel.try_recv() {
let window_id = crate::window::WindowId(super::WindowId::X(window_id));
sticky_exit_callback(
Event::RedrawRequested(crate::window::WindowId(super::WindowId::X(wid))),
Event::RedrawRequested(window_id),
&self.target,
&mut control_flow,
&mut callback,
@ -408,7 +414,7 @@ impl<T: 'static> EventLoop<T> {
super::WindowId::X(wid),
)) = event
{
wt.pending_redraws.lock().unwrap().insert(wid);
wt.redraw_sender.send(wid).unwrap();
} else {
callback(event, window_target, control_flow);
}

View file

@ -1,8 +1,6 @@
use raw_window_handle::unix::XlibHandle;
use std::{
cmp,
collections::HashSet,
env,
cmp, env,
ffi::CString,
mem::{self, replace, MaybeUninit},
os::raw::*,
@ -12,6 +10,7 @@ use std::{
};
use libc;
use mio_extras::channel::Sender;
use parking_lot::Mutex;
use crate::{
@ -104,7 +103,7 @@ pub struct UnownedWindow {
cursor_visible: Mutex<bool>,
ime_sender: Mutex<ImeSender>,
pub shared_state: Mutex<SharedState>,
pending_redraws: Arc<::std::sync::Mutex<HashSet<WindowId>>>,
redraw_sender: Sender<WindowId>,
}
impl UnownedWindow {
@ -249,7 +248,7 @@ impl UnownedWindow {
cursor_visible: Mutex::new(true),
ime_sender: Mutex::new(event_loop.ime_sender.clone()),
shared_state: SharedState::new(guessed_monitor, window_attrs.visible),
pending_redraws: event_loop.pending_redraws.clone(),
redraw_sender: event_loop.redraw_sender.clone(),
};
// Title must be set before mapping. Some tiling window managers (i.e. i3) use the window
@ -1314,10 +1313,7 @@ impl UnownedWindow {
#[inline]
pub fn request_redraw(&self) {
self.pending_redraws
.lock()
.unwrap()
.insert(WindowId(self.xwindow));
self.redraw_sender.send(WindowId(self.xwindow)).unwrap();
}
#[inline]