From 48cd3d0df989c27e20ee234a89007a733d014300 Mon Sep 17 00:00:00 2001 From: Ottatop Date: Thu, 29 Feb 2024 20:10:23 -0600 Subject: [PATCH] Remove `space_elements!` so uh when you impl SpaceElement you gotta actually remember to impl the geometry fn, which is why Alacritty was 44 pixels off in the other attempt at this --- src/api.rs | 88 +++----- src/focus.rs | 10 +- src/grab/move_grab.rs | 31 +-- src/grab/resize_grab.rs | 96 ++++---- src/handlers.rs | 40 ++-- src/handlers/xdg_shell.rs | 91 +------- src/handlers/xwayland.rs | 69 +++--- src/input.rs | 12 +- src/layout.rs | 36 ++- src/render.rs | 22 +- src/window.rs | 451 +++++++++++-------------------------- src/window/window_state.rs | 166 +++++++------- 12 files changed, 379 insertions(+), 733 deletions(-) diff --git a/src/api.rs b/src/api.rs index 6bd1b88..499c7cc 100644 --- a/src/api.rs +++ b/src/api.rs @@ -34,11 +34,11 @@ use pinnacle_api_defs::pinnacle::{ }, }; use smithay::{ - desktop::space::SpaceElement, + desktop::{space::SpaceElement, WindowSurface}, input::keyboard::XkbConfig, reexports::{calloop, input as libinput, wayland_protocols::xdg::shell::server}, utils::{Point, Rectangle, SERIAL_COUNTER}, - wayland::{compositor, shell::xdg::XdgToplevelSurfaceData}, + wayland::seat::WaylandFocus, }; use sysinfo::ProcessRefreshKind; use tokio::{ @@ -48,6 +48,7 @@ use tokio::{ }; use tokio_stream::{Stream, StreamExt}; use tonic::{Request, Response, Status, Streaming}; +use tracing::{error, warn}; use crate::{ config::ConnectorSavedState, @@ -56,7 +57,7 @@ use crate::{ output::OutputName, state::{State, WithState}, tag::{Tag, TagId}, - window::{window_state::WindowId, WindowElement}, + window::window_state::WindowId, }; type ResponseStream = Pin> + Send>>; @@ -316,7 +317,7 @@ impl input_service_server::InputService for InputService { }; if let Some(kb) = state.seat.get_keyboard() { if let Err(err) = kb.set_xkb_config(state, new_config) { - tracing::error!("Failed to set xkbconfig: {err}"); + error!("Failed to set xkbconfig: {err}"); } } }) @@ -557,7 +558,7 @@ impl process_service_server::ProcessService for ProcessService { .args(command) .spawn() else { - tracing::warn!("Tried to run {arg0}, but it doesn't exist",); + warn!("Tried to run {arg0}, but it doesn't exist",); return; }; @@ -584,7 +585,7 @@ impl process_service_server::ProcessService for ProcessService { match sender.send(response) { Ok(_) => (), Err(err) => { - tracing::error!(err = ?err); + error!(err = ?err); break; } } @@ -608,7 +609,7 @@ impl process_service_server::ProcessService for ProcessService { match sender.send(response) { Ok(_) => (), Err(err) => { - tracing::error!(err = ?err); + error!(err = ?err); break; } } @@ -627,7 +628,7 @@ impl process_service_server::ProcessService for ProcessService { // TODO: handle error let _ = sender.send(response); } - Err(err) => tracing::warn!("child wait() err: {err}"), + Err(err) => warn!("child wait() err: {err}"), } }); }) @@ -1122,15 +1123,17 @@ impl window_service_server::WindowService for WindowService { run_unary_no_response(&self.sender, move |state| { let Some(window) = window_id.window(state) else { return }; - match window { - WindowElement::Wayland(window) => { - window.toplevel().expect("in wayland enum").send_close() + match window.underlying_surface() { + WindowSurface::Wayland(toplevel) => toplevel.send_close(), + WindowSurface::X11(surface) => { + if !surface.is_override_redirect() { + if let Err(err) = surface.close() { + error!("failed to close x11 window: {err}"); + } + } else { + warn!("tried to close OR window"); + } } - WindowElement::X11(surface) => surface.close().expect("failed to close x11 win"), - WindowElement::X11OverrideRedirect(_) => { - tracing::warn!("tried to close override redirect window"); - } - _ => unreachable!(), } }) .await @@ -1356,32 +1359,14 @@ impl window_service_server::WindowService for WindowService { return; }; + if window.is_x11_override_redirect() { + return; + } + let Some(output) = window.output(state) else { return; }; - // if !matches!( - // &focus, - // FocusTarget::Window(WindowElement::X11OverrideRedirect(_)) - // ) { - // keyboard.set_focus(self, Some(focus.clone()), serial); - // } - // - // self.space.elements().for_each(|window| { - // if let WindowElement::Wayland(window) = window { - // window.toplevel().send_configure(); - // } - // }); - // } else { - // self.space.elements().for_each(|window| { - // window.set_activate(false); - // if let WindowElement::Wayland(window) = window { - // window.toplevel().send_configure(); - // } - // }); - // keyboard.set_focus(self, None, serial); - // } - for win in state.space.elements() { win.set_activate(false); } @@ -1432,8 +1417,8 @@ impl window_service_server::WindowService for WindowService { } for window in state.space.elements() { - if let WindowElement::Wayland(window) = window { - window.toplevel().expect("in wayland enum").send_configure(); + if let Some(toplevel) = window.toplevel() { + toplevel.send_configure(); } } @@ -1677,27 +1662,8 @@ impl window_service_server::WindowService for WindowService { }) }; - let (class, title) = window.as_ref().map_or((None, None), |win| match &win { - WindowElement::Wayland(_) => { - if let Some(wl_surf) = win.wl_surface() { - compositor::with_states(&wl_surf, |states| { - let lock = states - .data_map - .get::() - .expect("XdgToplevelSurfaceData wasn't in surface's data map") - .lock() - .expect("failed to acquire lock"); - (lock.app_id.clone(), lock.title.clone()) - }) - } else { - (None, None) - } - } - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { - (Some(surface.class()), Some(surface.title())) - } - _ => unreachable!(), - }); + let class = window.as_ref().and_then(|win| win.class()); + let title = window.as_ref().and_then(|win| win.title()); let focused = window.as_ref().and_then(|win| { state diff --git a/src/focus.rs b/src/focus.rs index 6ffcf3b..62fb430 100644 --- a/src/focus.rs +++ b/src/focus.rs @@ -56,8 +56,8 @@ impl State { if let Some(win) = ¤t_focus { assert!(!win.is_x11_override_redirect()); - if let WindowElement::Wayland(w) = win { - w.toplevel().expect("in wayland enum").send_configure(); + if let Some(toplevel) = win.toplevel() { + toplevel.send_configure(); } } @@ -437,13 +437,9 @@ impl WaylandFocus for FocusTarget { object_id: &smithay::reexports::wayland_server::backend::ObjectId, ) -> bool { match self { - FocusTarget::Window(WindowElement::Wayland(window)) => window.same_client_as(object_id), - FocusTarget::Window( - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface), - ) => surface.same_client_as(object_id), + FocusTarget::Window(window) => window.same_client_as(object_id), FocusTarget::Popup(popup) => popup.wl_surface().id().same_client_as(object_id), FocusTarget::LayerSurface(surf) => surf.wl_surface().id().same_client_as(object_id), - _ => unreachable!(), } } } diff --git a/src/grab/move_grab.rs b/src/grab/move_grab.rs index d826d74..579b767 100644 --- a/src/grab/move_grab.rs +++ b/src/grab/move_grab.rs @@ -51,13 +51,16 @@ impl PointerGrab for MoveSurfaceGrab { } state.space.raise_element(&self.window, false); - if let WindowElement::X11(surface) = &self.window { - state - .xwm - .as_mut() - .expect("no xwm") - .raise_window(surface) - .expect("failed to raise x11 win"); + if let Some(surface) = self.window.x11_surface() { + // INFO: can you raise OR windows or no idk + if !surface.is_override_redirect() { + state + .xwm + .as_mut() + .expect("no xwm") + .raise_window(surface) + .expect("failed to raise x11 win"); + } } let is_tiled = self @@ -136,12 +139,14 @@ impl PointerGrab for MoveSurfaceGrab { } }); - if let WindowElement::X11(surface) = &self.window { - let geo = surface.geometry(); - let new_geo = Rectangle::from_loc_and_size(new_loc, geo.size); - surface - .configure(new_geo) - .expect("failed to configure x11 win"); + if let Some(surface) = self.window.x11_surface() { + if !surface.is_override_redirect() { + let geo = surface.geometry(); + let new_geo = Rectangle::from_loc_and_size(new_loc, geo.size); + surface + .configure(new_geo) + .expect("failed to configure x11 win"); + } } let outputs = state.space.outputs_for_element(&self.window); diff --git a/src/grab/resize_grab.rs b/src/grab/resize_grab.rs index 4e84321..09d9552 100644 --- a/src/grab/resize_grab.rs +++ b/src/grab/resize_grab.rs @@ -1,17 +1,17 @@ // SPDX-License-Identifier: GPL-3.0-or-later use smithay::{ - desktop::space::SpaceElement, + desktop::{space::SpaceElement, utils::bbox_from_surface_tree, WindowSurface}, input::{ pointer::{AxisFrame, ButtonEvent, Focus, GrabStartData, PointerGrab, PointerInnerHandle}, Seat, SeatHandler, }, reexports::{ - wayland_protocols::xdg::shell::server::xdg_toplevel::{self}, + wayland_protocols::xdg::shell::server::xdg_toplevel, wayland_server::protocol::wl_surface::WlSurface, }, utils::{IsAlive, Logical, Point, Rectangle, Size}, - wayland::{compositor, shell::xdg::SurfaceCachedState}, + wayland::{compositor, seat::WaylandFocus, shell::xdg::SurfaceCachedState}, xwayland, }; @@ -158,28 +158,26 @@ impl PointerGrab for ResizeSurfaceGrab { new_window_height.clamp(min_height, max_height), )); - match &self.window { - WindowElement::Wayland(window) => { - let toplevel_surface = window.toplevel().expect("in wayland enum"); - - toplevel_surface.with_pending_state(|state| { + match self.window.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + toplevel.with_pending_state(|state| { state.states.set(xdg_toplevel::State::Resizing); state.size = Some(self.last_window_size); }); - toplevel_surface.send_pending_configure(); + toplevel.send_pending_configure(); } - WindowElement::X11(surface) => { - let loc = data - .space - .element_location(&self.window) - .expect("failed to get x11 win loc"); - surface - .configure(Rectangle::from_loc_and_size(loc, self.last_window_size)) - .expect("failed to configure x11 win"); + WindowSurface::X11(surface) => { + if !surface.is_override_redirect() { + let loc = data + .space + .element_location(&self.window) + .expect("failed to get x11 win loc"); + surface + .configure(Rectangle::from_loc_and_size(loc, self.last_window_size)) + .expect("failed to configure x11 win"); + } } - WindowElement::X11OverrideRedirect(_) => (), - _ => unreachable!(), } } @@ -208,17 +206,16 @@ impl PointerGrab for ResizeSurfaceGrab { return; } - match &self.window { - WindowElement::Wayland(window) => { - let toplevel_surface = window.toplevel().expect("in wayland enum"); - toplevel_surface.with_pending_state(|state| { + match self.window.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + toplevel.with_pending_state(|state| { state.states.unset(xdg_toplevel::State::Resizing); state.size = Some(self.last_window_size); }); - toplevel_surface.send_pending_configure(); + toplevel.send_pending_configure(); - toplevel_surface.wl_surface().with_state(|state| { + toplevel.wl_surface().with_state(|state| { // TODO: validate resize state state.resize_state = ResizeSurfaceState::WaitingForLastCommit { edges: self.edges, @@ -226,7 +223,10 @@ impl PointerGrab for ResizeSurfaceGrab { }; }); } - WindowElement::X11(surface) => { + WindowSurface::X11(surface) => { + if surface.is_override_redirect() { + return; + } let Some(surface) = surface.wl_surface() else { return }; surface.with_state(|state| { state.resize_state = ResizeSurfaceState::WaitingForLastCommit { @@ -235,8 +235,6 @@ impl PointerGrab for ResizeSurfaceGrab { }; }); } - WindowElement::X11OverrideRedirect(_) => (), - _ => unreachable!(), } } } @@ -418,12 +416,14 @@ pub fn handle_commit(state: &mut State, surface: &WlSurface) -> Option<()> { if new_loc.x.is_some() || new_loc.y.is_some() { state.space.map_element(window.clone(), window_loc, false); - if let WindowElement::X11(surface) = window { - let geo = surface.geometry(); - let new_geo = Rectangle::from_loc_and_size(window_loc, geo.size); - surface - .configure(new_geo) - .expect("failed to configure x11 win"); + if let Some(surface) = window.x11_surface() { + if !surface.is_override_redirect() { + let geo = surface.geometry(); + let new_geo = Rectangle::from_loc_and_size(window_loc, geo.size); + surface + .configure(new_geo) + .expect("failed to configure x11 win"); + } } } @@ -458,18 +458,14 @@ pub fn resize_request_client( .expect("resize request called on unmapped window"); let initial_window_size = window.geometry().size; - if let Some(WindowElement::Wayland(window)) = state.window_for_surface(surface) { - window - .toplevel() - .expect("in wayland enum") - .with_pending_state(|state| { + if let Some(window) = state.window_for_surface(surface) { + if let Some(toplevel) = window.toplevel() { + toplevel.with_pending_state(|state| { state.states.set(xdg_toplevel::State::Resizing); }); - window - .toplevel() - .expect("in wayland enum") - .send_pending_configure(); + toplevel.send_pending_configure(); + } } let grab = ResizeSurfaceGrab::start( @@ -512,18 +508,14 @@ pub fn resize_request_server( .expect("resize request called on unmapped window"); let initial_window_size = window.geometry().size; - if let Some(WindowElement::Wayland(window)) = state.window_for_surface(surface) { - window - .toplevel() - .expect("in wayland enum") - .with_pending_state(|state| { + if let Some(window) = state.window_for_surface(surface) { + if let Some(toplevel) = window.toplevel() { + toplevel.with_pending_state(|state| { state.states.set(xdg_toplevel::State::Resizing); }); - window - .toplevel() - .expect("in wayland enum") - .send_pending_configure(); + toplevel.send_pending_configure(); + } } let start_data = smithay::input::pointer::GrabStartData { diff --git a/src/handlers.rs b/src/handlers.rs index a958c08..e7177f2 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -60,7 +60,6 @@ use smithay::{ use crate::{ focus::FocusTarget, state::{ClientState, State, WithState}, - window::WindowElement, }; impl BufferHandler for State { @@ -107,9 +106,10 @@ impl CompositorHandler for State { fn commit(&mut self, surface: &WlSurface) { tracing::trace!("commit on surface {surface:?}"); + utils::on_commit_buffer_handler::(surface); + X11Wm::commit_hook::(surface); - utils::on_commit_buffer_handler::(surface); self.backend.early_import(surface); let mut root = surface.clone(); @@ -118,10 +118,10 @@ impl CompositorHandler for State { } if !compositor::is_sync_subsurface(surface) { - if let Some(win @ WindowElement::Wayland(window)) = &self.window_for_surface(&root) { + if let Some(window) = self.window_for_surface(&root) { window.on_commit(); - if let Some(loc) = win.with_state(|state| state.target_loc.take()) { - self.space.map_element(win.clone(), loc, false); + if let Some(loc) = window.with_state(|state| state.target_loc.take()) { + self.space.map_element(window.clone(), loc, false); } } }; @@ -149,7 +149,7 @@ impl CompositorHandler for State { self.output_focus_stack.current_focus(), self.space.outputs().next(), ) { - tracing::debug!("PLACING TOPLEVEL"); + tracing::debug!("Placing toplevel"); new_window.place_on_output(output); output.with_state(|state| state.focus_stack.set_focus(new_window.clone())); } @@ -180,22 +180,9 @@ impl CompositorHandler for State { SERIAL_COUNTER.next_serial(), ); }); - } else if let WindowElement::Wayland(window) = &new_window { - window.on_commit(); - let initial_configure_sent = compositor::with_states(surface, |states| { - states - .data_map - .get::() - .expect("XdgToplevelSurfaceData wasn't in surface's data map") - .lock() - .expect("Failed to lock Mutex") - .initial_configure_sent - }); - - if !initial_configure_sent { - tracing::debug!("Initial configure"); - window.toplevel().expect("in wayland enum").send_configure(); - } + } else if new_window.toplevel().is_some() { + new_window.on_commit(); + ensure_initial_configure(surface, self); } return; @@ -266,8 +253,11 @@ impl CompositorHandler for State { delegate_compositor!(State); fn ensure_initial_configure(surface: &WlSurface, state: &mut State) { - if let Some(window) = state.window_for_surface(surface) { - if let WindowElement::Wayland(window) = &window { + if let (Some(window), _) | (None, Some(window)) = ( + state.window_for_surface(surface), + state.new_window_for_surface(surface), + ) { + if let Some(toplevel) = window.toplevel() { let initial_configure_sent = compositor::with_states(surface, |states| { states .data_map @@ -280,7 +270,7 @@ fn ensure_initial_configure(surface: &WlSurface, state: &mut State) { if !initial_configure_sent { tracing::debug!("Initial configure"); - window.toplevel().expect("in wayland enum").send_configure(); + toplevel.send_configure(); } } return; diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs index 5fe8309..c0dd80a 100644 --- a/src/handlers/xdg_shell.rs +++ b/src/handlers/xdg_shell.rs @@ -17,8 +17,11 @@ use smithay::{ }, }, utils::{Logical, Point, Rectangle, Serial, SERIAL_COUNTER}, - wayland::shell::xdg::{ - PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState, + wayland::{ + seat::WaylandFocus, + shell::xdg::{ + PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState, + }, }, }; @@ -41,65 +44,8 @@ impl XdgShellHandler for State { state.states.set(xdg_toplevel::State::TiledRight); }); - let window = WindowElement::Wayland(Window::new_wayland_window(surface.clone())); + let window = WindowElement::new(Window::new_wayland_window(surface.clone())); self.new_windows.push(window); - - // if let (Some(output), _) | (None, Some(output)) = ( - // &self.focus_state.focused_output, - // self.space.outputs().next(), - // ) { - // tracing::debug!("PLACING TOPLEVEL"); - // window.place_on_output(output); - // } - // - // // note to self: don't reorder this - // // TODO: fix it so that reordering this doesn't break stuff - // self.windows.push(window.clone()); - // - // self.space.map_element(window.clone(), (0, 0), true); - // - // let win_clone = window.clone(); - // - // // Let the initial configure happen before updating the windows - // self.schedule( - // move |_data| { - // if let WindowElement::Wayland(window) = &win_clone { - // let initial_configure_sent = - // compositor::with_states(window.toplevel().wl_surface(), |states| { - // states - // .data_map - // .get::() - // .expect("XdgToplevelSurfaceData wasn't in surface's data map") - // .lock() - // .expect("Failed to lock Mutex") - // .initial_configure_sent - // }); - // - // initial_configure_sent - // } else { - // true - // } - // }, - // |data| { - // data.state.apply_window_rules(&window); - // - // if let Some(focused_output) = data.state.focus_state.focused_output.clone() { - // data.state.update_windows(&focused_output); - // } - // - // data.state.loop_handle.insert_idle(move |data| { - // data.state - // .seat - // .get_keyboard() - // .expect("Seat had no keyboard") // FIXME: actually handle error - // .set_focus( - // &mut data.state, - // Some(FocusTarget::Window(window)), - // SERIAL_COUNTER.next_serial(), - // ); - // }); - // }, - // ); } fn toplevel_destroyed(&mut self, surface: ToplevelSurface) { @@ -138,8 +84,8 @@ impl XdgShellHandler for State { // TODO: self.space.raise_element(win, true); self.z_index_stack.set_focus(win.clone()); - if let WindowElement::Wayland(win) = &win { - win.toplevel().expect("in wayland enum").send_configure(); + if let Some(toplevel) = win.toplevel() { + toplevel.send_configure(); } } self.seat @@ -733,27 +679,6 @@ impl XdgShellHandler for State { } } - // fn ack_configure(&mut self, surface: WlSurface, configure: Configure) { - // if let Some(window) = self.window_for_surface(&surface) { - // if let LocationRequestState::Requested(serial, new_loc) = - // window.with_state(|state| state.loc_request_state.clone()) - // { - // match &configure { - // Configure::Toplevel(configure) => { - // if configure.serial >= serial { - // tracing::debug!("acked configure, new loc is {:?}", new_loc); - // window.with_state(|state| { - // state.loc_request_state = - // LocationRequestState::Acknowledged(new_loc); - // }); - // } - // } - // Configure::Popup(_) => todo!(), - // } - // } - // } - // } - fn fullscreen_request(&mut self, surface: ToplevelSurface, mut wl_output: Option) { if !surface .current_state() diff --git a/src/handlers/xwayland.rs b/src/handlers/xwayland.rs index 4e5a4f5..37f4c78 100644 --- a/src/handlers/xwayland.rs +++ b/src/handlers/xwayland.rs @@ -1,13 +1,15 @@ // SPDX-License-Identifier: GPL-3.0-or-later use smithay::{ + desktop::Window, utils::{Logical, Point, Rectangle, SERIAL_COUNTER}, wayland::{ - selection::data_device::{ - clear_data_device_selection, current_data_device_selection_userdata, - request_data_device_client_selection, set_data_device_selection, - }, + seat::WaylandFocus, selection::{ + data_device::{ + clear_data_device_selection, current_data_device_selection_userdata, + request_data_device_client_selection, set_data_device_selection, + }, primary_selection::{ clear_primary_selection, current_primary_selection_userdata, request_primary_client_selection, set_primary_selection, @@ -36,12 +38,12 @@ impl XwmHandler for State { fn new_override_redirect_window(&mut self, _xwm: XwmId, _window: X11Surface) {} - fn map_window_request(&mut self, _xwm: XwmId, window: X11Surface) { + fn map_window_request(&mut self, _xwm: XwmId, surface: X11Surface) { tracing::trace!("map_window_request"); - assert!(!window.is_override_redirect()); + assert!(!surface.is_override_redirect()); - let window = WindowElement::X11(window); + let window = WindowElement::new(Window::new_x11_window(surface)); self.space.map_element(window.clone(), (0, 0), true); let bbox = self .space @@ -70,7 +72,7 @@ impl XwmHandler for State { ) .into(); - let WindowElement::X11(surface) = &window else { + let Some(surface) = window.x11_surface() else { unreachable!() }; @@ -122,14 +124,14 @@ impl XwmHandler for State { }); } - fn mapped_override_redirect_window(&mut self, _xwm: XwmId, window: X11Surface) { + fn mapped_override_redirect_window(&mut self, _xwm: XwmId, surface: X11Surface) { tracing::trace!("mapped_override_redirect_window"); - assert!(window.is_override_redirect()); + assert!(surface.is_override_redirect()); - let loc = window.geometry().loc; + let loc = surface.geometry().loc; - let window = WindowElement::X11OverrideRedirect(window); + let window = WindowElement::new(Window::new_x11_window(surface)); self.windows.push(window.clone()); self.z_index_stack.set_focus(window.clone()); @@ -139,18 +141,20 @@ impl XwmHandler for State { self.space.outputs().next(), ) { window.place_on_output(output); + // FIXME: setting focus here may possibly muck things up + // | or maybe they won't idk output.with_state(|state| state.focus_stack.set_focus(window.clone())) } self.space.map_element(window, loc, true); } - fn unmapped_window(&mut self, _xwm: XwmId, window: X11Surface) { + fn unmapped_window(&mut self, _xwm: XwmId, surface: X11Surface) { for output in self.space.outputs() { output.with_state(|state| { state.focus_stack.stack.retain(|win| { win.wl_surface() - .is_some_and(|surf| Some(surf) != window.wl_surface()) + .is_some_and(|surf| Some(surf) != surface.wl_surface()) }) }); } @@ -158,7 +162,7 @@ impl XwmHandler for State { let win = self .space .elements() - .find(|elem| matches!(elem, WindowElement::X11(surface) if surface == &window)) + .find(|elem| matches!(elem.x11_surface(), Some(surf) if surf == &surface)) .cloned(); if let Some(win) = win { @@ -178,8 +182,8 @@ impl XwmHandler for State { if let Some(FocusTarget::Window(win)) = &focus { self.space.raise_element(win, true); self.z_index_stack.set_focus(win.clone()); - if let WindowElement::Wayland(win) = &win { - win.toplevel().expect("in wayland enum").send_configure(); + if let Some(toplevel) = win.toplevel() { + toplevel.send_configure(); } } @@ -192,18 +196,18 @@ impl XwmHandler for State { } } - if !window.is_override_redirect() { + if !surface.is_override_redirect() { tracing::debug!("set mapped to false"); - window.set_mapped(false).expect("failed to unmap x11 win"); + surface.set_mapped(false).expect("failed to unmap x11 win"); } } - fn destroyed_window(&mut self, _xwm: XwmId, window: X11Surface) { + fn destroyed_window(&mut self, _xwm: XwmId, surface: X11Surface) { for output in self.space.outputs() { output.with_state(|state| { state.focus_stack.stack.retain(|win| { win.wl_surface() - .is_some_and(|surf| Some(surf) != window.wl_surface()) + .is_some_and(|surf| Some(surf) != surface.wl_surface()) }) }); } @@ -213,10 +217,8 @@ impl XwmHandler for State { .iter() .find(|elem| { matches!( - elem, - WindowElement::X11(surface) - | WindowElement::X11OverrideRedirect(surface) - if surface.wl_surface() == window.wl_surface() + elem.x11_surface(), + Some(surf) if surf.wl_surface() == surface.wl_surface() ) }) .cloned(); @@ -241,8 +243,8 @@ impl XwmHandler for State { if let Some(FocusTarget::Window(win)) = &focus { self.space.raise_element(win, true); self.z_index_stack.set_focus(win.clone()); - if let WindowElement::Wayland(win) = &win { - win.toplevel().expect("in wayland enum").send_configure(); + if let Some(toplevel) = win.toplevel() { + toplevel.send_configure(); } } @@ -283,14 +285,14 @@ impl XwmHandler for State { fn configure_notify( &mut self, _xwm: XwmId, - window: X11Surface, + surface: X11Surface, geometry: Rectangle, _above: Option, ) { let Some(win) = self .space .elements() - .find(|elem| matches!(elem, WindowElement::X11(surface) if surface == &window)) + .find(|elem| matches!(elem.x11_surface(), Some(surf) if surf == &surface)) .cloned() else { return; @@ -409,11 +411,12 @@ impl XwmHandler for State { .get_keyboard() .and_then(|kb| kb.current_focus()) .is_some_and(|focus| { - if let FocusTarget::Window(WindowElement::X11(surface)) = focus { - surface.xwm_id().expect("x11surface had no xwm id") == xwm - } else { - false + if let FocusTarget::Window(window) = focus { + if let Some(surface) = window.x11_surface() { + return surface.xwm_id().expect("x11surface had no xwm id") == xwm; + } } + false }) } diff --git a/src/input.rs b/src/input.rs index e40d2e4..d669aff 100644 --- a/src/input.rs +++ b/src/input.rs @@ -4,7 +4,7 @@ pub mod libinput; use std::{collections::HashMap, mem::Discriminant}; -use crate::{focus::FocusTarget, state::WithState, window::WindowElement}; +use crate::{focus::FocusTarget, state::WithState}; use pinnacle_api_defs::pinnacle::input::v0alpha1::{ set_libinput_setting_request::Setting, set_mousebind_request, SetKeybindResponse, SetMousebindResponse, @@ -351,14 +351,14 @@ impl State { if !matches!( &focus, - FocusTarget::Window(WindowElement::X11OverrideRedirect(_)) + FocusTarget::Window(window) if window.is_x11_override_redirect() ) { keyboard.set_focus(self, Some(focus.clone()), serial); } for window in self.space.elements() { - if let WindowElement::Wayland(window) = window { - window.toplevel().expect("in wayland enum").send_configure(); + if let Some(toplevel) = window.toplevel() { + toplevel.send_configure(); } } } else { @@ -367,8 +367,8 @@ impl State { state.focus_stack.unset_focus(); for window in state.focus_stack.stack.iter() { window.set_activate(false); - if let WindowElement::Wayland(window) = window { - window.toplevel().expect("in wayland enum").send_configure(); + if let Some(toplevel) = window.toplevel() { + toplevel.send_configure(); } } }); diff --git a/src/layout.rs b/src/layout.rs index 5bacc9e..f806fa7 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later use smithay::{ - desktop::layer_map_for_output, + desktop::{layer_map_for_output, WindowSurface}, output::Output, utils::{Logical, Point, Rectangle, Serial, Size}, wayland::{compositor, shell::xdg::XdgToplevelSurfaceData}, @@ -115,26 +115,20 @@ impl State { for win in windows_on_foc_tags.iter() { if win.with_state(|state| state.target_loc.is_some()) { - match win { - WindowElement::Wayland(wl_win) => { - let pending = compositor::with_states( - wl_win.toplevel().expect("in wayland enum").wl_surface(), - |states| { - states - .data_map - .get::() - .expect("XdgToplevelSurfaceData wasn't in surface's data map") - .lock() - .expect("Failed to lock Mutex") - .has_pending_changes() - }, - ); + match win.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + let pending = compositor::with_states(toplevel.wl_surface(), |states| { + states + .data_map + .get::() + .expect("XdgToplevelSurfaceData wasn't in surface's data map") + .lock() + .expect("Failed to lock Mutex") + .has_pending_changes() + }); if pending { - pending_wins.push(( - win.clone(), - wl_win.toplevel().expect("in wayland enum").send_configure(), - )) + pending_wins.push((win.clone(), toplevel.send_configure())) } else { let loc = win.with_state(|state| state.target_loc.take()); if let Some(loc) = loc { @@ -142,14 +136,12 @@ impl State { } } } - WindowElement::X11(_) => { + WindowSurface::X11(_) => { let loc = win.with_state(|state| state.target_loc.take()); if let Some(loc) = loc { self.space.map_element(win.clone(), loc, false); } } - WindowElement::X11OverrideRedirect(_) => (), - _ => unreachable!(), } } } diff --git a/src/render.rs b/src/render.rs index 849aebd..d09ea5c 100644 --- a/src/render.rs +++ b/src/render.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later -use std::sync::Mutex; +use std::{ops::Deref, sync::Mutex}; use smithay::{ backend::renderer::{ @@ -71,18 +71,8 @@ where scale: Scale, alpha: f32, ) -> Vec { - match self { - WindowElement::Wayland(window) => { - window.render_elements(renderer, location, scale, alpha) - } - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { - surface.render_elements(renderer, location, scale, alpha) - } - _ => unreachable!(), - } - .into_iter() - .map(C::from) - .collect() + self.deref() + .render_elements(renderer, location, scale, alpha) } } @@ -307,10 +297,8 @@ where let top_fullscreen_window = windows.iter().rev().find(|win| { let is_wayland_actually_fullscreen = { - if let WindowElement::Wayland(window) = win { - window - .toplevel() - .expect("in wayland enum") + if let Some(toplevel) = win.toplevel() { + toplevel .current_state() .states .contains(xdg_toplevel::State::Fullscreen) diff --git a/src/window.rs b/src/window.rs index eeff825..149cee6 100644 --- a/src/window.rs +++ b/src/window.rs @@ -2,40 +2,23 @@ pub mod rules; -use std::{cell::RefCell, time::Duration}; +use std::{cell::RefCell, ops::Deref}; use pinnacle_api_defs::pinnacle::signal::v0alpha1::{ WindowPointerEnterResponse, WindowPointerLeaveResponse, }; use smithay::{ backend::input::KeyState, - desktop::{ - utils::{ - send_dmabuf_feedback_surface_tree, send_frames_surface_tree, - take_presentation_feedback_surface_tree, with_surfaces_surface_tree, - OutputPresentationFeedback, - }, - Window, - }, + desktop::{space::SpaceElement, Window, WindowSurface}, input::{ keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{AxisFrame, MotionEvent, PointerTarget}, Seat, }, output::Output, - reexports::{ - wayland_protocols::wp::presentation_time::server::wp_presentation_feedback, - wayland_server::protocol::wl_surface::WlSurface, - }, - space_elements, - utils::{user_data::UserDataMap, Logical, Rectangle, Serial}, - wayland::{ - compositor::{self, SurfaceData}, - dmabuf::DmabufFeedback, - seat::WaylandFocus, - shell::xdg::XdgToplevelSurfaceData, - }, - xwayland::X11Surface, + reexports::wayland_server::protocol::wl_surface::WlSurface, + utils::{IsAlive, Logical, Point, Rectangle, Serial}, + wayland::{compositor, seat::WaylandFocus, shell::xdg::XdgToplevelSurfaceData}, }; use crate::state::{State, WithState}; @@ -44,143 +27,20 @@ use self::window_state::WindowElementState; pub mod window_state; -space_elements! { - /// The different types of windows. - #[derive(Debug, Clone, PartialEq)] - pub WindowElement; - /// This is a native Wayland window. - Wayland = Window, - /// This is an Xwayland window. - X11 = X11Surface, - /// This is an Xwayland override redirect window, which should not be messed with. - X11OverrideRedirect = X11Surface, +#[derive(Debug, Clone, PartialEq)] +pub struct WindowElement(Window); + +impl Deref for WindowElement { + type Target = Window; + + fn deref(&self) -> &Self::Target { + &self.0 + } } impl WindowElement { - pub fn with_surfaces(&self, processor: F) - where - F: FnMut(&WlSurface, &SurfaceData) + Copy, - { - match self { - WindowElement::Wayland(window) => window.with_surfaces(processor), - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { - if let Some(surface) = surface.wl_surface() { - with_surfaces_surface_tree(&surface, processor); - } - } - _ => unreachable!(), - } - } - - pub fn send_frame( - &self, - output: &Output, - time: T, - throttle: Option, - primary_scan_out_output: F, - ) where - T: Into, - F: FnMut(&WlSurface, &SurfaceData) -> Option + Copy, - { - match self { - WindowElement::Wayland(window) => { - window.send_frame(output, time, throttle, primary_scan_out_output) - } - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { - if let Some(surface) = surface.wl_surface() { - send_frames_surface_tree( - &surface, - output, - time, - throttle, - primary_scan_out_output, - ); - } - } - _ => unreachable!(), - } - } - - pub fn send_dmabuf_feedback<'a, P, F>( - &self, - output: &Output, - primary_scan_out_output: P, - select_dmabuf_feedback: F, - ) where - P: FnMut(&WlSurface, &SurfaceData) -> Option + Copy, - F: Fn(&WlSurface, &SurfaceData) -> &'a DmabufFeedback + Copy, - { - match self { - WindowElement::Wayland(window) => { - window.send_dmabuf_feedback( - output, - primary_scan_out_output, - select_dmabuf_feedback, - ); - } - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { - if let Some(surface) = surface.wl_surface() { - send_dmabuf_feedback_surface_tree( - &surface, - output, - primary_scan_out_output, - select_dmabuf_feedback, - ); - } - } - _ => unreachable!(), - } - } - - pub fn take_presentation_feedback( - &self, - output_feedback: &mut OutputPresentationFeedback, - primary_scan_out_output: F1, - presentation_feedback_flags: F2, - ) where - F1: FnMut(&WlSurface, &SurfaceData) -> Option + Copy, - F2: FnMut(&WlSurface, &SurfaceData) -> wp_presentation_feedback::Kind + Copy, - { - match self { - WindowElement::Wayland(window) => { - window.take_presentation_feedback( - output_feedback, - primary_scan_out_output, - presentation_feedback_flags, - ); - } - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { - if let Some(surface) = surface.wl_surface() { - take_presentation_feedback_surface_tree( - &surface, - output_feedback, - primary_scan_out_output, - presentation_feedback_flags, - ); - } - } - _ => unreachable!(), - } - } - - pub fn wl_surface(&self) -> Option { - match self { - WindowElement::Wayland(window) => window.wl_surface(), - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { - surface.wl_surface() - } - _ => unreachable!(), - } - } - - pub fn user_data(&self) -> &UserDataMap { - match self { - WindowElement::Wayland(window) => window.user_data(), - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { - surface.user_data() - } - _ => unreachable!(), - } + pub fn new(window: Window) -> Self { + Self(window) } /// Send a geometry change without mapping windows or sending @@ -191,16 +51,13 @@ impl WindowElement { /// RefCell Safety: This method uses a [`RefCell`] on this window. // TODO: ^ does that make things flicker? pub fn change_geometry(&self, new_geo: Rectangle) { - match self { - WindowElement::Wayland(window) => { - window - .toplevel() - .expect("in wayland enum") - .with_pending_state(|state| { - state.size = Some(new_geo.size); - }); + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + toplevel.with_pending_state(|state| { + state.size = Some(new_geo.size); + }); } - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { + WindowSurface::X11(surface) => { // TODO: maybe move this check elsewhere idk if !surface.is_override_redirect() { surface @@ -208,21 +65,16 @@ impl WindowElement { .expect("failed to configure x11 win"); } } - _ => unreachable!(), } self.with_state(|state| { state.target_loc = Some(new_geo.loc); }); - // self.with_state(|state| { - // state.loc_request_state = LocationRequestState::Sent(new_geo.loc); - // }); } pub fn class(&self) -> Option { - match self { - WindowElement::Wayland(window) => compositor::with_states( - window.toplevel().expect("in wayland enum").wl_surface(), - |states| { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + compositor::with_states(toplevel.wl_surface(), |states| { states .data_map .get::() @@ -231,20 +83,16 @@ impl WindowElement { .expect("Failed to lock Mutex") .app_id .clone() - }, - ), - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { - Some(surface.class()) + }) } - _ => unreachable!(), + WindowSurface::X11(surface) => Some(surface.class()), } } pub fn title(&self) -> Option { - match self { - WindowElement::Wayland(window) => compositor::with_states( - window.toplevel().expect("in wayland enum").wl_surface(), - |states| { + match self.0.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + compositor::with_states(toplevel.wl_surface(), |states| { states .data_map .get::() @@ -253,12 +101,9 @@ impl WindowElement { .expect("Failed to lock Mutex") .title .clone() - }, - ), - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { - Some(surface.title()) + }) } - _ => unreachable!(), + WindowSurface::X11(surface) => Some(surface.title()), } } @@ -312,58 +157,67 @@ impl WindowElement { }); } - /// Returns `true` if the window element is [`Wayland`]. - /// - /// [`Wayland`]: WindowElement::Wayland - #[must_use] - pub fn is_wayland(&self) -> bool { - matches!(self, Self::Wayland(..)) - } - - /// Returns `true` if the window element is [`X11`]. - /// - /// [`X11`]: WindowElement::X11 - #[must_use] - pub fn is_x11(&self) -> bool { - matches!(self, Self::X11(..)) - } - - /// Returns `true` if the window element is [`X11OverrideRedirect`]. - /// - /// [`X11OverrideRedirect`]: WindowElement::X11OverrideRedirect - #[must_use] pub fn is_x11_override_redirect(&self) -> bool { - matches!(self, Self::X11OverrideRedirect(..)) + matches!(self.x11_surface(), Some(surface) if surface.is_override_redirect()) + } +} + +impl SpaceElement for WindowElement { + fn bbox(&self) -> Rectangle { + self.0.bbox() + } + + fn is_in_input_region(&self, point: &Point) -> bool { + self.0.is_in_input_region(point) + } + + fn set_activate(&self, activated: bool) { + self.0.set_activate(activated) + } + + fn output_enter(&self, output: &Output, overlap: Rectangle) { + self.0.output_enter(output, overlap) + } + + fn output_leave(&self, output: &Output) { + self.0.output_leave(output) + } + + fn geometry(&self) -> Rectangle { + self.0.geometry() + } + + fn z_index(&self) -> u8 { + self.0.z_index() + } + + fn refresh(&self) { + self.0.refresh(); + } +} + +impl IsAlive for WindowElement { + fn alive(&self) -> bool { + self.0.alive() } } impl PointerTarget for WindowElement { fn frame(&self, seat: &Seat, state: &mut State) { - match self { - WindowElement::Wayland(window) => window - .wl_surface() - .expect("in wayland enum") - .frame(seat, state), - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { - surface.frame(seat, state) + match self.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + PointerTarget::frame(toplevel.wl_surface(), seat, state); } - _ => unreachable!(), + WindowSurface::X11(surface) => PointerTarget::frame(surface, seat, state), } } fn enter(&self, seat: &Seat, state: &mut State, event: &MotionEvent) { - // TODO: ssd - match self { - WindowElement::Wayland(window) => PointerTarget::enter( - &window.wl_surface().expect("in wayland enum"), - seat, - state, - event, - ), - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { - PointerTarget::enter(surface, seat, state, event) + match self.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + PointerTarget::enter(toplevel.wl_surface(), seat, state, event); } - _ => unreachable!(), + WindowSurface::X11(surface) => PointerTarget::enter(surface, seat, state, event), } let window_id = Some(self.with_state(|state| state.id.0)); @@ -375,18 +229,11 @@ impl PointerTarget for WindowElement { } fn motion(&self, seat: &Seat, state: &mut State, event: &MotionEvent) { - // TODO: ssd - match self { - WindowElement::Wayland(window) => PointerTarget::motion( - &window.wl_surface().expect("in wayland enum"), - seat, - state, - event, - ), - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { - PointerTarget::motion(surface, seat, state, event) + match self.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + PointerTarget::motion(toplevel.wl_surface(), seat, state, event); } - _ => unreachable!(), + WindowSurface::X11(surface) => PointerTarget::motion(surface, seat, state, event), } } @@ -396,20 +243,13 @@ impl PointerTarget for WindowElement { state: &mut State, event: &smithay::input::pointer::RelativeMotionEvent, ) { - // TODO: ssd - match self { - WindowElement::Wayland(window) => { - PointerTarget::relative_motion( - &window.wl_surface().expect("in wayland enum"), - seat, - state, - event, - ); + match self.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + PointerTarget::relative_motion(toplevel.wl_surface(), seat, state, event); } - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { + WindowSurface::X11(surface) => { PointerTarget::relative_motion(surface, seat, state, event); } - _ => unreachable!(), } } @@ -419,53 +259,29 @@ impl PointerTarget for WindowElement { state: &mut State, event: &smithay::input::pointer::ButtonEvent, ) { - // TODO: ssd - match self { - WindowElement::Wayland(window) => PointerTarget::button( - &window.wl_surface().expect("in wayland enum"), - seat, - state, - event, - ), - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { - PointerTarget::button(surface, seat, state, event) + match self.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + PointerTarget::button(toplevel.wl_surface(), seat, state, event); } - _ => unreachable!(), + WindowSurface::X11(surface) => PointerTarget::button(surface, seat, state, event), } } fn axis(&self, seat: &Seat, state: &mut State, frame: AxisFrame) { - // TODO: ssd - match self { - WindowElement::Wayland(window) => PointerTarget::axis( - &window.wl_surface().expect("in wayland enum"), - seat, - state, - frame, - ), - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { - PointerTarget::axis(surface, seat, state, frame) + match self.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + PointerTarget::axis(toplevel.wl_surface(), seat, state, frame); } - _ => unreachable!(), + WindowSurface::X11(surface) => PointerTarget::axis(surface, seat, state, frame), } } fn leave(&self, seat: &Seat, state: &mut State, serial: Serial, time: u32) { - // TODO: ssd - match self { - WindowElement::Wayland(window) => { - PointerTarget::leave( - &window.wl_surface().expect("in wayland enum"), - seat, - state, - serial, - time, - ); + match self.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + PointerTarget::leave(toplevel.wl_surface(), seat, state, serial, time); } - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { - PointerTarget::leave(surface, seat, state, serial, time) - } - _ => unreachable!(), + WindowSurface::X11(surface) => PointerTarget::leave(surface, seat, state, serial, time), } let window_id = Some(self.with_state(|state| state.id.0)); @@ -557,35 +373,22 @@ impl KeyboardTarget for WindowElement { keys: Vec>, serial: Serial, ) { - match self { - WindowElement::Wayland(window) => { - KeyboardTarget::enter( - &window.wl_surface().expect("in wayland enum"), - seat, - state, - keys, - serial, - ); + match self.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + KeyboardTarget::enter(toplevel.wl_surface(), seat, state, keys, serial); } - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { - KeyboardTarget::enter(surface, seat, state, keys, serial) + WindowSurface::X11(surface) => { + KeyboardTarget::enter(surface, seat, state, keys, serial); } - _ => unreachable!(), } } fn leave(&self, seat: &Seat, state: &mut State, serial: Serial) { - match self { - WindowElement::Wayland(window) => KeyboardTarget::leave( - &window.wl_surface().expect("in wayland enum"), - seat, - state, - serial, - ), - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { - KeyboardTarget::leave(surface, seat, state, serial) + match self.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + KeyboardTarget::leave(toplevel.wl_surface(), seat, state, serial); } - _ => unreachable!(), + WindowSurface::X11(surface) => KeyboardTarget::leave(surface, seat, state, serial), } } @@ -598,10 +401,10 @@ impl KeyboardTarget for WindowElement { serial: Serial, time: u32, ) { - match self { - WindowElement::Wayland(window) => { + match self.underlying_surface() { + WindowSurface::Wayland(toplevel) => { KeyboardTarget::key( - &window.wl_surface().expect("in wayland enum"), + toplevel.wl_surface(), seat, state, key, @@ -610,10 +413,9 @@ impl KeyboardTarget for WindowElement { time, ); } - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { + WindowSurface::X11(surface) => { KeyboardTarget::key(surface, seat, state, key, key_state, serial, time); } - _ => unreachable!(), } } @@ -624,20 +426,13 @@ impl KeyboardTarget for WindowElement { modifiers: ModifiersState, serial: Serial, ) { - match self { - WindowElement::Wayland(window) => { - KeyboardTarget::modifiers( - &window.wl_surface().expect("in wayland enum"), - seat, - state, - modifiers, - serial, - ); + match self.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + KeyboardTarget::modifiers(toplevel.wl_surface(), seat, state, modifiers, serial); } - WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => { + WindowSurface::X11(surface) => { KeyboardTarget::modifiers(surface, seat, state, modifiers, serial); } - _ => unreachable!(), } } } @@ -663,12 +458,18 @@ impl State { self.space .elements() .find(|window| window.wl_surface().map(|s| s == *surface).unwrap_or(false)) - .cloned() .or_else(|| { self.windows .iter() .find(|&win| win.wl_surface().is_some_and(|surf| &surf == surface)) - .cloned() }) + .cloned() + } + + pub fn new_window_for_surface(&self, surface: &WlSurface) -> Option { + self.new_windows + .iter() + .find(|&win| win.wl_surface().is_some_and(|surf| &surf == surface)) + .cloned() } } diff --git a/src/window/window_state.rs b/src/window/window_state.rs index 6df4710..9284bcf 100644 --- a/src/window/window_state.rs +++ b/src/window/window_state.rs @@ -3,7 +3,7 @@ use std::sync::atomic::{AtomicU32, Ordering}; use smithay::{ - desktop::space::SpaceElement, + desktop::{space::SpaceElement, WindowSurface}, reexports::wayland_protocols::xdg::shell::server::xdg_toplevel, utils::{Logical, Point, Rectangle}, }; @@ -81,30 +81,27 @@ impl WindowElement { state.fullscreen_or_maximized = FullscreenOrMaximized::Fullscreen; }); - match self { - WindowElement::Wayland(window) => { - window - .toplevel() - .expect("in wayland enum") - .with_pending_state(|state| { - state.states.unset(xdg_toplevel::State::Maximized); - state.states.set(xdg_toplevel::State::Fullscreen); - state.states.set(xdg_toplevel::State::TiledTop); - state.states.set(xdg_toplevel::State::TiledLeft); - state.states.set(xdg_toplevel::State::TiledBottom); - state.states.set(xdg_toplevel::State::TiledRight); - }); + match self.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + toplevel.with_pending_state(|state| { + state.states.unset(xdg_toplevel::State::Maximized); + state.states.set(xdg_toplevel::State::Fullscreen); + state.states.set(xdg_toplevel::State::TiledTop); + state.states.set(xdg_toplevel::State::TiledLeft); + state.states.set(xdg_toplevel::State::TiledBottom); + state.states.set(xdg_toplevel::State::TiledRight); + }); } - WindowElement::X11(surface) => { - surface - .set_maximized(false) - .expect("failed to set x11 win to maximized"); - surface - .set_fullscreen(true) - .expect("failed to set x11 win to not fullscreen"); + WindowSurface::X11(surface) => { + if !surface.is_override_redirect() { + surface + .set_maximized(false) + .expect("failed to set x11 win to maximized"); + surface + .set_fullscreen(true) + .expect("failed to set x11 win to not fullscreen"); + } } - WindowElement::X11OverrideRedirect(_) => (), - _ => unreachable!(), } } FullscreenOrMaximized::Fullscreen => { @@ -131,30 +128,27 @@ impl WindowElement { state.fullscreen_or_maximized = FullscreenOrMaximized::Maximized; }); - match self { - WindowElement::Wayland(window) => { - window - .toplevel() - .expect("in wayland enum") - .with_pending_state(|state| { - state.states.set(xdg_toplevel::State::Maximized); - state.states.unset(xdg_toplevel::State::Fullscreen); - state.states.set(xdg_toplevel::State::TiledTop); - state.states.set(xdg_toplevel::State::TiledLeft); - state.states.set(xdg_toplevel::State::TiledBottom); - state.states.set(xdg_toplevel::State::TiledRight); - }); + match self.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + toplevel.with_pending_state(|state| { + state.states.set(xdg_toplevel::State::Maximized); + state.states.unset(xdg_toplevel::State::Fullscreen); + state.states.set(xdg_toplevel::State::TiledTop); + state.states.set(xdg_toplevel::State::TiledLeft); + state.states.set(xdg_toplevel::State::TiledBottom); + state.states.set(xdg_toplevel::State::TiledRight); + }); } - WindowElement::X11(surface) => { - surface - .set_maximized(true) - .expect("failed to set x11 win to maximized"); - surface - .set_fullscreen(false) - .expect("failed to set x11 win to not fullscreen"); + WindowSurface::X11(surface) => { + if !surface.is_override_redirect() { + surface + .set_maximized(true) + .expect("failed to set x11 win to maximized"); + surface + .set_fullscreen(false) + .expect("failed to set x11 win to not fullscreen"); + } } - WindowElement::X11OverrideRedirect(_) => (), - _ => unreachable!(), } } FullscreenOrMaximized::Maximized => { @@ -176,60 +170,54 @@ impl WindowElement { /// Unsets maximized and fullscreen states for both wayland and xwayland windows /// and unsets tiled states for wayland windows. fn set_floating_states(&self) { - match self { - WindowElement::Wayland(window) => { - window - .toplevel() - .expect("in wayland enum") - .with_pending_state(|state| { - state.states.unset(xdg_toplevel::State::Maximized); - state.states.unset(xdg_toplevel::State::Fullscreen); - state.states.unset(xdg_toplevel::State::TiledTop); - state.states.unset(xdg_toplevel::State::TiledLeft); - state.states.unset(xdg_toplevel::State::TiledBottom); - state.states.unset(xdg_toplevel::State::TiledRight); - }); + match self.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + toplevel.with_pending_state(|state| { + state.states.unset(xdg_toplevel::State::Maximized); + state.states.unset(xdg_toplevel::State::Fullscreen); + state.states.unset(xdg_toplevel::State::TiledTop); + state.states.unset(xdg_toplevel::State::TiledLeft); + state.states.unset(xdg_toplevel::State::TiledBottom); + state.states.unset(xdg_toplevel::State::TiledRight); + }); } - WindowElement::X11(surface) => { - surface - .set_maximized(false) - .expect("failed to set x11 win to maximized"); - surface - .set_fullscreen(false) - .expect("failed to set x11 win to not fullscreen"); + WindowSurface::X11(surface) => { + if !surface.is_override_redirect() { + surface + .set_maximized(false) + .expect("failed to set x11 win to maximized"); + surface + .set_fullscreen(false) + .expect("failed to set x11 win to not fullscreen"); + } } - WindowElement::X11OverrideRedirect(_) => (), - _ => unreachable!(), } } /// Unsets maximized and fullscreen states for both wayland and xwayland windows /// and sets tiled states for wayland windows. fn set_tiled_states(&self) { - match self { - WindowElement::Wayland(window) => { - window - .toplevel() - .expect("in wayland enum") - .with_pending_state(|state| { - state.states.unset(xdg_toplevel::State::Maximized); - state.states.unset(xdg_toplevel::State::Fullscreen); - state.states.set(xdg_toplevel::State::TiledTop); - state.states.set(xdg_toplevel::State::TiledLeft); - state.states.set(xdg_toplevel::State::TiledBottom); - state.states.set(xdg_toplevel::State::TiledRight); - }); + match self.underlying_surface() { + WindowSurface::Wayland(toplevel) => { + toplevel.with_pending_state(|state| { + state.states.unset(xdg_toplevel::State::Maximized); + state.states.unset(xdg_toplevel::State::Fullscreen); + state.states.set(xdg_toplevel::State::TiledTop); + state.states.set(xdg_toplevel::State::TiledLeft); + state.states.set(xdg_toplevel::State::TiledBottom); + state.states.set(xdg_toplevel::State::TiledRight); + }); } - WindowElement::X11(surface) => { - surface - .set_maximized(false) - .expect("failed to set x11 win to maximized"); - surface - .set_fullscreen(false) - .expect("failed to set x11 win to not fullscreen"); + WindowSurface::X11(surface) => { + if !surface.is_override_redirect() { + surface + .set_maximized(false) + .expect("failed to set x11 win to maximized"); + surface + .set_fullscreen(false) + .expect("failed to set x11 win to not fullscreen"); + } } - WindowElement::X11OverrideRedirect(_) => (), - _ => unreachable!(), } } }