diff --git a/src/input/mod.rs b/src/input/mod.rs index 08bf703b6..c3ed86101 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -898,18 +898,20 @@ impl State { layers.layer_under(WlrLayer::Overlay, relative_pos.as_logical()) { let layer_loc = layers.layer_geometry(layer).unwrap().loc; - if layer.can_receive_keyboard_focus() - && layer - .surface_under( - relative_pos.as_logical() - layer_loc.to_f64(), - WindowSurfaceType::ALL, - ) - .is_some() - { - under = Some(layer.clone().into()); + if layer.can_receive_keyboard_focus() { + if let Some((wl_surface, _)) = layer.surface_under( + relative_pos.as_logical() - layer_loc.to_f64(), + WindowSurfaceType::ALL, + ) { + under = Some(wl_surface.into()); + } } } else { - under = Some(window.clone().into()); + under = PointerFocusTarget::under_surface( + window, + relative_pos.as_logical(), + ) + .map(|(target, _)| target) } } else { let done = { @@ -924,16 +926,16 @@ impl State { }) { let layer_loc = layers.layer_geometry(layer).unwrap().loc; - if layer.can_receive_keyboard_focus() - && layer - .surface_under( - relative_pos.as_logical() - layer_loc.to_f64(), - WindowSurfaceType::ALL, - ) - .is_some() - { - under = Some(layer.clone().into()); - true + if layer.can_receive_keyboard_focus() { + if let Some((wl_surface, _)) = layer.surface_under( + relative_pos.as_logical() - layer_loc.to_f64(), + WindowSurfaceType::ALL, + ) { + under = Some(wl_surface.into()); + true + } else { + false + } } else { false } @@ -962,16 +964,13 @@ impl State { { let layer_loc = layers.layer_geometry(layer).unwrap().loc; - if layer.can_receive_keyboard_focus() - && layer - .surface_under( - relative_pos.as_logical() - - layer_loc.to_f64(), - WindowSurfaceType::ALL, - ) - .is_some() - { - under = Some(layer.clone().into()); + if layer.can_receive_keyboard_focus() { + if let Some((wl_surface, _)) = layer.surface_under( + relative_pos.as_logical() - layer_loc.to_f64(), + WindowSurfaceType::ALL, + ) { + under = Some(wl_surface.into()); + } } }; } @@ -2192,7 +2191,7 @@ impl State { if let Some(session_lock) = session_lock { return session_lock.surfaces.get(output).map(|surface| { ( - PointerFocusTarget::LockSurface(surface.clone()), + PointerFocusTarget::WlSurface(surface.wl_surface().clone()), output_geo.loc, ) }); @@ -2202,14 +2201,14 @@ impl State { let layers = layer_map_for_output(output); if let Some(layer) = layers.layer_under(WlrLayer::Overlay, relative_pos.as_logical()) { let layer_loc = layers.layer_geometry(layer).unwrap().loc; - if layer - .surface_under( - relative_pos.as_logical() - layer_loc.to_f64(), - WindowSurfaceType::ALL, - ) - .is_some() - { - return Some((layer.clone().into(), output_geo.loc + layer_loc.as_global())); + if let Some((wl_surface, surface_loc)) = layer.surface_under( + relative_pos.as_logical() - layer_loc.to_f64(), + WindowSurfaceType::ALL, + ) { + return Some(( + wl_surface.into(), + output_geo.loc + layer_loc.as_global() + surface_loc.as_global(), + )); } } if let Some(or) = shell.override_redirect_windows.iter().find(|or| { @@ -2217,7 +2216,8 @@ impl State { }) { return Some((or.clone().into(), or.geometry().loc.as_global())); } - Some((window.clone().into(), output_geo.loc)) + PointerFocusTarget::under_surface(window, relative_pos.as_logical()) + .map(|(target, surface_loc)| (target, output_geo.loc + surface_loc.as_global())) } else { { let layers = layer_map_for_output(output); @@ -2226,16 +2226,13 @@ impl State { .or_else(|| layers.layer_under(WlrLayer::Top, relative_pos.as_logical())) { let layer_loc = layers.layer_geometry(layer).unwrap().loc; - if layer - .surface_under( - relative_pos.as_logical() - layer_loc.to_f64(), - WindowSurfaceType::ALL, - ) - .is_some() - { + if let Some((wl_surface, surface_loc)) = layer.surface_under( + relative_pos.as_logical() - layer_loc.to_f64(), + WindowSurfaceType::ALL, + ) { return Some(( - layer.clone().into(), - output_geo.loc + layer_loc.as_global(), + wl_surface.into(), + output_geo.loc + layer_loc.as_global() + surface_loc.as_global(), )); } } @@ -2255,16 +2252,13 @@ impl State { .or_else(|| layers.layer_under(WlrLayer::Background, relative_pos.as_logical())) { let layer_loc = layers.layer_geometry(layer).unwrap().loc; - if layer - .surface_under( - relative_pos.as_logical() - layer_loc.to_f64(), - WindowSurfaceType::ALL, - ) - .is_some() - { + if let Some((wl_surface, surface_loc)) = layer.surface_under( + relative_pos.as_logical() - layer_loc.to_f64(), + WindowSurfaceType::ALL, + ) { return Some(( - layer.clone().into(), - output_geo.loc + layer_loc.as_global(), + wl_surface.into(), + output_geo.loc + layer_loc.as_global() + surface_loc.as_global(), )); } } diff --git a/src/shell/focus/mod.rs b/src/shell/focus/mod.rs index c81d8b042..f9c29b18f 100644 --- a/src/shell/focus/mod.rs +++ b/src/shell/focus/mod.rs @@ -11,8 +11,10 @@ use smithay::{ output::Output, utils::{IsAlive, Serial, SERIAL_COUNTER}, wayland::{ + compositor::with_states, seat::WaylandFocus, shell::wlr_layer::{KeyboardInteractivity, Layer}, + shell::xdg::XdgPopupSurfaceData, }, }; use std::cell::RefCell; @@ -140,8 +142,8 @@ impl Shell { ) { let element = match target { Some(KeyboardFocusTarget::Element(mapped)) => Some(mapped.clone()), - Some(KeyboardFocusTarget::Fullscreen(window)) => { - state.common.shell.element_for_surface(window).cloned() + Some(KeyboardFocusTarget::WlSurface(surface)) => { + state.common.shell.element_for_wl_surface(surface).cloned() } _ => None, }; @@ -260,27 +262,33 @@ impl Common { trace!("Wrong Window, focus fixup"); } } else { - if let KeyboardFocusTarget::Popup(_) = target { + if let KeyboardFocusTarget::WlSurface(surface) = target { if let Some(popup_grab) = seat .user_data() .get::() .and_then(|x| x.take()) { - if !popup_grab.has_ended() { - if let Some(new) = popup_grab.current_grab() { - trace!("restore focus to previous popup grab"); - if let Some(keyboard) = seat.get_keyboard() { - keyboard.set_focus( - state, - Some(new.clone()), - SERIAL_COUNTER.next_serial(), - ); + if with_states(&surface, |states| { + states.data_map.get::().is_some() + }) { + if !popup_grab.has_ended() { + if let Some(new) = popup_grab.current_grab() { + trace!("restore focus to previous popup grab"); + if let Some(keyboard) = seat.get_keyboard() { + keyboard.set_focus( + state, + Some(new.clone()), + SERIAL_COUNTER.next_serial(), + ); + } + ActiveFocus::set(&seat, Some(new)); + seat.user_data() + .get_or_insert::( + PopupGrabData::default, + ) + .set(Some(popup_grab)); + continue; } - ActiveFocus::set(&seat, Some(new)); - seat.user_data() - .get_or_insert::(PopupGrabData::default) - .set(Some(popup_grab)); - continue; } } } @@ -333,19 +341,29 @@ fn focus_target_is_valid( target: KeyboardFocusTarget, ) -> bool { // If a session lock is active, only lock surfaces can be focused - if state.common.shell.session_lock.is_some() { - return matches!(target, KeyboardFocusTarget::LockSurface(_)); + if let Some(session_lock) = state.common.shell.session_lock.as_ref() { + return if let KeyboardFocusTarget::WlSurface(surface) = target { + session_lock + .surfaces + .values() + .any(|x| x.wl_surface() == &surface) + } else { + false + }; } // If an exclusive layer shell surface exists (on any output), only exclusive // shell surfaces can have focus, on the highest layer with exclusive surfaces. if let Some(layer) = exclusive_layer_surface_layer(state) { + // XXX TODO get layer surface for WlSurface, or parent of a subsurface + /* return if let KeyboardFocusTarget::LayerSurface(layer_surface) = target { let data = layer_surface.cached_state(); (data.keyboard_interactivity, data.layer) == (KeyboardInteractivity::Exclusive, layer) } else { false }; + */ } match target { @@ -372,9 +390,11 @@ fn focus_target_is_valid( (is_sticky || is_in_focus_stack) && !has_fullscreen } + /* KeyboardFocusTarget::LayerSurface(layer) => { layer_map_for_output(&output).layers().any(|l| l == &layer) } + */ KeyboardFocusTarget::Group(WindowGroup { node, .. }) => state .common .shell @@ -383,6 +403,7 @@ fn focus_target_is_valid( .1 .tiling_layer .has_node(&node), + /* KeyboardFocusTarget::Fullscreen(window) => { let workspace = state.common.shell.active_space(&output); let focus_stack = workspace.focus_stack.get(&seat); @@ -393,8 +414,9 @@ fn focus_target_is_valid( .unwrap_or(false) && workspace.get_fullscreen().is_some() } - KeyboardFocusTarget::Popup(_) => true, - KeyboardFocusTarget::LockSurface(_) => false, + */ + // TODO restrict when it handles all wl surfaces + KeyboardFocusTarget::WlSurface(_) => true, } } @@ -420,7 +442,7 @@ fn update_focus_target( .cloned() .map(KeyboardFocusTarget::from) } else if let Some(surface) = state.common.shell.active_space(&output).get_fullscreen() { - Some(KeyboardFocusTarget::Fullscreen(surface.clone())) + KeyboardFocusTarget::try_from(surface.clone()).ok() } else { state .common diff --git a/src/shell/focus/target.rs b/src/shell/focus/target.rs index 8078ed169..470f83be9 100644 --- a/src/shell/focus/target.rs +++ b/src/shell/focus/target.rs @@ -3,12 +3,12 @@ use std::sync::Weak; use crate::{ shell::{element::CosmicMapped, layout::tiling::ResizeForkTarget, CosmicSurface}, utils::prelude::*, - wayland::handlers::xdg_shell::popup::get_popup_toplevel, + wayland::handlers::xdg_shell::popup::get_surface_toplevel, }; use id_tree::NodeId; use smithay::{ backend::input::KeyState, - desktop::{LayerSurface, PopupKind}, + desktop::{LayerSurface, PopupKind, WindowSurface, WindowSurfaceType}, input::{ keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ @@ -20,65 +20,80 @@ use smithay::{ Seat, }, reexports::wayland_server::{backend::ObjectId, protocol::wl_surface::WlSurface, Resource}, - utils::{IsAlive, Serial}, + utils::{IsAlive, Logical, Point, Serial}, wayland::{seat::WaylandFocus, session_lock::LockSurface}, xwayland::X11Surface, }; +// discuss: should contain WlSurface, IcedElement #[derive(Debug, Clone, PartialEq)] pub enum PointerFocusTarget { + WlSurface(WlSurface), Element(CosmicMapped), - Fullscreen(CosmicSurface), - LayerSurface(LayerSurface), - Popup(PopupKind), - OverrideRedirect(X11Surface), + X11(X11Surface), ResizeFork(ResizeForkTarget), - LockSurface(LockSurface), } #[derive(Debug, Clone, PartialEq)] pub enum KeyboardFocusTarget { + // Unlike pointer target, should not be a subsurface + WlSurface(WlSurface), Element(CosmicMapped), - Fullscreen(CosmicSurface), Group(WindowGroup), - LayerSurface(LayerSurface), - Popup(PopupKind), - LockSurface(LockSurface), } // TODO: This should be TryFrom, but PopupGrab needs to be able to convert. Fix this in smithay impl From for PointerFocusTarget { fn from(target: KeyboardFocusTarget) -> Self { match target { + KeyboardFocusTarget::WlSurface(surface) => PointerFocusTarget::WlSurface(surface), KeyboardFocusTarget::Element(elem) => PointerFocusTarget::Element(elem), - KeyboardFocusTarget::Fullscreen(elem) => PointerFocusTarget::Fullscreen(elem), - KeyboardFocusTarget::LayerSurface(layer) => PointerFocusTarget::LayerSurface(layer), - KeyboardFocusTarget::Popup(popup) => PointerFocusTarget::Popup(popup), - KeyboardFocusTarget::LockSurface(lock) => PointerFocusTarget::LockSurface(lock), + // KeyboardFocusTarget::Fullscreen(elem) => PointerFocusTarget::Fullscreen(elem), _ => unreachable!("A window grab cannot start a popup grab"), } } } +// TODO get parent toplevel of subsurface impl TryFrom for KeyboardFocusTarget { type Error = (); fn try_from(target: PointerFocusTarget) -> Result { match target { + PointerFocusTarget::WlSurface(surface) => Ok(KeyboardFocusTarget::WlSurface(surface)), PointerFocusTarget::Element(mapped) => Ok(KeyboardFocusTarget::Element(mapped)), - PointerFocusTarget::Fullscreen(surf) => Ok(KeyboardFocusTarget::Fullscreen(surf)), - PointerFocusTarget::LayerSurface(layer) => Ok(KeyboardFocusTarget::LayerSurface(layer)), - PointerFocusTarget::Popup(popup) => Ok(KeyboardFocusTarget::Popup(popup)), - PointerFocusTarget::LockSurface(lock) => Ok(KeyboardFocusTarget::LockSurface(lock)), + PointerFocusTarget::X11(surface) => { + if let Some(wl_surface) = surface.wl_surface() { + Ok(KeyboardFocusTarget::WlSurface(wl_surface)) + } else { + Err(()) + } + } + // PointerFocusTarget::Fullscreen(surf) => Ok(KeyboardFocusTarget::Fullscreen(surf)), _ => Err(()), } } } +impl PointerFocusTarget { + pub fn under_surface>>( + surface: &CosmicSurface, + point: P, + ) -> Option<(Self, Point)> { + match surface.0.underlying_surface() { + WindowSurface::Wayland(_toplevel) => surface + .0 + .surface_under(point, WindowSurfaceType::ALL) + .map(|(wl_surface, point)| (Self::WlSurface(wl_surface), point)), + WindowSurface::X11(surface) => Some((Self::X11(surface.clone()), Point::default())), + } + } +} + impl KeyboardFocusTarget { pub fn toplevel(&self) -> Option { match self { KeyboardFocusTarget::Element(mapped) => mapped.wl_surface(), - KeyboardFocusTarget::Popup(PopupKind::Xdg(xdg)) => get_popup_toplevel(&xdg), + KeyboardFocusTarget::WlSurface(surface) => get_surface_toplevel(&surface), _ => None, } } @@ -100,13 +115,11 @@ impl PartialEq for WindowGroup { impl IsAlive for PointerFocusTarget { fn alive(&self) -> bool { match self { + // XXX? does this change anything + PointerFocusTarget::WlSurface(s) => s.alive(), PointerFocusTarget::Element(e) => e.alive(), - PointerFocusTarget::Fullscreen(f) => f.alive(), - PointerFocusTarget::LayerSurface(l) => l.alive(), - PointerFocusTarget::Popup(p) => p.alive(), - PointerFocusTarget::OverrideRedirect(s) => s.alive(), + PointerFocusTarget::X11(s) => s.alive(), PointerFocusTarget::ResizeFork(f) => f.alive(), - PointerFocusTarget::LockSurface(l) => l.alive(), } } } @@ -114,12 +127,9 @@ impl IsAlive for PointerFocusTarget { impl IsAlive for KeyboardFocusTarget { fn alive(&self) -> bool { match self { + KeyboardFocusTarget::WlSurface(s) => s.alive(), KeyboardFocusTarget::Element(e) => e.alive(), - KeyboardFocusTarget::Fullscreen(f) => f.alive(), KeyboardFocusTarget::Group(g) => g.alive.upgrade().is_some(), - KeyboardFocusTarget::LayerSurface(l) => l.alive(), - KeyboardFocusTarget::Popup(p) => p.alive(), - KeyboardFocusTarget::LockSurface(l) => l.alive(), } } } @@ -127,111 +137,62 @@ impl IsAlive for KeyboardFocusTarget { impl PointerTarget for PointerFocusTarget { fn enter(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { match self { + PointerFocusTarget::WlSurface(s) => PointerTarget::enter(s, seat, data, event), PointerFocusTarget::Element(w) => PointerTarget::enter(w, seat, data, event), - 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), + PointerFocusTarget::X11(s) => PointerTarget::enter(s, seat, data, event), PointerFocusTarget::ResizeFork(f) => PointerTarget::enter(f, seat, data, event), - PointerFocusTarget::LockSurface(l) => { - PointerTarget::enter(l.wl_surface(), seat, data, event) - } } } fn motion(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { match self { PointerFocusTarget::Element(w) => PointerTarget::motion(w, seat, data, event), - PointerFocusTarget::Fullscreen(w) => PointerTarget::motion(w, seat, data, event), - PointerFocusTarget::LayerSurface(l) => PointerTarget::motion(l, seat, data, event), - PointerFocusTarget::Popup(p) => { - PointerTarget::motion(p.wl_surface(), seat, data, event) - } - PointerFocusTarget::OverrideRedirect(s) => PointerTarget::motion(s, seat, data, event), + PointerFocusTarget::WlSurface(s) => PointerTarget::motion(s, seat, data, event), + PointerFocusTarget::X11(s) => PointerTarget::motion(s, seat, data, event), PointerFocusTarget::ResizeFork(f) => PointerTarget::motion(f, seat, data, event), - PointerFocusTarget::LockSurface(l) => { - PointerTarget::motion(l.wl_surface(), seat, data, event) - } } } fn relative_motion(&self, seat: &Seat, data: &mut State, event: &RelativeMotionEvent) { match self { - PointerFocusTarget::Element(w) => PointerTarget::relative_motion(w, seat, data, event), - PointerFocusTarget::Fullscreen(w) => { - PointerTarget::relative_motion(w, seat, data, event) - } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::relative_motion(l, seat, data, event) - } - PointerFocusTarget::Popup(p) => { - PointerTarget::relative_motion(p.wl_surface(), seat, data, event) - } - PointerFocusTarget::OverrideRedirect(s) => { + PointerFocusTarget::WlSurface(s) => { PointerTarget::relative_motion(s, seat, data, event) } + PointerFocusTarget::Element(w) => PointerTarget::relative_motion(w, seat, data, event), + PointerFocusTarget::X11(s) => PointerTarget::relative_motion(s, seat, data, event), PointerFocusTarget::ResizeFork(f) => { PointerTarget::relative_motion(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::relative_motion(l.wl_surface(), seat, data, event) - } } } fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { match self { + PointerFocusTarget::WlSurface(s) => PointerTarget::button(s, seat, data, event), PointerFocusTarget::Element(w) => PointerTarget::button(w, seat, data, event), - PointerFocusTarget::Fullscreen(w) => PointerTarget::button(w, seat, data, event), - PointerFocusTarget::LayerSurface(l) => PointerTarget::button(l, seat, data, event), - PointerFocusTarget::Popup(p) => { - PointerTarget::button(p.wl_surface(), seat, data, event) - } - PointerFocusTarget::OverrideRedirect(s) => PointerTarget::button(s, seat, data, event), + PointerFocusTarget::X11(s) => PointerTarget::button(s, seat, data, event), PointerFocusTarget::ResizeFork(f) => PointerTarget::button(f, seat, data, event), - PointerFocusTarget::LockSurface(l) => { - PointerTarget::button(l.wl_surface(), seat, data, event) - } } } fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { match self { + PointerFocusTarget::WlSurface(s) => PointerTarget::axis(s, seat, data, frame), PointerFocusTarget::Element(w) => PointerTarget::axis(w, seat, data, frame), - 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), + PointerFocusTarget::X11(s) => PointerTarget::axis(s, seat, data, frame), PointerFocusTarget::ResizeFork(f) => PointerTarget::axis(f, seat, data, frame), - PointerFocusTarget::LockSurface(l) => { - PointerTarget::axis(l.wl_surface(), seat, data, frame) - } } } fn frame(&self, seat: &Seat, data: &mut State) { match self { + PointerFocusTarget::WlSurface(s) => PointerTarget::frame(s, seat, data), PointerFocusTarget::Element(w) => PointerTarget::frame(w, seat, data), - PointerFocusTarget::Fullscreen(w) => PointerTarget::frame(w, seat, data), - PointerFocusTarget::LayerSurface(l) => PointerTarget::frame(l, seat, data), - PointerFocusTarget::Popup(p) => PointerTarget::frame(p.wl_surface(), seat, data), - PointerFocusTarget::OverrideRedirect(s) => PointerTarget::frame(s, seat, data), + PointerFocusTarget::X11(s) => PointerTarget::frame(s, seat, data), PointerFocusTarget::ResizeFork(f) => PointerTarget::frame(f, seat, data), - PointerFocusTarget::LockSurface(l) => PointerTarget::frame(l.wl_surface(), seat, data), } } fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: u32) { match self { + PointerFocusTarget::WlSurface(s) => PointerTarget::leave(s, seat, data, serial, time), PointerFocusTarget::Element(w) => PointerTarget::leave(w, seat, data, serial, time), - PointerFocusTarget::Fullscreen(w) => PointerTarget::leave(w, seat, data, serial, time), - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::leave(l, seat, data, serial, time) - } - PointerFocusTarget::Popup(p) => { - PointerTarget::leave(p.wl_surface(), seat, data, serial, time) - } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::leave(s, seat, data, serial, time) - } + PointerFocusTarget::X11(s) => PointerTarget::leave(s, seat, data, serial, time), PointerFocusTarget::ResizeFork(f) => PointerTarget::leave(f, seat, data, serial, time), - PointerFocusTarget::LockSurface(l) => { - PointerTarget::leave(l.wl_surface(), seat, data, serial, time) - } } } fn gesture_swipe_begin( @@ -241,27 +202,16 @@ impl PointerTarget for PointerFocusTarget { event: &GestureSwipeBeginEvent, ) { match self { - PointerFocusTarget::Element(w) => { - PointerTarget::gesture_swipe_begin(w, seat, data, event) + PointerFocusTarget::WlSurface(s) => { + PointerTarget::gesture_swipe_begin(s, seat, data, event) } - PointerFocusTarget::Fullscreen(w) => { + PointerFocusTarget::Element(w) => { PointerTarget::gesture_swipe_begin(w, seat, data, event) } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_swipe_begin(l, seat, data, event) - } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_swipe_begin(p.wl_surface(), seat, data, event) - } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::gesture_swipe_begin(s, seat, data, event) - } + PointerFocusTarget::X11(s) => PointerTarget::gesture_swipe_begin(s, seat, data, event), PointerFocusTarget::ResizeFork(f) => { PointerTarget::gesture_swipe_begin(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::gesture_swipe_begin(l.wl_surface(), seat, data, event) - } } } fn gesture_swipe_update( @@ -271,27 +221,16 @@ impl PointerTarget for PointerFocusTarget { event: &GestureSwipeUpdateEvent, ) { match self { - PointerFocusTarget::Element(w) => { - PointerTarget::gesture_swipe_update(w, seat, data, event) + PointerFocusTarget::WlSurface(s) => { + PointerTarget::gesture_swipe_update(s, seat, data, event) } - PointerFocusTarget::Fullscreen(w) => { + PointerFocusTarget::Element(w) => { PointerTarget::gesture_swipe_update(w, seat, data, event) } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_swipe_update(l, seat, data, event) - } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_swipe_update(p.wl_surface(), seat, data, event) - } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::gesture_swipe_update(s, seat, data, event) - } + PointerFocusTarget::X11(s) => PointerTarget::gesture_swipe_update(s, seat, data, event), PointerFocusTarget::ResizeFork(f) => { PointerTarget::gesture_swipe_update(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::gesture_swipe_update(l.wl_surface(), seat, data, event) - } } } fn gesture_swipe_end( @@ -301,27 +240,16 @@ impl PointerTarget for PointerFocusTarget { event: &GestureSwipeEndEvent, ) { match self { - PointerFocusTarget::Element(w) => { - PointerTarget::gesture_swipe_end(w, seat, data, event) + PointerFocusTarget::WlSurface(s) => { + PointerTarget::gesture_swipe_end(s, seat, data, event) } - PointerFocusTarget::Fullscreen(w) => { + PointerFocusTarget::Element(w) => { PointerTarget::gesture_swipe_end(w, seat, data, event) } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_swipe_end(l, seat, data, event) - } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_swipe_end(p.wl_surface(), seat, data, event) - } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::gesture_swipe_end(s, seat, data, event) - } + PointerFocusTarget::X11(s) => PointerTarget::gesture_swipe_end(s, seat, data, event), PointerFocusTarget::ResizeFork(f) => { PointerTarget::gesture_swipe_end(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::gesture_swipe_end(l.wl_surface(), seat, data, event) - } } } fn gesture_pinch_begin( @@ -331,27 +259,16 @@ impl PointerTarget for PointerFocusTarget { event: &GesturePinchBeginEvent, ) { match self { - PointerFocusTarget::Element(w) => { - PointerTarget::gesture_pinch_begin(w, seat, data, event) + PointerFocusTarget::WlSurface(s) => { + PointerTarget::gesture_pinch_begin(s, seat, data, event) } - PointerFocusTarget::Fullscreen(w) => { + PointerFocusTarget::Element(w) => { PointerTarget::gesture_pinch_begin(w, seat, data, event) } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_pinch_begin(l, seat, data, event) - } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_pinch_begin(p.wl_surface(), seat, data, event) - } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::gesture_pinch_begin(s, seat, data, event) - } + PointerFocusTarget::X11(s) => PointerTarget::gesture_pinch_begin(s, seat, data, event), PointerFocusTarget::ResizeFork(f) => { PointerTarget::gesture_pinch_begin(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::gesture_pinch_begin(l.wl_surface(), seat, data, event) - } } } fn gesture_pinch_update( @@ -361,27 +278,16 @@ impl PointerTarget for PointerFocusTarget { event: &GesturePinchUpdateEvent, ) { match self { - PointerFocusTarget::Element(w) => { - PointerTarget::gesture_pinch_update(w, seat, data, event) + PointerFocusTarget::WlSurface(s) => { + PointerTarget::gesture_pinch_update(s, seat, data, event) } - PointerFocusTarget::Fullscreen(w) => { + PointerFocusTarget::Element(w) => { PointerTarget::gesture_pinch_update(w, seat, data, event) } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_pinch_update(l, seat, data, event) - } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_pinch_update(p.wl_surface(), seat, data, event) - } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::gesture_pinch_update(s, seat, data, event) - } + PointerFocusTarget::X11(s) => PointerTarget::gesture_pinch_update(s, seat, data, event), PointerFocusTarget::ResizeFork(f) => { PointerTarget::gesture_pinch_update(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::gesture_pinch_update(l.wl_surface(), seat, data, event) - } } } fn gesture_pinch_end( @@ -391,27 +297,16 @@ impl PointerTarget for PointerFocusTarget { event: &GesturePinchEndEvent, ) { match self { - PointerFocusTarget::Element(w) => { - PointerTarget::gesture_pinch_end(w, seat, data, event) + PointerFocusTarget::WlSurface(s) => { + PointerTarget::gesture_pinch_end(s, seat, data, event) } - PointerFocusTarget::Fullscreen(w) => { + PointerFocusTarget::Element(w) => { PointerTarget::gesture_pinch_end(w, seat, data, event) } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_pinch_end(l, seat, data, event) - } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_pinch_end(p.wl_surface(), seat, data, event) - } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::gesture_pinch_end(s, seat, data, event) - } + PointerFocusTarget::X11(s) => PointerTarget::gesture_pinch_end(s, seat, data, event), PointerFocusTarget::ResizeFork(f) => { PointerTarget::gesture_pinch_end(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::gesture_pinch_end(l.wl_surface(), seat, data, event) - } } } fn gesture_hold_begin( @@ -421,50 +316,28 @@ impl PointerTarget for PointerFocusTarget { event: &GestureHoldBeginEvent, ) { match self { - PointerFocusTarget::Element(w) => { - PointerTarget::gesture_hold_begin(w, seat, data, event) + PointerFocusTarget::WlSurface(s) => { + PointerTarget::gesture_hold_begin(s, seat, data, event) } - PointerFocusTarget::Fullscreen(w) => { + PointerFocusTarget::Element(w) => { PointerTarget::gesture_hold_begin(w, seat, data, event) } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_hold_begin(l, seat, data, event) - } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_hold_begin(p.wl_surface(), seat, data, event) - } - PointerFocusTarget::OverrideRedirect(s) => { - PointerTarget::gesture_hold_begin(s, seat, data, event) - } + PointerFocusTarget::X11(s) => PointerTarget::gesture_hold_begin(s, seat, data, event), PointerFocusTarget::ResizeFork(f) => { PointerTarget::gesture_hold_begin(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::gesture_hold_begin(l.wl_surface(), seat, data, event) - } } } fn gesture_hold_end(&self, seat: &Seat, data: &mut State, event: &GestureHoldEndEvent) { match self { - PointerFocusTarget::Element(w) => PointerTarget::gesture_hold_end(w, seat, data, event), - PointerFocusTarget::Fullscreen(w) => { - PointerTarget::gesture_hold_end(w, seat, data, event) - } - PointerFocusTarget::LayerSurface(l) => { - PointerTarget::gesture_hold_end(l, seat, data, event) - } - PointerFocusTarget::Popup(p) => { - PointerTarget::gesture_hold_end(p.wl_surface(), seat, data, event) - } - PointerFocusTarget::OverrideRedirect(s) => { + PointerFocusTarget::WlSurface(s) => { PointerTarget::gesture_hold_end(s, seat, data, event) } + PointerFocusTarget::Element(w) => PointerTarget::gesture_hold_end(w, seat, data, event), + PointerFocusTarget::X11(s) => PointerTarget::gesture_hold_end(s, seat, data, event), PointerFocusTarget::ResizeFork(f) => { PointerTarget::gesture_hold_end(f, seat, data, event) } - PointerFocusTarget::LockSurface(l) => { - PointerTarget::gesture_hold_end(l.wl_surface(), seat, data, event) - } } } } @@ -478,34 +351,16 @@ impl KeyboardTarget for KeyboardFocusTarget { serial: Serial, ) { match self { + KeyboardFocusTarget::WlSurface(s) => KeyboardTarget::enter(s, seat, data, keys, serial), KeyboardFocusTarget::Element(w) => KeyboardTarget::enter(w, seat, data, keys, serial), - KeyboardFocusTarget::Fullscreen(w) => { - KeyboardTarget::enter(w, seat, data, keys, serial) - } KeyboardFocusTarget::Group(_) => {} - KeyboardFocusTarget::LayerSurface(l) => { - KeyboardTarget::enter(l, seat, data, keys, serial) - } - KeyboardFocusTarget::Popup(p) => { - KeyboardTarget::enter(p.wl_surface(), seat, data, keys, serial) - } - KeyboardFocusTarget::LockSurface(l) => { - KeyboardTarget::enter(l.wl_surface(), seat, data, keys, serial) - } } } fn leave(&self, seat: &Seat, data: &mut State, serial: Serial) { match self { + KeyboardFocusTarget::WlSurface(s) => KeyboardTarget::leave(s, seat, data, serial), KeyboardFocusTarget::Element(w) => KeyboardTarget::leave(w, seat, data, serial), - KeyboardFocusTarget::Fullscreen(w) => KeyboardTarget::leave(w, seat, data, serial), KeyboardFocusTarget::Group(_) => {} - KeyboardFocusTarget::LayerSurface(l) => KeyboardTarget::leave(l, seat, data, serial), - KeyboardFocusTarget::Popup(p) => { - KeyboardTarget::leave(p.wl_surface(), seat, data, serial) - } - KeyboardFocusTarget::LockSurface(l) => { - KeyboardTarget::leave(l.wl_surface(), seat, data, serial) - } } } fn key( @@ -518,22 +373,13 @@ impl KeyboardTarget for KeyboardFocusTarget { time: u32, ) { match self { - KeyboardFocusTarget::Element(w) => { - KeyboardTarget::key(w, seat, data, key, state, serial, time) + KeyboardFocusTarget::WlSurface(s) => { + KeyboardTarget::key(s, seat, data, key, state, serial, time) } - KeyboardFocusTarget::Fullscreen(w) => { + KeyboardFocusTarget::Element(w) => { KeyboardTarget::key(w, seat, data, key, state, serial, time) } KeyboardFocusTarget::Group(_) => {} - KeyboardFocusTarget::LayerSurface(l) => { - KeyboardTarget::key(l, seat, data, key, state, serial, time) - } - KeyboardFocusTarget::Popup(p) => { - KeyboardTarget::key(p.wl_surface(), seat, data, key, state, serial, time) - } - KeyboardFocusTarget::LockSurface(l) => { - KeyboardTarget::key(l.wl_surface(), seat, data, key, state, serial, time) - } } } fn modifiers( @@ -544,22 +390,13 @@ impl KeyboardTarget for KeyboardFocusTarget { serial: Serial, ) { match self { - KeyboardFocusTarget::Element(w) => { - KeyboardTarget::modifiers(w, seat, data, modifiers, serial) + KeyboardFocusTarget::WlSurface(s) => { + KeyboardTarget::modifiers(s, seat, data, modifiers, serial) } - KeyboardFocusTarget::Fullscreen(w) => { + KeyboardFocusTarget::Element(w) => { KeyboardTarget::modifiers(w, seat, data, modifiers, serial) } KeyboardFocusTarget::Group(_) => {} - KeyboardFocusTarget::LayerSurface(l) => { - KeyboardTarget::modifiers(l, seat, data, modifiers, serial) - } - KeyboardFocusTarget::Popup(p) => { - KeyboardTarget::modifiers(p.wl_surface(), seat, data, modifiers, serial) - } - KeyboardFocusTarget::LockSurface(l) => { - KeyboardTarget::modifiers(l.wl_surface(), seat, data, modifiers, serial) - } } } } @@ -567,22 +404,16 @@ impl KeyboardTarget for KeyboardFocusTarget { impl WaylandFocus for KeyboardFocusTarget { fn wl_surface(&self) -> Option { match self { + KeyboardFocusTarget::WlSurface(s) => Some(s.clone()), KeyboardFocusTarget::Element(w) => WaylandFocus::wl_surface(w), - KeyboardFocusTarget::Fullscreen(w) => WaylandFocus::wl_surface(w), KeyboardFocusTarget::Group(_) => None, - KeyboardFocusTarget::LayerSurface(l) => Some(l.wl_surface().clone()), - KeyboardFocusTarget::Popup(p) => Some(p.wl_surface().clone()), - KeyboardFocusTarget::LockSurface(l) => Some(l.wl_surface().clone()), } } fn same_client_as(&self, object_id: &ObjectId) -> bool { match self { + KeyboardFocusTarget::WlSurface(s) => s.id().same_client_as(object_id), KeyboardFocusTarget::Element(w) => WaylandFocus::same_client_as(w, object_id), - KeyboardFocusTarget::Fullscreen(w) => WaylandFocus::same_client_as(w, object_id), KeyboardFocusTarget::Group(_) => false, - KeyboardFocusTarget::LayerSurface(l) => l.wl_surface().id().same_client_as(object_id), - KeyboardFocusTarget::Popup(p) => p.wl_surface().id().same_client_as(object_id), - KeyboardFocusTarget::LockSurface(l) => l.wl_surface().id().same_client_as(object_id), } } } @@ -590,28 +421,22 @@ impl WaylandFocus for KeyboardFocusTarget { impl WaylandFocus for PointerFocusTarget { fn wl_surface(&self) -> Option { Some(match self { + PointerFocusTarget::WlSurface(s) => s.clone(), PointerFocusTarget::Element(w) => WaylandFocus::wl_surface(w)?, - PointerFocusTarget::Fullscreen(w) => WaylandFocus::wl_surface(w)?, - PointerFocusTarget::LayerSurface(l) => l.wl_surface().clone(), - PointerFocusTarget::Popup(p) => p.wl_surface().clone(), - PointerFocusTarget::OverrideRedirect(s) => { + PointerFocusTarget::X11(s) => { return s.wl_surface(); } PointerFocusTarget::ResizeFork(_) => { return None; } - PointerFocusTarget::LockSurface(l) => l.wl_surface().clone(), }) } fn same_client_as(&self, object_id: &ObjectId) -> bool { match self { + PointerFocusTarget::WlSurface(s) => s.id().same_client_as(object_id), PointerFocusTarget::Element(w) => WaylandFocus::same_client_as(w, object_id), - 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), + PointerFocusTarget::X11(s) => WaylandFocus::same_client_as(s, object_id), PointerFocusTarget::ResizeFork(_) => false, - PointerFocusTarget::LockSurface(l) => l.wl_surface().id().same_client_as(object_id), } } } @@ -622,27 +447,21 @@ impl From for PointerFocusTarget { } } -impl From for PointerFocusTarget { - fn from(s: CosmicSurface) -> Self { - PointerFocusTarget::Fullscreen(s) - } -} - -impl From for PointerFocusTarget { - fn from(l: LayerSurface) -> Self { - PointerFocusTarget::LayerSurface(l) +impl From for PointerFocusTarget { + fn from(s: WlSurface) -> Self { + PointerFocusTarget::WlSurface(s) } } impl From for PointerFocusTarget { fn from(p: PopupKind) -> Self { - PointerFocusTarget::Popup(p) + PointerFocusTarget::WlSurface(p.wl_surface().clone()) } } impl From for PointerFocusTarget { fn from(s: X11Surface) -> Self { - PointerFocusTarget::OverrideRedirect(s) + PointerFocusTarget::X11(s) } } @@ -654,7 +473,7 @@ impl From for PointerFocusTarget { impl From for PointerFocusTarget { fn from(l: LockSurface) -> Self { - PointerFocusTarget::LockSurface(l) + PointerFocusTarget::WlSurface(l.wl_surface().clone()) } } @@ -664,9 +483,11 @@ impl From for KeyboardFocusTarget { } } -impl From for KeyboardFocusTarget { - fn from(s: CosmicSurface) -> Self { - KeyboardFocusTarget::Fullscreen(s) +impl TryFrom for KeyboardFocusTarget { + type Error = (); + + fn try_from(s: CosmicSurface) -> Result { + Ok(KeyboardFocusTarget::WlSurface(s.wl_surface().ok_or(())?)) } } @@ -678,18 +499,18 @@ impl From for KeyboardFocusTarget { impl From for KeyboardFocusTarget { fn from(l: LayerSurface) -> Self { - KeyboardFocusTarget::LayerSurface(l) + KeyboardFocusTarget::WlSurface(l.wl_surface().clone()) } } impl From for KeyboardFocusTarget { fn from(p: PopupKind) -> Self { - KeyboardFocusTarget::Popup(p) + KeyboardFocusTarget::WlSurface(p.wl_surface().clone()) } } impl From for KeyboardFocusTarget { fn from(l: LockSurface) -> Self { - KeyboardFocusTarget::LockSurface(l) + KeyboardFocusTarget::WlSurface(l.wl_surface().clone()) } } diff --git a/src/shell/layout/floating/mod.rs b/src/shell/layout/floating/mod.rs index 524a2d4ee..36f2ded4f 100644 --- a/src/shell/layout/floating/mod.rs +++ b/src/shell/layout/floating/mod.rs @@ -40,7 +40,7 @@ use crate::{ }, state::State, utils::{prelude::*, tween::EaseRectangle}, - wayland::handlers::xdg_shell::popup::get_popup_toplevel, + wayland::handlers::xdg_shell::popup::get_surface_toplevel, }; mod grabs; @@ -906,11 +906,9 @@ impl FloatingLayout { }; let Some(focused) = (match target { - KeyboardFocusTarget::Popup(popup) => { - let Some(toplevel_surface) = (match popup { - PopupKind::Xdg(xdg) => get_popup_toplevel(&xdg), - PopupKind::InputMethod(_) => unreachable!(), - }) else { + KeyboardFocusTarget::WlSurface(surface) => { + // TODO support toplevel + let Some(toplevel_surface) = get_surface_toplevel(&surface) else { return MoveResult::None; }; self.space diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index af3361ca1..ed6c5f883 100644 --- a/src/shell/layout/tiling/mod.rs +++ b/src/shell/layout/tiling/mod.rs @@ -25,7 +25,7 @@ use crate::{ theme::group_color, utils::{prelude::*, tween::EaseRectangle}, wayland::{ - handlers::xdg_shell::popup::get_popup_toplevel, + handlers::xdg_shell::popup::get_surface_toplevel, protocols::{toplevel_info::ToplevelInfoState, workspace::WorkspaceHandle}, }, }; @@ -2787,26 +2787,25 @@ impl TilingLayout { mut target: KeyboardFocusTarget, ) -> Option<(NodeId, FocusedNodeData)> { // if the focus is currently on a popup, treat it's toplevel as the target - if let KeyboardFocusTarget::Popup(popup) = target { - let toplevel_surface = match popup { - PopupKind::Xdg(xdg) => get_popup_toplevel(&xdg), - PopupKind::InputMethod(_) => unreachable!(), - }?; - let root_id = tree.root_node_id()?; - let node = - tree.traverse_pre_order(root_id) - .unwrap() - .find(|node| match node.data() { - Data::Mapped { mapped, .. } => mapped - .windows() - .any(|(w, _)| w.wl_surface().as_ref() == Some(&toplevel_surface)), - _ => false, - })?; - - target = KeyboardFocusTarget::Element(match node.data() { - Data::Mapped { mapped, .. } => mapped.clone(), - _ => unreachable!(), - }); + if let KeyboardFocusTarget::WlSurface(surface) = &target { + // What if it's a popup with no toplevel? + if let Some(toplevel_surface) = get_surface_toplevel(surface) { + let root_id = tree.root_node_id()?; + let node = + tree.traverse_pre_order(root_id) + .unwrap() + .find(|node| match node.data() { + Data::Mapped { mapped, .. } => mapped + .windows() + .any(|(w, _)| w.wl_surface().as_ref() == Some(&toplevel_surface)), + _ => false, + })?; + + target = KeyboardFocusTarget::Element(match node.data() { + Data::Mapped { mapped, .. } => mapped.clone(), + _ => unreachable!(), + }); + } } match target { diff --git a/src/shell/mod.rs b/src/shell/mod.rs index de90788d0..2b1cf2bff 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -52,7 +52,7 @@ use crate::{ wayland::{ handlers::{ toplevel_management::ToplevelManagementExt, xdg_activation::ActivationContext, - xdg_shell::popup::get_popup_toplevel, + xdg_shell::popup::get_surface_toplevel, }, protocols::{ toplevel_info::ToplevelInfoState, @@ -1988,7 +1988,7 @@ impl Shell { to_workspace .fullscreen .as_ref() - .map(|f| KeyboardFocusTarget::from(f.surface.clone())) + .and_then(|f| KeyboardFocusTarget::try_from(f.surface.clone()).ok()) .unwrap_or_else(|| KeyboardFocusTarget::from(mapped.clone())) } else { KeyboardFocusTarget::from(mapped.clone()) @@ -2419,11 +2419,9 @@ impl Shell { let workspace = &mut set.workspaces[set.active]; let Some(focused) = (match target { - KeyboardFocusTarget::Popup(popup) => { - let Some(toplevel_surface) = (match popup { - PopupKind::Xdg(xdg) => get_popup_toplevel(&xdg), - PopupKind::InputMethod(_) => unreachable!(), - }) else { + // TODO update to handle toplevel + KeyboardFocusTarget::WlSurface(surface) => { + let Some(toplevel_surface) = get_surface_toplevel(&surface) else { return FocusResult::None; }; sticky_layer @@ -2555,8 +2553,8 @@ impl Shell { self.unmaximize_request(&last); } - if let Some(surface) = fullscreen { - MoveResult::MoveFurther(KeyboardFocusTarget::Fullscreen(surface)) + if let Some(wl_surface) = fullscreen.and_then(|f| f.wl_surface()) { + MoveResult::MoveFurther(KeyboardFocusTarget::WlSurface(wl_surface)) } else if let Some(set) = self .workspaces .sets diff --git a/src/wayland/handlers/xdg_shell/popup.rs b/src/wayland/handlers/xdg_shell/popup.rs index 55f3e2dfb..ee07b8ac3 100644 --- a/src/wayland/handlers/xdg_shell/popup.rs +++ b/src/wayland/handlers/xdg_shell/popup.rs @@ -19,7 +19,7 @@ use smithay::{ seat::WaylandFocus, shell::xdg::{ PopupSurface, PositionerState, SurfaceCachedState, ToplevelSurface, - XdgPopupSurfaceRoleAttributes, XDG_POPUP_ROLE, + XdgPopupSurfaceData, XDG_POPUP_ROLE, }, }, }; @@ -96,7 +96,7 @@ pub fn update_reactive_popups<'a>( let positioner = with_states(&surface.wl_surface(), |states| { let attributes = states .data_map - .get::>() + .get::() .unwrap() .lock() .unwrap(); @@ -372,13 +372,32 @@ fn get_anchor_point(positioner: &PositionerState) -> Point { .into() } +// XXX +pub fn get_surface_toplevel(surface: &WlSurface) -> Option { + let mut surface = surface.clone(); + while get_role(&surface) == Some(XDG_POPUP_ROLE) { + surface = with_states(&surface, |states| { + states + .data_map + .get::() + .unwrap() + .lock() + .unwrap() + .parent + .as_ref() + .cloned() + })?; + } + Some(surface) +} + pub fn get_popup_toplevel(popup: &PopupSurface) -> Option { let mut parent = popup.get_parent_surface()?; while get_role(&parent) == Some(XDG_POPUP_ROLE) { parent = with_states(&parent, |states| { states .data_map - .get::>() + .get::() .unwrap() .lock() .unwrap() @@ -402,7 +421,7 @@ fn get_popup_toplevel_coords(popup: &PopupSurface) -> Point { offset += with_states(&parent, |states| { states .data_map - .get::>() + .get::() .unwrap() .lock() .unwrap() @@ -413,7 +432,7 @@ fn get_popup_toplevel_coords(popup: &PopupSurface) -> Point { parent = with_states(&parent, |states| { states .data_map - .get::>() + .get::() .unwrap() .lock() .unwrap()