mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-12 05:31:31 +11:00
Merge pull request #250 from Osspial/master
Fix window contents not resizing in lockstep with window resize on win32
This commit is contained in:
commit
4202c35786
|
@ -22,6 +22,7 @@ use std::ptr;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
use std::sync::Condvar;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
use kernel32;
|
use kernel32;
|
||||||
|
@ -78,12 +79,18 @@ pub struct EventsLoop {
|
||||||
thread_id: winapi::DWORD,
|
thread_id: winapi::DWORD,
|
||||||
// Receiver for the events. The sender is in the background thread.
|
// Receiver for the events. The sender is in the background thread.
|
||||||
receiver: mpsc::Receiver<Event>,
|
receiver: mpsc::Receiver<Event>,
|
||||||
|
// Variable that contains the block state of the win32 event loop thread during a WM_SIZE event.
|
||||||
|
// The mutex's value is `true` when it's blocked, and should be set to false when it's done
|
||||||
|
// blocking. That's done by the parent thread when it receives a Resized event.
|
||||||
|
win32_block_loop: Arc<(Mutex<bool>, Condvar)>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventsLoop {
|
impl EventsLoop {
|
||||||
pub fn new() -> EventsLoop {
|
pub fn new() -> EventsLoop {
|
||||||
// The main events transfer channel.
|
// The main events transfer channel.
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
|
let win32_block_loop = Arc::new((Mutex::new(false), Condvar::new()));
|
||||||
|
let win32_block_loop_child = win32_block_loop.clone();
|
||||||
|
|
||||||
// Local channel in order to block the `new()` function until the background thread has
|
// Local channel in order to block the `new()` function until the background thread has
|
||||||
// an events queue.
|
// an events queue.
|
||||||
|
@ -94,6 +101,7 @@ impl EventsLoop {
|
||||||
*context_stash.borrow_mut() = Some(ThreadLocalData {
|
*context_stash.borrow_mut() = Some(ThreadLocalData {
|
||||||
sender: tx,
|
sender: tx,
|
||||||
windows: HashMap::with_capacity(4),
|
windows: HashMap::with_capacity(4),
|
||||||
|
win32_block_loop: win32_block_loop_child
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -139,6 +147,7 @@ impl EventsLoop {
|
||||||
EventsLoop {
|
EventsLoop {
|
||||||
thread_id: unsafe { kernel32::GetThreadId(thread.as_raw_handle()) },
|
thread_id: unsafe { kernel32::GetThreadId(thread.as_raw_handle()) },
|
||||||
receiver: rx,
|
receiver: rx,
|
||||||
|
win32_block_loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,8 +159,18 @@ impl EventsLoop {
|
||||||
Ok(e) => e,
|
Ok(e) => e,
|
||||||
Err(_) => return
|
Err(_) => return
|
||||||
};
|
};
|
||||||
|
let is_resize = match event {
|
||||||
|
Event::WindowEvent{ event: WindowEvent::Resized(..), .. } => true,
|
||||||
|
_ => false
|
||||||
|
};
|
||||||
|
|
||||||
callback(event);
|
callback(event);
|
||||||
|
if is_resize {
|
||||||
|
let (ref mutex, ref cvar) = *self.win32_block_loop;
|
||||||
|
let mut block_thread = mutex.lock().unwrap();
|
||||||
|
*block_thread = false;
|
||||||
|
cvar.notify_all();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,8 +182,18 @@ impl EventsLoop {
|
||||||
Ok(e) => e,
|
Ok(e) => e,
|
||||||
Err(_) => return
|
Err(_) => return
|
||||||
};
|
};
|
||||||
|
let is_resize = match event {
|
||||||
|
Event::WindowEvent{ event: WindowEvent::Resized(..), .. } => true,
|
||||||
|
_ => false
|
||||||
|
};
|
||||||
|
|
||||||
let flow = callback(event);
|
let flow = callback(event);
|
||||||
|
if is_resize {
|
||||||
|
let (ref mutex, ref cvar) = *self.win32_block_loop;
|
||||||
|
let mut block_thread = mutex.lock().unwrap();
|
||||||
|
*block_thread = false;
|
||||||
|
cvar.notify_all();
|
||||||
|
}
|
||||||
match flow {
|
match flow {
|
||||||
ControlFlow::Continue => continue,
|
ControlFlow::Continue => continue,
|
||||||
ControlFlow::Break => break,
|
ControlFlow::Break => break,
|
||||||
|
@ -240,7 +269,7 @@ lazy_static! {
|
||||||
// WPARAM and LPARAM are unused.
|
// WPARAM and LPARAM are unused.
|
||||||
static ref WAKEUP_MSG_ID: u32 = {
|
static ref WAKEUP_MSG_ID: u32 = {
|
||||||
unsafe {
|
unsafe {
|
||||||
user32::RegisterWindowMessageA("Winit::WakeupMsg".as_ptr() as *const i8)
|
user32::RegisterWindowMessageA("Winit::WakeupMsg\0".as_ptr() as *const i8)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Message sent when we want to execute a closure in the thread.
|
// Message sent when we want to execute a closure in the thread.
|
||||||
|
@ -248,7 +277,7 @@ lazy_static! {
|
||||||
// and LPARAM is unused.
|
// and LPARAM is unused.
|
||||||
static ref EXEC_MSG_ID: u32 = {
|
static ref EXEC_MSG_ID: u32 = {
|
||||||
unsafe {
|
unsafe {
|
||||||
user32::RegisterWindowMessageA("Winit::ExecMsg".as_ptr() as *const i8)
|
user32::RegisterWindowMessageA("Winit::ExecMsg\0".as_ptr() as *const i8)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -259,12 +288,14 @@ thread_local!(static CONTEXT_STASH: RefCell<Option<ThreadLocalData>> = RefCell::
|
||||||
struct ThreadLocalData {
|
struct ThreadLocalData {
|
||||||
sender: mpsc::Sender<Event>,
|
sender: mpsc::Sender<Event>,
|
||||||
windows: HashMap<winapi::HWND, Arc<Mutex<WindowState>>>,
|
windows: HashMap<winapi::HWND, Arc<Mutex<WindowState>>>,
|
||||||
|
win32_block_loop: Arc<(Mutex<bool>, Condvar)>
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utility function that dispatches an event on the current thread.
|
// Utility function that dispatches an event on the current thread.
|
||||||
fn send_event(event: Event) {
|
fn send_event(event: Event) {
|
||||||
CONTEXT_STASH.with(|context_stash| {
|
CONTEXT_STASH.with(|context_stash| {
|
||||||
let context_stash = context_stash.borrow();
|
let context_stash = context_stash.borrow();
|
||||||
|
|
||||||
let _ = context_stash.as_ref().unwrap().sender.send(event); // Ignoring if closed
|
let _ = context_stash.as_ref().unwrap().sender.send(event); // Ignoring if closed
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -302,9 +333,36 @@ pub unsafe extern "system" fn callback(window: winapi::HWND, msg: winapi::UINT,
|
||||||
use events::WindowEvent::Resized;
|
use events::WindowEvent::Resized;
|
||||||
let w = winapi::LOWORD(lparam as winapi::DWORD) as u32;
|
let w = winapi::LOWORD(lparam as winapi::DWORD) as u32;
|
||||||
let h = winapi::HIWORD(lparam as winapi::DWORD) as u32;
|
let h = winapi::HIWORD(lparam as winapi::DWORD) as u32;
|
||||||
send_event(Event::WindowEvent {
|
|
||||||
window_id: SuperWindowId(WindowId(window)),
|
// Wait for the parent thread to process the resize event before returning from the
|
||||||
event: Resized(w, h),
|
// callback.
|
||||||
|
CONTEXT_STASH.with(|context_stash| {
|
||||||
|
let mut context_stash = context_stash.borrow_mut();
|
||||||
|
let cstash = context_stash.as_mut().unwrap();
|
||||||
|
|
||||||
|
let event = Event::WindowEvent {
|
||||||
|
window_id: SuperWindowId(WindowId(window)),
|
||||||
|
event: Resized(w, h),
|
||||||
|
};
|
||||||
|
|
||||||
|
// If this window has been inserted into the window map, the resize event happened
|
||||||
|
// during the event loop. If it hasn't, the event happened on window creation and
|
||||||
|
// should be ignored.
|
||||||
|
if cstash.windows.get(&window).is_some() {
|
||||||
|
let (ref mutex, ref cvar) = *cstash.win32_block_loop;
|
||||||
|
let mut block_thread = mutex.lock().unwrap();
|
||||||
|
*block_thread = true;
|
||||||
|
|
||||||
|
// The event needs to be sent after the lock to ensure that `notify_all` is
|
||||||
|
// called after `wait`.
|
||||||
|
cstash.sender.send(event).ok();
|
||||||
|
|
||||||
|
while *block_thread {
|
||||||
|
block_thread = cvar.wait(block_thread).unwrap();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cstash.sender.send(event).ok();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
0
|
0
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue