xwayland: Globally track stacking order
This commit is contained in:
parent
6858238bd6
commit
55eb2fe88e
5 changed files with 102 additions and 150 deletions
|
|
@ -814,24 +814,6 @@ where
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(xwm) = state
|
|
||||||
.shell
|
|
||||||
.xwayland_state
|
|
||||||
.as_mut()
|
|
||||||
.and_then(|state| state.xwm.as_mut())
|
|
||||||
{
|
|
||||||
// we don't include the popup elements, which contain the OR windows, because we are not supposed to restack them
|
|
||||||
if let Err(err) =
|
|
||||||
xwm.update_stacking_order_upwards(window_elements.iter().rev().map(|e| e.id()))
|
|
||||||
{
|
|
||||||
warn!(
|
|
||||||
wm_id = ?xwm.id(),
|
|
||||||
?err,
|
|
||||||
"Failed to update Xwm stacking order.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
elements.extend(window_elements);
|
elements.extend(window_elements);
|
||||||
|
|
||||||
Ok(elements)
|
Ok(elements)
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,7 @@ fn main() -> Result<()> {
|
||||||
}
|
}
|
||||||
state.common.shell.refresh();
|
state.common.shell.refresh();
|
||||||
state::Common::refresh_focus(state);
|
state::Common::refresh_focus(state);
|
||||||
|
state.common.update_x11_stacking_order();
|
||||||
|
|
||||||
if state.common.shell.animations_going() {
|
if state.common.shell.animations_going() {
|
||||||
for output in state
|
for output in state
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,8 @@ use smithay::{
|
||||||
renderer::{
|
renderer::{
|
||||||
element::{
|
element::{
|
||||||
memory::MemoryRenderBufferRenderElement, surface::WaylandSurfaceRenderElement,
|
memory::MemoryRenderBufferRenderElement, surface::WaylandSurfaceRenderElement,
|
||||||
AsRenderElements, Element, Id as ElementId, Kind, RenderElement,
|
AsRenderElements,
|
||||||
},
|
},
|
||||||
utils::CommitCounter,
|
|
||||||
ImportAll, ImportMem, Renderer,
|
ImportAll, ImportMem, Renderer,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -49,7 +48,7 @@ use smithay::{
|
||||||
},
|
},
|
||||||
output::Output,
|
output::Output,
|
||||||
render_elements,
|
render_elements,
|
||||||
utils::{Buffer, IsAlive, Logical, Physical, Point, Rectangle, Scale, Serial, Size, Transform},
|
utils::{Buffer, IsAlive, Logical, Physical, Point, Rectangle, Scale, Serial, Size},
|
||||||
wayland::seat::WaylandFocus,
|
wayland::seat::WaylandFocus,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
|
|
@ -560,30 +559,10 @@ impl CosmicStack {
|
||||||
let windows = p.windows.lock().unwrap();
|
let windows = p.windows.lock().unwrap();
|
||||||
let active = p.active.load(Ordering::SeqCst);
|
let active = p.active.load(Ordering::SeqCst);
|
||||||
|
|
||||||
let (mut window_elements, popup_elements) = windows[active]
|
let (window_elements, popup_elements) = windows[active]
|
||||||
.split_render_elements::<R, CosmicStackRenderElement<R>>(
|
.split_render_elements::<R, CosmicStackRenderElement<R>>(
|
||||||
renderer, window_loc, scale, alpha,
|
renderer, window_loc, scale, alpha,
|
||||||
);
|
);
|
||||||
// preparing the other windows will fix their x11 stacking order.
|
|
||||||
// they won't actually be drawn due to the placeholder element.
|
|
||||||
for window in windows
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.filter(|(i, _)| *i != active)
|
|
||||||
.map(|(_, w)| w)
|
|
||||||
{
|
|
||||||
let location =
|
|
||||||
window_loc + offset - window.geometry().loc.to_physical_precise_round(scale);
|
|
||||||
let (elements, _) = window
|
|
||||||
.split_render_elements::<R, WaylandSurfaceRenderElement<R>>(
|
|
||||||
renderer, location, scale, alpha,
|
|
||||||
);
|
|
||||||
window_elements.extend(
|
|
||||||
elements
|
|
||||||
.into_iter()
|
|
||||||
.map(|e| PlaceholderElement(e.id().clone()).into()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
(window_elements, popup_elements)
|
(window_elements, popup_elements)
|
||||||
});
|
});
|
||||||
|
|
@ -1623,69 +1602,8 @@ impl PointerTarget<State> for CosmicStack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PlaceholderElement(ElementId);
|
|
||||||
|
|
||||||
impl Element for PlaceholderElement {
|
|
||||||
fn id(&self) -> &ElementId {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn current_commit(&self) -> CommitCounter {
|
|
||||||
0.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn src(&self) -> Rectangle<f64, Buffer> {
|
|
||||||
Rectangle::from_loc_and_size((0., 0.), (0., 0.))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn geometry(&self, _: Scale<f64>) -> Rectangle<i32, Physical> {
|
|
||||||
Rectangle::from_loc_and_size((0, 0), (0, 0))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn location(&self, _: Scale<f64>) -> Point<i32, Physical> {
|
|
||||||
(0, 0).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn transform(&self) -> Transform {
|
|
||||||
Transform::Normal
|
|
||||||
}
|
|
||||||
|
|
||||||
fn damage_since(
|
|
||||||
&self,
|
|
||||||
_: Scale<f64>,
|
|
||||||
_: Option<CommitCounter>,
|
|
||||||
) -> Vec<Rectangle<i32, Physical>> {
|
|
||||||
vec![]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn opaque_regions(&self, _scale: Scale<f64>) -> Vec<Rectangle<i32, Physical>> {
|
|
||||||
vec![]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alpha(&self) -> f32 {
|
|
||||||
1.0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn kind(&self) -> Kind {
|
|
||||||
Kind::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R: Renderer> RenderElement<R> for PlaceholderElement {
|
|
||||||
fn draw(
|
|
||||||
&self,
|
|
||||||
_: &mut <R as Renderer>::Frame<'_>,
|
|
||||||
_: Rectangle<f64, Buffer>,
|
|
||||||
_: Rectangle<i32, Physical>,
|
|
||||||
_: &[Rectangle<i32, Physical>],
|
|
||||||
) -> Result<(), <R as Renderer>::Error> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render_elements! {
|
render_elements! {
|
||||||
pub CosmicStackRenderElement<R> where R: ImportAll + ImportMem;
|
pub CosmicStackRenderElement<R> where R: ImportAll + ImportMem;
|
||||||
Header = MemoryRenderBufferRenderElement<R>,
|
Header = MemoryRenderBufferRenderElement<R>,
|
||||||
Window = WaylandSurfaceRenderElement<R>,
|
Window = WaylandSurfaceRenderElement<R>,
|
||||||
Placeholder = PlaceholderElement,
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1178,39 +1178,6 @@ impl Shell {
|
||||||
set.workspaces[set.active].tiling_layer.cleanup_drag();
|
set.workspaces[set.active].tiling_layer.cleanup_drag();
|
||||||
}
|
}
|
||||||
set.activate(idx, workspace_delta, &mut self.workspace_state.update())?;
|
set.activate(idx, workspace_delta, &mut self.workspace_state.update())?;
|
||||||
if let Some(xwm) = self
|
|
||||||
.xwayland_state
|
|
||||||
.as_mut()
|
|
||||||
.and_then(|state| state.xwm.as_mut())
|
|
||||||
{
|
|
||||||
{
|
|
||||||
for window in set.workspaces[set.active]
|
|
||||||
.tiling_layer
|
|
||||||
.mapped()
|
|
||||||
.map(|(w, _)| w)
|
|
||||||
.chain(set.workspaces[set.active].floating_layer.space.elements())
|
|
||||||
{
|
|
||||||
if let Some(surf) = window.active_window().x11_surface() {
|
|
||||||
let _ = xwm.raise_window(surf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for window in set.sticky_layer.space.elements() {
|
|
||||||
if let Some(surf) = window.active_window().x11_surface() {
|
|
||||||
let _ = xwm.raise_window(surf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(surf) = set.workspaces[set.active]
|
|
||||||
.fullscreen
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|f| f.surface.x11_surface())
|
|
||||||
{
|
|
||||||
let _ = xwm.raise_window(surf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for surface in &self.override_redirect_windows {
|
|
||||||
let _ = xwm.raise_window(surface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let output_geo = output.geometry();
|
let output_geo = output.geometry();
|
||||||
Ok(Some(
|
Ok(Some(
|
||||||
|
|
|
||||||
112
src/xwayland.rs
112
src/xwayland.rs
|
|
@ -136,6 +136,104 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Common {
|
||||||
|
fn is_x_focused(&self, xwm: XwmId) -> bool {
|
||||||
|
if let Some(keyboard) = self.last_active_seat().get_keyboard() {
|
||||||
|
if let Some(KeyboardFocusTarget::Element(mapped)) = keyboard.current_focus() {
|
||||||
|
if let Some(surface) = mapped.active_window().x11_surface() {
|
||||||
|
return surface.xwm_id().unwrap() == xwm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_x11_stacking_order(&mut self) {
|
||||||
|
let active_output = self.last_active_seat().active_output();
|
||||||
|
if let Some(xwm) = self
|
||||||
|
.shell
|
||||||
|
.xwayland_state
|
||||||
|
.as_mut()
|
||||||
|
.and_then(|state| state.xwm.as_mut())
|
||||||
|
{
|
||||||
|
// front to back, given that is how the workspace enumerates
|
||||||
|
let order = self
|
||||||
|
.shell
|
||||||
|
.workspaces
|
||||||
|
.sets
|
||||||
|
.iter()
|
||||||
|
.filter(|(output, _)| *output == &active_output)
|
||||||
|
.chain(
|
||||||
|
self.shell
|
||||||
|
.workspaces
|
||||||
|
.sets
|
||||||
|
.iter()
|
||||||
|
.filter(|(output, _)| *output != &active_output),
|
||||||
|
)
|
||||||
|
.flat_map(|(_, set)| {
|
||||||
|
set.sticky_layer
|
||||||
|
.mapped()
|
||||||
|
.flat_map(|mapped| {
|
||||||
|
let active = mapped.active_window();
|
||||||
|
std::iter::once(active.clone()).chain(
|
||||||
|
mapped
|
||||||
|
.is_stack()
|
||||||
|
.then(move || {
|
||||||
|
mapped
|
||||||
|
.windows()
|
||||||
|
.map(|(s, _)| s)
|
||||||
|
.filter(move |s| s != &active)
|
||||||
|
})
|
||||||
|
.into_iter()
|
||||||
|
.flatten(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.chain(
|
||||||
|
set.workspaces
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|(i, _)| *i == set.active)
|
||||||
|
.chain(
|
||||||
|
set.workspaces
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|(i, _)| *i != set.active),
|
||||||
|
)
|
||||||
|
.flat_map(|(_, workspace)| {
|
||||||
|
workspace.get_fullscreen().cloned().into_iter().chain(
|
||||||
|
workspace.mapped().flat_map(|mapped| {
|
||||||
|
let active = mapped.active_window();
|
||||||
|
std::iter::once(active.clone()).chain(
|
||||||
|
mapped
|
||||||
|
.is_stack()
|
||||||
|
.then(move || {
|
||||||
|
mapped
|
||||||
|
.windows()
|
||||||
|
.map(|(s, _)| s)
|
||||||
|
.filter(move |s| s != &active)
|
||||||
|
})
|
||||||
|
.into_iter()
|
||||||
|
.flatten(),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// we don't include the popup elements, which contain the OR windows, because we are not supposed to restack them.
|
||||||
|
// Which is also why we match upwards, to not disturb elements at the top.
|
||||||
|
//
|
||||||
|
// But this also means we need to match across all outputs and workspaces at once, to be sure nothing that shouldn't be on top of us is.
|
||||||
|
if let Err(err) = xwm.update_stacking_order_upwards(order.iter().rev()) {
|
||||||
|
warn!(wm_id = ?xwm.id(), ?err, "Failed to update Xwm stacking order.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl XwmHandler for State {
|
impl XwmHandler for State {
|
||||||
fn xwm_state(&mut self, _xwm: XwmId) -> &mut X11Wm {
|
fn xwm_state(&mut self, _xwm: XwmId) -> &mut X11Wm {
|
||||||
self.common
|
self.common
|
||||||
|
|
@ -583,17 +681,3 @@ impl XwmHandler for State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Common {
|
|
||||||
fn is_x_focused(&self, xwm: XwmId) -> bool {
|
|
||||||
if let Some(keyboard) = self.last_active_seat().get_keyboard() {
|
|
||||||
if let Some(KeyboardFocusTarget::Element(mapped)) = keyboard.current_focus() {
|
|
||||||
if let Some(surface) = mapped.active_window().x11_surface() {
|
|
||||||
return surface.xwm_id().unwrap() == xwm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue