window.rs

   1use std::{
   2    cell::{Ref, RefCell, RefMut},
   3    ffi::c_void,
   4    ptr::NonNull,
   5    rc::Rc,
   6    sync::{
   7        Arc,
   8        atomic::{AtomicBool, Ordering::SeqCst},
   9    },
  10};
  11
  12use accesskit::TreeUpdate;
  13use collections::{FxHashSet, HashMap};
  14use futures::channel::oneshot::Receiver;
  15
  16use raw_window_handle as rwh;
  17use wayland_backend::client::ObjectId;
  18use wayland_client::WEnum;
  19use wayland_client::{
  20    Proxy,
  21    protocol::{wl_output, wl_surface},
  22};
  23use wayland_protocols::wp::viewporter::client::wp_viewport;
  24use wayland_protocols::xdg::decoration::zv1::client::zxdg_toplevel_decoration_v1;
  25use wayland_protocols::xdg::shell::client::xdg_surface;
  26use wayland_protocols::xdg::shell::client::xdg_toplevel::{self};
  27use wayland_protocols::{
  28    wp::fractional_scale::v1::client::wp_fractional_scale_v1,
  29    xdg::dialog::v1::client::xdg_dialog_v1::XdgDialogV1,
  30};
  31use wayland_protocols_plasma::blur::client::org_kde_kwin_blur;
  32use wayland_protocols_wlr::layer_shell::v1::client::zwlr_layer_surface_v1;
  33
  34use crate::linux::wayland::{display::WaylandDisplay, serial::SerialKind};
  35use crate::linux::{Globals, Output, WaylandClientStatePtr, get_window};
  36use gpui::{
  37    AnyWindowHandle, Bounds, Capslock, Decorations, DevicePixels, GpuSpecs, Modifiers, Pixels,
  38    PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point,
  39    PromptButton, PromptLevel, RequestFrameOptions, ResizeEdge, Scene, Size, Tiling,
  40    TrivialActivationHandler, TrivialDeactivationHandler, WindowAppearance,
  41    WindowBackgroundAppearance, WindowBounds, WindowControlArea, WindowControls,
  42    WindowDecorations, WindowKind, WindowParams, layer_shell::LayerShellNotSupportedError, px,
  43    size,
  44};
  45use gpui_wgpu::{CompositorGpuHint, WgpuRenderer, WgpuSurfaceConfig};
  46
  47#[derive(Default)]
  48pub(crate) struct Callbacks {
  49    request_frame: Option<Box<dyn FnMut(RequestFrameOptions)>>,
  50    input: Option<Box<dyn FnMut(gpui::PlatformInput) -> gpui::DispatchEventResult>>,
  51    active_status_change: Option<Box<dyn FnMut(bool)>>,
  52    hover_status_change: Option<Box<dyn FnMut(bool)>>,
  53    resize: Option<Box<dyn FnMut(Size<Pixels>, f32)>>,
  54    moved: Option<Box<dyn FnMut()>>,
  55    should_close: Option<Box<dyn FnMut() -> bool>>,
  56    close: Option<Box<dyn FnOnce()>>,
  57    appearance_changed: Option<Box<dyn FnMut()>>,
  58}
  59
  60struct RawWindow {
  61    window: *mut c_void,
  62    display: *mut c_void,
  63}
  64
  65// Safety: The raw pointers in RawWindow point to Wayland surface/display
  66// which are valid for the window's lifetime. These are used only for
  67// passing to wgpu which needs Send+Sync for surface creation.
  68unsafe impl Send for RawWindow {}
  69unsafe impl Sync for RawWindow {}
  70
  71impl rwh::HasWindowHandle for RawWindow {
  72    fn window_handle(&self) -> Result<rwh::WindowHandle<'_>, rwh::HandleError> {
  73        let window = NonNull::new(self.window).unwrap();
  74        let handle = rwh::WaylandWindowHandle::new(window);
  75        Ok(unsafe { rwh::WindowHandle::borrow_raw(handle.into()) })
  76    }
  77}
  78impl rwh::HasDisplayHandle for RawWindow {
  79    fn display_handle(&self) -> Result<rwh::DisplayHandle<'_>, rwh::HandleError> {
  80        let display = NonNull::new(self.display).unwrap();
  81        let handle = rwh::WaylandDisplayHandle::new(display);
  82        Ok(unsafe { rwh::DisplayHandle::borrow_raw(handle.into()) })
  83    }
  84}
  85
  86#[derive(Debug)]
  87struct InProgressConfigure {
  88    size: Option<Size<Pixels>>,
  89    fullscreen: bool,
  90    maximized: bool,
  91    resizing: bool,
  92    tiling: Tiling,
  93}
  94
  95pub struct WaylandWindowState {
  96    surface_state: WaylandSurfaceState,
  97    acknowledged_first_configure: bool,
  98    parent: Option<WaylandWindowStatePtr>,
  99    children: FxHashSet<ObjectId>,
 100    pub surface: wl_surface::WlSurface,
 101    app_id: Option<String>,
 102    appearance: WindowAppearance,
 103    blur: Option<org_kde_kwin_blur::OrgKdeKwinBlur>,
 104    viewport: Option<wp_viewport::WpViewport>,
 105    outputs: HashMap<ObjectId, Output>,
 106    display: Option<(ObjectId, Output)>,
 107    globals: Globals,
 108    renderer: WgpuRenderer,
 109    bounds: Bounds<Pixels>,
 110    scale: f32,
 111    input_handler: Option<PlatformInputHandler>,
 112    decorations: WindowDecorations,
 113    background_appearance: WindowBackgroundAppearance,
 114    fullscreen: bool,
 115    maximized: bool,
 116    tiling: Tiling,
 117    window_bounds: Bounds<Pixels>,
 118    client: WaylandClientStatePtr,
 119    handle: AnyWindowHandle,
 120    active: bool,
 121    hovered: bool,
 122    in_progress_configure: Option<InProgressConfigure>,
 123    resize_throttle: bool,
 124    in_progress_window_controls: Option<WindowControls>,
 125    window_controls: WindowControls,
 126    client_inset: Option<Pixels>,
 127    a11y_active: Arc<AtomicBool>,
 128    accesskit: Option<accesskit_unix::Adapter>,
 129}
 130
 131pub enum WaylandSurfaceState {
 132    Xdg(WaylandXdgSurfaceState),
 133    LayerShell(WaylandLayerSurfaceState),
 134}
 135
 136impl WaylandSurfaceState {
 137    fn new(
 138        surface: &wl_surface::WlSurface,
 139        globals: &Globals,
 140        params: &WindowParams,
 141        parent: Option<WaylandWindowStatePtr>,
 142        target_output: Option<wl_output::WlOutput>,
 143    ) -> anyhow::Result<Self> {
 144        // For layer_shell windows, create a layer surface instead of an xdg surface
 145        if let WindowKind::LayerShell(options) = &params.kind {
 146            let Some(layer_shell) = globals.layer_shell.as_ref() else {
 147                return Err(LayerShellNotSupportedError.into());
 148            };
 149
 150            let layer_surface = layer_shell.get_layer_surface(
 151                &surface,
 152                target_output.as_ref(),
 153                super::layer_shell::wayland_layer(options.layer),
 154                options.namespace.clone(),
 155                &globals.qh,
 156                surface.id(),
 157            );
 158
 159            let width = f32::from(params.bounds.size.width);
 160            let height = f32::from(params.bounds.size.height);
 161            layer_surface.set_size(width as u32, height as u32);
 162
 163            layer_surface.set_anchor(super::layer_shell::wayland_anchor(options.anchor));
 164            layer_surface.set_keyboard_interactivity(
 165                super::layer_shell::wayland_keyboard_interactivity(options.keyboard_interactivity),
 166            );
 167
 168            if let Some(margin) = options.margin {
 169                layer_surface.set_margin(
 170                    f32::from(margin.0) as i32,
 171                    f32::from(margin.1) as i32,
 172                    f32::from(margin.2) as i32,
 173                    f32::from(margin.3) as i32,
 174                )
 175            }
 176
 177            if let Some(exclusive_zone) = options.exclusive_zone {
 178                layer_surface.set_exclusive_zone(f32::from(exclusive_zone) as i32);
 179            }
 180
 181            if let Some(exclusive_edge) = options.exclusive_edge {
 182                layer_surface
 183                    .set_exclusive_edge(super::layer_shell::wayland_anchor(exclusive_edge));
 184            }
 185
 186            return Ok(WaylandSurfaceState::LayerShell(WaylandLayerSurfaceState {
 187                layer_surface,
 188            }));
 189        }
 190
 191        // All other WindowKinds result in a regular xdg surface
 192        let xdg_surface = globals
 193            .wm_base
 194            .get_xdg_surface(&surface, &globals.qh, surface.id());
 195
 196        let toplevel = xdg_surface.get_toplevel(&globals.qh, surface.id());
 197        let xdg_parent = parent.as_ref().and_then(|w| w.toplevel());
 198
 199        if params.kind == WindowKind::Floating || params.kind == WindowKind::Dialog {
 200            toplevel.set_parent(xdg_parent.as_ref());
 201        }
 202
 203        let dialog = if params.kind == WindowKind::Dialog {
 204            let dialog = globals.dialog.as_ref().map(|dialog| {
 205                let xdg_dialog = dialog.get_xdg_dialog(&toplevel, &globals.qh, ());
 206                xdg_dialog.set_modal();
 207                xdg_dialog
 208            });
 209
 210            if let Some(parent) = parent.as_ref() {
 211                parent.add_child(surface.id());
 212            }
 213
 214            dialog
 215        } else {
 216            None
 217        };
 218
 219        if let Some(size) = params.window_min_size {
 220            toplevel.set_min_size(f32::from(size.width) as i32, f32::from(size.height) as i32);
 221        }
 222
 223        // Attempt to set up window decorations based on the requested configuration
 224        let decoration = globals
 225            .decoration_manager
 226            .as_ref()
 227            .map(|decoration_manager| {
 228                decoration_manager.get_toplevel_decoration(&toplevel, &globals.qh, surface.id())
 229            });
 230
 231        Ok(WaylandSurfaceState::Xdg(WaylandXdgSurfaceState {
 232            xdg_surface,
 233            toplevel,
 234            decoration,
 235            dialog,
 236        }))
 237    }
 238}
 239
 240pub struct WaylandXdgSurfaceState {
 241    xdg_surface: xdg_surface::XdgSurface,
 242    toplevel: xdg_toplevel::XdgToplevel,
 243    decoration: Option<zxdg_toplevel_decoration_v1::ZxdgToplevelDecorationV1>,
 244    dialog: Option<XdgDialogV1>,
 245}
 246
 247pub struct WaylandLayerSurfaceState {
 248    layer_surface: zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
 249}
 250
 251impl WaylandSurfaceState {
 252    fn ack_configure(&self, serial: u32) {
 253        match self {
 254            WaylandSurfaceState::Xdg(WaylandXdgSurfaceState { xdg_surface, .. }) => {
 255                xdg_surface.ack_configure(serial);
 256            }
 257            WaylandSurfaceState::LayerShell(WaylandLayerSurfaceState { layer_surface, .. }) => {
 258                layer_surface.ack_configure(serial);
 259            }
 260        }
 261    }
 262
 263    fn decoration(&self) -> Option<&zxdg_toplevel_decoration_v1::ZxdgToplevelDecorationV1> {
 264        if let WaylandSurfaceState::Xdg(WaylandXdgSurfaceState { decoration, .. }) = self {
 265            decoration.as_ref()
 266        } else {
 267            None
 268        }
 269    }
 270
 271    fn toplevel(&self) -> Option<&xdg_toplevel::XdgToplevel> {
 272        if let WaylandSurfaceState::Xdg(WaylandXdgSurfaceState { toplevel, .. }) = self {
 273            Some(toplevel)
 274        } else {
 275            None
 276        }
 277    }
 278
 279    fn set_geometry(&self, x: i32, y: i32, width: i32, height: i32) {
 280        match self {
 281            WaylandSurfaceState::Xdg(WaylandXdgSurfaceState { xdg_surface, .. }) => {
 282                xdg_surface.set_window_geometry(x, y, width, height);
 283            }
 284            WaylandSurfaceState::LayerShell(WaylandLayerSurfaceState { layer_surface, .. }) => {
 285                // cannot set window position of a layer surface
 286                layer_surface.set_size(width as u32, height as u32);
 287            }
 288        }
 289    }
 290
 291    fn destroy(&mut self) {
 292        match self {
 293            WaylandSurfaceState::Xdg(WaylandXdgSurfaceState {
 294                xdg_surface,
 295                toplevel,
 296                decoration: _decoration,
 297                dialog,
 298            }) => {
 299                // drop the dialog before toplevel so compositor can explicitly unapply it's effects
 300                if let Some(dialog) = dialog {
 301                    dialog.destroy();
 302                }
 303
 304                // The role object (toplevel) must always be destroyed before the xdg_surface.
 305                // See https://wayland.app/protocols/xdg-shell#xdg_surface:request:destroy
 306                toplevel.destroy();
 307                xdg_surface.destroy();
 308            }
 309            WaylandSurfaceState::LayerShell(WaylandLayerSurfaceState { layer_surface }) => {
 310                layer_surface.destroy();
 311            }
 312        }
 313    }
 314}
 315
 316#[derive(Clone)]
 317pub struct WaylandWindowStatePtr {
 318    state: Rc<RefCell<WaylandWindowState>>,
 319    callbacks: Rc<RefCell<Callbacks>>,
 320}
 321
 322impl WaylandWindowState {
 323    pub(crate) fn new(
 324        handle: AnyWindowHandle,
 325        surface: wl_surface::WlSurface,
 326        surface_state: WaylandSurfaceState,
 327        appearance: WindowAppearance,
 328        viewport: Option<wp_viewport::WpViewport>,
 329        client: WaylandClientStatePtr,
 330        globals: Globals,
 331        gpu_context: gpui_wgpu::GpuContext,
 332        compositor_gpu: Option<CompositorGpuHint>,
 333        options: WindowParams,
 334        parent: Option<WaylandWindowStatePtr>,
 335    ) -> anyhow::Result<Self> {
 336        let renderer = {
 337            let raw_window = RawWindow {
 338                window: surface.id().as_ptr().cast::<c_void>(),
 339                display: surface
 340                    .backend()
 341                    .upgrade()
 342                    .unwrap()
 343                    .display_ptr()
 344                    .cast::<c_void>(),
 345            };
 346            let config = WgpuSurfaceConfig {
 347                size: Size {
 348                    width: DevicePixels(f32::from(options.bounds.size.width) as i32),
 349                    height: DevicePixels(f32::from(options.bounds.size.height) as i32),
 350                },
 351                transparent: true,
 352            };
 353            WgpuRenderer::new(gpu_context, &raw_window, config, compositor_gpu)?
 354        };
 355
 356        if let WaylandSurfaceState::Xdg(ref xdg_state) = surface_state {
 357            if let Some(title) = options.titlebar.and_then(|titlebar| titlebar.title) {
 358                xdg_state.toplevel.set_title(title.to_string());
 359            }
 360            // Set max window size based on the GPU's maximum texture dimension.
 361            // This prevents the window from being resized larger than what the GPU can render.
 362            let max_texture_size = renderer.max_texture_size() as i32;
 363            xdg_state
 364                .toplevel
 365                .set_max_size(max_texture_size, max_texture_size);
 366        }
 367
 368        Ok(Self {
 369            surface_state,
 370            acknowledged_first_configure: false,
 371            parent,
 372            children: FxHashSet::default(),
 373            surface,
 374            app_id: None,
 375            blur: None,
 376            viewport,
 377            globals,
 378            outputs: HashMap::default(),
 379            display: None,
 380            renderer,
 381            bounds: options.bounds,
 382            scale: 1.0,
 383            input_handler: None,
 384            decorations: WindowDecorations::Client,
 385            background_appearance: WindowBackgroundAppearance::Opaque,
 386            fullscreen: false,
 387            maximized: false,
 388            tiling: Tiling::default(),
 389            window_bounds: options.bounds,
 390            in_progress_configure: None,
 391            resize_throttle: false,
 392            client,
 393            appearance,
 394            handle,
 395            active: false,
 396            hovered: false,
 397            in_progress_window_controls: None,
 398            window_controls: WindowControls::default(),
 399            client_inset: None,
 400            a11y_active: Arc::new(AtomicBool::new(false)),
 401            accesskit: None,
 402        })
 403    }
 404
 405    pub fn is_transparent(&self) -> bool {
 406        self.decorations == WindowDecorations::Client
 407            || self.background_appearance != WindowBackgroundAppearance::Opaque
 408    }
 409
 410    pub fn primary_output_scale(&mut self) -> i32 {
 411        let mut scale = 1;
 412        let mut current_output = self.display.take();
 413        for (id, output) in self.outputs.iter() {
 414            if let Some((_, output_data)) = &current_output {
 415                if output.scale > output_data.scale {
 416                    current_output = Some((id.clone(), output.clone()));
 417                }
 418            } else {
 419                current_output = Some((id.clone(), output.clone()));
 420            }
 421            scale = scale.max(output.scale);
 422        }
 423        self.display = current_output;
 424        scale
 425    }
 426
 427    pub fn inset(&self) -> Pixels {
 428        match self.decorations {
 429            WindowDecorations::Server => px(0.0),
 430            WindowDecorations::Client => self.client_inset.unwrap_or(px(0.0)),
 431        }
 432    }
 433}
 434
 435pub(crate) struct WaylandWindow(pub WaylandWindowStatePtr);
 436pub enum ImeInput {
 437    InsertText(String),
 438    SetMarkedText(String),
 439    UnmarkText,
 440    DeleteText,
 441}
 442
 443impl Drop for WaylandWindow {
 444    fn drop(&mut self) {
 445        let mut state = self.0.state.borrow_mut();
 446        let surface_id = state.surface.id();
 447        if let Some(parent) = state.parent.as_ref() {
 448            parent.state.borrow_mut().children.remove(&surface_id);
 449        }
 450
 451        let client = state.client.clone();
 452
 453        state.renderer.destroy();
 454
 455        // Destroy blur first, this has no dependencies.
 456        if let Some(blur) = &state.blur {
 457            blur.release();
 458        }
 459
 460        // Decorations must be destroyed before the xdg state.
 461        // See https://wayland.app/protocols/xdg-decoration-unstable-v1#zxdg_toplevel_decoration_v1
 462        if let Some(decoration) = &state.surface_state.decoration() {
 463            decoration.destroy();
 464        }
 465
 466        // Surface state might contain xdg_toplevel/xdg_surface which can be destroyed now that
 467        // decorations are gone. layer_surface has no dependencies.
 468        state.surface_state.destroy();
 469
 470        // Viewport must be destroyed before the wl_surface.
 471        // See https://wayland.app/protocols/viewporter#wp_viewport
 472        if let Some(viewport) = &state.viewport {
 473            viewport.destroy();
 474        }
 475
 476        // The wl_surface itself should always be destroyed last.
 477        state.surface.destroy();
 478
 479        let state_ptr = self.0.clone();
 480        state
 481            .globals
 482            .executor
 483            .spawn(async move {
 484                state_ptr.close();
 485                client.drop_window(&surface_id)
 486            })
 487            .detach();
 488        drop(state);
 489    }
 490}
 491
 492impl WaylandWindow {
 493    fn borrow(&self) -> Ref<'_, WaylandWindowState> {
 494        self.0.state.borrow()
 495    }
 496
 497    fn borrow_mut(&self) -> RefMut<'_, WaylandWindowState> {
 498        self.0.state.borrow_mut()
 499    }
 500
 501    pub fn new(
 502        handle: AnyWindowHandle,
 503        globals: Globals,
 504        gpu_context: gpui_wgpu::GpuContext,
 505        compositor_gpu: Option<CompositorGpuHint>,
 506        client: WaylandClientStatePtr,
 507        params: WindowParams,
 508        appearance: WindowAppearance,
 509        parent: Option<WaylandWindowStatePtr>,
 510        target_output: Option<wl_output::WlOutput>,
 511    ) -> anyhow::Result<(Self, ObjectId)> {
 512        let surface = globals.compositor.create_surface(&globals.qh, ());
 513        let surface_state =
 514            WaylandSurfaceState::new(&surface, &globals, &params, parent.clone(), target_output)?;
 515
 516        if let Some(fractional_scale_manager) = globals.fractional_scale_manager.as_ref() {
 517            fractional_scale_manager.get_fractional_scale(&surface, &globals.qh, surface.id());
 518        }
 519
 520        let viewport = globals
 521            .viewporter
 522            .as_ref()
 523            .map(|viewporter| viewporter.get_viewport(&surface, &globals.qh, ()));
 524
 525        let this = Self(WaylandWindowStatePtr {
 526            state: Rc::new(RefCell::new(WaylandWindowState::new(
 527                handle,
 528                surface.clone(),
 529                surface_state,
 530                appearance,
 531                viewport,
 532                client,
 533                globals,
 534                gpu_context,
 535                compositor_gpu,
 536                params,
 537                parent,
 538            )?)),
 539            callbacks: Rc::new(RefCell::new(Callbacks::default())),
 540        });
 541
 542        // Kick things off
 543        surface.commit();
 544
 545        Ok((this, surface.id()))
 546    }
 547}
 548
 549impl WaylandWindowStatePtr {
 550    pub fn handle(&self) -> AnyWindowHandle {
 551        self.state.borrow().handle
 552    }
 553
 554    pub fn surface(&self) -> wl_surface::WlSurface {
 555        self.state.borrow().surface.clone()
 556    }
 557
 558    pub fn toplevel(&self) -> Option<xdg_toplevel::XdgToplevel> {
 559        self.state.borrow().surface_state.toplevel().cloned()
 560    }
 561
 562    pub fn ptr_eq(&self, other: &Self) -> bool {
 563        Rc::ptr_eq(&self.state, &other.state)
 564    }
 565
 566    pub fn add_child(&self, child: ObjectId) {
 567        let mut state = self.state.borrow_mut();
 568        state.children.insert(child);
 569    }
 570
 571    pub fn is_blocked(&self) -> bool {
 572        let state = self.state.borrow();
 573        !state.children.is_empty()
 574    }
 575
 576    pub fn frame(&self) {
 577        let mut state = self.state.borrow_mut();
 578        state.surface.frame(&state.globals.qh, state.surface.id());
 579        state.resize_throttle = false;
 580        drop(state);
 581
 582        let mut cb = self.callbacks.borrow_mut();
 583        if let Some(fun) = cb.request_frame.as_mut() {
 584            fun(Default::default());
 585        }
 586    }
 587
 588    pub fn handle_xdg_surface_event(&self, event: xdg_surface::Event) {
 589        if let xdg_surface::Event::Configure { serial } = event {
 590            {
 591                let mut state = self.state.borrow_mut();
 592                if let Some(window_controls) = state.in_progress_window_controls.take() {
 593                    state.window_controls = window_controls;
 594
 595                    drop(state);
 596                    let mut callbacks = self.callbacks.borrow_mut();
 597                    if let Some(appearance_changed) = callbacks.appearance_changed.as_mut() {
 598                        appearance_changed();
 599                    }
 600                }
 601            }
 602            {
 603                let mut state = self.state.borrow_mut();
 604
 605                if let Some(mut configure) = state.in_progress_configure.take() {
 606                    let got_unmaximized = state.maximized && !configure.maximized;
 607                    state.fullscreen = configure.fullscreen;
 608                    state.maximized = configure.maximized;
 609                    state.tiling = configure.tiling;
 610                    // Limit interactive resizes to once per vblank
 611                    if configure.resizing && state.resize_throttle {
 612                        return;
 613                    } else if configure.resizing {
 614                        state.resize_throttle = true;
 615                    }
 616                    if !configure.fullscreen && !configure.maximized {
 617                        configure.size = if got_unmaximized {
 618                            Some(state.window_bounds.size)
 619                        } else {
 620                            compute_outer_size(state.inset(), configure.size, state.tiling)
 621                        };
 622                        if let Some(size) = configure.size {
 623                            state.window_bounds = Bounds {
 624                                origin: Point::default(),
 625                                size,
 626                            };
 627                        }
 628                    }
 629                    drop(state);
 630                    if let Some(size) = configure.size {
 631                        self.resize(size);
 632                    }
 633                }
 634            }
 635            let mut state = self.state.borrow_mut();
 636            state.surface_state.ack_configure(serial);
 637
 638            let window_geometry = inset_by_tiling(
 639                state.bounds.map_origin(|_| px(0.0)),
 640                state.inset(),
 641                state.tiling,
 642            )
 643            .map(|v| f32::from(v) as i32)
 644            .map_size(|v| if v <= 0 { 1 } else { v });
 645
 646            state.surface_state.set_geometry(
 647                window_geometry.origin.x,
 648                window_geometry.origin.y,
 649                window_geometry.size.width,
 650                window_geometry.size.height,
 651            );
 652
 653            let request_frame_callback = !state.acknowledged_first_configure;
 654            if request_frame_callback {
 655                state.acknowledged_first_configure = true;
 656                drop(state);
 657                self.frame();
 658            }
 659        }
 660    }
 661
 662    pub fn handle_toplevel_decoration_event(&self, event: zxdg_toplevel_decoration_v1::Event) {
 663        if let zxdg_toplevel_decoration_v1::Event::Configure { mode } = event {
 664            match mode {
 665                WEnum::Value(zxdg_toplevel_decoration_v1::Mode::ServerSide) => {
 666                    self.state.borrow_mut().decorations = WindowDecorations::Server;
 667                    let callback = self.callbacks.borrow_mut().appearance_changed.take();
 668                    if let Some(mut fun) = callback {
 669                        fun();
 670                        self.callbacks.borrow_mut().appearance_changed = Some(fun);
 671                    }
 672                }
 673                WEnum::Value(zxdg_toplevel_decoration_v1::Mode::ClientSide) => {
 674                    self.state.borrow_mut().decorations = WindowDecorations::Client;
 675                    // Update background to be transparent
 676                    let callback = self.callbacks.borrow_mut().appearance_changed.take();
 677                    if let Some(mut fun) = callback {
 678                        fun();
 679                        self.callbacks.borrow_mut().appearance_changed = Some(fun);
 680                    }
 681                }
 682                WEnum::Value(_) => {
 683                    log::warn!("Unknown decoration mode");
 684                }
 685                WEnum::Unknown(v) => {
 686                    log::warn!("Unknown decoration mode: {}", v);
 687                }
 688            }
 689        }
 690    }
 691
 692    pub fn handle_fractional_scale_event(&self, event: wp_fractional_scale_v1::Event) {
 693        if let wp_fractional_scale_v1::Event::PreferredScale { scale } = event {
 694            self.rescale(scale as f32 / 120.0);
 695        }
 696    }
 697
 698    pub fn handle_toplevel_event(&self, event: xdg_toplevel::Event) -> bool {
 699        match event {
 700            xdg_toplevel::Event::Configure {
 701                width,
 702                height,
 703                states,
 704            } => {
 705                let size = if width == 0 || height == 0 {
 706                    None
 707                } else {
 708                    Some(size(px(width as f32), px(height as f32)))
 709                };
 710
 711                let states = extract_states::<xdg_toplevel::State>(&states);
 712
 713                let mut tiling = Tiling::default();
 714                let mut fullscreen = false;
 715                let mut maximized = false;
 716                let mut resizing = false;
 717
 718                for state in states {
 719                    match state {
 720                        xdg_toplevel::State::Maximized => {
 721                            maximized = true;
 722                        }
 723                        xdg_toplevel::State::Fullscreen => {
 724                            fullscreen = true;
 725                        }
 726                        xdg_toplevel::State::Resizing => resizing = true,
 727                        xdg_toplevel::State::TiledTop => {
 728                            tiling.top = true;
 729                        }
 730                        xdg_toplevel::State::TiledLeft => {
 731                            tiling.left = true;
 732                        }
 733                        xdg_toplevel::State::TiledRight => {
 734                            tiling.right = true;
 735                        }
 736                        xdg_toplevel::State::TiledBottom => {
 737                            tiling.bottom = true;
 738                        }
 739                        _ => {
 740                            // noop
 741                        }
 742                    }
 743                }
 744
 745                if fullscreen || maximized {
 746                    tiling = Tiling::tiled();
 747                }
 748
 749                let mut state = self.state.borrow_mut();
 750                state.in_progress_configure = Some(InProgressConfigure {
 751                    size,
 752                    fullscreen,
 753                    maximized,
 754                    resizing,
 755                    tiling,
 756                });
 757
 758                false
 759            }
 760            xdg_toplevel::Event::Close => {
 761                let mut cb = self.callbacks.borrow_mut();
 762                if let Some(mut should_close) = cb.should_close.take() {
 763                    let result = (should_close)();
 764                    cb.should_close = Some(should_close);
 765                    if result {
 766                        drop(cb);
 767                        self.close();
 768                    }
 769                    result
 770                } else {
 771                    true
 772                }
 773            }
 774            xdg_toplevel::Event::WmCapabilities { capabilities } => {
 775                let mut window_controls = WindowControls::default();
 776
 777                let states = extract_states::<xdg_toplevel::WmCapabilities>(&capabilities);
 778
 779                for state in states {
 780                    match state {
 781                        xdg_toplevel::WmCapabilities::Maximize => {
 782                            window_controls.maximize = true;
 783                        }
 784                        xdg_toplevel::WmCapabilities::Minimize => {
 785                            window_controls.minimize = true;
 786                        }
 787                        xdg_toplevel::WmCapabilities::Fullscreen => {
 788                            window_controls.fullscreen = true;
 789                        }
 790                        xdg_toplevel::WmCapabilities::WindowMenu => {
 791                            window_controls.window_menu = true;
 792                        }
 793                        _ => {}
 794                    }
 795                }
 796
 797                let mut state = self.state.borrow_mut();
 798                state.in_progress_window_controls = Some(window_controls);
 799                false
 800            }
 801            _ => false,
 802        }
 803    }
 804
 805    pub fn handle_layersurface_event(&self, event: zwlr_layer_surface_v1::Event) -> bool {
 806        match event {
 807            zwlr_layer_surface_v1::Event::Configure {
 808                width,
 809                height,
 810                serial,
 811            } => {
 812                let size = if width == 0 || height == 0 {
 813                    None
 814                } else {
 815                    Some(size(px(width as f32), px(height as f32)))
 816                };
 817
 818                let mut state = self.state.borrow_mut();
 819                state.in_progress_configure = Some(InProgressConfigure {
 820                    size,
 821                    fullscreen: false,
 822                    maximized: false,
 823                    resizing: false,
 824                    tiling: Tiling::default(),
 825                });
 826                drop(state);
 827
 828                // just do the same thing we'd do as an xdg_surface
 829                self.handle_xdg_surface_event(xdg_surface::Event::Configure { serial });
 830
 831                false
 832            }
 833            zwlr_layer_surface_v1::Event::Closed => {
 834                // unlike xdg, we don't have a choice here: the surface is closing.
 835                true
 836            }
 837            _ => false,
 838        }
 839    }
 840
 841    #[allow(clippy::mutable_key_type)]
 842    pub fn handle_surface_event(
 843        &self,
 844        event: wl_surface::Event,
 845        outputs: HashMap<ObjectId, Output>,
 846    ) {
 847        let mut state = self.state.borrow_mut();
 848
 849        match event {
 850            wl_surface::Event::Enter { output } => {
 851                let id = output.id();
 852
 853                let Some(output) = outputs.get(&id) else {
 854                    return;
 855                };
 856
 857                state.outputs.insert(id, output.clone());
 858
 859                let scale = state.primary_output_scale();
 860
 861                // We use `PreferredBufferScale` instead to set the scale if it's available
 862                if state.surface.version() < wl_surface::EVT_PREFERRED_BUFFER_SCALE_SINCE {
 863                    state.surface.set_buffer_scale(scale);
 864                    drop(state);
 865                    self.rescale(scale as f32);
 866                }
 867            }
 868            wl_surface::Event::Leave { output } => {
 869                state.outputs.remove(&output.id());
 870
 871                let scale = state.primary_output_scale();
 872
 873                // We use `PreferredBufferScale` instead to set the scale if it's available
 874                if state.surface.version() < wl_surface::EVT_PREFERRED_BUFFER_SCALE_SINCE {
 875                    state.surface.set_buffer_scale(scale);
 876                    drop(state);
 877                    self.rescale(scale as f32);
 878                }
 879            }
 880            wl_surface::Event::PreferredBufferScale { factor } => {
 881                // We use `WpFractionalScale` instead to set the scale if it's available
 882                if state.globals.fractional_scale_manager.is_none() {
 883                    state.surface.set_buffer_scale(factor);
 884                    drop(state);
 885                    self.rescale(factor as f32);
 886                }
 887            }
 888            _ => {}
 889        }
 890    }
 891
 892    pub fn handle_ime(&self, ime: ImeInput) {
 893        if self.is_blocked() {
 894            return;
 895        }
 896        let mut state = self.state.borrow_mut();
 897        if let Some(mut input_handler) = state.input_handler.take() {
 898            drop(state);
 899            match ime {
 900                ImeInput::InsertText(text) => {
 901                    input_handler.replace_text_in_range(None, &text);
 902                }
 903                ImeInput::SetMarkedText(text) => {
 904                    input_handler.replace_and_mark_text_in_range(None, &text, None);
 905                }
 906                ImeInput::UnmarkText => {
 907                    input_handler.unmark_text();
 908                }
 909                ImeInput::DeleteText => {
 910                    if let Some(marked) = input_handler.marked_text_range() {
 911                        input_handler.replace_text_in_range(Some(marked), "");
 912                    }
 913                }
 914            }
 915            self.state.borrow_mut().input_handler = Some(input_handler);
 916        }
 917    }
 918
 919    pub fn get_ime_area(&self) -> Option<Bounds<Pixels>> {
 920        let mut state = self.state.borrow_mut();
 921        let mut bounds: Option<Bounds<Pixels>> = None;
 922        if let Some(mut input_handler) = state.input_handler.take() {
 923            drop(state);
 924            if let Some(selection) = input_handler.marked_text_range() {
 925                bounds = input_handler.bounds_for_range(selection.start..selection.start);
 926            }
 927            self.state.borrow_mut().input_handler = Some(input_handler);
 928        }
 929        bounds
 930    }
 931
 932    pub fn set_size_and_scale(&self, size: Option<Size<Pixels>>, scale: Option<f32>) {
 933        let (size, scale) = {
 934            let mut state = self.state.borrow_mut();
 935            if size.is_none_or(|size| size == state.bounds.size)
 936                && scale.is_none_or(|scale| scale == state.scale)
 937            {
 938                return;
 939            }
 940            if let Some(size) = size {
 941                state.bounds.size = size;
 942            }
 943            if let Some(scale) = scale {
 944                state.scale = scale;
 945            }
 946            let device_bounds = state.bounds.to_device_pixels(state.scale);
 947            state.renderer.update_drawable_size(device_bounds.size);
 948            (state.bounds.size, state.scale)
 949        };
 950
 951        let callback = self.callbacks.borrow_mut().resize.take();
 952        if let Some(mut fun) = callback {
 953            fun(size, scale);
 954            self.callbacks.borrow_mut().resize = Some(fun);
 955        }
 956
 957        {
 958            let state = self.state.borrow();
 959            if let Some(viewport) = &state.viewport {
 960                viewport
 961                    .set_destination(f32::from(size.width) as i32, f32::from(size.height) as i32);
 962            }
 963        }
 964    }
 965
 966    pub fn resize(&self, size: Size<Pixels>) {
 967        self.set_size_and_scale(Some(size), None);
 968    }
 969
 970    pub fn rescale(&self, scale: f32) {
 971        self.set_size_and_scale(None, Some(scale));
 972    }
 973
 974    pub fn close(&self) {
 975        let state = self.state.borrow();
 976        let client = state.client.get_client();
 977        #[allow(clippy::mutable_key_type)]
 978        let children = state.children.clone();
 979        drop(state);
 980
 981        for child in children {
 982            let mut client_state = client.borrow_mut();
 983            let window = get_window(&mut client_state, &child);
 984            drop(client_state);
 985
 986            if let Some(child) = window {
 987                child.close();
 988            }
 989        }
 990        let mut callbacks = self.callbacks.borrow_mut();
 991        if let Some(fun) = callbacks.close.take() {
 992            fun()
 993        }
 994    }
 995
 996    pub fn handle_input(&self, input: PlatformInput) {
 997        if self.is_blocked() {
 998            return;
 999        }
1000        let callback = self.callbacks.borrow_mut().input.take();
1001        if let Some(mut fun) = callback {
1002            let result = fun(input.clone());
1003            self.callbacks.borrow_mut().input = Some(fun);
1004            if !result.propagate {
1005                return;
1006            }
1007        }
1008        if let PlatformInput::KeyDown(event) = input
1009            && event.keystroke.modifiers.is_subset_of(&Modifiers::shift())
1010            && let Some(key_char) = &event.keystroke.key_char
1011        {
1012            let mut state = self.state.borrow_mut();
1013            if let Some(mut input_handler) = state.input_handler.take() {
1014                drop(state);
1015                input_handler.replace_text_in_range(None, key_char);
1016                self.state.borrow_mut().input_handler = Some(input_handler);
1017            }
1018        }
1019    }
1020
1021    pub fn set_focused(&self, focus: bool) {
1022        self.state.borrow_mut().active = focus;
1023        let callback = self.callbacks.borrow_mut().active_status_change.take();
1024        if let Some(mut fun) = callback {
1025            fun(focus);
1026            self.callbacks.borrow_mut().active_status_change = Some(fun);
1027        }
1028        let mut state = self.state.borrow_mut();
1029        if let Some(accesskit) = &mut state.accesskit {
1030            accesskit.update_window_focus_state(focus);
1031        }
1032    }
1033
1034    pub fn set_hovered(&self, focus: bool) {
1035        let callback = self.callbacks.borrow_mut().hover_status_change.take();
1036        if let Some(mut fun) = callback {
1037            fun(focus);
1038            self.callbacks.borrow_mut().hover_status_change = Some(fun);
1039        }
1040    }
1041
1042    pub fn set_appearance(&mut self, appearance: WindowAppearance) {
1043        self.state.borrow_mut().appearance = appearance;
1044
1045        let callback = self.callbacks.borrow_mut().appearance_changed.take();
1046        if let Some(mut fun) = callback {
1047            fun();
1048            self.callbacks.borrow_mut().appearance_changed = Some(fun);
1049        }
1050    }
1051
1052    pub fn primary_output_scale(&self) -> i32 {
1053        self.state.borrow_mut().primary_output_scale()
1054    }
1055}
1056
1057fn extract_states<'a, S: TryFrom<u32> + 'a>(states: &'a [u8]) -> impl Iterator<Item = S> + 'a
1058where
1059    <S as TryFrom<u32>>::Error: 'a,
1060{
1061    states
1062        .chunks_exact(4)
1063        .flat_map(TryInto::<[u8; 4]>::try_into)
1064        .map(u32::from_ne_bytes)
1065        .flat_map(S::try_from)
1066}
1067
1068impl rwh::HasWindowHandle for WaylandWindow {
1069    fn window_handle(&self) -> Result<rwh::WindowHandle<'_>, rwh::HandleError> {
1070        let surface = self.0.surface().id().as_ptr() as *mut libc::c_void;
1071        let c_ptr = NonNull::new(surface).ok_or(rwh::HandleError::Unavailable)?;
1072        let handle = rwh::WaylandWindowHandle::new(c_ptr);
1073        let raw_handle = rwh::RawWindowHandle::Wayland(handle);
1074        Ok(unsafe { rwh::WindowHandle::borrow_raw(raw_handle) })
1075    }
1076}
1077
1078impl rwh::HasDisplayHandle for WaylandWindow {
1079    fn display_handle(&self) -> Result<rwh::DisplayHandle<'_>, rwh::HandleError> {
1080        let display = self
1081            .0
1082            .surface()
1083            .backend()
1084            .upgrade()
1085            .ok_or(rwh::HandleError::Unavailable)?
1086            .display_ptr() as *mut libc::c_void;
1087
1088        let c_ptr = NonNull::new(display).ok_or(rwh::HandleError::Unavailable)?;
1089        let handle = rwh::WaylandDisplayHandle::new(c_ptr);
1090        let raw_handle = rwh::RawDisplayHandle::Wayland(handle);
1091        Ok(unsafe { rwh::DisplayHandle::borrow_raw(raw_handle) })
1092    }
1093}
1094
1095impl PlatformWindow for WaylandWindow {
1096    fn bounds(&self) -> Bounds<Pixels> {
1097        self.borrow().bounds
1098    }
1099
1100    fn is_maximized(&self) -> bool {
1101        self.borrow().maximized
1102    }
1103
1104    fn window_bounds(&self) -> WindowBounds {
1105        let state = self.borrow();
1106        if state.fullscreen {
1107            WindowBounds::Fullscreen(state.window_bounds)
1108        } else if state.maximized {
1109            WindowBounds::Maximized(state.window_bounds)
1110        } else {
1111            drop(state);
1112            WindowBounds::Windowed(self.bounds())
1113        }
1114    }
1115
1116    fn inner_window_bounds(&self) -> WindowBounds {
1117        let state = self.borrow();
1118        if state.fullscreen {
1119            WindowBounds::Fullscreen(state.window_bounds)
1120        } else if state.maximized {
1121            WindowBounds::Maximized(state.window_bounds)
1122        } else {
1123            let inset = state.inset();
1124            drop(state);
1125            WindowBounds::Windowed(self.bounds().inset(inset))
1126        }
1127    }
1128
1129    fn content_size(&self) -> Size<Pixels> {
1130        self.borrow().bounds.size
1131    }
1132
1133    fn resize(&mut self, size: Size<Pixels>) {
1134        let state = self.borrow();
1135        let state_ptr = self.0.clone();
1136
1137        // Keep window geometry consistent with configure handling. On Wayland, window geometry is
1138        // surface-local: resizing should not attempt to translate the window; the compositor
1139        // controls placement. We also account for client-side decoration insets and tiling.
1140        let window_geometry = inset_by_tiling(
1141            Bounds {
1142                origin: Point::default(),
1143                size,
1144            },
1145            state.inset(),
1146            state.tiling,
1147        )
1148        .map(|v| f32::from(v) as i32)
1149        .map_size(|v| if v <= 0 { 1 } else { v });
1150
1151        state.surface_state.set_geometry(
1152            window_geometry.origin.x,
1153            window_geometry.origin.y,
1154            window_geometry.size.width,
1155            window_geometry.size.height,
1156        );
1157
1158        state
1159            .globals
1160            .executor
1161            .spawn(async move { state_ptr.resize(size) })
1162            .detach();
1163    }
1164
1165    fn scale_factor(&self) -> f32 {
1166        self.borrow().scale
1167    }
1168
1169    fn appearance(&self) -> WindowAppearance {
1170        self.borrow().appearance
1171    }
1172
1173    fn display(&self) -> Option<Rc<dyn PlatformDisplay>> {
1174        let state = self.borrow();
1175        state.display.as_ref().map(|(id, display)| {
1176            Rc::new(WaylandDisplay {
1177                id: id.clone(),
1178                name: display.name.clone(),
1179                bounds: display.bounds.to_pixels(state.scale),
1180            }) as Rc<dyn PlatformDisplay>
1181        })
1182    }
1183
1184    fn mouse_position(&self) -> Point<Pixels> {
1185        self.borrow()
1186            .client
1187            .get_client()
1188            .borrow()
1189            .mouse_location
1190            .unwrap_or_default()
1191    }
1192
1193    fn modifiers(&self) -> Modifiers {
1194        self.borrow().client.get_client().borrow().modifiers
1195    }
1196
1197    fn capslock(&self) -> Capslock {
1198        self.borrow().client.get_client().borrow().capslock
1199    }
1200
1201    fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
1202        self.borrow_mut().input_handler = Some(input_handler);
1203    }
1204
1205    fn take_input_handler(&mut self) -> Option<PlatformInputHandler> {
1206        self.borrow_mut().input_handler.take()
1207    }
1208
1209    fn prompt(
1210        &self,
1211        _level: PromptLevel,
1212        _msg: &str,
1213        _detail: Option<&str>,
1214        _answers: &[PromptButton],
1215    ) -> Option<Receiver<usize>> {
1216        None
1217    }
1218
1219    fn activate(&self) {
1220        // Try to request an activation token. Even though the activation is likely going to be rejected,
1221        // KWin and Mutter can use the app_id to visually indicate we're requesting attention.
1222        let state = self.borrow();
1223        if let (Some(activation), Some(app_id)) = (&state.globals.activation, state.app_id.clone())
1224        {
1225            state.client.set_pending_activation(state.surface.id());
1226            let token = activation.get_activation_token(&state.globals.qh, ());
1227            // The serial isn't exactly important here, since the activation is probably going to be rejected anyway.
1228            let serial = state.client.get_serial(SerialKind::MousePress);
1229            token.set_app_id(app_id);
1230            token.set_serial(serial, &state.globals.seat);
1231            token.set_surface(&state.surface);
1232            token.commit();
1233        }
1234    }
1235
1236    fn is_active(&self) -> bool {
1237        self.borrow().active
1238    }
1239
1240    fn is_hovered(&self) -> bool {
1241        self.borrow().hovered
1242    }
1243
1244    fn set_title(&mut self, title: &str) {
1245        if let Some(toplevel) = self.borrow().surface_state.toplevel() {
1246            toplevel.set_title(title.to_string());
1247        }
1248    }
1249
1250    fn set_app_id(&mut self, app_id: &str) {
1251        let mut state = self.borrow_mut();
1252        if let Some(toplevel) = state.surface_state.toplevel() {
1253            toplevel.set_app_id(app_id.to_owned());
1254        }
1255        state.app_id = Some(app_id.to_owned());
1256    }
1257
1258    fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) {
1259        let mut state = self.borrow_mut();
1260        state.background_appearance = background_appearance;
1261        update_window(state);
1262    }
1263
1264    fn background_appearance(&self) -> WindowBackgroundAppearance {
1265        self.borrow().background_appearance
1266    }
1267
1268    fn is_subpixel_rendering_supported(&self) -> bool {
1269        let client = self.borrow().client.get_client();
1270        let state = client.borrow();
1271        state
1272            .gpu_context
1273            .borrow()
1274            .as_ref()
1275            .is_some_and(|ctx| ctx.supports_dual_source_blending())
1276    }
1277
1278    fn minimize(&self) {
1279        if let Some(toplevel) = self.borrow().surface_state.toplevel() {
1280            toplevel.set_minimized();
1281        }
1282    }
1283
1284    fn zoom(&self) {
1285        let state = self.borrow();
1286        if let Some(toplevel) = state.surface_state.toplevel() {
1287            if !state.maximized {
1288                toplevel.set_maximized();
1289            } else {
1290                toplevel.unset_maximized();
1291            }
1292        }
1293    }
1294
1295    fn toggle_fullscreen(&self) {
1296        let state = self.borrow();
1297        if let Some(toplevel) = state.surface_state.toplevel() {
1298            if !state.fullscreen {
1299                toplevel.set_fullscreen(None);
1300            } else {
1301                toplevel.unset_fullscreen();
1302            }
1303        }
1304    }
1305
1306    fn is_fullscreen(&self) -> bool {
1307        self.borrow().fullscreen
1308    }
1309
1310    fn on_request_frame(&self, callback: Box<dyn FnMut(RequestFrameOptions)>) {
1311        self.0.callbacks.borrow_mut().request_frame = Some(callback);
1312    }
1313
1314    fn on_input(&self, callback: Box<dyn FnMut(PlatformInput) -> gpui::DispatchEventResult>) {
1315        self.0.callbacks.borrow_mut().input = Some(callback);
1316    }
1317
1318    fn on_active_status_change(&self, callback: Box<dyn FnMut(bool)>) {
1319        self.0.callbacks.borrow_mut().active_status_change = Some(callback);
1320    }
1321
1322    fn on_hover_status_change(&self, callback: Box<dyn FnMut(bool)>) {
1323        self.0.callbacks.borrow_mut().hover_status_change = Some(callback);
1324    }
1325
1326    fn on_resize(&self, callback: Box<dyn FnMut(Size<Pixels>, f32)>) {
1327        self.0.callbacks.borrow_mut().resize = Some(callback);
1328    }
1329
1330    fn on_moved(&self, callback: Box<dyn FnMut()>) {
1331        self.0.callbacks.borrow_mut().moved = Some(callback);
1332    }
1333
1334    fn on_should_close(&self, callback: Box<dyn FnMut() -> bool>) {
1335        self.0.callbacks.borrow_mut().should_close = Some(callback);
1336    }
1337
1338    fn on_close(&self, callback: Box<dyn FnOnce()>) {
1339        self.0.callbacks.borrow_mut().close = Some(callback);
1340    }
1341
1342    fn on_hit_test_window_control(&self, _callback: Box<dyn FnMut() -> Option<WindowControlArea>>) {
1343    }
1344
1345    fn on_appearance_changed(&self, callback: Box<dyn FnMut()>) {
1346        self.0.callbacks.borrow_mut().appearance_changed = Some(callback);
1347    }
1348
1349    fn draw(&self, scene: &Scene) {
1350        let mut state = self.borrow_mut();
1351
1352        if state.renderer.device_lost() {
1353            let raw_window = RawWindow {
1354                window: state.surface.id().as_ptr().cast::<std::ffi::c_void>(),
1355                display: state
1356                    .surface
1357                    .backend()
1358                    .upgrade()
1359                    .unwrap()
1360                    .display_ptr()
1361                    .cast::<std::ffi::c_void>(),
1362            };
1363            let display_handle = rwh::HasDisplayHandle::display_handle(&raw_window)
1364                .unwrap()
1365                .as_raw();
1366            let window_handle = rwh::HasWindowHandle::window_handle(&raw_window)
1367                .unwrap()
1368                .as_raw();
1369
1370            state
1371                .renderer
1372                .recover(display_handle, window_handle)
1373                .unwrap_or_else(|err| {
1374                    panic!(
1375                        "GPU device lost and recovery failed. \
1376                        This may happen after system suspend/resume. \
1377                        Please restart the application.\n\nError: {err}"
1378                    )
1379                });
1380
1381            // The current scene references atlas textures that were cleared during recovery.
1382            // Skip this frame and let the next frame rebuild the scene with fresh textures.
1383            return;
1384        }
1385
1386        state.renderer.draw(scene);
1387    }
1388
1389    fn completed_frame(&self) {
1390        let state = self.borrow();
1391        state.surface.commit();
1392    }
1393
1394    fn sprite_atlas(&self) -> Arc<dyn PlatformAtlas> {
1395        let state = self.borrow();
1396        state.renderer.sprite_atlas().clone()
1397    }
1398
1399    fn show_window_menu(&self, position: Point<Pixels>) {
1400        let state = self.borrow();
1401        let serial = state.client.get_serial(SerialKind::MousePress);
1402        if let Some(toplevel) = state.surface_state.toplevel() {
1403            toplevel.show_window_menu(
1404                &state.globals.seat,
1405                serial,
1406                f32::from(position.x) as i32,
1407                f32::from(position.y) as i32,
1408            );
1409        }
1410    }
1411
1412    fn start_window_move(&self) {
1413        let state = self.borrow();
1414        let serial = state.client.get_serial(SerialKind::MousePress);
1415        if let Some(toplevel) = state.surface_state.toplevel() {
1416            toplevel._move(&state.globals.seat, serial);
1417        }
1418    }
1419
1420    fn start_window_resize(&self, edge: gpui::ResizeEdge) {
1421        let state = self.borrow();
1422        if let Some(toplevel) = state.surface_state.toplevel() {
1423            toplevel.resize(
1424                &state.globals.seat,
1425                state.client.get_serial(SerialKind::MousePress),
1426                edge.to_xdg(),
1427            )
1428        }
1429    }
1430
1431    fn window_decorations(&self) -> Decorations {
1432        let state = self.borrow();
1433        match state.decorations {
1434            WindowDecorations::Server => Decorations::Server,
1435            WindowDecorations::Client => Decorations::Client {
1436                tiling: state.tiling,
1437            },
1438        }
1439    }
1440
1441    fn request_decorations(&self, decorations: WindowDecorations) {
1442        let mut state = self.borrow_mut();
1443        match state.surface_state.decoration().as_ref() {
1444            Some(decoration) => {
1445                decoration.set_mode(decorations.to_xdg());
1446                state.decorations = decorations;
1447                update_window(state);
1448            }
1449            None => {
1450                if matches!(decorations, WindowDecorations::Server) {
1451                    log::info!(
1452                        "Server-side decorations requested, but the Wayland server does not support them. Falling back to client-side decorations."
1453                    );
1454                }
1455                state.decorations = WindowDecorations::Client;
1456                update_window(state);
1457            }
1458        }
1459    }
1460
1461    fn window_controls(&self) -> WindowControls {
1462        self.borrow().window_controls
1463    }
1464
1465    fn set_client_inset(&self, inset: Pixels) {
1466        let mut state = self.borrow_mut();
1467        if Some(inset) != state.client_inset {
1468            state.client_inset = Some(inset);
1469            update_window(state);
1470        }
1471    }
1472
1473    fn update_ime_position(&self, bounds: Bounds<Pixels>) {
1474        let state = self.borrow();
1475        state.client.update_ime_position(bounds);
1476    }
1477
1478    fn gpu_specs(&self) -> Option<GpuSpecs> {
1479        self.borrow().renderer.gpu_specs().into()
1480    }
1481
1482    fn a11y_init(&self, callbacks: gpui::A11yCallbacks) {
1483        let mut state = self.0.state.borrow_mut();
1484
1485        if state.accesskit.is_some() {
1486            panic!("cannot initialize accesskit twice");
1487        }
1488
1489        let original_activation = callbacks.activation;
1490        let activation = TrivialActivationHandler(Box::new({
1491            let a11y_active = state.a11y_active.clone();
1492            move || {
1493                let tree = (original_activation.0)();
1494                if tree.is_some() {
1495                    a11y_active.store(true, SeqCst);
1496                }
1497                tree
1498            }
1499        }));
1500
1501        let original_deactivation = callbacks.deactivation;
1502        let deactivation = TrivialDeactivationHandler(Box::new({
1503            let a11y_active = state.a11y_active.clone();
1504            move || {
1505                a11y_active.store(false, SeqCst);
1506                (original_deactivation.0)();
1507            }
1508        }));
1509
1510        state.accesskit = Some(accesskit_unix::Adapter::new(
1511            activation,
1512            callbacks.action,
1513            deactivation,
1514        ));
1515    }
1516
1517    fn a11y_tree_update(&mut self, tree_update: TreeUpdate) {
1518        let mut state = self.0.state.borrow_mut();
1519
1520        let Some(adapter) = &mut state.accesskit else {
1521            panic!("cannot update accesskit tree - not initialized");
1522        };
1523        
1524        adapter.update_if_active(|| tree_update);
1525    }
1526    
1527    fn a11y_update_window_bounds(&self) {
1528        // no-op - wayland does not let us get bounds for our window
1529    }
1530
1531    fn is_a11y_active(&self) -> bool {
1532        self.0.state.borrow().a11y_active.load(SeqCst)
1533    }
1534}
1535
1536fn update_window(mut state: RefMut<WaylandWindowState>) {
1537    let opaque = !state.is_transparent();
1538
1539    state.renderer.update_transparency(!opaque);
1540    let opaque_area = state.window_bounds.map(|v| f32::from(v) as i32);
1541    opaque_area.inset(f32::from(state.inset()) as i32);
1542
1543    let region = state
1544        .globals
1545        .compositor
1546        .create_region(&state.globals.qh, ());
1547    region.add(
1548        opaque_area.origin.x,
1549        opaque_area.origin.y,
1550        opaque_area.size.width,
1551        opaque_area.size.height,
1552    );
1553
1554    // Note that rounded corners make this rectangle API hard to work with.
1555    // As this is common when using CSD, let's just disable this API.
1556    if state.background_appearance == WindowBackgroundAppearance::Opaque
1557        && state.decorations == WindowDecorations::Server
1558    {
1559        // Promise the compositor that this region of the window surface
1560        // contains no transparent pixels. This allows the compositor to skip
1561        // updating whatever is behind the surface for better performance.
1562        state.surface.set_opaque_region(Some(&region));
1563    } else {
1564        state.surface.set_opaque_region(None);
1565    }
1566
1567    if let Some(ref blur_manager) = state.globals.blur_manager {
1568        if state.background_appearance == WindowBackgroundAppearance::Blurred {
1569            if state.blur.is_none() {
1570                let blur = blur_manager.create(&state.surface, &state.globals.qh, ());
1571                state.blur = Some(blur);
1572            }
1573            state.blur.as_ref().unwrap().commit();
1574        } else {
1575            // It probably doesn't hurt to clear the blur for opaque windows
1576            blur_manager.unset(&state.surface);
1577            if let Some(b) = state.blur.take() {
1578                b.release()
1579            }
1580        }
1581    }
1582
1583    region.destroy();
1584}
1585
1586pub(crate) trait WindowDecorationsExt {
1587    fn to_xdg(self) -> zxdg_toplevel_decoration_v1::Mode;
1588}
1589
1590impl WindowDecorationsExt for WindowDecorations {
1591    fn to_xdg(self) -> zxdg_toplevel_decoration_v1::Mode {
1592        match self {
1593            WindowDecorations::Client => zxdg_toplevel_decoration_v1::Mode::ClientSide,
1594            WindowDecorations::Server => zxdg_toplevel_decoration_v1::Mode::ServerSide,
1595        }
1596    }
1597}
1598
1599pub(crate) trait ResizeEdgeWaylandExt {
1600    fn to_xdg(self) -> xdg_toplevel::ResizeEdge;
1601}
1602
1603impl ResizeEdgeWaylandExt for ResizeEdge {
1604    fn to_xdg(self) -> xdg_toplevel::ResizeEdge {
1605        match self {
1606            ResizeEdge::Top => xdg_toplevel::ResizeEdge::Top,
1607            ResizeEdge::TopRight => xdg_toplevel::ResizeEdge::TopRight,
1608            ResizeEdge::Right => xdg_toplevel::ResizeEdge::Right,
1609            ResizeEdge::BottomRight => xdg_toplevel::ResizeEdge::BottomRight,
1610            ResizeEdge::Bottom => xdg_toplevel::ResizeEdge::Bottom,
1611            ResizeEdge::BottomLeft => xdg_toplevel::ResizeEdge::BottomLeft,
1612            ResizeEdge::Left => xdg_toplevel::ResizeEdge::Left,
1613            ResizeEdge::TopLeft => xdg_toplevel::ResizeEdge::TopLeft,
1614        }
1615    }
1616}
1617
1618/// The configuration event is in terms of the window geometry, which we are constantly
1619/// updating to account for the client decorations. But that's not the area we want to render
1620/// to, due to our intrusize CSD. So, here we calculate the 'actual' size, by adding back in the insets
1621fn compute_outer_size(
1622    inset: Pixels,
1623    new_size: Option<Size<Pixels>>,
1624    tiling: Tiling,
1625) -> Option<Size<Pixels>> {
1626    new_size.map(|mut new_size| {
1627        if !tiling.top {
1628            new_size.height += inset;
1629        }
1630        if !tiling.bottom {
1631            new_size.height += inset;
1632        }
1633        if !tiling.left {
1634            new_size.width += inset;
1635        }
1636        if !tiling.right {
1637            new_size.width += inset;
1638        }
1639
1640        new_size
1641    })
1642}
1643
1644fn inset_by_tiling(mut bounds: Bounds<Pixels>, inset: Pixels, tiling: Tiling) -> Bounds<Pixels> {
1645    if !tiling.top {
1646        bounds.origin.y += inset;
1647        bounds.size.height -= inset;
1648    }
1649    if !tiling.bottom {
1650        bounds.size.height -= inset;
1651    }
1652    if !tiling.left {
1653        bounds.origin.x += inset;
1654        bounds.size.width -= inset;
1655    }
1656    if !tiling.right {
1657        bounds.size.width -= inset;
1658    }
1659
1660    bounds
1661}