windows: Show error messages when zed failed to lanuch (#32537)

Now, if either `WindowsPlatform` or `BladeRenderer` fails to initialize,
a window will pop up to notify the user.


![image](https://github.com/user-attachments/assets/40fe7f1d-5218-4ee2-b4ec-0945fed2b743)


Release Notes:

- N/A
This commit is contained in:
张小白 2025-06-11 18:37:34 +08:00 committed by GitHub
parent 7d5a5d0984
commit a3cc063107
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 33 additions and 13 deletions

View file

@ -142,7 +142,11 @@ pub fn guess_compositor() -> &'static str {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub(crate) fn current_platform(_headless: bool) -> Rc<dyn Platform> { pub(crate) fn current_platform(_headless: bool) -> Rc<dyn Platform> {
Rc::new(WindowsPlatform::new()) Rc::new(
WindowsPlatform::new()
.inspect_err(|err| show_error("Error: Zed failed to launch", err.to_string()))
.unwrap(),
)
} }
pub(crate) trait Platform: 'static { pub(crate) trait Platform: 'static {

View file

@ -342,7 +342,7 @@ impl BladeRenderer {
let surface = context let surface = context
.gpu .gpu
.create_surface_configured(window, surface_config) .create_surface_configured(window, surface_config)
.unwrap(); .map_err(|err| anyhow::anyhow!("Failed to create surface: {err:?}"))?;
let command_encoder = context.gpu.create_command_encoder(gpu::CommandEncoderDesc { let command_encoder = context.gpu.create_command_encoder(gpu::CommandEncoderDesc {
name: "main", name: "main",

View file

@ -81,9 +81,9 @@ impl WindowsPlatformState {
} }
impl WindowsPlatform { impl WindowsPlatform {
pub(crate) fn new() -> Self { pub(crate) fn new() -> Result<Self> {
unsafe { unsafe {
OleInitialize(None).expect("unable to initialize Windows OLE"); OleInitialize(None).context("unable to initialize Windows OLE")?;
} }
let (main_sender, main_receiver) = flume::unbounded::<Runnable>(); let (main_sender, main_receiver) = flume::unbounded::<Runnable>();
let main_thread_id_win32 = unsafe { GetCurrentThreadId() }; let main_thread_id_win32 = unsafe { GetCurrentThreadId() };
@ -97,19 +97,19 @@ impl WindowsPlatform {
let foreground_executor = ForegroundExecutor::new(dispatcher); let foreground_executor = ForegroundExecutor::new(dispatcher);
let bitmap_factory = ManuallyDrop::new(unsafe { let bitmap_factory = ManuallyDrop::new(unsafe {
CoCreateInstance(&CLSID_WICImagingFactory, None, CLSCTX_INPROC_SERVER) CoCreateInstance(&CLSID_WICImagingFactory, None, CLSCTX_INPROC_SERVER)
.expect("Error creating bitmap factory.") .context("Error creating bitmap factory.")?
}); });
let text_system = Arc::new( let text_system = Arc::new(
DirectWriteTextSystem::new(&bitmap_factory) DirectWriteTextSystem::new(&bitmap_factory)
.expect("Error creating DirectWriteTextSystem"), .context("Error creating DirectWriteTextSystem")?,
); );
let icon = load_icon().unwrap_or_default(); let icon = load_icon().unwrap_or_default();
let state = RefCell::new(WindowsPlatformState::new()); let state = RefCell::new(WindowsPlatformState::new());
let raw_window_handles = RwLock::new(SmallVec::new()); let raw_window_handles = RwLock::new(SmallVec::new());
let gpu_context = BladeContext::new().expect("Unable to init GPU context"); let gpu_context = BladeContext::new().context("Unable to init GPU context")?;
let windows_version = WindowsVersion::new().expect("Error retrieve windows version"); let windows_version = WindowsVersion::new().context("Error retrieve windows version")?;
Self { Ok(Self {
state, state,
raw_window_handles, raw_window_handles,
gpu_context, gpu_context,
@ -122,7 +122,7 @@ impl WindowsPlatform {
bitmap_factory, bitmap_factory,
validation_number, validation_number,
main_thread_id_win32, main_thread_id_win32,
} })
} }
fn redraw_all(&self) { fn redraw_all(&self) {

View file

@ -8,7 +8,7 @@ use windows::{
}, },
Wdk::System::SystemServices::RtlGetVersion, Wdk::System::SystemServices::RtlGetVersion,
Win32::{Foundation::*, Graphics::Dwm::*, UI::WindowsAndMessaging::*}, Win32::{Foundation::*, Graphics::Dwm::*, UI::WindowsAndMessaging::*},
core::BOOL, core::{BOOL, HSTRING},
}; };
use crate::*; use crate::*;
@ -186,3 +186,14 @@ pub(crate) fn system_appearance() -> Result<WindowAppearance> {
fn is_color_light(color: &Color) -> bool { fn is_color_light(color: &Color) -> bool {
((5 * color.G as u32) + (2 * color.R as u32) + color.B as u32) > (8 * 128) ((5 * color.G as u32) + (2 * color.R as u32) + color.B as u32) > (8 * 128)
} }
pub(crate) fn show_error(title: &str, content: String) {
let _ = unsafe {
MessageBoxW(
None,
&HSTRING::from(content),
&HSTRING::from(title),
MB_ICONERROR | MB_SYSTEMMODAL,
)
};
}

View file

@ -1258,7 +1258,7 @@ mod windows_renderer {
use std::num::NonZeroIsize; use std::num::NonZeroIsize;
use windows::Win32::{Foundation::HWND, UI::WindowsAndMessaging::GWLP_HINSTANCE}; use windows::Win32::{Foundation::HWND, UI::WindowsAndMessaging::GWLP_HINSTANCE};
use crate::get_window_long; use crate::{get_window_long, show_error};
pub(super) fn init( pub(super) fn init(
context: &BladeContext, context: &BladeContext,
@ -1270,7 +1270,12 @@ mod windows_renderer {
size: Default::default(), size: Default::default(),
transparent, transparent,
}; };
BladeRenderer::new(context, &raw, config) BladeRenderer::new(context, &raw, config).inspect_err(|err| {
show_error(
"Error: Zed failed to initialize BladeRenderer",
err.to_string(),
)
})
} }
struct RawWindow { struct RawWindow {