Update Smithay, with Window that supports X11 surfaces

This commit is contained in:
Ian Douglas Scott 2024-02-21 13:24:56 -08:00 committed by Victoria Brekenfeld
parent 849882a7db
commit 3036448c19
24 changed files with 482 additions and 619 deletions

2
Cargo.lock generated
View file

@ -4443,7 +4443,7 @@ checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
[[package]] [[package]]
name = "smithay" name = "smithay"
version = "0.3.0" version = "0.3.0"
source = "git+https://github.com/smithay//smithay?rev=094fa3f7c3#094fa3f7c3909a7815000174807d1d962d555718" source = "git+https://github.com/smithay//smithay?rev=7f9e6d5#7f9e6d51e8a12fc992c305de03820a44811b8c18"
dependencies = [ dependencies = [
"appendlist", "appendlist",
"ash", "ash",

View file

@ -108,4 +108,4 @@ inherits = "release"
lto = "fat" lto = "fat"
[patch."https://github.com/Smithay/smithay.git"] [patch."https://github.com/Smithay/smithay.git"]
smithay = {git = "https://github.com/smithay//smithay", rev = "094fa3f7c3"} smithay = {git = "https://github.com/smithay//smithay", rev = "7f9e6d5"}

View file

@ -642,7 +642,7 @@ impl State {
if non_desktop { if non_desktop {
let Ok(output_name) = drm_helpers::interface_name(&device.drm, conn) else { let Ok(output_name) = drm_helpers::interface_name(&device.drm, conn) else {
continue continue;
}; };
let drm_helpers::EdidInfo { let drm_helpers::EdidInfo {
model, model,
@ -779,7 +779,7 @@ impl State {
if non_desktop { if non_desktop {
let Ok(output_name) = drm_helpers::interface_name(&device.drm, conn) else { let Ok(output_name) = drm_helpers::interface_name(&device.drm, conn) else {
continue continue;
}; };
let drm_helpers::EdidInfo { let drm_helpers::EdidInfo {
model, model,

View file

@ -302,7 +302,9 @@ fn try_vulkan_allocator(node: &DrmNode) -> Option<Allocator> {
let Some(device) = devices let Some(device) = devices
.filter(|phd| { .filter(|phd| {
phd.has_device_extension(smithay::reexports::ash::extensions::ext::PhysicalDeviceDrm::name()) phd.has_device_extension(
smithay::reexports::ash::extensions::ext::PhysicalDeviceDrm::name(),
)
}) })
.find(|phd| { .find(|phd| {
phd.primary_node().unwrap() == Some(*node) || phd.render_node().unwrap() == Some(*node) phd.primary_node().unwrap() == Some(*node) || phd.render_node().unwrap() == Some(*node)

View file

@ -1156,7 +1156,9 @@ impl State {
} }
InputEvent::TouchDown { event, .. } => { InputEvent::TouchDown { event, .. } => {
if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() { if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() {
let Some(output) = mapped_output_for_device(&self.common, &event.device()).cloned() else { let Some(output) =
mapped_output_for_device(&self.common, &event.device()).cloned()
else {
return; return;
}; };
@ -1187,7 +1189,9 @@ impl State {
} }
InputEvent::TouchMotion { event, .. } => { InputEvent::TouchMotion { event, .. } => {
if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() { if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() {
let Some(output) = mapped_output_for_device(&self.common, &event.device()).cloned() else { let Some(output) =
mapped_output_for_device(&self.common, &event.device()).cloned()
else {
return; return;
}; };
@ -1227,7 +1231,9 @@ impl State {
InputEvent::TouchFrame { event: _, .. } => {} InputEvent::TouchFrame { event: _, .. } => {}
InputEvent::TabletToolAxis { event, .. } => { InputEvent::TabletToolAxis { event, .. } => {
if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() { if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() {
let Some(output) = mapped_output_for_device(&self.common, &event.device()).cloned() else { let Some(output) =
mapped_output_for_device(&self.common, &event.device()).cloned()
else {
return; return;
}; };
let geometry = output.geometry(); let geometry = output.geometry();
@ -1288,7 +1294,9 @@ impl State {
} }
InputEvent::TabletToolProximity { event, .. } => { InputEvent::TabletToolProximity { event, .. } => {
if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() { if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() {
let Some(output) = mapped_output_for_device(&self.common, &event.device()).cloned() else { let Some(output) =
mapped_output_for_device(&self.common, &event.device()).cloned()
else {
return; return;
}; };
let geometry = output.geometry(); let geometry = output.geometry();

View file

@ -843,10 +843,7 @@ impl SpaceElement for CosmicMapped {
impl X11Relatable for CosmicMapped { impl X11Relatable for CosmicMapped {
fn is_window(&self, window: &X11Surface) -> bool { fn is_window(&self, window: &X11Surface) -> bool {
match self.active_window() { self.active_window().x11_surface() == Some(window)
CosmicSurface::X11(surface) => &surface == window,
_ => false,
}
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -20,7 +20,7 @@ use tracing::{debug, trace};
use self::target::{KeyboardFocusTarget, WindowGroup}; use self::target::{KeyboardFocusTarget, WindowGroup};
use super::{layout::floating::FloatingLayout, CosmicSurface}; use super::layout::floating::FloatingLayout;
pub mod target; pub mod target;
@ -207,11 +207,11 @@ fn raise_with_children(floating_layer: &mut FloatingLayout, focused: &CosmicMapp
.space .space
.elements() .elements()
.filter(|elem| { .filter(|elem| {
let parent = match elem.active_window() { let parent = elem
CosmicSurface::Wayland(w) => w.toplevel().parent(), .active_window()
_ => None, .0
}; .toplevel()
.and_then(|toplevel| toplevel.parent());
parent == focused.active_window().wl_surface() parent == focused.active_window().wl_surface()
}) })
.cloned() .cloned()

View file

@ -24,7 +24,9 @@ fn toggle_stacking(state: &mut State, mapped: &CosmicMapped) {
fn move_prev_workspace(state: &mut State, mapped: &CosmicMapped) { fn move_prev_workspace(state: &mut State, mapped: &CosmicMapped) {
let seat = state.common.last_active_seat().clone(); let seat = state.common.last_active_seat().clone();
let (current_handle, output) = { let (current_handle, output) = {
let Some(ws) = state.common.shell.space_for(mapped) else { return }; let Some(ws) = state.common.shell.space_for(mapped) else {
return;
};
(ws.handle, ws.output.clone()) (ws.handle, ws.output.clone())
}; };
let maybe_handle = state let maybe_handle = state
@ -59,7 +61,9 @@ fn move_prev_workspace(state: &mut State, mapped: &CosmicMapped) {
fn move_next_workspace(state: &mut State, mapped: &CosmicMapped) { fn move_next_workspace(state: &mut State, mapped: &CosmicMapped) {
let seat = state.common.last_active_seat().clone(); let seat = state.common.last_active_seat().clone();
let (current_handle, output) = { let (current_handle, output) = {
let Some(ws) = state.common.shell.space_for(mapped) else { return }; let Some(ws) = state.common.shell.space_for(mapped) else {
return;
};
(ws.handle, ws.output.clone()) (ws.handle, ws.output.clone())
}; };
let maybe_handle = state let maybe_handle = state

View file

@ -230,7 +230,7 @@ impl PointerGrab<State> for MoveGrab {
.as_logical() .as_logical()
.overlaps_or_touches(Rectangle::from_loc_and_size( .overlaps_or_touches(Rectangle::from_loc_and_size(
handle.current_location().to_i32_floor(), handle.current_location().to_i32_floor(),
(0,0), (0, 0),
)) ))
}) })
.cloned() .cloned()

View file

@ -7,13 +7,12 @@ use crate::{
element::CosmicMapped, element::CosmicMapped,
focus::target::PointerFocusTarget, focus::target::PointerFocusTarget,
grabs::{ReleaseMode, ResizeEdge}, grabs::{ReleaseMode, ResizeEdge},
CosmicSurface,
}, },
utils::prelude::*, utils::prelude::*,
}; };
use smithay::{ use smithay::{
backend::input::ButtonState, backend::input::ButtonState,
desktop::space::SpaceElement, desktop::{space::SpaceElement, WindowSurface},
input::{ input::{
pointer::{ pointer::{
AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent,
@ -118,9 +117,10 @@ impl PointerGrab<State> for ResizeSurfaceGrab {
self.window.set_resizing(true); self.window.set_resizing(true);
self.window.set_geometry(Rectangle::from_loc_and_size( self.window.set_geometry(Rectangle::from_loc_and_size(
match self.window.active_window() { if let Some(s) = self.window.active_window().x11_surface() {
CosmicSurface::X11(s) => s.geometry().loc.as_global(), s.geometry().loc.as_global()
_ => (0, 0).into(), } else {
(0, 0).into()
}, },
self.last_window_size.as_global(), self.last_window_size.as_global(),
)); ));
@ -356,20 +356,19 @@ impl ResizeSurfaceGrab {
if let Some(new_location) = new_location { if let Some(new_location) = new_location {
for (window, offset) in window.windows() { for (window, offset) in window.windows() {
match window { match window.0.underlying_surface() {
CosmicSurface::Wayland(window) => { WindowSurface::Wayland(toplevel) => {
update_reactive_popups( update_reactive_popups(
&window, toplevel,
new_location + offset.as_global(), new_location + offset.as_global(),
floating_layer.space.outputs(), floating_layer.space.outputs(),
); );
} }
CosmicSurface::X11(surface) => { WindowSurface::X11(surface) => {
let mut geometry = surface.geometry(); let mut geometry = surface.geometry();
geometry.loc += (location - new_location).as_logical(); geometry.loc += (location - new_location).as_logical();
let _ = surface.configure(geometry); let _ = surface.configure(geometry);
} }
_ => unreachable!(),
} }
} }
floating_layer floating_layer
@ -402,9 +401,10 @@ impl ResizeSurfaceGrab {
self.window.set_resizing(false); self.window.set_resizing(false);
self.window.set_geometry(Rectangle::from_loc_and_size( self.window.set_geometry(Rectangle::from_loc_and_size(
match self.window.active_window() { if let Some(x11_surface) = self.window.active_window().x11_surface() {
CosmicSurface::X11(s) => s.geometry().loc.as_global(), x11_surface.geometry().loc.as_global()
_ => (0, 0).into(), } else {
(0, 0).into()
}, },
self.last_window_size.as_global(), self.last_window_size.as_global(),
)); ));

View file

@ -2,6 +2,7 @@
use regex::RegexSet; use regex::RegexSet;
use smithay::{ use smithay::{
desktop::WindowSurface,
wayland::{compositor::with_states, shell::xdg::XdgToplevelSurfaceData}, wayland::{compositor::with_states, shell::xdg::XdgToplevelSurfaceData},
xwayland::xwm::WmWindowType, xwayland::xwm::WmWindowType,
}; };
@ -100,9 +101,9 @@ lazy_static::lazy_static! {
pub fn is_dialog(window: &CosmicSurface) -> bool { pub fn is_dialog(window: &CosmicSurface) -> bool {
// Check "window type" // Check "window type"
match window { match window.0.underlying_surface() {
CosmicSurface::Wayland(window) => { WindowSurface::Wayland(toplevel) => {
if with_states(window.toplevel().wl_surface(), |states| { if with_states(toplevel.wl_surface(), |states| {
let attrs = states let attrs = states
.data_map .data_map
.get::<XdgToplevelSurfaceData>() .get::<XdgToplevelSurfaceData>()
@ -114,7 +115,7 @@ pub fn is_dialog(window: &CosmicSurface) -> bool {
return true; return true;
} }
} }
CosmicSurface::X11(surface) => { WindowSurface::X11(surface) => {
if surface.is_override_redirect() if surface.is_override_redirect()
|| surface.is_popup() || surface.is_popup()
|| !matches!( || !matches!(
@ -125,7 +126,6 @@ pub fn is_dialog(window: &CosmicSurface) -> bool {
return true; return true;
} }
} }
_ => {}
}; };
// Check if sizing suggest dialog // Check if sizing suggest dialog

View file

@ -58,11 +58,19 @@ impl KeyboardGrab<State> for SwapWindowGrab {
.iter() .iter()
.filter(|(_, action)| matches!(action, Action::Focus(_))) .filter(|(_, action)| matches!(action, Action::Focus(_)))
.map(|(pattern, action)| { .map(|(pattern, action)| {
let Action::Focus(direction) = action else { unreachable!() }; let Action::Focus(direction) = action else {
unreachable!()
};
(pattern.key, *direction) (pattern.key, *direction)
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let Some(direction) = syms.iter().find_map(|sym| focus_bindings.iter().find_map(|(key, direction)| (key.is_some() && sym == key.as_ref().unwrap()).then_some(*direction))) else { return }; let Some(direction) = syms.iter().find_map(|sym| {
focus_bindings.iter().find_map(|(key, direction)| {
(key.is_some() && sym == key.as_ref().unwrap()).then_some(*direction)
})
}) else {
return;
};
data.handle_action( data.handle_action(
Action::Focus(direction), Action::Focus(direction),

View file

@ -462,7 +462,9 @@ impl TilingLayout {
pub fn replace_window(&mut self, old: &CosmicMapped, new: &CosmicMapped) { pub fn replace_window(&mut self, old: &CosmicMapped, new: &CosmicMapped) {
let gaps = self.gaps(); let gaps = self.gaps();
let Some(old_id) = old.tiling_node_id.lock().unwrap().clone() else { return }; let Some(old_id) = old.tiling_node_id.lock().unwrap().clone() else {
return;
};
let mut tree = self.queue.trees.back().unwrap().0.copy_clone(); let mut tree = self.queue.trees.back().unwrap().0.copy_clone();
if let Ok(node) = tree.get_mut(&old_id) { if let Ok(node) = tree.get_mut(&old_id) {
@ -501,7 +503,13 @@ impl TilingLayout {
match desc.stack_window { match desc.stack_window {
Some(stack_surface) => { Some(stack_surface) => {
let node = this_tree.get(&desc.node).ok()?; let node = this_tree.get(&desc.node).ok()?;
let Data::Mapped { mapped: this_mapped, .. } = node.data() else { return None }; let Data::Mapped {
mapped: this_mapped,
..
} = node.data()
else {
return None;
};
let this_stack = this_mapped.stack_ref()?; let this_stack = this_mapped.stack_ref()?;
this_stack.remove_window(&stack_surface); this_stack.remove_window(&stack_surface);
if !this_stack.alive() { if !this_stack.alive() {
@ -698,7 +706,9 @@ impl TilingLayout {
} }
} }
(None, None) => { (None, None) => {
let Some(other_tree) = other_tree.as_mut() else { unreachable!() }; let Some(other_tree) = other_tree.as_mut() else {
unreachable!()
};
let this_node = this_tree.get_mut(&this_desc.node).ok()?; let this_node = this_tree.get_mut(&this_desc.node).ok()?;
let other_node = other_tree.get_mut(&other_desc.node).ok()?; let other_node = other_tree.get_mut(&other_desc.node).ok()?;
@ -842,7 +852,13 @@ impl TilingLayout {
return None; return None;
} }
let this_node = this_tree.get_mut(&this_desc.node).ok()?; let this_node = this_tree.get_mut(&this_desc.node).ok()?;
let Data::Mapped { mapped: this_mapped, .. } = this_node.data() else { return None }; let Data::Mapped {
mapped: this_mapped,
..
} = this_node.data()
else {
return None;
};
let this_mapped = this_mapped.clone(); let this_mapped = this_mapped.clone();
let geometry = *this_node.data().geometry(); let geometry = *this_node.data().geometry();
assert!(this_mapped.is_stack()); assert!(this_mapped.is_stack());
@ -927,7 +943,13 @@ impl TilingLayout {
let other_tree = other_tree.as_mut().unwrap_or(&mut this_tree); let other_tree = other_tree.as_mut().unwrap_or(&mut this_tree);
let other_node = other_tree.get_mut(&other_desc.node).ok()?; let other_node = other_tree.get_mut(&other_desc.node).ok()?;
let Data::Mapped { mapped: other_mapped, .. } = other_node.data() else { return None }; let Data::Mapped {
mapped: other_mapped,
..
} = other_node.data()
else {
return None;
};
let other_mapped = other_mapped.clone(); let other_mapped = other_mapped.clone();
let geometry = *other_node.data().geometry(); let geometry = *other_node.data().geometry();
assert!(other_mapped.is_stack()); assert!(other_mapped.is_stack());
@ -1259,9 +1281,7 @@ impl TilingLayout {
let Some(target) = seat.get_keyboard().unwrap().current_focus() else { let Some(target) = seat.get_keyboard().unwrap().current_focus() else {
return MoveResult::None; return MoveResult::None;
}; };
let Some((node_id, data)) = let Some((node_id, data)) = TilingLayout::currently_focused_node(&mut tree, target) else {
TilingLayout::currently_focused_node(&mut tree, target)
else {
return MoveResult::None; return MoveResult::None;
}; };
@ -1587,14 +1607,10 @@ impl TilingLayout {
let Some(target) = seat.get_keyboard().unwrap().current_focus() else { let Some(target) = seat.get_keyboard().unwrap().current_focus() else {
return FocusResult::None; return FocusResult::None;
}; };
let Some(focused) = let Some(focused) = TilingLayout::currently_focused_node(tree, target).or_else(|| {
TilingLayout::currently_focused_node(tree, target).or_else( TilingLayout::last_active_window(tree, focus_stack)
|| { .map(|(id, mapped)| (id, FocusedNodeData::Window(mapped)))
TilingLayout::last_active_window(tree, focus_stack) }) else {
.map(|(id, mapped)| (id, FocusedNodeData::Window(mapped)))
},
)
else {
return FocusResult::None; return FocusResult::None;
}; };
@ -2252,21 +2268,23 @@ impl TilingLayout {
let gaps = self.gaps(); let gaps = self.gaps();
let mut tree = self.queue.trees.back().unwrap().0.copy_clone(); let mut tree = self.queue.trees.back().unwrap().0.copy_clone();
let Some(root_id) = tree.root_node_id() else { return false }; let Some(root_id) = tree.root_node_id() else {
let Some(mut node_id) = return false;
(match TilingLayout::currently_focused_node(&tree, focused.clone()) { };
Some((_id, FocusedNodeData::Window(mapped))) => let Some(mut node_id) = (match TilingLayout::currently_focused_node(&tree, focused.clone())
// we need to make sure the id belongs to this tree.. {
{ Some((_id, FocusedNodeData::Window(mapped))) =>
tree.traverse_pre_order_ids(root_id) // we need to make sure the id belongs to this tree..
.unwrap() {
.find(|id| tree.get(id).unwrap().data().is_mapped(Some(&mapped))) tree.traverse_pre_order_ids(root_id)
} .unwrap()
Some((id, FocusedNodeData::Group(_, _))) => Some(id), // in this case the workspace handle was already matched, so the id is to be trusted .find(|id| tree.get(id).unwrap().data().is_mapped(Some(&mapped)))
_ => None, }
}) else { Some((id, FocusedNodeData::Group(_, _))) => Some(id), // in this case the workspace handle was already matched, so the id is to be trusted
return false _ => None,
}; }) else {
return false;
};
while let Some(group_id) = tree.get(&node_id).unwrap().parent().cloned() { while let Some(group_id) = tree.get(&node_id).unwrap().parent().cloned() {
let orientation = tree.get(&group_id).unwrap().data().orientation(); let orientation = tree.get(&group_id).unwrap().data().orientation();
@ -3138,8 +3156,8 @@ impl TilingLayout {
.unwrap() .unwrap()
.position(|node| { .position(|node| {
let Some(geo) = geometries.get(node) else { let Some(geo) = geometries.get(node) else {
return false; return false;
}; };
match orientation { match orientation {
Orientation::Vertical => location.x < geo.loc.x, Orientation::Vertical => location.x < geo.loc.x,
Orientation::Horizontal => location.y < geo.loc.y, Orientation::Horizontal => location.y < geo.loc.y,

View file

@ -15,7 +15,7 @@ use keyframe::{ease, functions::EaseInOutCubic};
use smithay::{ use smithay::{
desktop::{ desktop::{
layer_map_for_output, space::SpaceElement, LayerSurface, PopupKind, PopupManager, layer_map_for_output, space::SpaceElement, LayerSurface, PopupKind, PopupManager,
WindowSurfaceType, WindowSurface, WindowSurfaceType,
}, },
input::{ input::{
pointer::{Focus, GrabStartData as PointerGrabStartData, MotionEvent}, pointer::{Focus, GrabStartData as PointerGrabStartData, MotionEvent},
@ -170,10 +170,11 @@ pub enum ActivationKey {
impl From<&CosmicSurface> for ActivationKey { impl From<&CosmicSurface> for ActivationKey {
fn from(value: &CosmicSurface) -> Self { fn from(value: &CosmicSurface) -> Self {
match value { match value.0.underlying_surface() {
CosmicSurface::Wayland(w) => ActivationKey::Wayland(w.toplevel().wl_surface().clone()), WindowSurface::Wayland(toplevel) => {
CosmicSurface::X11(s) => ActivationKey::X11(s.window_id()), ActivationKey::Wayland(toplevel.wl_surface().clone())
_ => unreachable!(), }
WindowSurface::X11(s) => ActivationKey::X11(s.window_id()),
} }
} }
} }
@ -1091,19 +1092,19 @@ impl Shell {
.map(|(_, w, _)| w) .map(|(_, w, _)| w)
.chain(set.workspaces[set.active].floating_layer.space.elements()) .chain(set.workspaces[set.active].floating_layer.space.elements())
{ {
if let CosmicSurface::X11(surf) = window.active_window() { if let Some(surf) = window.active_window().x11_surface() {
let _ = xwm.raise_window(&surf); let _ = xwm.raise_window(surf);
} }
} }
for window in set.sticky_layer.space.elements() { for window in set.sticky_layer.space.elements() {
if let CosmicSurface::X11(surf) = window.active_window() { if let Some(surf) = window.active_window().x11_surface() {
let _ = xwm.raise_window(&surf); let _ = xwm.raise_window(surf);
} }
} }
if let Some(CosmicSurface::X11(ref surf)) = set.workspaces[set.active] if let Some(surf) = set.workspaces[set.active]
.fullscreen .fullscreen
.as_ref() .as_ref()
.map(|f| &f.surface) .and_then(|f| f.surface.x11_surface())
{ {
let _ = xwm.raise_window(surf); let _ = xwm.raise_window(surf);
} }
@ -1258,6 +1259,19 @@ impl Shell {
}) })
} }
pub fn element_for_x11_surface(&self, surface: &X11Surface) -> Option<&CosmicMapped> {
self.workspaces.sets.values().find_map(|set| {
set.sticky_layer
.mapped()
.find(|w| w.windows().any(|(s, _)| s.x11_surface() == Some(surface)))
.or_else(|| {
set.workspaces
.iter()
.find_map(|w| w.element_for_x11_surface(surface))
})
})
}
pub fn space_for(&self, mapped: &CosmicMapped) -> Option<&Workspace> { pub fn space_for(&self, mapped: &CosmicMapped) -> Option<&Workspace> {
self.workspaces self.workspaces
.spaces() .spaces()
@ -1554,25 +1568,24 @@ impl Shell {
.unwrap(); .unwrap();
let (window, seat, output) = state.common.shell.pending_windows.remove(pos); let (window, seat, output) = state.common.shell.pending_windows.remove(pos);
let parent_is_sticky = match window.clone() { let parent_is_sticky = if let Some(toplevel) = window.0.toplevel() {
CosmicSurface::Wayland(toplevel) => { if let Some(parent) = toplevel.parent() {
if let Some(parent) = toplevel.toplevel().parent() { if let Some(elem) = state.common.shell.element_for_wl_surface(&parent) {
if let Some(elem) = state.common.shell.element_for_wl_surface(&parent) { state
state .common
.common .shell
.shell .workspaces
.workspaces .sets
.sets .values()
.values() .any(|set| set.sticky_layer.mapped().any(|m| m == elem))
.any(|set| set.sticky_layer.mapped().any(|m| m == elem))
} else {
false
}
} else { } else {
false false
} }
} else {
false
} }
_ => false, } else {
false
}; };
let pending_activation = state let pending_activation = state
@ -2013,11 +2026,11 @@ impl Shell {
.unwrap() .unwrap()
.loc .loc
.to_global(&workspace.output); .to_global(&workspace.output);
for (toplevel, offset) in mapped.windows() { for (window, offset) in mapped.windows() {
if let CosmicSurface::Wayland(toplevel) = toplevel { if let Some(toplevel) = window.0.toplevel() {
let window_geo_offset = toplevel.geometry().loc.as_global(); let window_geo_offset = window.geometry().loc.as_global();
update_reactive_popups( update_reactive_popups(
&toplevel, toplevel,
element_loc + offset.as_global() + window_geo_offset, element_loc + offset.as_global() + window_geo_offset,
self.outputs(), self.outputs(),
); );

View file

@ -44,6 +44,7 @@ use smithay::{
seat::WaylandFocus, seat::WaylandFocus,
xdg_activation::{XdgActivationState, XdgActivationToken}, xdg_activation::{XdgActivationState, XdgActivationToken},
}, },
xwayland::X11Surface,
}; };
use std::{ use std::{
collections::{HashMap, HashSet, VecDeque}, collections::{HashMap, HashSet, VecDeque},
@ -418,6 +419,13 @@ impl Workspace {
}) })
} }
pub fn element_for_x11_surface(&self, surface: &X11Surface) -> Option<&CosmicMapped> {
self.floating_layer
.mapped()
.chain(self.tiling_layer.mapped().map(|(_, w, _)| w))
.find(|e| e.windows().any(|(w, _)| w.x11_surface() == Some(surface)))
}
pub fn element_under( pub fn element_under(
&mut self, &mut self,
location: Point<f64, Global>, location: Point<f64, Global>,

View file

@ -1,9 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use crate::{ use crate::{state::ClientState, utils::prelude::*, wayland::protocols::screencopy::SessionType};
shell::CosmicSurface, state::ClientState, utils::prelude::*,
wayland::protocols::screencopy::SessionType,
};
use calloop::Interest; use calloop::Interest;
use smithay::{ use smithay::{
backend::renderer::utils::{on_commit_buffer_handler, with_renderer_surface_state}, backend::renderer::utils::{on_commit_buffer_handler, with_renderer_surface_state},
@ -157,21 +154,14 @@ impl CompositorHandler for State {
.find(|(window, _, _)| window.wl_surface().as_ref() == Some(surface)) .find(|(window, _, _)| window.wl_surface().as_ref() == Some(surface))
.cloned() .cloned()
{ {
match window { if let Some(toplevel) = window.0.toplevel() {
CosmicSurface::Wayland(ref wl_window) => { if self.toplevel_ensure_initial_configure(&toplevel)
let toplevel = wl_window.toplevel(); && with_renderer_surface_state(&surface, |state| state.buffer().is_some())
if self.toplevel_ensure_initial_configure(&toplevel) .unwrap_or(false)
&& with_renderer_surface_state(&surface, |state| state.buffer().is_some()) {
.unwrap_or(false) window.on_commit();
{ Shell::map_window(self, &window);
window.on_commit();
Shell::map_window(self, &window);
} else {
return;
}
} }
CosmicSurface::X11(_) => {}
_ => unreachable!(),
} }
} }

View file

@ -20,10 +20,7 @@ use smithay::{
}; };
use wayland_backend::protocol::WEnum; use wayland_backend::protocol::WEnum;
use crate::{ use crate::{shell::CosmicMapped, state::State};
shell::{CosmicMapped, CosmicSurface},
state::State,
};
pub struct PreferredDecorationMode(RefCell<Option<XdgMode>>); pub struct PreferredDecorationMode(RefCell<Option<XdgMode>>);
@ -60,53 +57,61 @@ impl PreferredDecorationMode {
impl State { impl State {
pub fn new_decoration(mapped: &CosmicMapped, surface: &WlSurface) -> KdeMode { pub fn new_decoration(mapped: &CosmicMapped, surface: &WlSurface) -> KdeMode {
if mapped.is_stack() { if mapped.is_stack() {
if let Some((CosmicSurface::Wayland(window), _)) = mapped if let Some((window, _)) = mapped
.windows() .windows()
.find(|(window, _)| window.wl_surface().as_ref() == Some(surface)) .find(|(window, _)| window.wl_surface().as_ref() == Some(surface))
{ {
window if let Some(toplevel) = window.0.toplevel() {
.toplevel() toplevel.with_pending_state(|state| {
.with_pending_state(|state| state.decoration_mode = Some(XdgMode::ServerSide)); state.decoration_mode = Some(XdgMode::ServerSide)
window.toplevel().send_configure(); });
toplevel.send_configure();
}
} }
KdeMode::Server KdeMode::Server
} else { } else {
if let Some((CosmicSurface::Wayland(window), _)) = mapped if let Some((window, _)) = mapped
.windows() .windows()
.find(|(window, _)| window.wl_surface().as_ref() == Some(surface)) .find(|(window, _)| window.wl_surface().as_ref() == Some(surface))
{ {
window if let Some(toplevel) = window.0.toplevel() {
.toplevel() toplevel.with_pending_state(|state| {
.with_pending_state(|state| state.decoration_mode = Some(XdgMode::ClientSide)); state.decoration_mode = Some(XdgMode::ClientSide)
window.toplevel().send_configure(); });
toplevel.send_configure();
}
} }
KdeMode::Client KdeMode::Client
} }
} }
pub fn request_mode(mapped: &CosmicMapped, surface: &WlSurface, mode: XdgMode) { pub fn request_mode(mapped: &CosmicMapped, surface: &WlSurface, mode: XdgMode) {
if let Some((CosmicSurface::Wayland(window), _)) = mapped if let Some((window, _)) = mapped
.windows() .windows()
.find(|(window, _)| window.wl_surface().as_ref() == Some(surface)) .find(|(window, _)| window.wl_surface().as_ref() == Some(surface))
{ {
PreferredDecorationMode::update(&window, Some(mode)); if let Some(toplevel) = window.0.toplevel() {
window.toplevel().with_pending_state(|state| { PreferredDecorationMode::update(&window.0, Some(mode));
state.decoration_mode = Some(mode); toplevel.with_pending_state(|state| {
}); state.decoration_mode = Some(mode);
window.toplevel().send_configure(); });
toplevel.send_configure();
}
} }
} }
pub fn unset_mode(mapped: &CosmicMapped, surface: &WlSurface) { pub fn unset_mode(mapped: &CosmicMapped, surface: &WlSurface) {
if let Some((CosmicSurface::Wayland(window), _)) = mapped if let Some((window, _)) = mapped
.windows() .windows()
.find(|(window, _)| window.wl_surface().as_ref() == Some(surface)) .find(|(window, _)| window.wl_surface().as_ref() == Some(surface))
{ {
PreferredDecorationMode::update(&window, None); if let Some(toplevel) = window.0.toplevel() {
window.toplevel().with_pending_state(|state| { PreferredDecorationMode::update(&window.0, None);
state.decoration_mode = None; toplevel.with_pending_state(|state| {
}); state.decoration_mode = None;
window.toplevel().send_configure(); });
toplevel.send_configure();
}
} }
} }
} }

View file

@ -30,7 +30,7 @@ impl DmabufHandler for State {
Ok(Some(node)) => { Ok(Some(node)) => {
// kms backend // kms backend
let Ok(buffer) = import_notifier.successful::<State>() else { let Ok(buffer) = import_notifier.successful::<State>() else {
return return;
}; };
if let BackendData::Kms(kms_state) = &mut self.backend { if let BackendData::Kms(kms_state) = &mut self.backend {

View file

@ -68,7 +68,12 @@ impl ToplevelManagementHandler for State {
workspace: ZcosmicWorkspaceHandleV1, workspace: ZcosmicWorkspaceHandleV1,
_output: Output, _output: Output,
) { ) {
let Some(to_handle) = self.common.shell.workspace_state.get_workspace_handle(&workspace) else { let Some(to_handle) = self
.common
.shell
.workspace_state
.get_workspace_handle(&workspace)
else {
return; return;
}; };

View file

@ -61,14 +61,16 @@ impl XdgActivationHandler for State {
// Tokens without validation aren't allowed to steal focus // Tokens without validation aren't allowed to steal focus
let Some((serial, seat)) = data.serial else { let Some((serial, seat)) = data.serial else {
data.user_data.insert_if_missing(|| ActivationContext::UrgentOnly); data.user_data
.insert_if_missing(|| ActivationContext::UrgentOnly);
debug!(?token, "created urgent-only token for missing seat/serial"); debug!(?token, "created urgent-only token for missing seat/serial");
return true return true;
}; };
let Some(seat) = Seat::from_resource(&seat) else { let Some(seat) = Seat::from_resource(&seat) else {
data.user_data.insert_if_missing(|| ActivationContext::UrgentOnly); data.user_data
.insert_if_missing(|| ActivationContext::UrgentOnly);
debug!(?token, "created urgent-only token for unknown seat"); debug!(?token, "created urgent-only token for unknown seat");
return true return true;
}; };
// At this point we don't bother with urgent-only tokens. // At this point we don't bother with urgent-only tokens.

View file

@ -9,7 +9,7 @@ use smithay::{
delegate_xdg_shell, delegate_xdg_shell,
desktop::{ desktop::{
find_popup_root_surface, PopupGrab, PopupKeyboardGrab, PopupKind, PopupPointerGrab, find_popup_root_surface, PopupGrab, PopupKeyboardGrab, PopupKind, PopupPointerGrab,
PopupUngrabStrategy, Window, PopupUngrabStrategy,
}, },
input::{pointer::Focus, Seat}, input::{pointer::Focus, Seat},
output::Output, output::Output,
@ -43,7 +43,7 @@ impl XdgShellHandler for State {
fn new_toplevel(&mut self, surface: ToplevelSurface) { fn new_toplevel(&mut self, surface: ToplevelSurface) {
let seat = self.common.last_active_seat().clone(); let seat = self.common.last_active_seat().clone();
let window = CosmicSurface::Wayland(Window::new(surface)); let window = CosmicSurface::from(surface);
self.common.shell.pending_windows.push((window, seat, None)); self.common.shell.pending_windows.push((window, seat, None));
// We will position the window after the first commit, when we know its size hints // We will position the window after the first commit, when we know its size hints
} }

View file

@ -3,7 +3,7 @@
use crate::{shell::Shell, utils::prelude::*}; use crate::{shell::Shell, utils::prelude::*};
use smithay::{ use smithay::{
desktop::{ desktop::{
layer_map_for_output, space::SpaceElement, LayerSurface, PopupKind, PopupManager, Window, layer_map_for_output, space::SpaceElement, LayerSurface, PopupKind, PopupManager,
WindowSurfaceType, WindowSurfaceType,
}, },
output::Output, output::Output,
@ -18,8 +18,8 @@ use smithay::{
compositor::{get_role, with_states}, compositor::{get_role, with_states},
seat::WaylandFocus, seat::WaylandFocus,
shell::xdg::{ shell::xdg::{
PopupSurface, PositionerState, SurfaceCachedState, XdgPopupSurfaceRoleAttributes, PopupSurface, PositionerState, SurfaceCachedState, ToplevelSurface,
XDG_POPUP_ROLE, XdgPopupSurfaceRoleAttributes, XDG_POPUP_ROLE,
}, },
}, },
}; };
@ -85,12 +85,12 @@ impl Shell {
} }
pub fn update_reactive_popups<'a>( pub fn update_reactive_popups<'a>(
window: &Window, toplevel: &ToplevelSurface,
loc: Point<i32, Global>, loc: Point<i32, Global>,
outputs: impl Iterator<Item = &'a Output>, outputs: impl Iterator<Item = &'a Output>,
) { ) {
let output_geo = outputs.map(|o| o.geometry()).collect::<Vec<_>>(); let output_geo = outputs.map(|o| o.geometry()).collect::<Vec<_>>();
for (popup, _) in PopupManager::popups_for_surface(window.toplevel().wl_surface()) { for (popup, _) in PopupManager::popups_for_surface(toplevel.wl_surface()) {
match popup { match popup {
PopupKind::Xdg(surface) => { PopupKind::Xdg(surface) => {
let positioner = with_states(&surface.wl_surface(), |states| { let positioner = with_states(&surface.wl_surface(), |states| {

View file

@ -153,8 +153,7 @@ impl XwmHandler for State {
} }
let startup_id = window.startup_id(); let startup_id = window.startup_id();
let surface = CosmicSurface::X11(window.clone()); if self.common.shell.element_for_x11_surface(&window).is_some() {
if self.common.shell.element_for_surface(&surface).is_some() {
return; return;
} }
@ -175,6 +174,7 @@ impl XwmHandler for State {
); );
} }
let surface = CosmicSurface::from(window);
self.common self.common
.shell .shell
.pending_windows .pending_windows
@ -187,13 +187,7 @@ impl XwmHandler for State {
.shell .shell
.pending_windows .pending_windows
.iter() .iter()
.find(|(window, _, _)| { .find(|(window, _, _)| window.x11_surface() == Some(&surface))
if let CosmicSurface::X11(window) = window {
window == &surface
} else {
false
}
})
.cloned() .cloned()
{ {
if !self if !self
@ -202,10 +196,7 @@ impl XwmHandler for State {
.pending_activations .pending_activations
.contains_key(&crate::shell::ActivationKey::X11(surface.window_id())) .contains_key(&crate::shell::ActivationKey::X11(surface.window_id()))
{ {
if let Some(startup_id) = match &window { if let Some(startup_id) = window.x11_surface().and_then(|x| x.startup_id()) {
CosmicSurface::X11(x11) => x11.startup_id(),
_ => None,
} {
if let Some(context) = self if let Some(context) = self
.common .common
.shell .shell
@ -238,7 +229,6 @@ impl XwmHandler for State {
} }
fn unmapped_window(&mut self, _xwm: XwmId, window: X11Surface) { fn unmapped_window(&mut self, _xwm: XwmId, window: X11Surface) {
let surface = CosmicSurface::X11(window.clone());
if window.is_override_redirect() { if window.is_override_redirect() {
self.common self.common
.shell .shell
@ -247,7 +237,7 @@ impl XwmHandler for State {
} else if let Some((element, space)) = self } else if let Some((element, space)) = self
.common .common
.shell .shell
.element_for_surface(&surface) .element_for_x11_surface(&window)
.cloned() .cloned()
.and_then(|element| { .and_then(|element| {
self.common self.common
@ -257,7 +247,12 @@ impl XwmHandler for State {
}) })
{ {
if element.is_stack() && element.stack_ref().unwrap().len() >= 2 { if element.is_stack() && element.stack_ref().unwrap().len() >= 2 {
element.stack_ref().unwrap().remove_window(&surface); if let Some((surface, _)) = element
.windows()
.find(|(w, _)| w.x11_surface() == Some(&window))
{
element.stack_ref().unwrap().remove_window(&surface);
}
} else { } else {
space.unmap(&element); space.unmap(&element);
} }
@ -322,11 +317,7 @@ impl XwmHandler for State {
) { ) {
// We only allow floating X11 windows to resize themselves. Nothing else // We only allow floating X11 windows to resize themselves. Nothing else
let mut current_geo = window.geometry(); let mut current_geo = window.geometry();
if let Some(mapped) = self if let Some(mapped) = self.common.shell.element_for_x11_surface(&window) {
.common
.shell
.element_for_surface(&CosmicSurface::X11(window.clone()))
{
let space = self.common.shell.space_for(mapped).unwrap(); let space = self.common.shell.space_for(mapped).unwrap();
if space.is_floating(mapped) { if space.is_floating(mapped) {
mapped.set_geometry( mapped.set_geometry(
@ -424,24 +415,26 @@ impl XwmHandler for State {
} }
fn maximize_request(&mut self, _xwm: XwmId, window: X11Surface) { fn maximize_request(&mut self, _xwm: XwmId, window: X11Surface) {
let surface = CosmicSurface::X11(window); if let Some(mapped) = self.common.shell.element_for_x11_surface(&window).cloned() {
if let Some(mapped) = self.common.shell.element_for_surface(&surface).cloned() {
self.common.shell.maximize_request(&mapped); self.common.shell.maximize_request(&mapped);
} }
} }
fn unmaximize_request(&mut self, _xwm: XwmId, window: X11Surface) { fn unmaximize_request(&mut self, _xwm: XwmId, window: X11Surface) {
let surface = CosmicSurface::X11(window); if let Some(mapped) = self.common.shell.element_for_x11_surface(&window).cloned() {
if let Some(mapped) = self.common.shell.element_for_surface(&surface).cloned() {
self.common.shell.unmaximize_request(&mapped); self.common.shell.unmaximize_request(&mapped);
} }
} }
fn fullscreen_request(&mut self, _xwm: XwmId, window: X11Surface) { fn fullscreen_request(&mut self, _xwm: XwmId, window: X11Surface) {
let surface = CosmicSurface::X11(window); if let Some(mapped) = self.common.shell.element_for_x11_surface(&window).cloned() {
if let Some(mapped) = self.common.shell.element_for_surface(&surface).cloned() {
if let Some(workspace) = self.common.shell.space_for_mut(&mapped) { if let Some(workspace) = self.common.shell.space_for_mut(&mapped) {
workspace.fullscreen_request(&surface, None) if let Some((surface, _)) = mapped
.windows()
.find(|(w, _)| w.x11_surface() == Some(&window))
{
workspace.fullscreen_request(&surface, None)
}
} }
} else { } else {
let output = self.common.last_active_seat().active_output(); let output = self.common.last_active_seat().active_output();
@ -450,7 +443,7 @@ impl XwmHandler for State {
.shell .shell
.pending_windows .pending_windows
.iter_mut() .iter_mut()
.find(|(s, _, _)| s == &surface) .find(|(s, _, _)| s.x11_surface() == Some(&window))
.map(|(_, _, o)| o) .map(|(_, _, o)| o)
{ {
*o = Some(output); *o = Some(output);
@ -459,10 +452,12 @@ impl XwmHandler for State {
} }
fn unfullscreen_request(&mut self, _xwm: XwmId, window: X11Surface) { fn unfullscreen_request(&mut self, _xwm: XwmId, window: X11Surface) {
let surface = CosmicSurface::X11(window); if let Some(mapped) = self.common.shell.element_for_x11_surface(&window).cloned() {
if let Some(mapped) = self.common.shell.element_for_surface(&surface).cloned() {
if let Some(workspace) = self.common.shell.space_for_mut(&mapped) { if let Some(workspace) = self.common.shell.space_for_mut(&mapped) {
let (window, _) = mapped.windows().find(|(w, _)| w == &surface).unwrap(); let (window, _) = mapped
.windows()
.find(|(w, _)| w.x11_surface() == Some(&window))
.unwrap();
let previous = workspace.unfullscreen_request(&window); let previous = workspace.unfullscreen_request(&window);
assert!(previous.is_none()); assert!(previous.is_none());
} }
@ -539,7 +534,7 @@ impl Common {
fn is_x_focused(&self, xwm: XwmId) -> bool { fn is_x_focused(&self, xwm: XwmId) -> bool {
if let Some(keyboard) = self.last_active_seat().get_keyboard() { if let Some(keyboard) = self.last_active_seat().get_keyboard() {
if let Some(KeyboardFocusTarget::Element(mapped)) = keyboard.current_focus() { if let Some(KeyboardFocusTarget::Element(mapped)) = keyboard.current_focus() {
if let CosmicSurface::X11(surface) = mapped.active_window() { if let Some(surface) = mapped.active_window().x11_surface() {
return surface.xwm_id().unwrap() == xwm; return surface.xwm_id().unwrap() == xwm;
} }
} }