From 10053e2566c6c3312e2312088e40b757daeab189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=B0=8F=E7=99=BD?= <364772080@qq.com> Date: Sat, 22 Feb 2025 23:39:43 +0800 Subject: [PATCH] windows: Fix incorrect button ID setting for TaskDialog (#25391) Closes #22821 It turns out that on Windows, the `Cancel` button should **always** have a button ID of `2`. Even if the button label is something like "Don't Cancel", when the user presses the `Esc` key, Windows will still report that the button with ID `2` was pressed. Release Notes: - N/A --- crates/gpui/src/platform/windows/window.rs | 30 ++++++++++++++-------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/crates/gpui/src/platform/windows/window.rs b/crates/gpui/src/platform/windows/window.rs index d85762680adc0d83428e982dbf0cf3d53f2ada00..b3813b9a249620eca55de970ef3f30d87e878bf7 100644 --- a/crates/gpui/src/platform/windows/window.rs +++ b/crates/gpui/src/platform/windows/window.rs @@ -14,7 +14,6 @@ use ::util::ResultExt; use anyhow::{Context as _, Result}; use async_task::Runnable; use futures::channel::oneshot::{self, Receiver}; -use itertools::Itertools; use raw_window_handle as rwh; use smallvec::SmallVec; use windows::{ @@ -577,8 +576,7 @@ impl PlatformWindow for WindowsWindow { .executor .spawn(async move { unsafe { - let mut config; - config = std::mem::zeroed::(); + let mut config = TASKDIALOGCONFIG::default(); config.cbSize = std::mem::size_of::() as _; config.hwndParent = handle; let title; @@ -599,19 +597,26 @@ impl PlatformWindow for WindowsWindow { }; config.pszWindowTitle = title; config.Anonymous1.pszMainIcon = main_icon; - let instruction = msg.encode_utf16().chain(Some(0)).collect_vec(); + let instruction = HSTRING::from(msg); config.pszMainInstruction = PCWSTR::from_raw(instruction.as_ptr()); let hints_encoded; if let Some(ref hints) = detail_string { - hints_encoded = hints.encode_utf16().chain(Some(0)).collect_vec(); + hints_encoded = HSTRING::from(hints); config.pszContent = PCWSTR::from_raw(hints_encoded.as_ptr()); }; + let mut button_id_map = Vec::with_capacity(answers.len()); let mut buttons = Vec::new(); let mut btn_encoded = Vec::new(); for (index, btn_string) in answers.iter().enumerate() { - let encoded = btn_string.encode_utf16().chain(Some(0)).collect_vec(); + let encoded = HSTRING::from(btn_string); + let button_id = if btn_string == "Cancel" { + IDCANCEL.0 + } else { + index as i32 - 100 + }; + button_id_map.push(button_id); buttons.push(TASKDIALOG_BUTTON { - nButtonID: index as _, + nButtonID: button_id, pszButtonText: PCWSTR::from_raw(encoded.as_ptr()), }); btn_encoded.push(encoded); @@ -622,9 +627,14 @@ impl PlatformWindow for WindowsWindow { config.pfCallback = None; let mut res = std::mem::zeroed(); let _ = TaskDialogIndirect(&config, Some(&mut res), None, None) - .inspect_err(|e| log::error!("unable to create task dialog: {}", e)); - - let _ = done_tx.send(res as usize); + .context("unable to create task dialog") + .log_err(); + + let clicked = button_id_map + .iter() + .position(|&button_id| button_id == res) + .unwrap(); + let _ = done_tx.send(clicked); } }) .detach();