From b1e22aa5597a57882e862ca03ef6440d9e5ec4dd Mon Sep 17 00:00:00 2001 From: Jurgis Date: Mon, 29 Jun 2020 01:17:27 +0300 Subject: [PATCH] Make drag and drop optional (fixes OleInitialize failure #1255) (#1524) Co-authored-by: Osspial --- CHANGELOG.md | 3 ++- src/platform/windows.rs | 14 ++++++++++++++ src/platform_impl/windows/event_loop.rs | 2 +- src/platform_impl/windows/mod.rs | 14 +++++++++++++- src/platform_impl/windows/window.rs | 13 ++++++++++--- 5 files changed, 40 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0888252c..8c042e13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ - On Unix, X11 and Wayland are now optional features (enabled by default) - On X11, fix deadlock when calling `set_fullscreen_inner`. - On Web, prevent the webpage from scrolling when the user is focused on a winit canvas - +- On Windows, drag and drop is now optional and must be enabled with `WindowBuilderExtWindows::with_drag_and_drop(true)`. - On Wayland, fix deadlock when calling to `set_inner_size` from a callback. - On macOS, add `hide__other_applications` to `EventLoopWindowTarget` via existing `EventLoopWindowTargetExtMacOS` trait. `hide_other_applications` will hide other applications by calling `-[NSApplication hideOtherApplications: nil]`. - On android added support for `run_return`. @@ -23,6 +23,7 @@ - On Web, replaced zero timeout for `ControlFlow::Poll` with `requestAnimationFrame` - On Web, fix a possible panic during event handling - On macOS, fix `EventLoopProxy` leaking memory for every instance. +- On Windows, drag and drop can now be disabled with `WindowBuilderExtWindows::with_drag_and_drop(false)`. # 0.22.0 (2020-03-09) diff --git a/src/platform/windows.rs b/src/platform/windows.rs index a356f1e1..a040be36 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -117,6 +117,14 @@ pub trait WindowBuilderExtWindows { /// This sets `WS_EX_NOREDIRECTIONBITMAP`. fn with_no_redirection_bitmap(self, flag: bool) -> WindowBuilder; + + /// Enables or disables drag and drop support (enabled by default). Will interfere with other crates + /// that use multi-threaded COM API (`CoInitializeEx` with `COINIT_MULTITHREADED` instead of + /// `COINIT_APARTMENTTHREADED`) on the same thread. Note that winit may still attempt to initialize + /// COM API regardless of this option. Currently only fullscreen mode does that, but there may be more in the future. + /// If you need COM API with `COINIT_MULTITHREADED` you must initialize it before calling any winit functions. + /// See https://docs.microsoft.com/en-us/windows/win32/api/objbase/nf-objbase-coinitialize#remarks for more information. + fn with_drag_and_drop(self, flag: bool) -> WindowBuilder; } impl WindowBuilderExtWindows for WindowBuilder { @@ -137,6 +145,12 @@ impl WindowBuilderExtWindows for WindowBuilder { self.platform_specific.no_redirection_bitmap = flag; self } + + #[inline] + fn with_drag_and_drop(mut self, flag: bool) -> WindowBuilder { + self.platform_specific.drag_and_drop = flag; + self + } } /// Additional methods on `MonitorHandle` that are specific to Windows. diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index a7deac50..739990a6 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -82,7 +82,7 @@ lazy_static! { pub(crate) struct SubclassInput { pub window_state: Arc>, pub event_loop_runner: EventLoopRunnerShared, - pub file_drop_handler: FileDropHandler, + pub file_drop_handler: Option, } impl SubclassInput { diff --git a/src/platform_impl/windows/mod.rs b/src/platform_impl/windows/mod.rs index 021c903b..498cdfb8 100644 --- a/src/platform_impl/windows/mod.rs +++ b/src/platform_impl/windows/mod.rs @@ -14,11 +14,23 @@ pub use self::icon::WinIcon as PlatformIcon; use crate::event::DeviceId as RootDeviceId; use crate::icon::Icon; -#[derive(Clone, Default)] +#[derive(Clone)] pub struct PlatformSpecificWindowBuilderAttributes { pub parent: Option, pub taskbar_icon: Option, pub no_redirection_bitmap: bool, + pub drag_and_drop: bool, +} + +impl Default for PlatformSpecificWindowBuilderAttributes { + fn default() -> Self { + Self { + parent: None, + taskbar_icon: None, + no_redirection_bitmap: false, + drag_and_drop: true, + } + } } unsafe impl Send for PlatformSpecificWindowBuilderAttributes {} diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 45a3b5de..0f4dcf8b 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -70,8 +70,9 @@ impl Window { // // done. you owe me -- ossi unsafe { + let drag_and_drop = pl_attr.drag_and_drop; init(w_attr, pl_attr, event_loop).map(|win| { - let file_drop_handler = { + let file_drop_handler = if drag_and_drop { use winapi::shared::winerror::{OLE_E_WRONGCOMPOBJ, RPC_E_CHANGED_MODE, S_OK}; let ole_init_result = ole2::OleInitialize(ptr::null_mut()); @@ -80,7 +81,11 @@ impl Window { if ole_init_result == OLE_E_WRONGCOMPOBJ { panic!("OleInitialize failed! Result was: `OLE_E_WRONGCOMPOBJ`"); } else if ole_init_result == RPC_E_CHANGED_MODE { - panic!("OleInitialize failed! Result was: `RPC_E_CHANGED_MODE`"); + panic!( + "OleInitialize failed! Result was: `RPC_E_CHANGED_MODE`. \ + Make sure other crates are not using multithreaded COM library \ + on the same thread or disable drag and drop support." + ); } let file_drop_runner = event_loop.runner_shared.clone(); @@ -99,7 +104,9 @@ impl Window { ole2::RegisterDragDrop(win.window.0, handler_interface_ptr), S_OK ); - file_drop_handler + Some(file_drop_handler) + } else { + None }; let subclass_input = event_loop::SubclassInput {