From 94d7c4463e03285d34e4a073d0ee9bbba04df627 Mon Sep 17 00:00:00 2001 From: Ottatop Date: Fri, 28 Jul 2023 14:33:14 -0500 Subject: [PATCH] Move grab requests, clean up stuff --- src/cursor.rs | 2 +- src/grab/move_grab.rs | 71 ++++++++++++++++- src/grab/resize_grab.rs | 106 ++++++++++++++++++++++++- src/handlers.rs | 21 ++--- src/handlers/xwayland.rs | 111 +++++++------------------- src/input.rs | 8 +- src/layout.rs | 7 +- src/main.rs | 3 +- src/render.rs | 4 +- src/state.rs | 10 ++- src/window.rs | 18 ++++- src/xdg.rs | 3 - src/xdg/request.rs | 167 --------------------------------------- 13 files changed, 252 insertions(+), 279 deletions(-) delete mode 100644 src/xdg.rs delete mode 100644 src/xdg/request.rs diff --git a/src/cursor.rs b/src/cursor.rs index f8e3478..60dcae0 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -51,7 +51,7 @@ fn nearest_images(size: u32, images: &[Image]) -> impl Iterator { let nearest_image = images .iter() .min_by_key(|image| (size as i32 - image.size as i32).abs()) - .unwrap(); + .expect("no nearest image"); images.iter().filter(move |image| { image.width == nearest_image.width && image.height == nearest_image.height diff --git a/src/grab/move_grab.rs b/src/grab/move_grab.rs index beb4325..2cdfe62 100644 --- a/src/grab/move_grab.rs +++ b/src/grab/move_grab.rs @@ -5,13 +5,14 @@ use smithay::{ // NOTE: maybe alias this to PointerGrabStartData because there's another GrabStartData in // | input::keyboard input::{ - pointer::PointerGrab, pointer::{ AxisFrame, ButtonEvent, GrabStartData, MotionEvent, PointerInnerHandle, RelativeMotionEvent, }, - SeatHandler, + pointer::{Focus, PointerGrab}, + Seat, SeatHandler, }, + reexports::wayland_server::protocol::wl_surface::WlSurface, utils::{IsAlive, Logical, Point, Rectangle}, }; @@ -140,3 +141,69 @@ impl PointerGrab> for MoveSurfaceGrab> { &self.start_data } } + +pub fn move_request_client( + state: &mut State, + surface: &WlSurface, + seat: &Seat>, + serial: smithay::utils::Serial, +) { + let pointer = seat.get_pointer().expect("seat had no pointer"); + if let Some(start_data) = crate::pointer::pointer_grab_start_data(&pointer, surface, serial) { + let Some(window) = state.window_for_surface(surface) else { + tracing::error!("Surface had no window, cancelling move request"); + return; + }; + + let initial_window_loc = state + .space + .element_location(&window) + .expect("move request was called on an unmapped window"); + + let grab = MoveSurfaceGrab { + start_data, + window, + initial_window_loc, + }; + + pointer.set_grab(state, grab, serial, Focus::Clear); + } else { + tracing::warn!("no grab start data"); + } +} + +pub fn move_request_server( + state: &mut State, + surface: &WlSurface, + seat: &Seat>, + serial: smithay::utils::Serial, +) { + let pointer = seat.get_pointer().expect("seat had no pointer"); + let Some(window) = state.window_for_surface(surface) else { + tracing::error!("Surface had no window, cancelling move request"); + return; + }; + + let initial_window_loc = state + .space + .element_location(&window) + .expect("move request was called on an unmapped window"); + + const BUTTON_LEFT: u32 = 0x110; + + let start_data = smithay::input::pointer::GrabStartData { + focus: pointer + .current_focus() + .map(|focus| (focus, initial_window_loc)), + button: BUTTON_LEFT, + location: pointer.current_location(), + }; + + let grab = MoveSurfaceGrab { + start_data, + window, + initial_window_loc, + }; + + pointer.set_grab(state, grab, serial, Focus::Clear); +} diff --git a/src/grab/resize_grab.rs b/src/grab/resize_grab.rs index aaf8e1f..262c99f 100644 --- a/src/grab/resize_grab.rs +++ b/src/grab/resize_grab.rs @@ -3,8 +3,8 @@ use smithay::{ desktop::space::SpaceElement, input::{ - pointer::{AxisFrame, ButtonEvent, GrabStartData, PointerGrab, PointerInnerHandle}, - SeatHandler, + pointer::{AxisFrame, ButtonEvent, Focus, GrabStartData, PointerGrab, PointerInnerHandle}, + Seat, SeatHandler, }, reexports::{ wayland_protocols::xdg::shell::server::xdg_toplevel::{self}, @@ -335,3 +335,105 @@ pub fn handle_commit(state: &mut State, surface: &WlSurface) -> O Some(()) } + +pub fn resize_request_client( + state: &mut State, + surface: &WlSurface, + seat: &Seat>, + serial: smithay::utils::Serial, + edges: xdg_toplevel::ResizeEdge, + button_used: u32, +) { + let pointer = seat.get_pointer().expect("seat had no pointer"); + + if let Some(start_data) = crate::pointer::pointer_grab_start_data(&pointer, surface, serial) { + let Some(window) = state.window_for_surface(surface) else { + tracing::error!("Surface had no window, cancelling resize request"); + return; + }; + + if window.with_state(|state| state.floating.is_tiled()) { + return; + } + + let initial_window_loc = state + .space + .element_location(&window) + .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().with_pending_state(|state| { + state.states.set(xdg_toplevel::State::Resizing); + }); + + window.toplevel().send_pending_configure(); + } + + let grab = ResizeSurfaceGrab::start( + start_data, + window, + ResizeEdge(edges), + Rectangle::from_loc_and_size(initial_window_loc, initial_window_size), + button_used, + ); + + if let Some(grab) = grab { + pointer.set_grab(state, grab, serial, Focus::Clear); + } + } +} + +pub fn resize_request_server( + state: &mut State, + surface: &WlSurface, + seat: &Seat>, + serial: smithay::utils::Serial, + edges: xdg_toplevel::ResizeEdge, + button_used: u32, +) { + let pointer = seat.get_pointer().expect("seat had no pointer"); + + let Some(window) = state.window_for_surface(surface) else { + tracing::error!("Surface had no window, cancelling resize request"); + return; + }; + + if window.with_state(|state| state.floating.is_tiled()) { + return; + } + + let initial_window_loc = state + .space + .element_location(&window) + .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().with_pending_state(|state| { + state.states.set(xdg_toplevel::State::Resizing); + }); + + window.toplevel().send_pending_configure(); + } + + let start_data = smithay::input::pointer::GrabStartData { + focus: pointer + .current_focus() + .map(|focus| (focus, initial_window_loc)), + button: button_used, + location: pointer.current_location(), + }; + + let grab = ResizeSurfaceGrab::start( + start_data, + window, + ResizeEdge(edges), + Rectangle::from_loc_and_size(initial_window_loc, initial_window_size), + button_used, + ); + + if let Some(grab) = grab { + pointer.set_grab(state, grab, serial, Focus::Clear); + } +} diff --git a/src/handlers.rs b/src/handlers.rs index c31a701..f29bdc2 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -221,13 +221,14 @@ impl SeatHandler for State { } fn focus_changed(&mut self, seat: &Seat, focused: Option<&Self::KeyboardFocus>) { - if let Some(focus) = focused.and_then(|focus| focus.wl_surface()) { - if let Some(window) = self.window_for_surface(&focus) { - self.focus_state.set_focus(window); - // let focus = focused.and_then(|surf| self.display_handle.get_client(surf.id()).ok()); - // set_data_device_focus(&self.display_handle, seat, focus); - } + if let Some(focus) = + focused.and_then(|focused| self.window_for_surface(&focused.wl_surface()?)) + { + self.focus_state.set_focus(focus); } + let focus_client = + focused.and_then(|surf| self.display_handle.get_client(surf.wl_surface()?.id()).ok()); + set_data_device_focus(&self.display_handle, seat, focus_client); } } delegate_seat!(@ State); @@ -286,7 +287,7 @@ impl XdgShellHandler for State { self.focus_state .focused_output .as_ref() - .unwrap() + .expect("no focused output") .with_state(|op_state| { op_state .tags @@ -392,9 +393,9 @@ impl XdgShellHandler for State { } fn move_request(&mut self, surface: ToplevelSurface, seat: WlSeat, serial: Serial) { - crate::xdg::request::move_request( + crate::grab::move_grab::move_request_client( self, - &surface, + surface.wl_surface(), &Seat::from_resource(&seat).expect("Couldn't get seat from WlSeat"), serial, ); @@ -408,7 +409,7 @@ impl XdgShellHandler for State { edges: ResizeEdge, ) { const BUTTON_LEFT: u32 = 0x110; - crate::xdg::request::resize_request( + crate::grab::resize_grab::resize_request_client( self, surface.wl_surface(), &Seat::from_resource(&seat).expect("Couldn't get seat from WlSeat"), diff --git a/src/handlers/xwayland.rs b/src/handlers/xwayland.rs index a2e0653..0a5fd0e 100644 --- a/src/handlers/xwayland.rs +++ b/src/handlers/xwayland.rs @@ -4,11 +4,8 @@ // // SPDX-License-Identifier: MPL-2.0 -use std::time::Duration; use smithay::{ - desktop::{space::SpaceElement, utils::surface_primary_scanout_output}, - input::pointer::Focus, reexports::wayland_server::Resource, utils::{Logical, Rectangle, SERIAL_COUNTER}, wayland::compositor::{self, CompositorHandler}, @@ -20,7 +17,6 @@ use smithay::{ use crate::{ backend::Backend, - grab::resize_grab::{ResizeSurfaceGrab, ResizeSurfaceState}, state::{CalloopData, WithState}, window::{WindowBlocker, WindowElement, BLOCKER_COUNTER, window_state::Float}, focus::FocusTarget, }; @@ -52,7 +48,7 @@ impl XwmHandler for CalloopData { window.set_mapped(true).expect("failed to map x11 window"); let window = WindowElement::X11(window); self.state.space.map_element(window.clone(), (0, 0), true); - let bbox = self.state.space.element_bbox(&window).unwrap(); + let bbox = self.state.space.element_bbox(&window).expect("called element_bbox on an unmapped window"); let WindowElement::X11(surface) = &window else { unreachable!() }; tracing::debug!("map_window_request, configuring with bbox {bbox:?}"); surface @@ -109,7 +105,7 @@ impl XwmHandler for CalloopData { .focus_state .focused_output .as_ref() - .unwrap() + .expect("no focused output") .with_state(|op_state| { op_state .tags @@ -228,7 +224,7 @@ impl XwmHandler for CalloopData { } } - fn destroyed_window(&mut self, xwm: XwmId, window: X11Surface) { + fn destroyed_window(&mut self, _xwm: XwmId, window: X11Surface) { let win = self .state .windows @@ -253,13 +249,13 @@ impl XwmHandler for CalloopData { fn configure_request( &mut self, - xwm: XwmId, + _xwm: XwmId, window: X11Surface, - x: Option, - y: Option, + _x: Option, + _y: Option, w: Option, h: Option, - reorder: Option, + _reorder: Option, ) { let mut geo = window.geometry(); if let Some(w) = w { @@ -276,10 +272,10 @@ impl XwmHandler for CalloopData { fn configure_notify( &mut self, - xwm: XwmId, + _xwm: XwmId, window: X11Surface, geometry: Rectangle, - above: Option, + _above: Option, ) { // tracing::debug!("x11 configure_notify"); let Some(win) = self @@ -299,81 +295,34 @@ impl XwmHandler for CalloopData { // TODO: anvil has a TODO here } - fn maximize_request(&mut self, xwm: XwmId, window: X11Surface) { - // TODO: - } - - fn unmaximize_request(&mut self, xwm: XwmId, window: X11Surface) { - // TODO: - } - - fn fullscreen_request(&mut self, xwm: XwmId, window: X11Surface) { - // TODO: - // window.set_fullscreen(true).unwrap(); - } - - fn unfullscreen_request(&mut self, xwm: XwmId, window: X11Surface) { - // TODO: - } + // fn maximize_request(&mut self, xwm: XwmId, window: X11Surface) { + // // TODO: + // } + // + // fn unmaximize_request(&mut self, xwm: XwmId, window: X11Surface) { + // // TODO: + // } + // + // fn fullscreen_request(&mut self, xwm: XwmId, window: X11Surface) { + // // TODO: + // // window.set_fullscreen(true).unwrap(); + // } + // + // fn unfullscreen_request(&mut self, xwm: XwmId, window: X11Surface) { + // // TODO: + // } fn resize_request( &mut self, _xwm: XwmId, - window: X11Surface, - button: u32, - resize_edge: smithay::xwayland::xwm::ResizeEdge, + _window: X11Surface, + _button: u32, + _resize_edge: smithay::xwayland::xwm::ResizeEdge, ) { - // let seat = &self.state.seat; - // let pointer = seat.get_pointer().expect("failed to get pointer"); - // let start_data = pointer.grab_start_data().expect("no grab start data"); - // - // let Some(win) = self - // .state - // .space - // .elements() - // .find(|elem| matches!(elem, WindowElement::X11(surface) if surface == &window)) - // else { - // return; - // }; - // - // let initial_window_location = self - // .state - // .space - // .element_location(win) - // .expect("failed to get x11 loc"); - // let initial_window_size = win.geometry().size; - // - // if let Some(wl_surface) = win.wl_surface() { - // wl_surface.with_state(|state| { - // state.resize_state = ResizeSurfaceState::Resizing { - // edges: resize_edge.into(), - // initial_window_rect: Rectangle::from_loc_and_size( - // initial_window_location, - // initial_window_size, - // ), - // }; - // }); - // - // let grab = ResizeSurfaceGrab::start( - // start_data, - // win.clone(), - // resize_edge.into(), - // Rectangle::from_loc_and_size(initial_window_location, initial_window_size), - // button, // BUTTON_LEFT - // ); - // - // if let Some(grab) = grab { - // pointer.set_grab( - // &mut self.state, - // grab, - // SERIAL_COUNTER.next_serial(), - // Focus::Clear, - // ); - // } - // } + // TODO: } - fn move_request(&mut self, xwm: XwmId, window: X11Surface, button: u32) { + fn move_request(&mut self, _xwm: XwmId, _window: X11Surface, _button: u32) { // TODO: } diff --git a/src/input.rs b/src/input.rs index 88c420f..6ee161a 100644 --- a/src/input.rs +++ b/src/input.rs @@ -79,7 +79,7 @@ impl State { if self.move_mode { if event.button_code() == BUTTON_LEFT { if let Some(wl_surf) = window.wl_surface() { - crate::xdg::request::move_request_force( + crate::grab::move_grab::move_request_server( self, &wl_surf, &self.seat.clone(), @@ -127,7 +127,7 @@ impl State { }; if let Some(wl_surf) = window.wl_surface() { - crate::xdg::request::resize_request_force( + crate::grab::resize_grab::resize_request_server( self, &wl_surf, &self.seat.clone(), @@ -146,7 +146,9 @@ impl State { .expect("no xwm") .raise_window(surface) .expect("failed to raise x11 win"); - surface.set_activated(true).unwrap(); + surface + .set_activated(true) + .expect("failed to set x11 win to activated"); } tracing::debug!( diff --git a/src/layout.rs b/src/layout.rs index 7c177dc..bfe2ede 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -432,7 +432,12 @@ impl State { } } - let output = self.focus_state.focused_output.clone().unwrap(); // FIXME: unwrap + // TODO: don't use the focused output, use the outputs the two windows are on + let output = self + .focus_state + .focused_output + .clone() + .expect("no focused output"); self.re_layout(&output); } } diff --git a/src/main.rs b/src/main.rs index 24de813..cd84528 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ //! While Pinnacle is not a library, this documentation serves to guide those who want to //! contribute or learn how building something like this works. -// #![deny(unused_imports)] // gonna force myself to keep stuff clean +#![deny(unused_imports)] // gonna force myself to keep stuff clean #![warn(clippy::unwrap_used)] mod api; @@ -25,7 +25,6 @@ mod render; mod state; mod tag; mod window; -mod xdg; use std::error::Error; diff --git a/src/render.rs b/src/render.rs index 6f3dcbc..3152138 100644 --- a/src/render.rs +++ b/src/render.rs @@ -5,7 +5,7 @@ use smithay::{ element::{surface::WaylandSurfaceRenderElement, AsRenderElements, Wrap}, ImportAll, ImportMem, Renderer, Texture, }, - desktop::space::{SpaceElement, SpaceRenderElements}, + desktop::space::SpaceRenderElements, render_elements, utils::{Physical, Point, Scale}, }; @@ -44,7 +44,7 @@ where scale: Scale, alpha: f32, ) -> Vec { - let window_bbox = self.bbox(); + // let window_bbox = self.bbox(); match self { WindowElement::Wayland(window) => { AsRenderElements::::render_elements::>( diff --git a/src/state.rs b/src/state.rs index 4795b70..a1deee4 100644 --- a/src/state.rs +++ b/src/state.rs @@ -47,7 +47,7 @@ use smithay::{ Display, DisplayHandle, }, }, - utils::{Clock, IsAlive, Logical, Monotonic, Point, Size}, + utils::{Clock, Logical, Monotonic, Point, Size}, wayland::{ compositor::{self, CompositorClientState, CompositorState}, data_device::DataDeviceState, @@ -159,7 +159,13 @@ impl State { .space .element_location(&window) .unwrap_or((0, 0).into()); - let window_size = window.geometry().size; + let mut window_size = window.geometry().size; + if let Some(width) = width { + window_size.w = width; + } + if let Some(height) = height { + window_size.h = height; + } window.request_size_change(self, window_loc, window_size); } Msg::MoveWindowToTag { window_id, tag_id } => { diff --git a/src/window.rs b/src/window.rs index 0cd7c08..df7cc44 100644 --- a/src/window.rs +++ b/src/window.rs @@ -206,7 +206,9 @@ impl WindowElement { // state.resize_state = WindowResizeState::Acknowledged(new_loc); // }); if !surface.is_override_redirect() { - surface.set_mapped(true).unwrap(); + surface + .set_mapped(true) + .expect("failed to set x11 win to mapped"); } state.space.map_element(self.clone(), new_loc, false); // if let Some(focused_output) = state.focus_state.focused_output.clone() { @@ -500,7 +502,12 @@ pub fn toggle_floating(state: &mut State, window: &WindowElement) window_state.floating = Float::Tiled(Some(( // We get the location this way because window.geometry().loc // doesn't seem to be the actual location - state.space.element_location(window).unwrap(), + + // TODO: remove the expect, maybe store the location in state + state + .space + .element_location(window) + .expect("toggled float on an unmapped floating window"), window.geometry().size, ))); @@ -520,7 +527,12 @@ pub fn toggle_floating(state: &mut State, window: &WindowElement) window.request_size_change(state, prev_loc, prev_size); } - let output = state.focus_state.focused_output.clone().unwrap(); + // TODO: don't use the focused output, use the one the window is on + let output = state + .focus_state + .focused_output + .clone() + .expect("no focused output"); state.re_layout(&output); let render = output.with_state(|op_state| { diff --git a/src/xdg.rs b/src/xdg.rs deleted file mode 100644 index 48fb421..0000000 --- a/src/xdg.rs +++ /dev/null @@ -1,3 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -pub mod request; diff --git a/src/xdg/request.rs b/src/xdg/request.rs deleted file mode 100644 index 339bc2f..0000000 --- a/src/xdg/request.rs +++ /dev/null @@ -1,167 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -use smithay::{ - desktop::space::SpaceElement, - input::{pointer::Focus, Seat}, - reexports::{ - wayland_protocols::xdg::shell::server::xdg_toplevel, - wayland_server::protocol::wl_surface::WlSurface, - }, - utils::Rectangle, - wayland::shell::xdg::ToplevelSurface, -}; - -use crate::{ - backend::Backend, - grab::{ - move_grab::MoveSurfaceGrab, - resize_grab::{ResizeEdge, ResizeSurfaceGrab}, - }, - state::{State, WithState}, - window::WindowElement, -}; - -pub fn move_request( - state: &mut State, - surface: &ToplevelSurface, - seat: &Seat>, - serial: smithay::utils::Serial, -) { - let wl_surface = surface.wl_surface(); - - let pointer = seat.get_pointer().unwrap(); - if let Some(start_data) = crate::pointer::pointer_grab_start_data(&pointer, wl_surface, serial) - { - let window = state.window_for_surface(wl_surface).unwrap(); - - let initial_window_loc = state.space.element_location(&window).unwrap(); - - let grab = MoveSurfaceGrab { - start_data, - window, - initial_window_loc, - }; - - pointer.set_grab(state, grab, serial, Focus::Clear); - } else { - tracing::warn!("no grab start data"); - } -} - -// TODO: see how this interacts with drag and drop and other grabs -pub fn move_request_force( - state: &mut State, - surface: &WlSurface, - seat: &Seat>, - serial: smithay::utils::Serial, -) { - let pointer = seat.get_pointer().unwrap(); - let window = state.window_for_surface(surface).unwrap(); - - let initial_window_loc = state.space.element_location(&window).unwrap(); - - let start_data = smithay::input::pointer::GrabStartData { - focus: pointer - .current_focus() - .map(|focus| (focus, initial_window_loc)), - button: 0x110, - location: pointer.current_location(), - }; - - let grab = MoveSurfaceGrab { - start_data, - window, - initial_window_loc, - }; - - pointer.set_grab(state, grab, serial, Focus::Clear); -} - -pub fn resize_request( - state: &mut State, - surface: &WlSurface, - seat: &Seat>, - serial: smithay::utils::Serial, - edges: xdg_toplevel::ResizeEdge, - button_used: u32, -) { - let pointer = seat.get_pointer().unwrap(); - - if let Some(start_data) = crate::pointer::pointer_grab_start_data(&pointer, surface, serial) { - let window = state.window_for_surface(surface).unwrap(); - if window.with_state(|state| state.floating.is_tiled()) { - return; - } - - let initial_window_loc = state.space.element_location(&window).unwrap(); - let initial_window_size = window.geometry().size; - - if let Some(WindowElement::Wayland(window)) = state.window_for_surface(surface) { - window.toplevel().with_pending_state(|state| { - state.states.set(xdg_toplevel::State::Resizing); - }); - - window.toplevel().send_pending_configure(); - } - - let grab = ResizeSurfaceGrab::start( - start_data, - window, - ResizeEdge(edges), - Rectangle::from_loc_and_size(initial_window_loc, initial_window_size), - button_used, - ); - - if let Some(grab) = grab { - pointer.set_grab(state, grab, serial, Focus::Clear); - } - } -} - -pub fn resize_request_force( - state: &mut State, - surface: &WlSurface, - seat: &Seat>, - serial: smithay::utils::Serial, - edges: xdg_toplevel::ResizeEdge, - button_used: u32, -) { - let pointer = seat.get_pointer().unwrap(); - - let window = state.window_for_surface(surface).unwrap(); - - if window.with_state(|state| state.floating.is_tiled()) { - return; - } - - let initial_window_loc = state.space.element_location(&window).unwrap(); - let initial_window_size = window.geometry().size; - - if let Some(WindowElement::Wayland(window)) = state.window_for_surface(surface) { - window.toplevel().with_pending_state(|state| { - state.states.set(xdg_toplevel::State::Resizing); - }); - - window.toplevel().send_pending_configure(); - } - - let start_data = smithay::input::pointer::GrabStartData { - focus: pointer - .current_focus() - .map(|focus| (focus, initial_window_loc)), - button: button_used, - location: pointer.current_location(), - }; - - let grab = ResizeSurfaceGrab::start( - start_data, - window, - ResizeEdge(edges), - Rectangle::from_loc_and_size(initial_window_loc, initial_window_size), - button_used, - ); - - if let Some(grab) = grab { - pointer.set_grab(state, grab, serial, Focus::Clear); - } -}