mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-02-24 00:37:43 +11:00
Fix unsoundness on Windows (#601)
* Fix unsoundness in windows backend * Synchronize window state properly * update changelog and add a comment to execute_in_thread * Formatting fixes and improve changelog message
This commit is contained in:
parent
df9b23c96a
commit
21ff2e0ffc
4 changed files with 150 additions and 159 deletions
|
@ -1,5 +1,6 @@
|
|||
# Unreleased
|
||||
|
||||
- Fixed thread-safety issues in several `Window` functions on Windows.
|
||||
- On MacOS, the key state for modifiers key events is now properly set.
|
||||
- On iOS, the view is now set correctly. This makes it possible to render things (instead of being stuck on a black screen), and touch events work again.
|
||||
- Added NetBSD support.
|
||||
|
|
|
@ -58,6 +58,7 @@ use platform::platform::dpi::{
|
|||
get_hwnd_scale_factor,
|
||||
};
|
||||
use platform::platform::event::{handle_extended_keys, process_key_params, vkey_to_winit_vkey};
|
||||
use platform::platform::icon::WinIcon;
|
||||
use platform::platform::raw_input::{get_raw_input_data, get_raw_mouse_button_state};
|
||||
use platform::platform::window::adjust_size;
|
||||
|
||||
|
@ -94,6 +95,13 @@ pub struct WindowState {
|
|||
// This is different from the value in `SavedWindowInfo`! That one represents the DPI saved upon entering
|
||||
// fullscreen. This will always be the most recent DPI for the window.
|
||||
pub dpi_factor: f64,
|
||||
pub fullscreen: Option<::MonitorId>,
|
||||
pub window_icon: Option<WinIcon>,
|
||||
pub taskbar_icon: Option<WinIcon>,
|
||||
pub decorations: bool,
|
||||
pub always_on_top: bool,
|
||||
pub maximized: bool,
|
||||
pub resizable: bool,
|
||||
}
|
||||
|
||||
impl WindowState {
|
||||
|
@ -326,6 +334,11 @@ impl EventsLoopProxy {
|
|||
///
|
||||
/// The `Inserted` can be used to inject a `WindowState` for the callback to use. The state is
|
||||
/// removed automatically if the callback receives a `WM_CLOSE` message for the window.
|
||||
///
|
||||
/// Note that if you are using this to change some property of a window and updating
|
||||
/// `WindowState` then you should call this within the lock of `WindowState`. Otherwise the
|
||||
/// events may be sent to the other thread in different order to the one in which you set
|
||||
/// `WindowState`, leaving them out of sync.
|
||||
pub fn execute_in_thread<F>(&self, function: F)
|
||||
where
|
||||
F: FnMut(Inserter) + Send + 'static,
|
||||
|
|
|
@ -22,11 +22,13 @@ pub enum IconType {
|
|||
Big = winuser::ICON_BIG as isize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct WinIcon {
|
||||
pub handle: HICON,
|
||||
}
|
||||
|
||||
unsafe impl Send for WinIcon {}
|
||||
|
||||
impl WinIcon {
|
||||
#[allow(dead_code)]
|
||||
pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Self, util::WinError> {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#![cfg(target_os = "windows")]
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::ffi::OsStr;
|
||||
use std::{io, mem, ptr};
|
||||
use std::cell::Cell;
|
||||
use std::ffi::OsStr;
|
||||
use std::os::windows::ffi::OsStrExt;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::mpsc::channel;
|
||||
|
@ -11,7 +11,7 @@ use winapi::ctypes::c_int;
|
|||
use winapi::shared::minwindef::{BOOL, DWORD, FALSE, LPARAM, TRUE, UINT, WORD, WPARAM};
|
||||
use winapi::shared::windef::{HDC, HWND, LPPOINT, POINT, RECT};
|
||||
use winapi::um::{combaseapi, dwmapi, libloaderapi, winuser};
|
||||
use winapi::um::objbase::{COINIT_MULTITHREADED};
|
||||
use winapi::um::objbase::COINIT_MULTITHREADED;
|
||||
use winapi::um::shobjidl_core::{CLSID_TaskbarList, ITaskbarList2};
|
||||
use winapi::um::winnt::{LONG, LPCWSTR};
|
||||
|
||||
|
@ -27,7 +27,8 @@ use {
|
|||
};
|
||||
use platform::platform::{Cursor, PlatformSpecificWindowBuilderAttributes, WindowId};
|
||||
use platform::platform::dpi::{dpi_to_scale_factor, get_window_dpi, get_window_scale_factor};
|
||||
use platform::platform::events_loop::{self, DESTROY_MSG_ID, EventsLoop, INITIAL_DPI_MSG_ID};
|
||||
use platform::platform::events_loop::{self, EventsLoop, DESTROY_MSG_ID, INITIAL_DPI_MSG_ID};
|
||||
use platform::platform::events_loop::WindowState;
|
||||
use platform::platform::icon::{self, IconType, WinIcon};
|
||||
use platform::platform::monitor::get_available_monitors;
|
||||
use platform::platform::raw_input::register_all_mice_and_keyboards_for_raw_input;
|
||||
|
@ -40,25 +41,13 @@ pub struct Window {
|
|||
/// Main handle for the window.
|
||||
window: WindowWrapper,
|
||||
|
||||
decorations: Cell<bool>,
|
||||
maximized: Cell<bool>,
|
||||
resizable: Cell<bool>,
|
||||
fullscreen: RefCell<Option<::MonitorId>>,
|
||||
always_on_top: Cell<bool>,
|
||||
|
||||
/// The current window state.
|
||||
window_state: Arc<Mutex<events_loop::WindowState>>,
|
||||
|
||||
window_icon: Cell<Option<WinIcon>>,
|
||||
taskbar_icon: Cell<Option<WinIcon>>,
|
||||
window_state: Arc<Mutex<WindowState>>,
|
||||
|
||||
// The events loop proxy.
|
||||
events_loop_proxy: events_loop::EventsLoopProxy,
|
||||
}
|
||||
|
||||
unsafe impl Send for Window {}
|
||||
unsafe impl Sync for Window {}
|
||||
|
||||
// https://blogs.msdn.microsoft.com/oldnewthing/20131017-00/?p=2903
|
||||
// The idea here is that we use the AdjustWindowRectEx function to calculate how much additional
|
||||
// non-client area gets added due to the styles we passed. To make the math simple,
|
||||
|
@ -283,32 +272,25 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn set_resizable(&self, resizable: bool) {
|
||||
if resizable == self.resizable.get() {
|
||||
return;
|
||||
}
|
||||
if self.fullscreen.borrow().is_some() {
|
||||
let mut window_state = self.window_state.lock().unwrap();
|
||||
if mem::replace(&mut window_state.resizable, resizable) != resizable {
|
||||
// If we're in fullscreen, update stored configuration but don't apply anything.
|
||||
self.resizable.replace(resizable);
|
||||
return;
|
||||
}
|
||||
if window_state.fullscreen.is_none() {
|
||||
let mut style = unsafe {
|
||||
winuser::GetWindowLongW(self.window.0, winuser::GWL_STYLE)
|
||||
};
|
||||
|
||||
let mut style = unsafe {
|
||||
winuser::GetWindowLongW(self.window.0, winuser::GWL_STYLE)
|
||||
};
|
||||
if resizable {
|
||||
style |= WS_RESIZABLE as LONG;
|
||||
} else {
|
||||
style &= !WS_RESIZABLE as LONG;
|
||||
}
|
||||
if resizable {
|
||||
style |= WS_RESIZABLE as LONG;
|
||||
} else {
|
||||
style &= !WS_RESIZABLE as LONG;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
winuser::SetWindowLongW(
|
||||
self.window.0,
|
||||
winuser::GWL_STYLE,
|
||||
style as _,
|
||||
);
|
||||
};
|
||||
self.resizable.replace(resizable);
|
||||
unsafe {
|
||||
winuser::SetWindowLongW(self.window.0, winuser::GWL_STYLE, style as _);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `hwnd` of this window.
|
||||
|
@ -391,15 +373,12 @@ impl Window {
|
|||
#[inline]
|
||||
pub fn grab_cursor(&self, grab: bool) -> Result<(), String> {
|
||||
let currently_grabbed = unsafe { self.cursor_is_grabbed() }?;
|
||||
let window_state = Arc::clone(&self.window_state);
|
||||
{
|
||||
let window_state_lock = window_state.lock().unwrap();
|
||||
if currently_grabbed == grab
|
||||
&& grab == window_state_lock.cursor_grabbed {
|
||||
return Ok(());
|
||||
}
|
||||
let window_state_lock = self.window_state.lock().unwrap();
|
||||
if currently_grabbed == grab && grab == window_state_lock.cursor_grabbed {
|
||||
return Ok(());
|
||||
}
|
||||
let window = self.window.clone();
|
||||
let window_state = Arc::clone(&self.window_state);
|
||||
let (tx, rx) = channel();
|
||||
self.events_loop_proxy.execute_in_thread(move |_| {
|
||||
let result = unsafe { Self::grab_cursor_inner(&window, grab) };
|
||||
|
@ -408,6 +387,7 @@ impl Window {
|
|||
}
|
||||
let _ = tx.send(result);
|
||||
});
|
||||
drop(window_state_lock);
|
||||
rx.recv().unwrap()
|
||||
}
|
||||
|
||||
|
@ -421,18 +401,17 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn hide_cursor(&self, hide: bool) {
|
||||
let window_state = Arc::clone(&self.window_state);
|
||||
{
|
||||
let window_state_lock = window_state.lock().unwrap();
|
||||
// We don't want to increment/decrement the display count more than once!
|
||||
if hide == window_state_lock.cursor_hidden { return; }
|
||||
}
|
||||
let window_state_lock = self.window_state.lock().unwrap();
|
||||
// We don't want to increment/decrement the display count more than once!
|
||||
if hide == window_state_lock.cursor_hidden { return; }
|
||||
let (tx, rx) = channel();
|
||||
let window_state = Arc::clone(&self.window_state);
|
||||
self.events_loop_proxy.execute_in_thread(move |_| {
|
||||
unsafe { Self::hide_cursor_inner(hide) };
|
||||
window_state.lock().unwrap().cursor_hidden = hide;
|
||||
let _ = tx.send(());
|
||||
});
|
||||
drop(window_state_lock);
|
||||
rx.recv().unwrap()
|
||||
}
|
||||
|
||||
|
@ -468,9 +447,12 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn set_maximized(&self, maximized: bool) {
|
||||
self.maximized.replace(maximized);
|
||||
let mut window_state = self.window_state.lock().unwrap();
|
||||
window_state.maximized = true;
|
||||
// We only maximize if we're not in fullscreen.
|
||||
if self.fullscreen.borrow().is_some() { return; }
|
||||
if window_state.fullscreen.is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
let window = self.window.clone();
|
||||
unsafe {
|
||||
|
@ -488,10 +470,8 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe fn set_fullscreen_style(&self) -> (LONG, LONG) {
|
||||
let mut window_state = self.window_state.lock().unwrap();
|
||||
|
||||
if self.fullscreen.borrow().is_none() || window_state.saved_window_info.is_none() {
|
||||
unsafe fn set_fullscreen_style(&self, window_state: &mut WindowState) -> (LONG, LONG) {
|
||||
if window_state.fullscreen.is_none() || window_state.saved_window_info.is_none() {
|
||||
let rect = util::get_window_rect(self.window.0).expect("`GetWindowRect` failed");
|
||||
let dpi_factor = Some(self.get_hidpi_factor());
|
||||
window_state.saved_window_info = Some(events_loop::SavedWindowInfo {
|
||||
|
@ -507,16 +487,14 @@ impl Window {
|
|||
let mut placement: winuser::WINDOWPLACEMENT = mem::zeroed();
|
||||
placement.length = mem::size_of::<winuser::WINDOWPLACEMENT>() as u32;
|
||||
winuser::GetWindowPlacement(self.window.0, &mut placement);
|
||||
self.maximized.replace(placement.showCmd == (winuser::SW_SHOWMAXIMIZED as u32));
|
||||
window_state.maximized = placement.showCmd == (winuser::SW_SHOWMAXIMIZED as u32);
|
||||
let saved_window_info = window_state.saved_window_info.as_ref().unwrap();
|
||||
|
||||
(saved_window_info.style, saved_window_info.ex_style)
|
||||
}
|
||||
|
||||
unsafe fn restore_saved_window(&self) {
|
||||
unsafe fn restore_saved_window(&self, window_state_lock: &mut WindowState) {
|
||||
let (rect, mut style, ex_style) = {
|
||||
let mut window_state_lock = self.window_state.lock().unwrap();
|
||||
|
||||
// 'saved_window_info' can be None if the window has never been
|
||||
// in fullscreen mode before this method gets called.
|
||||
if window_state_lock.saved_window_info.is_none() {
|
||||
|
@ -537,8 +515,8 @@ impl Window {
|
|||
let window = self.window.clone();
|
||||
let window_state = Arc::clone(&self.window_state);
|
||||
|
||||
let maximized = self.maximized.get();
|
||||
let resizable = self.resizable.get();
|
||||
let resizable = window_state_lock.resizable;
|
||||
let maximized = window_state_lock.maximized;
|
||||
|
||||
// We're restoring the window to its size and position from before being fullscreened.
|
||||
// `ShowWindow` resizes the window, so it must be called from the main thread.
|
||||
|
@ -585,6 +563,7 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn set_fullscreen(&self, monitor: Option<RootMonitorId>) {
|
||||
let mut window_state_lock = self.window_state.lock().unwrap();
|
||||
unsafe {
|
||||
match &monitor {
|
||||
&Some(RootMonitorId { ref inner }) => {
|
||||
|
@ -593,8 +572,7 @@ impl Window {
|
|||
let window = self.window.clone();
|
||||
let window_state = Arc::clone(&self.window_state);
|
||||
|
||||
let (style, ex_style) = self.set_fullscreen_style();
|
||||
|
||||
let (style, ex_style) = self.set_fullscreen_style(&mut window_state_lock);
|
||||
self.events_loop_proxy.execute_in_thread(move |_| {
|
||||
let _ = Self::grab_cursor_inner(&window, false);
|
||||
|
||||
|
@ -634,27 +612,23 @@ impl Window {
|
|||
});
|
||||
}
|
||||
&None => {
|
||||
self.restore_saved_window();
|
||||
self.restore_saved_window(&mut window_state_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.fullscreen.replace(monitor);
|
||||
window_state_lock.fullscreen = monitor;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_decorations(&self, decorations: bool) {
|
||||
if self.decorations.get() == decorations {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut window_state = self.window_state.lock().unwrap();
|
||||
if mem::replace(&mut window_state.decorations, decorations) != decorations {
|
||||
let style_flags = (winuser::WS_CAPTION | winuser::WS_THICKFRAME) as LONG;
|
||||
let ex_style_flags = (winuser::WS_EX_WINDOWEDGE) as LONG;
|
||||
|
||||
// if we are in fullscreen mode, we only change the saved window info
|
||||
if self.fullscreen.borrow().is_some() {
|
||||
{
|
||||
let mut window_state = self.window_state.lock().unwrap();
|
||||
// if we are in fullscreen mode, we only change the saved window info
|
||||
if window_state.fullscreen.is_some() {
|
||||
let saved = window_state.saved_window_info.as_mut().unwrap();
|
||||
|
||||
unsafe {
|
||||
|
@ -677,81 +651,73 @@ impl Window {
|
|||
saved.ex_style as _,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self.decorations.replace(decorations);
|
||||
return;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let mut rect: RECT = mem::zeroed();
|
||||
winuser::GetWindowRect(self.window.0, &mut rect);
|
||||
|
||||
let mut style = winuser::GetWindowLongW(self.window.0, winuser::GWL_STYLE);
|
||||
let mut ex_style = winuser::GetWindowLongW(self.window.0, winuser::GWL_EXSTYLE);
|
||||
unjust_window_rect(&mut rect, style as _, ex_style as _);
|
||||
|
||||
if decorations {
|
||||
style = style | style_flags;
|
||||
ex_style = ex_style | ex_style_flags;
|
||||
} else {
|
||||
style = style & !style_flags;
|
||||
ex_style = ex_style & !ex_style_flags;
|
||||
unsafe {
|
||||
let mut rect: RECT = mem::zeroed();
|
||||
winuser::GetWindowRect(self.window.0, &mut rect);
|
||||
|
||||
let mut style = winuser::GetWindowLongW(self.window.0, winuser::GWL_STYLE);
|
||||
let mut ex_style = winuser::GetWindowLongW(self.window.0, winuser::GWL_EXSTYLE);
|
||||
unjust_window_rect(&mut rect, style as _, ex_style as _);
|
||||
|
||||
if decorations {
|
||||
style = style | style_flags;
|
||||
ex_style = ex_style | ex_style_flags;
|
||||
} else {
|
||||
style = style & !style_flags;
|
||||
ex_style = ex_style & !ex_style_flags;
|
||||
}
|
||||
|
||||
let window = self.window.clone();
|
||||
|
||||
self.events_loop_proxy.execute_in_thread(move |_| {
|
||||
winuser::SetWindowLongW(window.0, winuser::GWL_STYLE, style);
|
||||
winuser::SetWindowLongW(window.0, winuser::GWL_EXSTYLE, ex_style);
|
||||
winuser::AdjustWindowRectEx(&mut rect, style as _, 0, ex_style as _);
|
||||
|
||||
winuser::SetWindowPos(
|
||||
window.0,
|
||||
ptr::null_mut(),
|
||||
rect.left,
|
||||
rect.top,
|
||||
rect.right - rect.left,
|
||||
rect.bottom - rect.top,
|
||||
winuser::SWP_ASYNCWINDOWPOS
|
||||
| winuser::SWP_NOZORDER
|
||||
| winuser::SWP_NOACTIVATE
|
||||
| winuser::SWP_FRAMECHANGED,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let window = self.window.clone();
|
||||
|
||||
self.events_loop_proxy.execute_in_thread(move |_| {
|
||||
winuser::SetWindowLongW(window.0, winuser::GWL_STYLE, style);
|
||||
winuser::SetWindowLongW(window.0, winuser::GWL_EXSTYLE, ex_style);
|
||||
winuser::AdjustWindowRectEx(&mut rect, style as _, 0, ex_style as _);
|
||||
|
||||
winuser::SetWindowPos(
|
||||
window.0,
|
||||
ptr::null_mut(),
|
||||
rect.left,
|
||||
rect.top,
|
||||
rect.right - rect.left,
|
||||
rect.bottom - rect.top,
|
||||
winuser::SWP_ASYNCWINDOWPOS
|
||||
| winuser::SWP_NOZORDER
|
||||
| winuser::SWP_NOACTIVATE
|
||||
| winuser::SWP_FRAMECHANGED,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
self.decorations.replace(decorations);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_always_on_top(&self, always_on_top: bool) {
|
||||
if self.always_on_top.get() == always_on_top {
|
||||
return;
|
||||
let mut window_state = self.window_state.lock().unwrap();
|
||||
if mem::replace(&mut window_state.always_on_top, always_on_top) != always_on_top {
|
||||
let window = self.window.clone();
|
||||
self.events_loop_proxy.execute_in_thread(move |_| {
|
||||
let insert_after = if always_on_top {
|
||||
winuser::HWND_TOPMOST
|
||||
} else {
|
||||
winuser::HWND_NOTOPMOST
|
||||
};
|
||||
unsafe {
|
||||
winuser::SetWindowPos(
|
||||
window.0,
|
||||
insert_after,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
winuser::SWP_ASYNCWINDOWPOS | winuser::SWP_NOMOVE | winuser::SWP_NOSIZE,
|
||||
);
|
||||
winuser::UpdateWindow(window.0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let window = self.window.clone();
|
||||
self.events_loop_proxy.execute_in_thread(move |_| {
|
||||
let insert_after = if always_on_top {
|
||||
winuser::HWND_TOPMOST
|
||||
} else {
|
||||
winuser::HWND_NOTOPMOST
|
||||
};
|
||||
unsafe {
|
||||
winuser::SetWindowPos(
|
||||
window.0,
|
||||
insert_after,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
winuser::SWP_ASYNCWINDOWPOS | winuser::SWP_NOMOVE | winuser::SWP_NOSIZE,
|
||||
);
|
||||
winuser::UpdateWindow(window.0);
|
||||
}
|
||||
});
|
||||
|
||||
self.always_on_top.replace(always_on_top);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -771,7 +737,7 @@ impl Window {
|
|||
} else {
|
||||
icon::unset_for_window(self.window.0, IconType::Small);
|
||||
}
|
||||
self.window_icon.replace(window_icon);
|
||||
self.window_state.lock().unwrap().window_icon = window_icon;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -784,7 +750,7 @@ impl Window {
|
|||
} else {
|
||||
icon::unset_for_window(self.window.0, IconType::Big);
|
||||
}
|
||||
self.taskbar_icon.replace(taskbar_icon);
|
||||
self.window_state.lock().unwrap().taskbar_icon = taskbar_icon;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -809,15 +775,25 @@ impl Drop for Window {
|
|||
#[derive(Clone)]
|
||||
pub struct WindowWrapper(HWND, HDC);
|
||||
|
||||
// Send is not implemented for HWND and HDC, we have to wrap it and implement it manually.
|
||||
// Send and Sync are not implemented for HWND and HDC, we have to wrap it and implement them manually.
|
||||
// For more info see:
|
||||
// https://github.com/retep998/winapi-rs/issues/360
|
||||
// https://github.com/retep998/winapi-rs/issues/396
|
||||
unsafe impl Sync for WindowWrapper {}
|
||||
unsafe impl Send for WindowWrapper {}
|
||||
|
||||
pub unsafe fn adjust_size(physical_size: PhysicalSize, style: DWORD, ex_style: DWORD) -> (LONG, LONG) {
|
||||
pub unsafe fn adjust_size(
|
||||
physical_size: PhysicalSize,
|
||||
style: DWORD,
|
||||
ex_style: DWORD,
|
||||
) -> (LONG, LONG) {
|
||||
let (width, height): (u32, u32) = physical_size.into();
|
||||
let mut rect = RECT { left: 0, right: width as LONG, top: 0, bottom: height as LONG };
|
||||
let mut rect = RECT {
|
||||
left: 0,
|
||||
right: width as LONG,
|
||||
top: 0,
|
||||
bottom: height as LONG,
|
||||
};
|
||||
winuser::AdjustWindowRectEx(&mut rect, style, 0, ex_style);
|
||||
(rect.right - rect.left, rect.bottom - rect.top)
|
||||
}
|
||||
|
@ -1029,6 +1005,13 @@ unsafe fn init(
|
|||
mouse_in_window: false,
|
||||
saved_window_info: None,
|
||||
dpi_factor,
|
||||
fullscreen: attributes.fullscreen.clone(),
|
||||
window_icon,
|
||||
taskbar_icon,
|
||||
decorations: attributes.decorations,
|
||||
maximized: attributes.maximized,
|
||||
resizable: attributes.resizable,
|
||||
always_on_top: attributes.always_on_top,
|
||||
};
|
||||
// Creating a mutex to track the current window state
|
||||
Arc::new(Mutex::new(window_state))
|
||||
|
@ -1048,14 +1031,7 @@ unsafe fn init(
|
|||
|
||||
let win = Window {
|
||||
window: real_window,
|
||||
window_state: window_state,
|
||||
decorations: Cell::new(attributes.decorations),
|
||||
maximized: Cell::new(attributes.maximized.clone()),
|
||||
resizable: Cell::new(attributes.resizable.clone()),
|
||||
fullscreen: RefCell::new(attributes.fullscreen.clone()),
|
||||
always_on_top: Cell::new(attributes.always_on_top),
|
||||
window_icon: Cell::new(window_icon),
|
||||
taskbar_icon: Cell::new(taskbar_icon),
|
||||
window_state,
|
||||
events_loop_proxy,
|
||||
};
|
||||
|
||||
|
@ -1112,7 +1088,6 @@ unsafe fn register_window_class(
|
|||
class_name
|
||||
}
|
||||
|
||||
|
||||
struct ComInitialized(*mut ());
|
||||
impl Drop for ComInitialized {
|
||||
fn drop(&mut self) {
|
||||
|
|
Loading…
Add table
Reference in a new issue