Windows: fix crash with unhandled window (#9164)
On Windows, some windows may be created that are not managed by the application. For example, the Japanese IME creates pop-ups like this one. <img width="325" alt="image" src="https://github.com/zed-industries/zed/assets/6465609/503aaa0a-7568-485a-a138-e689ae67001c"> The internal data associated with such a window is different from `WindowsWindowInner` and will crash if referenced. Therefore, before calling `try_get_window_inner`, it checks if it is an owned window. Release Notes: - N/A
This commit is contained in:
parent
ceadb39c38
commit
a04932c4eb
2 changed files with 33 additions and 10 deletions
|
@ -72,13 +72,15 @@ pub(crate) struct WindowsPlatformSystemSettings {
|
||||||
pub(crate) wheel_scroll_lines: u32,
|
pub(crate) wheel_scroll_lines: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WindowHandleValues = HashSet<isize>;
|
||||||
|
|
||||||
pub(crate) struct WindowsPlatformInner {
|
pub(crate) struct WindowsPlatformInner {
|
||||||
background_executor: BackgroundExecutor,
|
background_executor: BackgroundExecutor,
|
||||||
pub(crate) foreground_executor: ForegroundExecutor,
|
pub(crate) foreground_executor: ForegroundExecutor,
|
||||||
main_receiver: flume::Receiver<Runnable>,
|
main_receiver: flume::Receiver<Runnable>,
|
||||||
text_system: Arc<WindowsTextSystem>,
|
text_system: Arc<WindowsTextSystem>,
|
||||||
callbacks: Mutex<Callbacks>,
|
callbacks: Mutex<Callbacks>,
|
||||||
pub(crate) window_handles: RefCell<HashSet<AnyWindowHandle>>,
|
pub(crate) window_handle_values: RefCell<WindowHandleValues>,
|
||||||
pub(crate) event: HANDLE,
|
pub(crate) event: HANDLE,
|
||||||
pub(crate) settings: RefCell<WindowsPlatformSystemSettings>,
|
pub(crate) settings: RefCell<WindowsPlatformSystemSettings>,
|
||||||
}
|
}
|
||||||
|
@ -165,7 +167,7 @@ impl WindowsPlatform {
|
||||||
let foreground_executor = ForegroundExecutor::new(dispatcher);
|
let foreground_executor = ForegroundExecutor::new(dispatcher);
|
||||||
let text_system = Arc::new(WindowsTextSystem::new());
|
let text_system = Arc::new(WindowsTextSystem::new());
|
||||||
let callbacks = Mutex::new(Callbacks::default());
|
let callbacks = Mutex::new(Callbacks::default());
|
||||||
let window_handles = RefCell::new(HashSet::new());
|
let window_handle_values = RefCell::new(HashSet::new());
|
||||||
let settings = RefCell::new(WindowsPlatformSystemSettings::new());
|
let settings = RefCell::new(WindowsPlatformSystemSettings::new());
|
||||||
let inner = Rc::new(WindowsPlatformInner {
|
let inner = Rc::new(WindowsPlatformInner {
|
||||||
background_executor,
|
background_executor,
|
||||||
|
@ -173,7 +175,7 @@ impl WindowsPlatform {
|
||||||
main_receiver,
|
main_receiver,
|
||||||
text_system,
|
text_system,
|
||||||
callbacks,
|
callbacks,
|
||||||
window_handles,
|
window_handle_values,
|
||||||
event,
|
event,
|
||||||
settings,
|
settings,
|
||||||
});
|
});
|
||||||
|
@ -188,6 +190,15 @@ impl WindowsPlatform {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !self
|
||||||
|
.inner
|
||||||
|
.window_handle_values
|
||||||
|
.borrow()
|
||||||
|
.contains(&msg.hwnd.0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(inner) = try_get_window_inner(msg.hwnd) {
|
if let Some(inner) = try_get_window_inner(msg.hwnd) {
|
||||||
inner.handle_immediate_msg(msg.message, msg.wParam, msg.lParam)
|
inner.handle_immediate_msg(msg.message, msg.wParam, msg.lParam)
|
||||||
} else {
|
} else {
|
||||||
|
@ -202,7 +213,11 @@ impl WindowsPlatform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "system" fn invalidate_window_callback(hwnd: HWND, _: LPARAM) -> BOOL {
|
unsafe extern "system" fn invalidate_window_callback(hwnd: HWND, lparam: LPARAM) -> BOOL {
|
||||||
|
let window_handle_values = unsafe { &*(lparam.0 as *const WindowHandleValues) };
|
||||||
|
if !window_handle_values.contains(&hwnd.0) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
if let Some(inner) = try_get_window_inner(hwnd) {
|
if let Some(inner) = try_get_window_inner(hwnd) {
|
||||||
inner.invalidate_client_area();
|
inner.invalidate_client_area();
|
||||||
}
|
}
|
||||||
|
@ -210,12 +225,12 @@ unsafe extern "system" fn invalidate_window_callback(hwnd: HWND, _: LPARAM) -> B
|
||||||
}
|
}
|
||||||
|
|
||||||
/// invalidates all windows belonging to a thread causing a paint message to be scheduled
|
/// invalidates all windows belonging to a thread causing a paint message to be scheduled
|
||||||
fn invalidate_thread_windows(win32_thread_id: u32) {
|
fn invalidate_thread_windows(win32_thread_id: u32, window_handle_values: &WindowHandleValues) {
|
||||||
unsafe {
|
unsafe {
|
||||||
EnumThreadWindows(
|
EnumThreadWindows(
|
||||||
win32_thread_id,
|
win32_thread_id,
|
||||||
Some(invalidate_window_callback),
|
Some(invalidate_window_callback),
|
||||||
LPARAM::default(),
|
LPARAM(window_handle_values as *const _ as isize),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -244,7 +259,12 @@ impl Platform for WindowsPlatform {
|
||||||
|
|
||||||
// compositor clock ticked so we should draw a frame
|
// compositor clock ticked so we should draw a frame
|
||||||
if wait_result == 1 {
|
if wait_result == 1 {
|
||||||
unsafe { invalidate_thread_windows(GetCurrentThreadId()) };
|
unsafe {
|
||||||
|
invalidate_thread_windows(
|
||||||
|
GetCurrentThreadId(),
|
||||||
|
&self.inner.window_handle_values.borrow(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
while unsafe { PeekMessageW(&mut msg, HWND::default(), 0, 0, PM_REMOVE) }.as_bool()
|
while unsafe { PeekMessageW(&mut msg, HWND::default(), 0, 0, PM_REMOVE) }.as_bool()
|
||||||
{
|
{
|
||||||
|
|
|
@ -302,8 +302,8 @@ impl WindowsWindowInner {
|
||||||
if let Some(callback) = callbacks.close.take() {
|
if let Some(callback) = callbacks.close.take() {
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
let mut window_handles = self.platform_inner.window_handles.borrow_mut();
|
let mut window_handles = self.platform_inner.window_handle_values.borrow_mut();
|
||||||
window_handles.remove(&self.handle);
|
window_handles.remove(&self.hwnd.0);
|
||||||
if window_handles.is_empty() {
|
if window_handles.is_empty() {
|
||||||
self.platform_inner
|
self.platform_inner
|
||||||
.foreground_executor
|
.foreground_executor
|
||||||
|
@ -680,7 +680,10 @@ impl WindowsWindow {
|
||||||
inner: context.inner.unwrap(),
|
inner: context.inner.unwrap(),
|
||||||
drag_drop_handler,
|
drag_drop_handler,
|
||||||
};
|
};
|
||||||
platform_inner.window_handles.borrow_mut().insert(handle);
|
platform_inner
|
||||||
|
.window_handle_values
|
||||||
|
.borrow_mut()
|
||||||
|
.insert(wnd.inner.hwnd.0);
|
||||||
match options.bounds {
|
match options.bounds {
|
||||||
WindowBounds::Fullscreen => wnd.toggle_full_screen(),
|
WindowBounds::Fullscreen => wnd.toggle_full_screen(),
|
||||||
WindowBounds::Maximized => wnd.maximize(),
|
WindowBounds::Maximized => wnd.maximize(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue