Fix 100s freeze on boot on X11 (#13156)

Conrad Irwin created

Release Notes:

- Fixed switching between dark and light mode with no windows open.

Change summary

crates/gpui/src/app.rs                               |  1 
crates/gpui/src/platform/linux/platform.rs           | 10 --
crates/gpui/src/platform/linux/wayland/client.rs     | 18 ----
crates/gpui/src/platform/linux/xdg_desktop_portal.rs | 54 ++++---------
crates/gpui/src/window.rs                            |  2 
5 files changed, 23 insertions(+), 62 deletions(-)

Detailed changes

crates/gpui/src/app.rs 🔗

@@ -479,6 +479,7 @@ impl AppContext {
                 Ok(mut window) => {
                     let root_view = build_root_view(&mut WindowContext::new(cx, &mut window));
                     window.root_view.replace(root_view.into());
+                    WindowContext::new(cx, &mut window).defer(|cx| cx.appearance_changed());
                     cx.window_handles.insert(id, window.handle);
                     cx.windows.get_mut(id).unwrap().replace(window);
                     Ok(handle)

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

@@ -34,7 +34,6 @@ use wayland_protocols::wp::cursor_shape::v1::client::wp_cursor_shape_device_v1::
 use xkbcommon::xkb::{self, Keycode, Keysym, State};
 
 use crate::platform::linux::wayland::WaylandClient;
-use crate::platform::linux::xdg_desktop_portal::{should_auto_hide_scrollbars, window_appearance};
 use crate::{
     px, Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CosmicTextSystem, CursorStyle,
     DisplayId, ForegroundExecutor, Keymap, Keystroke, LinuxDispatcher, Menu, MenuItem, Modifiers,
@@ -105,18 +104,13 @@ impl LinuxCommon {
         let dispatcher = Arc::new(LinuxDispatcher::new(main_sender.clone()));
 
         let background_executor = BackgroundExecutor::new(dispatcher.clone());
-        let appearance = window_appearance(&background_executor)
-            .log_err()
-            .unwrap_or(WindowAppearance::Light);
-        let auto_hide_scrollbars =
-            should_auto_hide_scrollbars(&background_executor).unwrap_or(false);
 
         let common = LinuxCommon {
             background_executor,
             foreground_executor: ForegroundExecutor::new(dispatcher.clone()),
             text_system,
-            appearance,
-            auto_hide_scrollbars,
+            appearance: WindowAppearance::Light,
+            auto_hide_scrollbars: false,
             callbacks,
             signal,
             menus: Vec::new(),

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

@@ -63,9 +63,7 @@ use crate::platform::linux::is_within_click_distance;
 use crate::platform::linux::wayland::cursor::Cursor;
 use crate::platform::linux::wayland::serial::{SerialKind, SerialTracker};
 use crate::platform::linux::wayland::window::WaylandWindow;
-use crate::platform::linux::xdg_desktop_portal::{
-    cursor_settings, Event as XDPEvent, XDPEventSource,
-};
+use crate::platform::linux::xdg_desktop_portal::{Event as XDPEvent, XDPEventSource};
 use crate::platform::linux::LinuxClient;
 use crate::platform::PlatformWindow;
 use crate::{
@@ -464,8 +462,6 @@ impl WaylandClient {
             })
             .unwrap();
 
-        let foreground = common.foreground_executor.clone();
-
         let mut state = Rc::new(RefCell::new(WaylandClientState {
             serial_tracker: SerialTracker::new(),
             globals,
@@ -527,18 +523,6 @@ impl WaylandClient {
             pending_open_uri: None,
         }));
 
-        foreground
-            .spawn({
-                let state = state.clone();
-                async move {
-                    if let Ok((theme, size)) = cursor_settings().await {
-                        let mut state = state.borrow_mut();
-                        state.cursor.set_theme(theme.as_str(), size);
-                    }
-                }
-            })
-            .detach();
-
         WaylandSource::new(conn, event_queue)
             .insert(handle)
             .unwrap();

crates/gpui/src/platform/linux/xdg_desktop_portal.rs 🔗

@@ -29,6 +29,24 @@ impl XDPEventSource {
             .spawn(async move {
                 let settings = Settings::new().await?;
 
+                if let Ok(initial_appearance) = settings.color_scheme().await {
+                    sender.send(Event::WindowAppearance(WindowAppearance::from_native(
+                        initial_appearance,
+                    )))?;
+                }
+                if let Ok(initial_theme) = settings
+                    .read::<String>("org.gnome.desktop.interface", "cursor-theme")
+                    .await
+                {
+                    sender.send(Event::CursorTheme(initial_theme))?;
+                }
+                if let Ok(initial_size) = settings
+                    .read::<u32>("org.gnome.desktop.interface", "cursor-size")
+                    .await
+                {
+                    sender.send(Event::CursorSize(initial_size))?;
+                }
+
                 if let Ok(mut cursor_theme_changed) = settings
                     .receive_setting_changed_with_args(
                         "org.gnome.desktop.interface",
@@ -147,39 +165,3 @@ impl WindowAppearance {
         *self = Self::from_native(cs);
     }
 }
-
-pub fn window_appearance(executor: &BackgroundExecutor) -> Result<WindowAppearance, anyhow::Error> {
-    executor.block(async {
-        let settings = Settings::new().await?;
-
-        let scheme = settings.color_scheme().await?;
-
-        let appearance = WindowAppearance::from_native(scheme);
-
-        Ok(appearance)
-    })
-}
-
-pub fn should_auto_hide_scrollbars(executor: &BackgroundExecutor) -> Result<bool, anyhow::Error> {
-    executor.block(async {
-        let settings = Settings::new().await?;
-        let auto_hide = settings
-            .read::<bool>("org.gnome.desktop.interface", "overlay-scrolling")
-            .await?;
-
-        Ok(auto_hide)
-    })
-}
-
-pub async fn cursor_settings() -> Result<(String, Option<u32>), anyhow::Error> {
-    let settings = Settings::new().await?;
-    let cursor_theme = settings
-        .read::<String>("org.gnome.desktop.interface", "cursor-theme")
-        .await?;
-    let cursor_size = settings
-        .read::<u32>("org.gnome.desktop.interface", "cursor-size")
-        .await
-        .ok();
-
-    Ok((cursor_theme, cursor_size))
-}

crates/gpui/src/window.rs 🔗

@@ -1158,7 +1158,7 @@ impl<'a> WindowContext<'a> {
         self.window.platform_window.is_fullscreen()
     }
 
-    fn appearance_changed(&mut self) {
+    pub(crate) fn appearance_changed(&mut self) {
         self.window.appearance = self.window.platform_window.appearance();
 
         self.window