diff --git a/crates/gpui/src/platform/test/platform.rs b/crates/gpui/src/platform/test/platform.rs index 31f48511d7..e26f29e463 100644 --- a/crates/gpui/src/platform/test/platform.rs +++ b/crates/gpui/src/platform/test/platform.rs @@ -13,6 +13,11 @@ use std::{ rc::{Rc, Weak}, sync::Arc, }; +#[cfg(target_os = "windows")] +use windows::Win32::{ + Graphics::Imaging::{CLSID_WICImagingFactory, IWICImagingFactory}, + System::Com::{CoCreateInstance, CLSCTX_INPROC_SERVER}, +}; /// TestPlatform implements the Platform trait for use in tests. pub(crate) struct TestPlatform { @@ -28,6 +33,8 @@ pub(crate) struct TestPlatform { pub(crate) prompts: RefCell, pub opened_url: RefCell>, pub text_system: Arc, + #[cfg(target_os = "windows")] + bitmap_factory: std::mem::ManuallyDrop, weak: Weak, } @@ -40,10 +47,14 @@ pub(crate) struct TestPrompts { impl TestPlatform { pub fn new(executor: BackgroundExecutor, foreground_executor: ForegroundExecutor) -> Rc { #[cfg(target_os = "windows")] - unsafe { + let bitmap_factory = unsafe { windows::Win32::System::Ole::OleInitialize(None) .expect("unable to initialize Windows OLE"); - } + std::mem::ManuallyDrop::new( + CoCreateInstance(&CLSID_WICImagingFactory, None, CLSCTX_INPROC_SERVER) + .expect("Error creating bitmap factory."), + ) + }; #[cfg(target_os = "macos")] let text_system = Arc::new(crate::platform::mac::MacTextSystem::new()); @@ -52,7 +63,10 @@ impl TestPlatform { let text_system = Arc::new(crate::platform::linux::CosmicTextSystem::new()); #[cfg(target_os = "windows")] - let text_system = Arc::new(crate::platform::windows::DirectWriteTextSystem::new().unwrap()); + let text_system = Arc::new( + crate::platform::windows::DirectWriteTextSystem::new(&bitmap_factory) + .expect("Unable to initialize direct write."), + ); Rc::new_cyclic(|weak| TestPlatform { background_executor: executor, @@ -66,6 +80,8 @@ impl TestPlatform { current_primary_item: Mutex::new(None), weak: weak.clone(), opened_url: Default::default(), + #[cfg(target_os = "windows")] + bitmap_factory, text_system, }) } @@ -303,3 +319,13 @@ impl Platform for TestPlatform { unimplemented!() } } + +#[cfg(target_os = "windows")] +impl Drop for TestPlatform { + fn drop(&mut self) { + unsafe { + std::mem::ManuallyDrop::drop(&mut self.bitmap_factory); + windows::Win32::System::Ole::OleUninitialize(); + } + } +} diff --git a/crates/gpui/src/platform/windows/direct_write.rs b/crates/gpui/src/platform/windows/direct_write.rs index aad8e09322..6155f2edec 100644 --- a/crates/gpui/src/platform/windows/direct_write.rs +++ b/crates/gpui/src/platform/windows/direct_write.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, mem::ManuallyDrop, sync::Arc}; +use std::{borrow::Cow, sync::Arc}; use ::util::ResultExt; use anyhow::{anyhow, Result}; @@ -16,9 +16,9 @@ use windows::{ DirectWrite::*, Dxgi::Common::*, Gdi::LOGFONTW, - Imaging::{D2D::IWICImagingFactory2, *}, + Imaging::*, }, - System::{Com::*, SystemServices::LOCALE_NAME_MAX_LENGTH}, + System::SystemServices::LOCALE_NAME_MAX_LENGTH, UI::WindowsAndMessaging::*, }, }; @@ -40,7 +40,7 @@ pub(crate) struct DirectWriteTextSystem(RwLock); struct DirectWriteComponent { locale: String, factory: IDWriteFactory5, - bitmap_factory: ManuallyDrop, + bitmap_factory: AgileReference, d2d1_factory: ID2D1Factory, in_memory_loader: IDWriteInMemoryFontFileLoader, builder: IDWriteFontSetBuilder1, @@ -53,10 +53,6 @@ struct GlyphRenderContext { dc_target: ID2D1DeviceContext4, } -// All use of the IUnknown methods should be "thread-safe". -unsafe impl Sync for DirectWriteComponent {} -unsafe impl Send for DirectWriteComponent {} - struct DirectWriteState { components: DirectWriteComponent, system_ui_font_name: SharedString, @@ -75,12 +71,10 @@ struct FontIdentifier { } impl DirectWriteComponent { - pub fn new() -> Result { + pub fn new(bitmap_factory: &IWICImagingFactory) -> Result { unsafe { let factory: IDWriteFactory5 = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED)?; - let bitmap_factory: IWICImagingFactory2 = - CoCreateInstance(&CLSID_WICImagingFactory2, None, CLSCTX_INPROC_SERVER)?; - let bitmap_factory = ManuallyDrop::new(bitmap_factory); + let bitmap_factory = AgileReference::new(bitmap_factory)?; let d2d1_factory: ID2D1Factory = D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, None)?; // The `IDWriteInMemoryFontFileLoader` here is supported starting from @@ -145,8 +139,8 @@ impl GlyphRenderContext { } impl DirectWriteTextSystem { - pub(crate) fn new() -> Result { - let components = DirectWriteComponent::new()?; + pub(crate) fn new(bitmap_factory: &IWICImagingFactory) -> Result { + let components = DirectWriteComponent::new(bitmap_factory)?; let system_font_collection = unsafe { let mut result = std::mem::zeroed(); components @@ -172,11 +166,6 @@ impl DirectWriteTextSystem { font_id_by_identifier: HashMap::default(), }))) } - - pub(crate) fn destroy(&self) { - let mut lock = self.0.write(); - unsafe { ManuallyDrop::drop(&mut lock.components.bitmap_factory) }; - } } impl PlatformTextSystem for DirectWriteTextSystem { @@ -798,8 +787,9 @@ impl DirectWriteState { bitmap_dpi = 192.0; } + let bitmap_factory = self.components.bitmap_factory.resolve()?; unsafe { - let bitmap = self.components.bitmap_factory.CreateBitmap( + let bitmap = bitmap_factory.CreateBitmap( bitmap_width, bitmap_height, bitmap_format, @@ -901,7 +891,7 @@ impl DirectWriteState { pixel[2] = (pixel[2] as f32 / a) as u8; } } else { - let scaler = self.components.bitmap_factory.CreateBitmapScaler()?; + let scaler = bitmap_factory.CreateBitmapScaler()?; scaler.Initialize( &bitmap, bitmap_size.width.0 as u32, diff --git a/crates/gpui/src/platform/windows/platform.rs b/crates/gpui/src/platform/windows/platform.rs index 82c2353019..45e404788d 100644 --- a/crates/gpui/src/platform/windows/platform.rs +++ b/crates/gpui/src/platform/windows/platform.rs @@ -4,6 +4,7 @@ use std::{ cell::{Cell, RefCell}, ffi::{c_void, OsString}, + mem::ManuallyDrop, os::windows::ffi::{OsStrExt, OsStringExt}, path::{Path, PathBuf}, rc::Rc, @@ -21,7 +22,10 @@ use windows::{ Win32::{ Foundation::*, Globalization::u_memcpy, - Graphics::Gdi::*, + Graphics::{ + Gdi::*, + Imaging::{CLSID_WICImagingFactory, IWICImagingFactory}, + }, Security::Credentials::*, System::{ Com::*, @@ -53,6 +57,7 @@ pub(crate) struct WindowsPlatform { clipboard_hash_format: u32, clipboard_metadata_format: u32, windows_version: WindowsVersion, + bitmap_factory: ManuallyDrop, } pub(crate) struct WindowsPlatformState { @@ -91,8 +96,14 @@ impl WindowsPlatform { let dispatcher = Arc::new(WindowsDispatcher::new()); let background_executor = BackgroundExecutor::new(dispatcher.clone()); let foreground_executor = ForegroundExecutor::new(dispatcher); - let text_system = - Arc::new(DirectWriteTextSystem::new().expect("Error creating DirectWriteTextSystem")); + let bitmap_factory = ManuallyDrop::new(unsafe { + CoCreateInstance(&CLSID_WICImagingFactory, None, CLSCTX_INPROC_SERVER) + .expect("Error creating bitmap factory.") + }); + let text_system = Arc::new( + DirectWriteTextSystem::new(&bitmap_factory) + .expect("Error creating DirectWriteTextSystem"), + ); let icon = load_icon().unwrap_or_default(); let state = RefCell::new(WindowsPlatformState::new()); let raw_window_handles = RwLock::new(SmallVec::new()); @@ -111,6 +122,7 @@ impl WindowsPlatform { clipboard_hash_format, clipboard_metadata_format, windows_version, + bitmap_factory, } } @@ -584,8 +596,10 @@ impl Platform for WindowsPlatform { impl Drop for WindowsPlatform { fn drop(&mut self) { - self.text_system.destroy(); - unsafe { OleUninitialize() }; + unsafe { + ManuallyDrop::drop(&mut self.bitmap_factory); + OleUninitialize(); + } } }