Get xwayland snapshots partially working

This commit is contained in:
Ottatop 2024-05-24 16:13:00 -05:00 committed by Ottatop
parent e6b18fcec2
commit ff2b78f828
8 changed files with 121 additions and 27 deletions

View file

@ -738,6 +738,14 @@ impl tag_service_server::TagService for TagService {
return;
};
let Some(output) = tag.output(&state.pinnacle) else {
return;
};
let snapshots = state.backend.with_renderer(|renderer| {
capture_snapshots_on_output(&mut state.pinnacle, renderer, &output)
});
match set_or_toggle {
SetOrToggle::Set => tag.set_active(true, state),
SetOrToggle::Unset => tag.set_active(false, state),
@ -745,12 +753,12 @@ impl tag_service_server::TagService for TagService {
SetOrToggle::Unspecified => unreachable!(),
}
let Some(output) = tag.output(&state.pinnacle) else {
return;
};
state.pinnacle.fixup_xwayland_window_layering();
output.with_state_mut(|op_state| {
op_state.new_wait_layout_transaction(state.pinnacle.loop_handle.clone(), snapshots)
});
state.pinnacle.request_layout(&output);
state.update_keyboard_focus(&output);
state.schedule_render(&output);
@ -773,6 +781,10 @@ impl tag_service_server::TagService for TagService {
return;
};
let snapshots = state.backend.with_renderer(|renderer| {
capture_snapshots_on_output(&mut state.pinnacle, renderer, &output)
});
output.with_state(|op_state| {
for op_tag in op_state.tags.iter() {
op_tag.set_active(false, state);
@ -782,6 +794,10 @@ impl tag_service_server::TagService for TagService {
state.pinnacle.fixup_xwayland_window_layering();
output.with_state_mut(|op_state| {
op_state.new_wait_layout_transaction(state.pinnacle.loop_handle.clone(), snapshots)
});
state.pinnacle.request_layout(&output);
state.update_keyboard_focus(&output);
state.schedule_render(&output);

View file

@ -21,7 +21,10 @@ use smithay::{
use tonic::{Request, Response, Status};
use tracing::warn;
use crate::{output::OutputName, state::WithState, tag::TagId, window::window_state::WindowId};
use crate::{
output::OutputName, render::util::snapshot::capture_snapshots_on_output, state::WithState,
tag::TagId, window::window_state::WindowId,
};
use super::{run_unary, run_unary_no_response, StateFnSender};
@ -136,6 +139,12 @@ impl window_service_server::WindowService for WindowService {
return;
};
let snapshots = window.output(pinnacle).map(|output| {
state.backend.with_renderer(|renderer| {
capture_snapshots_on_output(pinnacle, renderer, &output)
})
});
match set_or_toggle {
SetOrToggle::Set => {
if !window.with_state(|state| state.fullscreen_or_maximized.is_fullscreen()) {
@ -155,6 +164,12 @@ impl window_service_server::WindowService for WindowService {
return;
};
if let Some(snapshots) = snapshots {
output.with_state_mut(|op_state| {
op_state.new_wait_layout_transaction(pinnacle.loop_handle.clone(), snapshots)
});
}
pinnacle.request_layout(&output);
state.schedule_render(&output);
})
@ -185,6 +200,12 @@ impl window_service_server::WindowService for WindowService {
return;
};
let snapshots = window.output(pinnacle).map(|output| {
state.backend.with_renderer(|renderer| {
capture_snapshots_on_output(pinnacle, renderer, &output)
})
});
match set_or_toggle {
SetOrToggle::Set => {
if !window.with_state(|state| state.fullscreen_or_maximized.is_maximized()) {
@ -204,6 +225,12 @@ impl window_service_server::WindowService for WindowService {
return;
};
if let Some(snapshots) = snapshots {
output.with_state_mut(|op_state| {
op_state.new_wait_layout_transaction(pinnacle.loop_handle.clone(), snapshots)
});
}
pinnacle.request_layout(&output);
state.schedule_render(&output);
})
@ -234,6 +261,12 @@ impl window_service_server::WindowService for WindowService {
return;
};
let snapshots = window.output(pinnacle).map(|output| {
state.backend.with_renderer(|renderer| {
capture_snapshots_on_output(pinnacle, renderer, &output)
})
});
match set_or_toggle {
SetOrToggle::Set => {
if !window.with_state(|state| state.floating_or_tiled.is_floating()) {
@ -253,6 +286,12 @@ impl window_service_server::WindowService for WindowService {
return;
};
if let Some(snapshots) = snapshots {
output.with_state_mut(|op_state| {
op_state.new_wait_layout_transaction(pinnacle.loop_handle.clone(), snapshots)
});
}
pinnacle.request_layout(&output);
state.schedule_render(&output);
})
@ -363,12 +402,24 @@ impl window_service_server::WindowService for WindowService {
let Some(tag) = tag_id.tag(pinnacle) else { return };
let snapshots = window.output(pinnacle).map(|output| {
state.backend.with_renderer(|renderer| {
capture_snapshots_on_output(pinnacle, renderer, &output)
})
});
window.with_state_mut(|state| {
state.tags = vec![tag.clone()];
});
let Some(output) = tag.output(pinnacle) else { return };
if let Some(snapshots) = snapshots {
output.with_state_mut(|op_state| {
op_state.new_wait_layout_transaction(pinnacle.loop_handle.clone(), snapshots)
});
}
pinnacle.request_layout(&output);
state.schedule_render(&output);
@ -405,6 +456,12 @@ impl window_service_server::WindowService for WindowService {
};
let Some(tag) = tag_id.tag(pinnacle) else { return };
let snapshots = window.output(pinnacle).map(|output| {
state.backend.with_renderer(|renderer| {
capture_snapshots_on_output(pinnacle, renderer, &output)
})
});
// TODO: turn state.tags into a hashset
match set_or_toggle {
SetOrToggle::Set => window.with_state_mut(|state| {
@ -425,6 +482,13 @@ impl window_service_server::WindowService for WindowService {
}
let Some(output) = tag.output(pinnacle) else { return };
if let Some(snapshots) = snapshots {
output.with_state_mut(|op_state| {
op_state.new_wait_layout_transaction(pinnacle.loop_handle.clone(), snapshots)
});
}
pinnacle.request_layout(&output);
state.schedule_render(&output);

View file

@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-or-later
use smithay::{desktop::space::SpaceElement, output::Output, utils::SERIAL_COUNTER};
use tracing::warn;
use crate::{
state::{Pinnacle, State, WithState},
@ -77,14 +76,7 @@ impl Pinnacle {
}
/// Raise a window to the top of the z-index stack.
///
/// This does nothing if the window is unmapped.
pub fn raise_window(&mut self, window: WindowElement, activate: bool) {
if self.space.elements().all(|win| win != window) {
warn!("Tried to raise an unmapped window");
return;
}
self.space.raise_element(&window, activate);
self.z_index_stack.retain(|win| win != window);

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pub mod session_lock;
pub mod window;
mod xdg_shell;
mod xwayland;
@ -32,7 +33,7 @@ use smithay::{
Client, Resource,
},
},
utils::{Logical, Point, Rectangle, SERIAL_COUNTER},
utils::{Logical, Point, Rectangle},
wayland::{
buffer::BufferHandler,
compositor::{
@ -202,6 +203,8 @@ impl CompositorHandler for State {
.retain(|win| win != unmapped_window);
self.pinnacle.windows.push(unmapped_window.clone());
self.pinnacle.raise_window(unmapped_window.clone(), true);
self.pinnacle.apply_window_rules(&unmapped_window);
if let Some(focused_output) = self.pinnacle.focused_output().cloned() {

1
src/handlers/window.rs Normal file
View file

@ -0,0 +1 @@

View file

@ -26,6 +26,7 @@ use tracing::{debug, error, trace, warn};
use crate::{
cursor::Cursor,
focus::keyboard::KeyboardFocusTarget,
render::util::snapshot::capture_snapshots_on_output,
state::{Pinnacle, State, WithState},
window::{window_state::FloatingOrTiled, WindowElement},
};
@ -104,7 +105,8 @@ impl XwmHandler for State {
});
}
// TODO: will an unmap -> map duplicate the window
// TODO: do snapshot and transaction here BUT ONLY IF TILED AND ON ACTIVE TAG
self.pinnacle.windows.push(window.clone());
self.pinnacle.raise_window(window.clone(), true);
@ -432,13 +434,27 @@ impl State {
.iter()
.find(|elem| elem.x11_surface() == Some(&surface))
.cloned();
if let Some(win) = win {
debug!("removing x11 window from windows");
let snapshots = win.output(&self.pinnacle).map(|output| {
self.backend.with_renderer(|renderer| {
capture_snapshots_on_output(&mut self.pinnacle, renderer, &output)
})
});
self.pinnacle.remove_window(&win, false);
if let Some(output) = win.output(&self.pinnacle) {
if let Some(snapshots) = snapshots {
output.with_state_mut(|state| {
state.new_wait_layout_transaction(
self.pinnacle.loop_handle.clone(),
snapshots,
)
});
}
self.pinnacle.request_layout(&output);
self.update_keyboard_focus(&output);
self.schedule_render(&output);

View file

@ -32,6 +32,9 @@ use crate::{
window::WindowElement,
};
/// The timeout before transactions stop applying.
const TIMEOUT: Duration = Duration::from_millis(1000);
/// Type for window snapshots.
pub type LayoutSnapshot = RenderSnapshot<WaylandSurfaceRenderElement<GlesRenderer>>;
@ -56,10 +59,10 @@ pub struct LayoutTransaction {
}
impl LayoutTransaction {
/// Schedule an event after the timeout to check for stuff.
/// Schedule an event after the timeout to check for readiness.
fn register_wakeup(loop_handle: &LoopHandle<'static, State>) {
let _ = loop_handle.insert_source(
Timer::from_duration(Duration::from_millis(150)),
Timer::from_duration(TIMEOUT + Duration::from_millis(10)),
|_, _, _| TimeoutAction::Drop,
);
}
@ -117,12 +120,12 @@ impl LayoutTransaction {
/// Returns whether all pending windows have committed their serials or the timeout has been
/// reached.
pub fn ready(&self) -> bool {
Instant::now().duration_since(self.start_time) >= Duration::from_millis(150)
|| (!self.wait
&& self
.pending_windows
.iter()
.all(|(win, serial)| win.is_serial_committed(*serial)))
Instant::now().duration_since(self.start_time) >= TIMEOUT
// || (!self.wait
// && self
// .pending_windows
// .iter()
// .all(|(win, serial)| win.is_serial_committed(*serial)))
}
}

View file

@ -100,7 +100,7 @@ impl WindowElement {
alpha: f32,
) {
self.with_state_mut(|state| {
if state.snapshot.is_none() {
if state.snapshot.is_none() || self.is_x11() {
let elements = self.render_elements(renderer, location, scale, alpha);
state.snapshot = Some(RenderSnapshot::new(elements, scale));
}
@ -117,10 +117,9 @@ pub fn capture_snapshots_on_output(
let windows_on_foc_tags = output.with_state(|state| {
let focused_tags = state.focused_tags().collect::<Vec<_>>();
pinnacle
.windows
.z_index_stack
.iter()
.rev()
.filter(|win| !win.is_x11_override_redirect())
.filter(|win| {
win.with_state(|state| state.tags.iter().any(|tg| focused_tags.contains(&tg)))
})