Update Smithay, with Window that supports X11 surfaces
This commit is contained in:
parent
849882a7db
commit
3036448c19
24 changed files with 482 additions and 619 deletions
|
|
@ -843,10 +843,7 @@ impl SpaceElement for CosmicMapped {
|
|||
|
||||
impl X11Relatable for CosmicMapped {
|
||||
fn is_window(&self, window: &X11Surface) -> bool {
|
||||
match self.active_window() {
|
||||
CosmicSurface::X11(surface) => &surface == window,
|
||||
_ => false,
|
||||
}
|
||||
self.active_window().x11_surface() == Some(window)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -20,7 +20,7 @@ use tracing::{debug, trace};
|
|||
|
||||
use self::target::{KeyboardFocusTarget, WindowGroup};
|
||||
|
||||
use super::{layout::floating::FloatingLayout, CosmicSurface};
|
||||
use super::layout::floating::FloatingLayout;
|
||||
|
||||
pub mod target;
|
||||
|
||||
|
|
@ -207,11 +207,11 @@ fn raise_with_children(floating_layer: &mut FloatingLayout, focused: &CosmicMapp
|
|||
.space
|
||||
.elements()
|
||||
.filter(|elem| {
|
||||
let parent = match elem.active_window() {
|
||||
CosmicSurface::Wayland(w) => w.toplevel().parent(),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let parent = elem
|
||||
.active_window()
|
||||
.0
|
||||
.toplevel()
|
||||
.and_then(|toplevel| toplevel.parent());
|
||||
parent == focused.active_window().wl_surface()
|
||||
})
|
||||
.cloned()
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@ fn toggle_stacking(state: &mut State, mapped: &CosmicMapped) {
|
|||
fn move_prev_workspace(state: &mut State, mapped: &CosmicMapped) {
|
||||
let seat = state.common.last_active_seat().clone();
|
||||
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())
|
||||
};
|
||||
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) {
|
||||
let seat = state.common.last_active_seat().clone();
|
||||
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())
|
||||
};
|
||||
let maybe_handle = state
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ impl PointerGrab<State> for MoveGrab {
|
|||
.as_logical()
|
||||
.overlaps_or_touches(Rectangle::from_loc_and_size(
|
||||
handle.current_location().to_i32_floor(),
|
||||
(0,0),
|
||||
(0, 0),
|
||||
))
|
||||
})
|
||||
.cloned()
|
||||
|
|
|
|||
|
|
@ -7,13 +7,12 @@ use crate::{
|
|||
element::CosmicMapped,
|
||||
focus::target::PointerFocusTarget,
|
||||
grabs::{ReleaseMode, ResizeEdge},
|
||||
CosmicSurface,
|
||||
},
|
||||
utils::prelude::*,
|
||||
};
|
||||
use smithay::{
|
||||
backend::input::ButtonState,
|
||||
desktop::space::SpaceElement,
|
||||
desktop::{space::SpaceElement, WindowSurface},
|
||||
input::{
|
||||
pointer::{
|
||||
AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent,
|
||||
|
|
@ -118,9 +117,10 @@ impl PointerGrab<State> for ResizeSurfaceGrab {
|
|||
|
||||
self.window.set_resizing(true);
|
||||
self.window.set_geometry(Rectangle::from_loc_and_size(
|
||||
match self.window.active_window() {
|
||||
CosmicSurface::X11(s) => s.geometry().loc.as_global(),
|
||||
_ => (0, 0).into(),
|
||||
if let Some(s) = self.window.active_window().x11_surface() {
|
||||
s.geometry().loc.as_global()
|
||||
} else {
|
||||
(0, 0).into()
|
||||
},
|
||||
self.last_window_size.as_global(),
|
||||
));
|
||||
|
|
@ -356,20 +356,19 @@ impl ResizeSurfaceGrab {
|
|||
|
||||
if let Some(new_location) = new_location {
|
||||
for (window, offset) in window.windows() {
|
||||
match window {
|
||||
CosmicSurface::Wayland(window) => {
|
||||
match window.0.underlying_surface() {
|
||||
WindowSurface::Wayland(toplevel) => {
|
||||
update_reactive_popups(
|
||||
&window,
|
||||
toplevel,
|
||||
new_location + offset.as_global(),
|
||||
floating_layer.space.outputs(),
|
||||
);
|
||||
}
|
||||
CosmicSurface::X11(surface) => {
|
||||
WindowSurface::X11(surface) => {
|
||||
let mut geometry = surface.geometry();
|
||||
geometry.loc += (location - new_location).as_logical();
|
||||
let _ = surface.configure(geometry);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
floating_layer
|
||||
|
|
@ -402,9 +401,10 @@ impl ResizeSurfaceGrab {
|
|||
|
||||
self.window.set_resizing(false);
|
||||
self.window.set_geometry(Rectangle::from_loc_and_size(
|
||||
match self.window.active_window() {
|
||||
CosmicSurface::X11(s) => s.geometry().loc.as_global(),
|
||||
_ => (0, 0).into(),
|
||||
if let Some(x11_surface) = self.window.active_window().x11_surface() {
|
||||
x11_surface.geometry().loc.as_global()
|
||||
} else {
|
||||
(0, 0).into()
|
||||
},
|
||||
self.last_window_size.as_global(),
|
||||
));
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use regex::RegexSet;
|
||||
use smithay::{
|
||||
desktop::WindowSurface,
|
||||
wayland::{compositor::with_states, shell::xdg::XdgToplevelSurfaceData},
|
||||
xwayland::xwm::WmWindowType,
|
||||
};
|
||||
|
|
@ -100,9 +101,9 @@ lazy_static::lazy_static! {
|
|||
|
||||
pub fn is_dialog(window: &CosmicSurface) -> bool {
|
||||
// Check "window type"
|
||||
match window {
|
||||
CosmicSurface::Wayland(window) => {
|
||||
if with_states(window.toplevel().wl_surface(), |states| {
|
||||
match window.0.underlying_surface() {
|
||||
WindowSurface::Wayland(toplevel) => {
|
||||
if with_states(toplevel.wl_surface(), |states| {
|
||||
let attrs = states
|
||||
.data_map
|
||||
.get::<XdgToplevelSurfaceData>()
|
||||
|
|
@ -114,7 +115,7 @@ pub fn is_dialog(window: &CosmicSurface) -> bool {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
CosmicSurface::X11(surface) => {
|
||||
WindowSurface::X11(surface) => {
|
||||
if surface.is_override_redirect()
|
||||
|| surface.is_popup()
|
||||
|| !matches!(
|
||||
|
|
@ -125,7 +126,6 @@ pub fn is_dialog(window: &CosmicSurface) -> bool {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
// Check if sizing suggest dialog
|
||||
|
|
|
|||
|
|
@ -58,11 +58,19 @@ impl KeyboardGrab<State> for SwapWindowGrab {
|
|||
.iter()
|
||||
.filter(|(_, action)| matches!(action, Action::Focus(_)))
|
||||
.map(|(pattern, action)| {
|
||||
let Action::Focus(direction) = action else { unreachable!() };
|
||||
let Action::Focus(direction) = action else {
|
||||
unreachable!()
|
||||
};
|
||||
(pattern.key, *direction)
|
||||
})
|
||||
.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(
|
||||
Action::Focus(direction),
|
||||
|
|
|
|||
|
|
@ -462,7 +462,9 @@ impl TilingLayout {
|
|||
|
||||
pub fn replace_window(&mut self, old: &CosmicMapped, new: &CosmicMapped) {
|
||||
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();
|
||||
|
||||
if let Ok(node) = tree.get_mut(&old_id) {
|
||||
|
|
@ -501,7 +503,13 @@ impl TilingLayout {
|
|||
match desc.stack_window {
|
||||
Some(stack_surface) => {
|
||||
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()?;
|
||||
this_stack.remove_window(&stack_surface);
|
||||
if !this_stack.alive() {
|
||||
|
|
@ -698,7 +706,9 @@ impl TilingLayout {
|
|||
}
|
||||
}
|
||||
(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 other_node = other_tree.get_mut(&other_desc.node).ok()?;
|
||||
|
||||
|
|
@ -842,7 +852,13 @@ impl TilingLayout {
|
|||
return None;
|
||||
}
|
||||
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 geometry = *this_node.data().geometry();
|
||||
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_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 geometry = *other_node.data().geometry();
|
||||
assert!(other_mapped.is_stack());
|
||||
|
|
@ -1259,9 +1281,7 @@ impl TilingLayout {
|
|||
let Some(target) = seat.get_keyboard().unwrap().current_focus() else {
|
||||
return MoveResult::None;
|
||||
};
|
||||
let Some((node_id, data)) =
|
||||
TilingLayout::currently_focused_node(&mut tree, target)
|
||||
else {
|
||||
let Some((node_id, data)) = TilingLayout::currently_focused_node(&mut tree, target) else {
|
||||
return MoveResult::None;
|
||||
};
|
||||
|
||||
|
|
@ -1587,14 +1607,10 @@ impl TilingLayout {
|
|||
let Some(target) = seat.get_keyboard().unwrap().current_focus() else {
|
||||
return FocusResult::None;
|
||||
};
|
||||
let Some(focused) =
|
||||
TilingLayout::currently_focused_node(tree, target).or_else(
|
||||
|| {
|
||||
TilingLayout::last_active_window(tree, focus_stack)
|
||||
.map(|(id, mapped)| (id, FocusedNodeData::Window(mapped)))
|
||||
},
|
||||
)
|
||||
else {
|
||||
let Some(focused) = TilingLayout::currently_focused_node(tree, target).or_else(|| {
|
||||
TilingLayout::last_active_window(tree, focus_stack)
|
||||
.map(|(id, mapped)| (id, FocusedNodeData::Window(mapped)))
|
||||
}) else {
|
||||
return FocusResult::None;
|
||||
};
|
||||
|
||||
|
|
@ -2252,21 +2268,23 @@ impl TilingLayout {
|
|||
let gaps = self.gaps();
|
||||
|
||||
let mut tree = self.queue.trees.back().unwrap().0.copy_clone();
|
||||
let Some(root_id) = tree.root_node_id() else { return false };
|
||||
let Some(mut node_id) =
|
||||
(match TilingLayout::currently_focused_node(&tree, focused.clone()) {
|
||||
Some((_id, FocusedNodeData::Window(mapped))) =>
|
||||
// we need to make sure the id belongs to this tree..
|
||||
{
|
||||
tree.traverse_pre_order_ids(root_id)
|
||||
.unwrap()
|
||||
.find(|id| tree.get(id).unwrap().data().is_mapped(Some(&mapped)))
|
||||
}
|
||||
Some((id, FocusedNodeData::Group(_, _))) => Some(id), // in this case the workspace handle was already matched, so the id is to be trusted
|
||||
_ => None,
|
||||
}) else {
|
||||
return false
|
||||
};
|
||||
let Some(root_id) = tree.root_node_id() else {
|
||||
return false;
|
||||
};
|
||||
let Some(mut node_id) = (match TilingLayout::currently_focused_node(&tree, focused.clone())
|
||||
{
|
||||
Some((_id, FocusedNodeData::Window(mapped))) =>
|
||||
// we need to make sure the id belongs to this tree..
|
||||
{
|
||||
tree.traverse_pre_order_ids(root_id)
|
||||
.unwrap()
|
||||
.find(|id| tree.get(id).unwrap().data().is_mapped(Some(&mapped)))
|
||||
}
|
||||
Some((id, FocusedNodeData::Group(_, _))) => Some(id), // in this case the workspace handle was already matched, so the id is to be trusted
|
||||
_ => None,
|
||||
}) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
while let Some(group_id) = tree.get(&node_id).unwrap().parent().cloned() {
|
||||
let orientation = tree.get(&group_id).unwrap().data().orientation();
|
||||
|
|
@ -3138,8 +3156,8 @@ impl TilingLayout {
|
|||
.unwrap()
|
||||
.position(|node| {
|
||||
let Some(geo) = geometries.get(node) else {
|
||||
return false;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
match orientation {
|
||||
Orientation::Vertical => location.x < geo.loc.x,
|
||||
Orientation::Horizontal => location.y < geo.loc.y,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ use keyframe::{ease, functions::EaseInOutCubic};
|
|||
use smithay::{
|
||||
desktop::{
|
||||
layer_map_for_output, space::SpaceElement, LayerSurface, PopupKind, PopupManager,
|
||||
WindowSurfaceType,
|
||||
WindowSurface, WindowSurfaceType,
|
||||
},
|
||||
input::{
|
||||
pointer::{Focus, GrabStartData as PointerGrabStartData, MotionEvent},
|
||||
|
|
@ -170,10 +170,11 @@ pub enum ActivationKey {
|
|||
|
||||
impl From<&CosmicSurface> for ActivationKey {
|
||||
fn from(value: &CosmicSurface) -> Self {
|
||||
match value {
|
||||
CosmicSurface::Wayland(w) => ActivationKey::Wayland(w.toplevel().wl_surface().clone()),
|
||||
CosmicSurface::X11(s) => ActivationKey::X11(s.window_id()),
|
||||
_ => unreachable!(),
|
||||
match value.0.underlying_surface() {
|
||||
WindowSurface::Wayland(toplevel) => {
|
||||
ActivationKey::Wayland(toplevel.wl_surface().clone())
|
||||
}
|
||||
WindowSurface::X11(s) => ActivationKey::X11(s.window_id()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1091,19 +1092,19 @@ impl Shell {
|
|||
.map(|(_, w, _)| w)
|
||||
.chain(set.workspaces[set.active].floating_layer.space.elements())
|
||||
{
|
||||
if let CosmicSurface::X11(surf) = window.active_window() {
|
||||
let _ = xwm.raise_window(&surf);
|
||||
if let Some(surf) = window.active_window().x11_surface() {
|
||||
let _ = xwm.raise_window(surf);
|
||||
}
|
||||
}
|
||||
for window in set.sticky_layer.space.elements() {
|
||||
if let CosmicSurface::X11(surf) = window.active_window() {
|
||||
let _ = xwm.raise_window(&surf);
|
||||
if let Some(surf) = window.active_window().x11_surface() {
|
||||
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
|
||||
.as_ref()
|
||||
.map(|f| &f.surface)
|
||||
.and_then(|f| f.surface.x11_surface())
|
||||
{
|
||||
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> {
|
||||
self.workspaces
|
||||
.spaces()
|
||||
|
|
@ -1554,25 +1568,24 @@ impl Shell {
|
|||
.unwrap();
|
||||
let (window, seat, output) = state.common.shell.pending_windows.remove(pos);
|
||||
|
||||
let parent_is_sticky = match window.clone() {
|
||||
CosmicSurface::Wayland(toplevel) => {
|
||||
if let Some(parent) = toplevel.toplevel().parent() {
|
||||
if let Some(elem) = state.common.shell.element_for_wl_surface(&parent) {
|
||||
state
|
||||
.common
|
||||
.shell
|
||||
.workspaces
|
||||
.sets
|
||||
.values()
|
||||
.any(|set| set.sticky_layer.mapped().any(|m| m == elem))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
let parent_is_sticky = if let Some(toplevel) = window.0.toplevel() {
|
||||
if let Some(parent) = toplevel.parent() {
|
||||
if let Some(elem) = state.common.shell.element_for_wl_surface(&parent) {
|
||||
state
|
||||
.common
|
||||
.shell
|
||||
.workspaces
|
||||
.sets
|
||||
.values()
|
||||
.any(|set| set.sticky_layer.mapped().any(|m| m == elem))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
_ => false,
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let pending_activation = state
|
||||
|
|
@ -2013,11 +2026,11 @@ impl Shell {
|
|||
.unwrap()
|
||||
.loc
|
||||
.to_global(&workspace.output);
|
||||
for (toplevel, offset) in mapped.windows() {
|
||||
if let CosmicSurface::Wayland(toplevel) = toplevel {
|
||||
let window_geo_offset = toplevel.geometry().loc.as_global();
|
||||
for (window, offset) in mapped.windows() {
|
||||
if let Some(toplevel) = window.0.toplevel() {
|
||||
let window_geo_offset = window.geometry().loc.as_global();
|
||||
update_reactive_popups(
|
||||
&toplevel,
|
||||
toplevel,
|
||||
element_loc + offset.as_global() + window_geo_offset,
|
||||
self.outputs(),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ use smithay::{
|
|||
seat::WaylandFocus,
|
||||
xdg_activation::{XdgActivationState, XdgActivationToken},
|
||||
},
|
||||
xwayland::X11Surface,
|
||||
};
|
||||
use std::{
|
||||
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(
|
||||
&mut self,
|
||||
location: Point<f64, Global>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue