Windows: Make EventLoopWindowTarget independent of UserEvent type (#3061)
* make `EventLoopWindowTarget` independent of UserEvent type the `EventLoopWindowTarget` is needed for window creation. conceptually, only `EventLoop` and `EventLoopProxy` need to be parameterized, and all other parts of the backend should be agnostic about the user event type, parallel to how `Event<T>` is parameterized, but `WindowEvent` is not. this change removes the dependency on the type of user events from the `EventLoopWindowTarget` for the Windows backend, but keep a phantom data to keep the API intact. to achieve this, I moved the `Receiver` end of the mpsc channel from `ThreadMsgTargetData` into `EventLoop` itself, so the `UserEvent` is only passed between `EventLoop` and `EventLoopProxy`, all other part of the backend just use unit type as a placeholder for user events. it's similar to the macos backend where an erased `EventHandler` trait object is used so all component except `EventLoop` and `EventLoopProxy` need to be parameterized. however `EventLoop` of the Windows backend already use an `Box<dyn FnMut>` to wrap the user provided event handler callback, so no need for an dedicated trait object, I just modified the wrapper to replace the placeholder user event with real value pulled from the channel. I find this is the approach which need minimum change to be made to existing code. but it does the job and could serve as a starting point to future Windows backend re-works. * fix CI clippy failure. * make UserEventPlaceholder a new type instead of alias * invariance is maintained by top-level EventLoopWindowTarget<T> this field is transitional and her to keep API compatibility only. the correct variance and such is already ensured by the top-level `EventLoopWindowTarget`, just use `PhantomData<T>` here.
This commit is contained in:
parent
ac247cd081
commit
dd127463c5
4 changed files with 94 additions and 46 deletions
|
|
@ -50,7 +50,7 @@ pub struct EventLoop<T: 'static> {
|
||||||
/// `&EventLoop`.
|
/// `&EventLoop`.
|
||||||
pub struct EventLoopWindowTarget<T: 'static> {
|
pub struct EventLoopWindowTarget<T: 'static> {
|
||||||
pub(crate) p: platform_impl::EventLoopWindowTarget<T>,
|
pub(crate) p: platform_impl::EventLoopWindowTarget<T>,
|
||||||
pub(crate) _marker: PhantomData<*mut ()>, // Not Send nor Sync
|
pub(crate) _marker: PhantomData<*mut T>, // Not Send nor Sync + invariant over T
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Object that allows building the event loop.
|
/// Object that allows building the event loop.
|
||||||
|
|
|
||||||
|
|
@ -98,17 +98,38 @@ use self::runner::RunnerState;
|
||||||
|
|
||||||
use super::{window::set_skip_taskbar, SelectedCursor};
|
use super::{window::set_skip_taskbar, SelectedCursor};
|
||||||
|
|
||||||
pub(crate) struct WindowData<T: 'static> {
|
/// some backends like macos uses an uninhabited `Never` type,
|
||||||
|
/// on windows, `UserEvent`s are also dispatched through the
|
||||||
|
/// WNDPROC callback, and due to the re-entrant nature of the
|
||||||
|
/// callback, recursively delivered events must be queued in a
|
||||||
|
/// buffer, the current implementation put this queue in
|
||||||
|
/// `EventLoopRunner`, which is shared between the event pumping
|
||||||
|
/// loop and the callback. because it's hard to decide from the
|
||||||
|
/// outside whether a event needs to be buffered, I decided not
|
||||||
|
/// use `Event<Never>` for the shared runner state, but use unit
|
||||||
|
/// as a placeholder so user events can be buffered as usual,
|
||||||
|
/// the real `UserEvent` is pulled from the mpsc channel directly
|
||||||
|
/// when the placeholder event is delivered to the event handler
|
||||||
|
pub(crate) struct UserEventPlaceholder;
|
||||||
|
|
||||||
|
// here below, the generic `EventLoopRunnerShared<T>` is replaced with
|
||||||
|
// `EventLoopRunnerShared<UserEventPlaceholder>` so we can get rid
|
||||||
|
// of the generic parameter T in types which don't depend on T.
|
||||||
|
// this is the approach which requires minimum changes to current
|
||||||
|
// backend implementation. it should be considered transitional
|
||||||
|
// and should be refactored and cleaned up eventually, I hope.
|
||||||
|
|
||||||
|
pub(crate) struct WindowData {
|
||||||
pub window_state: Arc<Mutex<WindowState>>,
|
pub window_state: Arc<Mutex<WindowState>>,
|
||||||
pub event_loop_runner: EventLoopRunnerShared<T>,
|
pub event_loop_runner: EventLoopRunnerShared<UserEventPlaceholder>,
|
||||||
pub key_event_builder: KeyEventBuilder,
|
pub key_event_builder: KeyEventBuilder,
|
||||||
pub _file_drop_handler: Option<FileDropHandler>,
|
pub _file_drop_handler: Option<FileDropHandler>,
|
||||||
pub userdata_removed: Cell<bool>,
|
pub userdata_removed: Cell<bool>,
|
||||||
pub recurse_depth: Cell<u32>,
|
pub recurse_depth: Cell<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> WindowData<T> {
|
impl WindowData {
|
||||||
fn send_event(&self, event: Event<T>) {
|
fn send_event(&self, event: Event<UserEventPlaceholder>) {
|
||||||
self.event_loop_runner.send_event(event);
|
self.event_loop_runner.send_event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,13 +138,12 @@ impl<T> WindowData<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ThreadMsgTargetData<T: 'static> {
|
struct ThreadMsgTargetData {
|
||||||
event_loop_runner: EventLoopRunnerShared<T>,
|
event_loop_runner: EventLoopRunnerShared<UserEventPlaceholder>,
|
||||||
user_event_receiver: Receiver<T>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ThreadMsgTargetData<T> {
|
impl ThreadMsgTargetData {
|
||||||
fn send_event(&self, event: Event<T>) {
|
fn send_event(&self, event: Event<UserEventPlaceholder>) {
|
||||||
self.event_loop_runner.send_event(event);
|
self.event_loop_runner.send_event(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -136,7 +156,8 @@ pub(crate) enum ProcResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EventLoop<T: 'static> {
|
pub struct EventLoop<T: 'static> {
|
||||||
thread_msg_sender: Sender<T>,
|
user_event_sender: Sender<T>,
|
||||||
|
user_event_receiver: Receiver<T>,
|
||||||
window_target: RootELW<T>,
|
window_target: RootELW<T>,
|
||||||
msg_hook: Option<Box<dyn FnMut(*const c_void) -> bool + 'static>>,
|
msg_hook: Option<Box<dyn FnMut(*const c_void) -> bool + 'static>>,
|
||||||
}
|
}
|
||||||
|
|
@ -160,7 +181,8 @@ impl Default for PlatformSpecificEventLoopAttributes {
|
||||||
pub struct EventLoopWindowTarget<T: 'static> {
|
pub struct EventLoopWindowTarget<T: 'static> {
|
||||||
thread_id: u32,
|
thread_id: u32,
|
||||||
thread_msg_target: HWND,
|
thread_msg_target: HWND,
|
||||||
pub(crate) runner_shared: EventLoopRunnerShared<T>,
|
pub(crate) runner_shared: EventLoopRunnerShared<UserEventPlaceholder>,
|
||||||
|
_marker: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: 'static> EventLoop<T> {
|
impl<T: 'static> EventLoop<T> {
|
||||||
|
|
@ -182,24 +204,26 @@ impl<T: 'static> EventLoop<T> {
|
||||||
become_dpi_aware();
|
become_dpi_aware();
|
||||||
}
|
}
|
||||||
|
|
||||||
let thread_msg_target = create_event_target_window::<T>();
|
let thread_msg_target = create_event_target_window();
|
||||||
|
|
||||||
let runner_shared = Rc::new(EventLoopRunner::new(thread_msg_target));
|
let runner_shared = Rc::new(EventLoopRunner::new(thread_msg_target));
|
||||||
|
|
||||||
let thread_msg_sender =
|
let (user_event_sender, user_event_receiver) = mpsc::channel();
|
||||||
insert_event_target_window_data::<T>(thread_msg_target, runner_shared.clone());
|
insert_event_target_window_data(thread_msg_target, runner_shared.clone());
|
||||||
raw_input::register_all_mice_and_keyboards_for_raw_input(
|
raw_input::register_all_mice_and_keyboards_for_raw_input(
|
||||||
thread_msg_target,
|
thread_msg_target,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(EventLoop {
|
Ok(EventLoop {
|
||||||
thread_msg_sender,
|
user_event_sender,
|
||||||
|
user_event_receiver,
|
||||||
window_target: RootELW {
|
window_target: RootELW {
|
||||||
p: EventLoopWindowTarget {
|
p: EventLoopWindowTarget {
|
||||||
thread_id,
|
thread_id,
|
||||||
thread_msg_target,
|
thread_msg_target,
|
||||||
runner_shared,
|
runner_shared,
|
||||||
|
_marker: PhantomData,
|
||||||
},
|
},
|
||||||
_marker: PhantomData,
|
_marker: PhantomData,
|
||||||
},
|
},
|
||||||
|
|
@ -229,11 +253,28 @@ impl<T: 'static> EventLoop<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let event_loop_windows_ref = &self.window_target;
|
let event_loop_windows_ref = &self.window_target;
|
||||||
|
let user_event_receiver = &self.user_event_receiver;
|
||||||
// # Safety
|
// # Safety
|
||||||
// We make sure to call runner.clear_event_handler() before
|
// We make sure to call runner.clear_event_handler() before
|
||||||
// returning
|
// returning
|
||||||
unsafe {
|
unsafe {
|
||||||
runner.set_event_handler(move |event| event_handler(event, event_loop_windows_ref));
|
runner.set_event_handler(move |event| {
|
||||||
|
// the shared `EventLoopRunner` is not parameterized
|
||||||
|
// `EventLoopProxy::send_event()` calls `PostMessage`
|
||||||
|
// to wakeup and dispatch a placeholder `UserEvent`,
|
||||||
|
// when we received the placeholder event here, the
|
||||||
|
// real UserEvent(T) should already be put in the
|
||||||
|
// mpsc channel and ready to be pulled
|
||||||
|
let event = match event.map_nonuser_event() {
|
||||||
|
Ok(non_user_event) => non_user_event,
|
||||||
|
Err(_user_event_placeholder) => Event::UserEvent(
|
||||||
|
user_event_receiver
|
||||||
|
.try_recv()
|
||||||
|
.expect("user event signaled but not received"),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
event_handler(event, event_loop_windows_ref)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -273,6 +314,7 @@ impl<T: 'static> EventLoop<T> {
|
||||||
{
|
{
|
||||||
let runner = &self.window_target.p.runner_shared;
|
let runner = &self.window_target.p.runner_shared;
|
||||||
let event_loop_windows_ref = &self.window_target;
|
let event_loop_windows_ref = &self.window_target;
|
||||||
|
let user_event_receiver = &self.user_event_receiver;
|
||||||
|
|
||||||
// # Safety
|
// # Safety
|
||||||
// We make sure to call runner.clear_event_handler() before
|
// We make sure to call runner.clear_event_handler() before
|
||||||
|
|
@ -282,7 +324,17 @@ impl<T: 'static> EventLoop<T> {
|
||||||
// to leave the runner in an unsound state with an associated
|
// to leave the runner in an unsound state with an associated
|
||||||
// event handler.
|
// event handler.
|
||||||
unsafe {
|
unsafe {
|
||||||
runner.set_event_handler(move |event| event_handler(event, event_loop_windows_ref));
|
runner.set_event_handler(move |event| {
|
||||||
|
let event = match event.map_nonuser_event() {
|
||||||
|
Ok(non_user_event) => non_user_event,
|
||||||
|
Err(_user_event_placeholder) => Event::UserEvent(
|
||||||
|
user_event_receiver
|
||||||
|
.recv()
|
||||||
|
.expect("user event signaled but not received"),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
event_handler(event, event_loop_windows_ref)
|
||||||
|
});
|
||||||
runner.wakeup();
|
runner.wakeup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -468,7 +520,7 @@ impl<T: 'static> EventLoop<T> {
|
||||||
pub fn create_proxy(&self) -> EventLoopProxy<T> {
|
pub fn create_proxy(&self) -> EventLoopProxy<T> {
|
||||||
EventLoopProxy {
|
EventLoopProxy {
|
||||||
target_window: self.window_target.p.thread_msg_target,
|
target_window: self.window_target.p.thread_msg_target,
|
||||||
event_send: self.thread_msg_sender.clone(),
|
event_send: self.user_event_sender.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -779,14 +831,14 @@ static THREAD_EVENT_TARGET_WINDOW_CLASS: Lazy<Vec<u16>> =
|
||||||
/// <https://docs.microsoft.com/en-us/windows/win32/shell/taskbar#taskbar-creation-notification>
|
/// <https://docs.microsoft.com/en-us/windows/win32/shell/taskbar#taskbar-creation-notification>
|
||||||
pub static TASKBAR_CREATED: LazyMessageId = LazyMessageId::new("TaskbarCreated\0");
|
pub static TASKBAR_CREATED: LazyMessageId = LazyMessageId::new("TaskbarCreated\0");
|
||||||
|
|
||||||
fn create_event_target_window<T: 'static>() -> HWND {
|
fn create_event_target_window() -> HWND {
|
||||||
use windows_sys::Win32::UI::WindowsAndMessaging::CS_HREDRAW;
|
use windows_sys::Win32::UI::WindowsAndMessaging::CS_HREDRAW;
|
||||||
use windows_sys::Win32::UI::WindowsAndMessaging::CS_VREDRAW;
|
use windows_sys::Win32::UI::WindowsAndMessaging::CS_VREDRAW;
|
||||||
unsafe {
|
unsafe {
|
||||||
let class = WNDCLASSEXW {
|
let class = WNDCLASSEXW {
|
||||||
cbSize: mem::size_of::<WNDCLASSEXW>() as u32,
|
cbSize: mem::size_of::<WNDCLASSEXW>() as u32,
|
||||||
style: CS_HREDRAW | CS_VREDRAW,
|
style: CS_HREDRAW | CS_VREDRAW,
|
||||||
lpfnWndProc: Some(thread_event_target_callback::<T>),
|
lpfnWndProc: Some(thread_event_target_callback),
|
||||||
cbClsExtra: 0,
|
cbClsExtra: 0,
|
||||||
cbWndExtra: 0,
|
cbWndExtra: 0,
|
||||||
hInstance: util::get_instance_handle(),
|
hInstance: util::get_instance_handle(),
|
||||||
|
|
@ -839,21 +891,14 @@ fn create_event_target_window<T: 'static>() -> HWND {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_event_target_window_data<T>(
|
fn insert_event_target_window_data(
|
||||||
thread_msg_target: HWND,
|
thread_msg_target: HWND,
|
||||||
event_loop_runner: EventLoopRunnerShared<T>,
|
event_loop_runner: EventLoopRunnerShared<UserEventPlaceholder>,
|
||||||
) -> Sender<T> {
|
) {
|
||||||
let (tx, rx) = mpsc::channel();
|
let userdata = ThreadMsgTargetData { event_loop_runner };
|
||||||
|
|
||||||
let userdata = ThreadMsgTargetData {
|
|
||||||
event_loop_runner,
|
|
||||||
user_event_receiver: rx,
|
|
||||||
};
|
|
||||||
let input_ptr = Box::into_raw(Box::new(userdata));
|
let input_ptr = Box::into_raw(Box::new(userdata));
|
||||||
|
|
||||||
unsafe { super::set_window_long(thread_msg_target, GWL_USERDATA, input_ptr as isize) };
|
unsafe { super::set_window_long(thread_msg_target, GWL_USERDATA, input_ptr as isize) };
|
||||||
|
|
||||||
tx
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Capture mouse input, allowing `window` to receive mouse events when the cursor is outside of
|
/// Capture mouse input, allowing `window` to receive mouse events when the cursor is outside of
|
||||||
|
|
@ -883,7 +928,7 @@ fn normalize_pointer_pressure(pressure: u32) -> Option<Force> {
|
||||||
|
|
||||||
/// Emit a `ModifiersChanged` event whenever modifiers have changed.
|
/// Emit a `ModifiersChanged` event whenever modifiers have changed.
|
||||||
/// Returns the current modifier state
|
/// Returns the current modifier state
|
||||||
fn update_modifiers<T>(window: HWND, userdata: &WindowData<T>) {
|
fn update_modifiers(window: HWND, userdata: &WindowData) {
|
||||||
use crate::event::WindowEvent::ModifiersChanged;
|
use crate::event::WindowEvent::ModifiersChanged;
|
||||||
|
|
||||||
let modifiers = {
|
let modifiers = {
|
||||||
|
|
@ -905,7 +950,7 @@ fn update_modifiers<T>(window: HWND, userdata: &WindowData<T>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn gain_active_focus<T>(window: HWND, userdata: &WindowData<T>) {
|
unsafe fn gain_active_focus(window: HWND, userdata: &WindowData) {
|
||||||
use crate::event::WindowEvent::Focused;
|
use crate::event::WindowEvent::Focused;
|
||||||
|
|
||||||
update_modifiers(window, userdata);
|
update_modifiers(window, userdata);
|
||||||
|
|
@ -916,7 +961,7 @@ unsafe fn gain_active_focus<T>(window: HWND, userdata: &WindowData<T>) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn lose_active_focus<T>(window: HWND, userdata: &WindowData<T>) {
|
unsafe fn lose_active_focus(window: HWND, userdata: &WindowData) {
|
||||||
use crate::event::WindowEvent::{Focused, ModifiersChanged};
|
use crate::event::WindowEvent::{Focused, ModifiersChanged};
|
||||||
|
|
||||||
userdata.window_state_lock().modifiers_state = ModifiersState::empty();
|
userdata.window_state_lock().modifiers_state = ModifiersState::empty();
|
||||||
|
|
@ -973,7 +1018,7 @@ pub(super) unsafe extern "system" fn public_window_callback<T: 'static>(
|
||||||
return DefWindowProcW(window, msg, wparam, lparam);
|
return DefWindowProcW(window, msg, wparam, lparam);
|
||||||
},
|
},
|
||||||
(0, _) => return unsafe { DefWindowProcW(window, msg, wparam, lparam) },
|
(0, _) => return unsafe { DefWindowProcW(window, msg, wparam, lparam) },
|
||||||
_ => userdata as *mut WindowData<T>,
|
_ => userdata as *mut WindowData,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (result, userdata_removed, recurse_depth) = {
|
let (result, userdata_removed, recurse_depth) = {
|
||||||
|
|
@ -997,12 +1042,12 @@ pub(super) unsafe extern "system" fn public_window_callback<T: 'static>(
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn public_window_callback_inner<T: 'static>(
|
unsafe fn public_window_callback_inner(
|
||||||
window: HWND,
|
window: HWND,
|
||||||
msg: u32,
|
msg: u32,
|
||||||
wparam: WPARAM,
|
wparam: WPARAM,
|
||||||
lparam: LPARAM,
|
lparam: LPARAM,
|
||||||
userdata: &WindowData<T>,
|
userdata: &WindowData,
|
||||||
) -> LRESULT {
|
) -> LRESULT {
|
||||||
let mut result = ProcResult::DefWindowProc(wparam);
|
let mut result = ProcResult::DefWindowProc(wparam);
|
||||||
|
|
||||||
|
|
@ -2299,14 +2344,14 @@ unsafe fn public_window_callback_inner<T: 'static>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "system" fn thread_event_target_callback<T: 'static>(
|
unsafe extern "system" fn thread_event_target_callback(
|
||||||
window: HWND,
|
window: HWND,
|
||||||
msg: u32,
|
msg: u32,
|
||||||
wparam: WPARAM,
|
wparam: WPARAM,
|
||||||
lparam: LPARAM,
|
lparam: LPARAM,
|
||||||
) -> LRESULT {
|
) -> LRESULT {
|
||||||
let userdata_ptr =
|
let userdata_ptr =
|
||||||
unsafe { super::get_window_long(window, GWL_USERDATA) } as *mut ThreadMsgTargetData<T>;
|
unsafe { super::get_window_long(window, GWL_USERDATA) } as *mut ThreadMsgTargetData;
|
||||||
if userdata_ptr.is_null() {
|
if userdata_ptr.is_null() {
|
||||||
// `userdata_ptr` will always be null for the first `WM_GETMINMAXINFO`, as well as `WM_NCCREATE` and
|
// `userdata_ptr` will always be null for the first `WM_GETMINMAXINFO`, as well as `WM_NCCREATE` and
|
||||||
// `WM_CREATE`.
|
// `WM_CREATE`.
|
||||||
|
|
@ -2359,9 +2404,12 @@ unsafe extern "system" fn thread_event_target_callback<T: 'static>(
|
||||||
}
|
}
|
||||||
|
|
||||||
_ if msg == USER_EVENT_MSG_ID.get() => {
|
_ if msg == USER_EVENT_MSG_ID.get() => {
|
||||||
if let Ok(event) = userdata.user_event_receiver.recv() {
|
// synthesis a placeholder UserEvent, so that if the callback is
|
||||||
userdata.send_event(Event::UserEvent(event));
|
// re-entered it can be buffered for later delivery. the real
|
||||||
}
|
// user event is still in the mpsc channel and will be pulled
|
||||||
|
// once the placeholder event is delivered to the wrapper
|
||||||
|
// `event_handler`
|
||||||
|
userdata.send_event(Event::UserEvent(UserEventPlaceholder));
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
_ if msg == EXEC_MSG_ID.get() => {
|
_ if msg == EXEC_MSG_ID.get() => {
|
||||||
|
|
@ -2384,7 +2432,7 @@ unsafe extern "system" fn thread_event_target_callback<T: 'static>(
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn handle_raw_input<T: 'static>(userdata: &ThreadMsgTargetData<T>, data: RAWINPUT) {
|
unsafe fn handle_raw_input(userdata: &ThreadMsgTargetData, data: RAWINPUT) {
|
||||||
use crate::event::{
|
use crate::event::{
|
||||||
DeviceEvent::{Button, Key, Motion, MouseMotion, MouseWheel},
|
DeviceEvent::{Button, Key, Motion, MouseMotion, MouseWheel},
|
||||||
ElementState::{Pressed, Released},
|
ElementState::{Pressed, Released},
|
||||||
|
|
|
||||||
|
|
@ -416,7 +416,7 @@ impl<T> BufferedEvent<T> {
|
||||||
|
|
||||||
let window_flags = unsafe {
|
let window_flags = unsafe {
|
||||||
let userdata =
|
let userdata =
|
||||||
get_window_long(window_id.0.into(), GWL_USERDATA) as *mut WindowData<T>;
|
get_window_long(window_id.0.into(), GWL_USERDATA) as *mut WindowData;
|
||||||
(*userdata).window_state_lock().window_flags
|
(*userdata).window_state_lock().window_flags
|
||||||
};
|
};
|
||||||
window_flags.set_size((window_id.0).0, inner_size);
|
window_flags.set_size((window_id.0).0, inner_size);
|
||||||
|
|
|
||||||
|
|
@ -1127,7 +1127,7 @@ impl<'a, T: 'static> InitData<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_window_data(&self, win: &Window) -> event_loop::WindowData<T> {
|
unsafe fn create_window_data(&self, win: &Window) -> event_loop::WindowData {
|
||||||
let file_drop_handler = if self.pl_attribs.drag_and_drop {
|
let file_drop_handler = if self.pl_attribs.drag_and_drop {
|
||||||
let ole_init_result = unsafe { OleInitialize(ptr::null_mut()) };
|
let ole_init_result = unsafe { OleInitialize(ptr::null_mut()) };
|
||||||
// It is ok if the initialize result is `S_FALSE` because it might happen that
|
// It is ok if the initialize result is `S_FALSE` because it might happen that
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue