Rework fullscreen tracking, fix fullscreen on udev

This commit is contained in:
Ottatop 2023-08-12 12:01:55 -05:00
parent 0ead02921f
commit d75e0dad22
6 changed files with 93 additions and 53 deletions

View file

@ -32,7 +32,8 @@ use smithay::{
renderer::{ renderer::{
damage::{self, OutputDamageTracker}, damage::{self, OutputDamageTracker},
element::{ element::{
texture::TextureBuffer, AsRenderElements, RenderElement, RenderElementStates, self, surface::WaylandSurfaceRenderElement, texture::TextureBuffer,
AsRenderElements, RenderElement, RenderElementStates,
}, },
gles::{GlesRenderer, GlesTexture}, gles::{GlesRenderer, GlesTexture},
multigpu::{gbm::GbmGlesBackend, GpuManager, MultiRenderer, MultiTexture}, multigpu::{gbm::GbmGlesBackend, GpuManager, MultiRenderer, MultiTexture},
@ -98,7 +99,7 @@ use smithay_drm_extras::{
use crate::{ use crate::{
api::msg::{Args, OutgoingMsg}, api::msg::{Args, OutgoingMsg},
render::{pointer::PointerElement, CustomRenderElements, OutputRenderElements}, render::{pointer::PointerElement, CustomRenderElements, OutputRenderElements},
state::{take_presentation_feedback, CalloopData, State, SurfaceDmabufFeedback}, state::{take_presentation_feedback, CalloopData, State, SurfaceDmabufFeedback, WithState},
window::WindowElement, window::WindowElement,
}; };
@ -1377,6 +1378,7 @@ impl State<UdevData> {
&mut self.cursor_status, &mut self.cursor_status,
self.dnd_icon.as_ref(), self.dnd_icon.as_ref(),
&self.clock, &self.clock,
&self.focus_state.focus_stack,
); );
let reschedule = match &result { let reschedule = match &result {
Ok(has_rendered) => !has_rendered, Ok(has_rendered) => !has_rendered,
@ -1482,11 +1484,12 @@ fn render_surface<'a>(
cursor_status: &mut CursorImageStatus, cursor_status: &mut CursorImageStatus,
dnd_icon: Option<&WlSurface>, dnd_icon: Option<&WlSurface>,
clock: &Clock<Monotonic>, clock: &Clock<Monotonic>,
focus_stack: &[WindowElement],
) -> Result<bool, SwapBuffersError> { ) -> Result<bool, SwapBuffersError> {
let output_geometry = space.output_geometry(output).unwrap(); let output_geometry = space.output_geometry(output).unwrap();
let scale = Scale::from(output.current_scale().fractional_scale()); let scale = Scale::from(output.current_scale().fractional_scale());
let mut custom_elements: Vec<CustomRenderElements<_>> = Vec::new(); let mut custom_render_elements: Vec<CustomRenderElements<_>> = Vec::new();
// draw input method surface if any // draw input method surface if any
let rectangle = input_method.coordinates(); let rectangle = input_method.coordinates();
let position = Point::from(( let position = Point::from((
@ -1494,7 +1497,7 @@ fn render_surface<'a>(
rectangle.loc.y + rectangle.size.h, rectangle.loc.y + rectangle.size.h,
)); ));
input_method.with_surface(|surface| { input_method.with_surface(|surface| {
custom_elements.extend(AsRenderElements::<UdevRenderer<'a, '_>>::render_elements( custom_render_elements.extend(AsRenderElements::<UdevRenderer<'a, '_>>::render_elements(
&SurfaceTree::from_surface(surface), &SurfaceTree::from_surface(surface),
renderer, renderer,
position.to_physical_precise_round(scale), position.to_physical_precise_round(scale),
@ -1537,7 +1540,7 @@ fn render_surface<'a>(
pointer_element.set_status(cursor_status.clone()); pointer_element.set_status(cursor_status.clone());
} }
custom_elements.extend(pointer_element.render_elements( custom_render_elements.extend(pointer_element.render_elements(
renderer, renderer,
cursor_pos_scaled, cursor_pos_scaled,
scale, scale,
@ -1545,7 +1548,7 @@ fn render_surface<'a>(
)); ));
if let Some(dnd_icon) = dnd_icon { if let Some(dnd_icon) = dnd_icon {
custom_elements.extend(AsRenderElements::render_elements( custom_render_elements.extend(AsRenderElements::render_elements(
&smithay::desktop::space::SurfaceTree::from_surface(dnd_icon), &smithay::desktop::space::SurfaceTree::from_surface(dnd_icon),
renderer, renderer,
cursor_pos_scaled, cursor_pos_scaled,
@ -1555,19 +1558,57 @@ fn render_surface<'a>(
} }
} }
let mut output_render_elements = custom_elements let output_render_elements = {
.into_iter() let top_fullscreen_window = focus_stack.iter().rev().find(|win| {
.map(OutputRenderElements::from) win.with_state(|state| {
.collect::<Vec<_>>(); state.status.is_fullscreen() && state.tags.iter().any(|tag| tag.active())
})
});
let space_render_elements = // If fullscreen windows exist, render only the topmost one
space::space_render_elements(renderer, [space], output, 1.0).unwrap(); // TODO: wait until the fullscreen window has committed, this will stop flickering
if let Some(window) = top_fullscreen_window {
let mut output_render_elements =
Vec::<OutputRenderElements<_, WaylandSurfaceRenderElement<_>>>::new();
output_render_elements.extend( let window_render_elements: Vec<WaylandSurfaceRenderElement<_>> =
space_render_elements window.render_elements(renderer, (0, 0).into(), scale, 1.0);
.into_iter()
.map(OutputRenderElements::Space), output_render_elements.extend(
); custom_render_elements
.into_iter()
.map(OutputRenderElements::from),
);
output_render_elements.extend(
window_render_elements
.into_iter()
.map(|elem| OutputRenderElements::Window(element::Wrap::from(elem))),
);
output_render_elements
} else {
// render everything
let space_render_elements =
space::space_render_elements(renderer, [space], output, 1.0)
.expect("Failed to get render elements");
let mut output_render_elements =
Vec::<OutputRenderElements<_, WaylandSurfaceRenderElement<_>>>::new();
output_render_elements.extend(
custom_render_elements
.into_iter()
.map(OutputRenderElements::from),
);
output_render_elements.extend(
space_render_elements
.into_iter()
.map(OutputRenderElements::from),
);
output_render_elements
}
};
let res = surface.compositor.render_frame::<_, _, GlesTexture>( let res = surface.compositor.render_frame::<_, _, GlesTexture>(
renderer, renderer,

View file

@ -295,21 +295,20 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
)); ));
} }
let active_tag_with_fullscreen = {
output.with_state(|state| {
state
.tags
.iter()
.filter(|tag| tag.active())
.find(|tag| tag.fullscreen_window().is_some())
.cloned()
})
};
let output_render_elements = { let output_render_elements = {
let renderer = state.backend_data.backend.renderer(); let renderer = state.backend_data.backend.renderer();
if let Some(tag) = active_tag_with_fullscreen { let top_fullscreen_window =
state.focus_state.focus_stack.iter().rev().find(|win| {
win.with_state(|state| {
state.status.is_fullscreen()
&& state.tags.iter().any(|tag| tag.active())
})
});
// If fullscreen windows exist, render only the topmost one
// TODO: wait until the fullscreen window has committed, this will stop flickering
if let Some(window) = top_fullscreen_window {
let mut output_render_elements = Vec::< let mut output_render_elements = Vec::<
OutputRenderElements< OutputRenderElements<
GlesRenderer, GlesRenderer,
@ -317,7 +316,6 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
>, >,
>::new(); >::new();
let Some(window) = tag.fullscreen_window() else { unreachable!() };
let window_render_elements: Vec<WaylandSurfaceRenderElement<_>> = let window_render_elements: Vec<WaylandSurfaceRenderElement<_>> =
window.render_elements(renderer, (0, 0).into(), scale, 1.0); window.render_elements(renderer, (0, 0).into(), scale, 1.0);
@ -335,6 +333,7 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
output_render_elements output_render_elements
} else { } else {
// render everything
let space_render_elements = let space_render_elements =
space::space_render_elements(renderer, [&state.space], &output, 1.0) space::space_render_elements(renderer, [&state.space], &output, 1.0)
.expect("Failed to get render elements"); .expect("Failed to get render elements");

View file

@ -326,7 +326,7 @@ impl<B: Backend> XdgShellHandler for State<B> {
window.with_state(|state| { window.with_state(|state| {
let tags = state.tags.iter(); let tags = state.tags.iter();
for tag in tags { for tag in tags {
tag.set_fullscreen_window(window.clone()); // tag.set_fullscreen_window(window.clone());
} }
}); });
} }
@ -352,7 +352,7 @@ impl<B: Backend> XdgShellHandler for State<B> {
if let Some(window) = self.window_for_surface(surface.wl_surface()) { if let Some(window) = self.window_for_surface(surface.wl_surface()) {
window.with_state(|state| { window.with_state(|state| {
for tag in state.tags.iter() { for tag in state.tags.iter() {
tag.set_fullscreen_window(None); // tag.set_fullscreen_window(None);
} }
}); });
} }

View file

@ -57,7 +57,6 @@ impl<B: Backend> State<B> {
where where
P: Into<Point<f64, Logical>>, P: Into<Point<f64, Logical>>,
{ {
// TODO: fullscreen
let point: Point<f64, Logical> = point.into(); let point: Point<f64, Logical> = point.into();
let output = self.space.outputs().find(|op| { let output = self.space.outputs().find(|op| {
@ -74,14 +73,15 @@ impl<B: Backend> State<B> {
let layers = layer_map_for_output(output); let layers = layer_map_for_output(output);
let top_fullscreen_window = self.focus_state.focus_stack.iter().rev().find(|win| {
win.with_state(|state| {
state.status.is_fullscreen() && state.tags.iter().any(|tag| tag.active())
})
});
// I think I'm going a bit too far with the functional stuff // I think I'm going a bit too far with the functional stuff
[output] top_fullscreen_window
.into_iter() .map(|window| (FocusTarget::from(window.clone()), output_geo.loc))
.flat_map(|op| op.with_state(|state| state.tags.clone()))
.filter(|tag| tag.active())
.find(|tag| tag.fullscreen_window().is_some())
.and_then(|tag| tag.fullscreen_window())
.map(|window| (FocusTarget::from(window), output_geo.loc))
.or_else(|| { .or_else(|| {
layers layers
.layer_under(wlr_layer::Layer::Overlay, point) .layer_under(wlr_layer::Layer::Overlay, point)

View file

@ -12,7 +12,7 @@ use smithay::{
use crate::window::WindowElement; use crate::window::WindowElement;
use self::pointer::PointerRenderElement; use self::pointer::{PointerElement, PointerRenderElement};
pub mod pointer; pub mod pointer;
@ -60,3 +60,15 @@ where
.collect() .collect()
} }
} }
pub fn render_elements<R, T>(
renderer: &mut R,
pointer_element: &mut PointerElement<T>,
) -> Vec<OutputRenderElements<R, WaylandSurfaceRenderElement<R>>>
where
R: Renderer + ImportAll,
<R as Renderer>::TextureId: 'static,
T: Texture,
{
vec![]
}

View file

@ -13,7 +13,6 @@ use crate::{
backend::Backend, backend::Backend,
layout::Layout, layout::Layout,
state::{State, WithState}, state::{State, WithState},
window::WindowElement,
}; };
static TAG_ID_COUNTER: AtomicU32 = AtomicU32::new(0); static TAG_ID_COUNTER: AtomicU32 = AtomicU32::new(0);
@ -45,8 +44,6 @@ struct TagInner {
active: bool, active: bool,
/// What layout this tag has. /// What layout this tag has.
layout: Layout, layout: Layout,
/// The fullscreen window, if any.
fullscreen_window: Option<WindowElement>,
} }
impl PartialEq for TagInner { impl PartialEq for TagInner {
@ -84,14 +81,6 @@ impl Tag {
pub fn set_layout(&self, layout: Layout) { pub fn set_layout(&self, layout: Layout) {
self.0.borrow_mut().layout = layout; self.0.borrow_mut().layout = layout;
} }
pub fn fullscreen_window(&self) -> Option<WindowElement> {
self.0.borrow().fullscreen_window.clone()
}
pub fn set_fullscreen_window(&self, window: impl Into<Option<WindowElement>>) {
self.0.borrow_mut().fullscreen_window = window.into();
}
} }
impl Tag { impl Tag {
@ -101,7 +90,6 @@ impl Tag {
name, name,
active: false, active: false,
layout: Layout::MasterStack, // TODO: get from config layout: Layout::MasterStack, // TODO: get from config
fullscreen_window: None,
}))) })))
} }