copilot: Track focus of modal + close modal on ESC (#9217)

Piotr Osiewicz created

I've also made Copilot's modal regain focus whenever you click on it, as
otherwise there's nothing inside of it that can gain focus. Clicks do
not fall through a modal, which I think is nice.



Release Notes:

- Fixed the issue where pressing ESC (`menu::Cancel`) did not exit the
Copilot modal. Fixes #8852

Change summary

Cargo.lock                       |  1 +
crates/copilot_ui/Cargo.toml     |  1 +
crates/copilot_ui/src/sign_in.rs | 12 ++++++++++--
3 files changed, 12 insertions(+), 2 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -2493,6 +2493,7 @@ dependencies = [
  "fs",
  "gpui",
  "language",
+ "menu",
  "settings",
  "ui",
  "util",

crates/copilot_ui/Cargo.toml 🔗

@@ -19,6 +19,7 @@ editor.workspace = true
 fs.workspace = true
 gpui.workspace = true
 language.workspace = true
+menu.workspace = true
 settings.workspace = true
 ui.workspace = true
 util.workspace = true

crates/copilot_ui/src/sign_in.rs 🔗

@@ -1,8 +1,8 @@
 use copilot::{request::PromptUserDeviceFlow, Copilot, Status};
 use gpui::{
     div, svg, AppContext, ClipboardItem, DismissEvent, Element, EventEmitter, FocusHandle,
-    FocusableView, InteractiveElement, IntoElement, Model, ParentElement, Render, Styled,
-    Subscription, ViewContext,
+    FocusableView, InteractiveElement, IntoElement, Model, MouseDownEvent, ParentElement, Render,
+    Styled, Subscription, ViewContext,
 };
 use ui::{prelude::*, Button, IconName, Label};
 use workspace::ModalView;
@@ -185,11 +185,19 @@ impl Render for CopilotCodeVerification {
 
         v_flex()
             .id("copilot code verification")
+            .track_focus(&self.focus_handle)
             .elevation_3(cx)
             .w_96()
             .items_center()
             .p_4()
             .gap_2()
+            .on_action(cx.listener(|_, _: &menu::Cancel, cx| {
+                cx.emit(DismissEvent);
+            }))
+            .capture_any_mouse_down(cx.listener(|this, _: &MouseDownEvent, cx| {
+                cx.focus(&this.focus_handle);
+                cx.stop_propagation();
+            }))
             .child(
                 svg()
                     .w_32()