linux: Prompt library fixes (#16850)

apricotbucket28 and Junkui Zhang created

This PR fixes two issues:
1. The prompt library window didn't set an `app_id` on Linux, which
caused it to be missing the Zed logo
2. A dangling reference to the window in the Wayland client code, which
caused the prompt library window not to close. See:
https://github.com/zed-industries/zed/pull/13201

Release Notes:

- Linux: Fixed the prompt library not closing on Wayland

---------

Co-authored-by: Junkui Zhang <364772080@qq.com>

Change summary

Cargo.lock                                       | 1 +
crates/assistant/Cargo.toml                      | 7 ++++---
crates/assistant/src/prompt_library.rs           | 5 ++++-
crates/gpui/src/platform.rs                      | 3 ++-
crates/gpui/src/platform/linux/wayland/client.rs | 3 ++-
5 files changed, 13 insertions(+), 6 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -406,6 +406,7 @@ dependencies = [
  "proto",
  "rand 0.8.5",
  "regex",
+ "release_channel",
  "rope",
  "schemars",
  "search",

crates/assistant/Cargo.toml 🔗

@@ -32,8 +32,8 @@ client.workspace = true
 clock.workspace = true
 collections.workspace = true
 command_palette_hooks.workspace = true
-db.workspace = true
 context_servers.workspace = true
+db.workspace = true
 editor.workspace = true
 feature_flags.workspace = true
 fs.workspace = true
@@ -58,9 +58,11 @@ open_ai = { workspace = true, features = ["schemars"] }
 ordered-float.workspace = true
 parking_lot.workspace = true
 paths.workspace = true
+picker.workspace = true
 project.workspace = true
 proto.workspace = true
 regex.workspace = true
+release_channel.workspace = true
 rope.workspace = true
 schemars.workspace = true
 search.workspace = true
@@ -68,8 +70,8 @@ semantic_index.workspace = true
 serde.workspace = true
 serde_json.workspace = true
 settings.workspace = true
-smallvec.workspace = true
 similar.workspace = true
+smallvec.workspace = true
 smol.workspace = true
 telemetry_events.workspace = true
 terminal.workspace = true
@@ -81,7 +83,6 @@ ui.workspace = true
 util.workspace = true
 uuid.workspace = true
 workspace.workspace = true
-picker.workspace = true
 zed_actions.workspace = true
 
 [dev-dependencies]

crates/assistant/src/prompt_library.rs 🔗

@@ -23,6 +23,7 @@ use language_model::{
 };
 use parking_lot::RwLock;
 use picker::{Picker, PickerDelegate};
+use release_channel::ReleaseChannel;
 use rope::Rope;
 use serde::{Deserialize, Serialize};
 use settings::Settings;
@@ -94,14 +95,16 @@ pub fn open_prompt_library(
         cx.spawn(|cx| async move {
             let store = store.await?;
             cx.update(|cx| {
+                let app_id = ReleaseChannel::global(cx).app_id();
                 let bounds = Bounds::centered(None, size(px(1024.0), px(768.0)), cx);
                 cx.open_window(
                     WindowOptions {
                         titlebar: Some(TitlebarOptions {
                             title: Some("Prompt Library".into()),
-                            appears_transparent: !cfg!(windows),
+                            appears_transparent: cfg!(target_os = "macos"),
                             traffic_light_position: Some(point(px(9.0), px(9.0))),
                         }),
+                        app_id: Some(app_id.to_owned()),
                         window_bounds: Some(WindowBounds::Windowed(bounds)),
                         ..Default::default()
                     },

crates/gpui/src/platform.rs 🔗

@@ -815,7 +815,8 @@ pub struct TitlebarOptions {
     /// The initial title of the window
     pub title: Option<SharedString>,
 
-    /// Whether the titlebar should appear transparent (macOS only)
+    /// Should the default system titlebar be hidden to allow for a custom-drawn titlebar? (macOS and Windows only)
+    /// Refer to [`WindowOptions::window_decorations`] on Linux
     pub appears_transparent: bool,
 
     /// The position of the macOS traffic light buttons

crates/gpui/src/platform/linux/wayland/client.rs 🔗

@@ -982,7 +982,8 @@ impl Dispatch<xdg_toplevel::XdgToplevel, ObjectId> for WaylandClientStatePtr {
         let should_close = window.handle_toplevel_event(event);
 
         if should_close {
-            this.drop_window(surface_id);
+            // The close logic will be handled in drop_window()
+            window.close();
         }
     }
 }