From 5dfefedb02fb25b585f44c1e07c56dc7d27a311d Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Mon, 23 Jan 2023 20:32:37 +0100 Subject: [PATCH] xwayland: Add input handling for override redirect windows --- src/input/mod.rs | 62 ++++++++++++++++++++++++++++---- src/shell/element/window.rs | 2 -- src/shell/focus/target.rs | 20 +++++++++++ src/shell/layout/floating/mod.rs | 2 +- 4 files changed, 76 insertions(+), 10 deletions(-) diff --git a/src/input/mod.rs b/src/input/mod.rs index e59e3c24..b777547e 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -8,7 +8,7 @@ use crate::{ floating::SeatMoveGrabState, tiling::{Direction, FocusResult}, }, - Workspace, + Ordering, OverrideRedirectWindow, Workspace, }, // shell::grabs::SeatMoveGrabState state::Common, utils::prelude::*, @@ -16,11 +16,14 @@ use crate::{ }; use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::InputType; use smithay::{ - backend::input::{ - Axis, AxisSource, Device, DeviceCapability, InputBackend, InputEvent, KeyState, - PointerAxisEvent, + backend::{ + input::{ + Axis, AxisSource, Device, DeviceCapability, InputBackend, InputEvent, KeyState, + PointerAxisEvent, + }, + renderer::element::Id, }, - desktop::{layer_map_for_output, WindowSurfaceType}, + desktop::{layer_map_for_output, space::SpaceElement, WindowSurfaceType}, input::{ keyboard::{keysyms, FilterResult, KeysymHandle, XkbConfig}, pointer::{AxisFrame, ButtonEvent, CursorImageStatus, MotionEvent}, @@ -314,12 +317,13 @@ impl State { let serial = SERIAL_COUNTER.next_serial(); let relative_pos = self.common.shell.map_global_to_space(position, &output); - let workspace = self.common.shell.active_space_mut(&output); + let workspace = self.common.shell.active_space(&output); let under = State::surface_under( position, relative_pos, &output, output_geometry, + &self.common.shell.override_redirect_windows, &workspace, ); @@ -362,13 +366,14 @@ impl State { geometry.size, ); let relative_pos = self.common.shell.map_global_to_space(position, &output); - let workspace = self.common.shell.active_space_mut(&output); + let workspace = self.common.shell.active_space(&output); let serial = SERIAL_COUNTER.next_serial(); let under = State::surface_under( position, relative_pos, &output, geometry, + &self.common.shell.override_redirect_windows, &workspace, ); @@ -909,6 +914,7 @@ impl State { relative_pos: Point, output: &Output, output_geo: Rectangle, + override_redirect_windows: &[OverrideRedirectWindow], workspace: &Workspace, ) -> Option<(PointerFocusTarget, Point)> { let layers = layer_map_for_output(output); @@ -936,12 +942,54 @@ impl State { return Some((layer.clone().into(), output_geo.loc + layer_loc)); } } + if let Some(or) = override_redirect_windows.iter().find(|or| { + or.above == Ordering::Above + && or + .surface + .is_in_input_region(&(global_pos - or.surface.geometry().loc.to_f64())) + }) { + return Some((or.surface.clone().into(), or.surface.geometry().loc)); + } if let Some((mapped, loc)) = workspace.element_under(relative_pos) { + let filter = workspace + .mapped() + .skip_while(|m| *m != mapped) + .collect::>(); + if let Some(or) = override_redirect_windows + .iter() + .filter(|or| { + if let Ordering::AboveWindow(w) = &or.above { + !filter.iter().any(|f| { + f.wl_surface() + .map(|s| Id::from_wayland_resource(&s)) + .as_ref() + == Some(&w) + }) + } else { + false + } + }) + .find(|or| { + or.surface + .is_in_input_region(&(global_pos - or.surface.geometry().loc.to_f64())) + }) + { + return Some((or.surface.clone().into(), or.surface.geometry().loc)); + } + return Some(( mapped.clone().into(), loc + (global_pos - relative_pos).to_i32_round(), )); } + if let Some(or) = override_redirect_windows.iter().find(|or| { + or.above == Ordering::Below + && or + .surface + .is_in_input_region(&(global_pos - or.surface.geometry().loc.to_f64())) + }) { + return Some((or.surface.clone().into(), or.surface.geometry().loc)); + } if let Some(layer) = layers .layer_under(WlrLayer::Bottom, relative_pos) .or_else(|| layers.layer_under(WlrLayer::Background, relative_pos)) diff --git a/src/shell/element/window.rs b/src/shell/element/window.rs index a4ceefec..786d89b0 100644 --- a/src/shell/element/window.rs +++ b/src/shell/element/window.rs @@ -272,7 +272,6 @@ impl SpaceElement for CosmicWindow { self.0.with_program(|p| { let mut bbox = SpaceElement::bbox(&p.window); if p.has_ssd() { - bbox.loc.y -= SSD_HEIGHT; bbox.size.h += SSD_HEIGHT; } bbox @@ -310,7 +309,6 @@ impl SpaceElement for CosmicWindow { self.0.with_program(|p| { let mut geo = SpaceElement::geometry(&p.window); if p.has_ssd() { - geo.loc.y -= SSD_HEIGHT; geo.size.h += SSD_HEIGHT; } geo diff --git a/src/shell/focus/target.rs b/src/shell/focus/target.rs index 97391d77..d686c8d2 100644 --- a/src/shell/focus/target.rs +++ b/src/shell/focus/target.rs @@ -17,6 +17,7 @@ use smithay::{ reexports::wayland_server::{backend::ObjectId, protocol::wl_surface::WlSurface, Resource}, utils::{IsAlive, Serial}, wayland::seat::WaylandFocus, + xwayland::X11Surface, }; #[derive(Debug, Clone, PartialEq)] @@ -25,6 +26,7 @@ pub enum PointerFocusTarget { Fullscreen(CosmicSurface), LayerSurface(LayerSurface), Popup(PopupKind), + OverrideRedirect(X11Surface), } #[derive(Debug, Clone, PartialEq)] @@ -70,6 +72,7 @@ impl IsAlive for PointerFocusTarget { PointerFocusTarget::Fullscreen(f) => f.alive(), PointerFocusTarget::LayerSurface(l) => l.alive(), PointerFocusTarget::Popup(p) => p.alive(), + PointerFocusTarget::OverrideRedirect(s) => s.alive(), } } } @@ -93,6 +96,7 @@ impl PointerTarget for PointerFocusTarget { PointerFocusTarget::Fullscreen(w) => PointerTarget::enter(w, seat, data, event), PointerFocusTarget::LayerSurface(l) => PointerTarget::enter(l, seat, data, event), PointerFocusTarget::Popup(p) => PointerTarget::enter(p.wl_surface(), seat, data, event), + PointerFocusTarget::OverrideRedirect(s) => PointerTarget::enter(s, seat, data, event), } } fn motion(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { @@ -103,6 +107,7 @@ impl PointerTarget for PointerFocusTarget { PointerFocusTarget::Popup(p) => { PointerTarget::motion(p.wl_surface(), seat, data, event) } + PointerFocusTarget::OverrideRedirect(s) => PointerTarget::enter(s, seat, data, event), } } fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { @@ -113,6 +118,7 @@ impl PointerTarget for PointerFocusTarget { PointerFocusTarget::Popup(p) => { PointerTarget::button(p.wl_surface(), seat, data, event) } + PointerFocusTarget::OverrideRedirect(s) => PointerTarget::button(s, seat, data, event), } } fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { @@ -121,6 +127,7 @@ impl PointerTarget for PointerFocusTarget { PointerFocusTarget::Fullscreen(w) => PointerTarget::axis(w, seat, data, frame), PointerFocusTarget::LayerSurface(l) => PointerTarget::axis(l, seat, data, frame), PointerFocusTarget::Popup(p) => PointerTarget::axis(p.wl_surface(), seat, data, frame), + PointerFocusTarget::OverrideRedirect(s) => PointerTarget::axis(s, seat, data, frame), } } fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: u32) { @@ -133,6 +140,9 @@ impl PointerTarget for PointerFocusTarget { PointerFocusTarget::Popup(p) => { PointerTarget::leave(p.wl_surface(), seat, data, serial, time) } + PointerFocusTarget::OverrideRedirect(s) => { + PointerTarget::leave(s, seat, data, serial, time) + } } } } @@ -248,6 +258,9 @@ impl WaylandFocus for PointerFocusTarget { PointerFocusTarget::Fullscreen(w) => WaylandFocus::wl_surface(w)?, PointerFocusTarget::LayerSurface(l) => l.wl_surface().clone(), PointerFocusTarget::Popup(p) => p.wl_surface().clone(), + PointerFocusTarget::OverrideRedirect(s) => { + return s.wl_surface(); + } }) } fn same_client_as(&self, object_id: &ObjectId) -> bool { @@ -256,6 +269,7 @@ impl WaylandFocus for PointerFocusTarget { PointerFocusTarget::Fullscreen(w) => WaylandFocus::same_client_as(w, object_id), PointerFocusTarget::LayerSurface(l) => l.wl_surface().id().same_client_as(object_id), PointerFocusTarget::Popup(p) => p.wl_surface().id().same_client_as(object_id), + PointerFocusTarget::OverrideRedirect(s) => WaylandFocus::same_client_as(s, object_id), } } } @@ -284,6 +298,12 @@ impl From for PointerFocusTarget { } } +impl From for PointerFocusTarget { + fn from(s: X11Surface) -> Self { + PointerFocusTarget::OverrideRedirect(s) + } +} + impl From for KeyboardFocusTarget { fn from(w: CosmicMapped) -> Self { KeyboardFocusTarget::Element(w) diff --git a/src/shell/layout/floating/mod.rs b/src/shell/layout/floating/mod.rs index c8633fe7..0a25def7 100644 --- a/src/shell/layout/floating/mod.rs +++ b/src/shell/layout/floating/mod.rs @@ -209,7 +209,7 @@ impl FloatingLayout { } pub fn mapped(&self) -> impl Iterator { - self.space.elements() + self.space.elements().rev() } pub fn windows(&self) -> impl Iterator + '_ {