mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 22:01:31 +11:00
X11: Fix request_redraw
not waking the event loop (#1756)
This commit is contained in:
parent
3a077ff211
commit
45e4fd6ec1
|
@ -9,6 +9,7 @@
|
||||||
- On Windows, fix use after free crash during window destruction.
|
- On Windows, fix use after free crash during window destruction.
|
||||||
- On Web, fix `WindowEvent::ReceivedCharacter` never being sent on key input.
|
- On Web, fix `WindowEvent::ReceivedCharacter` never being sent on key input.
|
||||||
- On macOS, fix compilation when targeting aarch64
|
- On macOS, fix compilation when targeting aarch64
|
||||||
|
- On X11, fix `Window::request_redraw` not waking the event loop.
|
||||||
|
|
||||||
# 0.23.0 (2020-10-02)
|
# 0.23.0 (2020-10-02)
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub use self::{
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::{HashMap, HashSet},
|
collections::HashMap,
|
||||||
ffi::CStr,
|
ffi::CStr,
|
||||||
mem::{self, MaybeUninit},
|
mem::{self, MaybeUninit},
|
||||||
ops::Deref,
|
ops::Deref,
|
||||||
|
@ -32,7 +32,7 @@ use std::{
|
||||||
ptr,
|
ptr,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
slice,
|
slice,
|
||||||
sync::{mpsc, Arc, Mutex, Weak},
|
sync::{mpsc, Arc, Weak},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@ use crate::{
|
||||||
|
|
||||||
const X_TOKEN: Token = Token(0);
|
const X_TOKEN: Token = Token(0);
|
||||||
const USER_TOKEN: Token = Token(1);
|
const USER_TOKEN: Token = Token(1);
|
||||||
|
const REDRAW_TOKEN: Token = Token(2);
|
||||||
|
|
||||||
pub struct EventLoopWindowTarget<T> {
|
pub struct EventLoopWindowTarget<T> {
|
||||||
xconn: Arc<XConnection>,
|
xconn: Arc<XConnection>,
|
||||||
|
@ -67,13 +68,14 @@ 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>>>,
|
||||||
pending_redraws: Arc<Mutex<HashSet<WindowId>>>,
|
redraw_sender: Sender<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,
|
||||||
event_processor: EventProcessor<T>,
|
event_processor: EventProcessor<T>,
|
||||||
|
redraw_channel: Receiver<WindowId>,
|
||||||
user_channel: Receiver<T>,
|
user_channel: Receiver<T>,
|
||||||
user_sender: Sender<T>,
|
user_sender: Sender<T>,
|
||||||
target: Rc<RootELW<T>>,
|
target: Rc<RootELW<T>>,
|
||||||
|
@ -174,32 +176,16 @@ impl<T: 'static> EventLoop<T> {
|
||||||
|
|
||||||
xconn.update_cached_wm_info(root);
|
xconn.update_cached_wm_info(root);
|
||||||
|
|
||||||
let pending_redraws: Arc<Mutex<HashSet<WindowId>>> = Default::default();
|
|
||||||
|
|
||||||
let mut mod_keymap = ModifierKeymap::new();
|
let mut mod_keymap = ModifierKeymap::new();
|
||||||
mod_keymap.reset_from_x_connection(&xconn);
|
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 poll = Poll::new().unwrap();
|
||||||
|
|
||||||
let (user_sender, user_channel) = channel();
|
let (user_sender, user_channel) = channel();
|
||||||
|
let (redraw_sender, redraw_channel) = channel();
|
||||||
|
|
||||||
poll.register(
|
poll.register(
|
||||||
&EventedFd(&get_xtarget(&target).xconn.x11_fd),
|
&EventedFd(&xconn.x11_fd),
|
||||||
X_TOKEN,
|
X_TOKEN,
|
||||||
Ready::readable(),
|
Ready::readable(),
|
||||||
PollOpt::level(),
|
PollOpt::level(),
|
||||||
|
@ -214,6 +200,29 @@ impl<T: 'static> EventLoop<T> {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.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 {
|
let event_processor = EventProcessor {
|
||||||
target: target.clone(),
|
target: target.clone(),
|
||||||
dnd,
|
dnd,
|
||||||
|
@ -239,6 +248,7 @@ impl<T: 'static> EventLoop<T> {
|
||||||
|
|
||||||
let result = EventLoop {
|
let result = EventLoop {
|
||||||
poll,
|
poll,
|
||||||
|
redraw_channel,
|
||||||
user_channel,
|
user_channel,
|
||||||
user_sender,
|
user_sender,
|
||||||
event_processor,
|
event_processor,
|
||||||
|
@ -277,8 +287,6 @@ impl<T: 'static> EventLoop<T> {
|
||||||
// Process all pending events
|
// Process all pending events
|
||||||
self.drain_events(&mut callback, &mut control_flow);
|
self.drain_events(&mut callback, &mut control_flow);
|
||||||
|
|
||||||
let wt = get_xtarget(&self.target);
|
|
||||||
|
|
||||||
// Empty the user event buffer
|
// Empty the user event buffer
|
||||||
{
|
{
|
||||||
while let Ok(event) = self.user_channel.try_recv() {
|
while let Ok(event) = self.user_channel.try_recv() {
|
||||||
|
@ -301,12 +309,10 @@ impl<T: 'static> EventLoop<T> {
|
||||||
}
|
}
|
||||||
// Empty the redraw requests
|
// Empty the redraw requests
|
||||||
{
|
{
|
||||||
// Release the lock to prevent deadlock
|
while let Ok(window_id) = self.redraw_channel.try_recv() {
|
||||||
let windows: Vec<_> = wt.pending_redraws.lock().unwrap().drain().collect();
|
let window_id = crate::window::WindowId(super::WindowId::X(window_id));
|
||||||
|
|
||||||
for wid in windows {
|
|
||||||
sticky_exit_callback(
|
sticky_exit_callback(
|
||||||
Event::RedrawRequested(crate::window::WindowId(super::WindowId::X(wid))),
|
Event::RedrawRequested(window_id),
|
||||||
&self.target,
|
&self.target,
|
||||||
&mut control_flow,
|
&mut control_flow,
|
||||||
&mut callback,
|
&mut callback,
|
||||||
|
@ -408,7 +414,7 @@ impl<T: 'static> EventLoop<T> {
|
||||||
super::WindowId::X(wid),
|
super::WindowId::X(wid),
|
||||||
)) = event
|
)) = event
|
||||||
{
|
{
|
||||||
wt.pending_redraws.lock().unwrap().insert(wid);
|
wt.redraw_sender.send(wid).unwrap();
|
||||||
} else {
|
} else {
|
||||||
callback(event, window_target, control_flow);
|
callback(event, window_target, control_flow);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
use raw_window_handle::unix::XlibHandle;
|
use raw_window_handle::unix::XlibHandle;
|
||||||
use std::{
|
use std::{
|
||||||
cmp,
|
cmp, env,
|
||||||
collections::HashSet,
|
|
||||||
env,
|
|
||||||
ffi::CString,
|
ffi::CString,
|
||||||
mem::{self, replace, MaybeUninit},
|
mem::{self, replace, MaybeUninit},
|
||||||
os::raw::*,
|
os::raw::*,
|
||||||
|
@ -12,6 +10,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use libc;
|
use libc;
|
||||||
|
use mio_extras::channel::Sender;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -104,7 +103,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>,
|
||||||
pending_redraws: Arc<::std::sync::Mutex<HashSet<WindowId>>>,
|
redraw_sender: Sender<WindowId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UnownedWindow {
|
impl UnownedWindow {
|
||||||
|
@ -249,7 +248,7 @@ 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),
|
||||||
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
|
// Title must be set before mapping. Some tiling window managers (i.e. i3) use the window
|
||||||
|
@ -1314,10 +1313,7 @@ impl UnownedWindow {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn request_redraw(&self) {
|
pub fn request_redraw(&self) {
|
||||||
self.pending_redraws
|
self.redraw_sender.send(WindowId(self.xwindow)).unwrap();
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.insert(WindowId(self.xwindow));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
Loading…
Reference in a new issue