diff --git a/crates/gpui/src/platform/windows/platform.rs b/crates/gpui/src/platform/windows/platform.rs index ba3db5e8e7..2fd7bad5ff 100644 --- a/crates/gpui/src/platform/windows/platform.rs +++ b/crates/gpui/src/platform/windows/platform.rs @@ -14,7 +14,7 @@ use std::{ }; use ::util::{ResultExt, SemanticVersion}; -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, Context, Result}; use async_task::Runnable; use copypasta::{ClipboardContext, ClipboardProvider}; use futures::channel::oneshot::{self, Receiver}; @@ -62,6 +62,7 @@ pub(crate) struct WindowsPlatformInner { pub raw_window_handles: RwLock>, pub(crate) dispatch_event: OwnedHandle, pub(crate) settings: RefCell, + pub icon: HICON, } impl WindowsPlatformInner { @@ -156,6 +157,7 @@ impl WindowsPlatform { let callbacks = Mutex::new(Callbacks::default()); let raw_window_handles = RwLock::new(SmallVec::new()); let settings = RefCell::new(WindowsPlatformSystemSettings::new()); + let icon = load_icon().unwrap_or_default(); let inner = Rc::new(WindowsPlatformInner { background_executor, foreground_executor, @@ -165,6 +167,7 @@ impl WindowsPlatform { raw_window_handles, dispatch_event, settings, + icon, }); Self { inner } } @@ -881,3 +884,19 @@ fn fallback_vsync_fn() -> impl Fn(HANDLE) -> bool + Send { (unsafe { WaitForSingleObject(timer_stop_event, interval) }) == WAIT_TIMEOUT } } + +fn load_icon() -> Result { + let module = unsafe { GetModuleHandleW(None).context("unable to get module handle")? }; + let handle = unsafe { + LoadImageW( + module, + IDI_APPLICATION, + IMAGE_ICON, + 0, + 0, + LR_DEFAULTSIZE | LR_SHARED, + ) + .context("unable to load icon file")? + }; + Ok(HICON(handle.0)) +} diff --git a/crates/gpui/src/platform/windows/window.rs b/crates/gpui/src/platform/windows/window.rs index 094c45108a..7bbf8645ef 100644 --- a/crates/gpui/src/platform/windows/window.rs +++ b/crates/gpui/src/platform/windows/window.rs @@ -1097,7 +1097,7 @@ impl WindowsWindow { handle: AnyWindowHandle, options: WindowParams, ) -> Self { - let classname = register_wnd_class(); + let classname = register_wnd_class(platform_inner.icon); let hide_title_bar = options .titlebar .as_ref() @@ -1556,13 +1556,14 @@ impl IDropTarget_Impl for WindowsDragDropHandler { } } -fn register_wnd_class() -> PCWSTR { +fn register_wnd_class(icon_handle: HICON) -> PCWSTR { const CLASS_NAME: PCWSTR = w!("Zed::Window"); static ONCE: Once = Once::new(); ONCE.call_once(|| { let wc = WNDCLASSW { lpfnWndProc: Some(wnd_proc), + hIcon: icon_handle, hCursor: unsafe { LoadCursorW(None, IDC_ARROW).ok().unwrap() }, lpszClassName: PCWSTR(CLASS_NAME.as_ptr()), style: CS_HREDRAW | CS_VREDRAW, diff --git a/crates/zed/build.rs b/crates/zed/build.rs index c40c15737d..e17cf0bb55 100644 --- a/crates/zed/build.rs +++ b/crates/zed/build.rs @@ -50,15 +50,18 @@ fn main() { println!("cargo:rustc-link-arg=/stack:{}", 8 * 1024 * 1024); let manifest = std::path::Path::new("resources/windows/manifest.xml"); + let icon = std::path::Path::new("resources/windows/app-icon.ico"); println!("cargo:rerun-if-changed={}", manifest.display()); - println!("cargo:rustc-link-arg-bins=/MANIFEST:EMBED"); + println!("cargo:rerun-if-changed={}", icon.display()); + println!("cargo:rustc-link-arg-bins=/MANIFEST:EMBED"); println!( "cargo:rustc-link-arg-bins=/MANIFESTINPUT:{}", manifest.canonicalize().unwrap().display() ); - let res = winresource::WindowsResource::new(); + let mut res = winresource::WindowsResource::new(); + res.set_icon(icon.to_str().unwrap()); if let Err(e) = res.compile() { eprintln!("{}", e); std::process::exit(1); diff --git a/crates/zed/resources/windows/app-icon.ico b/crates/zed/resources/windows/app-icon.ico new file mode 100644 index 0000000000..321e90fcfa Binary files /dev/null and b/crates/zed/resources/windows/app-icon.ico differ