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::{
damage::{self, OutputDamageTracker},
element::{
texture::TextureBuffer, AsRenderElements, RenderElement, RenderElementStates,
self, surface::WaylandSurfaceRenderElement, texture::TextureBuffer,
AsRenderElements, RenderElement, RenderElementStates,
},
gles::{GlesRenderer, GlesTexture},
multigpu::{gbm::GbmGlesBackend, GpuManager, MultiRenderer, MultiTexture},
@ -98,7 +99,7 @@ use smithay_drm_extras::{
use crate::{
api::msg::{Args, OutgoingMsg},
render::{pointer::PointerElement, CustomRenderElements, OutputRenderElements},
state::{take_presentation_feedback, CalloopData, State, SurfaceDmabufFeedback},
state::{take_presentation_feedback, CalloopData, State, SurfaceDmabufFeedback, WithState},
window::WindowElement,
};
@ -1377,6 +1378,7 @@ impl State<UdevData> {
&mut self.cursor_status,
self.dnd_icon.as_ref(),
&self.clock,
&self.focus_state.focus_stack,
);
let reschedule = match &result {
Ok(has_rendered) => !has_rendered,
@ -1482,11 +1484,12 @@ fn render_surface<'a>(
cursor_status: &mut CursorImageStatus,
dnd_icon: Option<&WlSurface>,
clock: &Clock<Monotonic>,
focus_stack: &[WindowElement],
) -> Result<bool, SwapBuffersError> {
let output_geometry = space.output_geometry(output).unwrap();
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
let rectangle = input_method.coordinates();
let position = Point::from((
@ -1494,7 +1497,7 @@ fn render_surface<'a>(
rectangle.loc.y + rectangle.size.h,
));
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),
renderer,
position.to_physical_precise_round(scale),
@ -1537,7 +1540,7 @@ fn render_surface<'a>(
pointer_element.set_status(cursor_status.clone());
}
custom_elements.extend(pointer_element.render_elements(
custom_render_elements.extend(pointer_element.render_elements(
renderer,
cursor_pos_scaled,
scale,
@ -1545,7 +1548,7 @@ fn render_surface<'a>(
));
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),
renderer,
cursor_pos_scaled,
@ -1555,19 +1558,57 @@ fn render_surface<'a>(
}
}
let mut output_render_elements = custom_elements
.into_iter()
.map(OutputRenderElements::from)
.collect::<Vec<_>>();
let output_render_elements = {
let top_fullscreen_window = focus_stack.iter().rev().find(|win| {
win.with_state(|state| {
state.status.is_fullscreen() && state.tags.iter().any(|tag| tag.active())
})
});
let space_render_elements =
space::space_render_elements(renderer, [space], output, 1.0).unwrap();
// 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::<OutputRenderElements<_, WaylandSurfaceRenderElement<_>>>::new();
output_render_elements.extend(
space_render_elements
.into_iter()
.map(OutputRenderElements::Space),
);
let window_render_elements: Vec<WaylandSurfaceRenderElement<_>> =
window.render_elements(renderer, (0, 0).into(), scale, 1.0);
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>(
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 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::<
OutputRenderElements<
GlesRenderer,
@ -317,7 +316,6 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
>,
>::new();
let Some(window) = tag.fullscreen_window() else { unreachable!() };
let window_render_elements: Vec<WaylandSurfaceRenderElement<_>> =
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
} else {
// render everything
let space_render_elements =
space::space_render_elements(renderer, [&state.space], &output, 1.0)
.expect("Failed to get render elements");

View file

@ -326,7 +326,7 @@ impl<B: Backend> XdgShellHandler for State<B> {
window.with_state(|state| {
let tags = state.tags.iter();
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()) {
window.with_state(|state| {
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
P: Into<Point<f64, Logical>>,
{
// TODO: fullscreen
let point: Point<f64, Logical> = point.into();
let output = self.space.outputs().find(|op| {
@ -74,14 +73,15 @@ impl<B: Backend> State<B> {
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
[output]
.into_iter()
.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))
top_fullscreen_window
.map(|window| (FocusTarget::from(window.clone()), output_geo.loc))
.or_else(|| {
layers
.layer_under(wlr_layer::Layer::Overlay, point)

View file

@ -12,7 +12,7 @@ use smithay::{
use crate::window::WindowElement;
use self::pointer::PointerRenderElement;
use self::pointer::{PointerElement, PointerRenderElement};
pub mod pointer;
@ -60,3 +60,15 @@ where
.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,
layout::Layout,
state::{State, WithState},
window::WindowElement,
};
static TAG_ID_COUNTER: AtomicU32 = AtomicU32::new(0);
@ -45,8 +44,6 @@ struct TagInner {
active: bool,
/// What layout this tag has.
layout: Layout,
/// The fullscreen window, if any.
fullscreen_window: Option<WindowElement>,
}
impl PartialEq for TagInner {
@ -84,14 +81,6 @@ impl Tag {
pub fn set_layout(&self, 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 {
@ -101,7 +90,6 @@ impl Tag {
name,
active: false,
layout: Layout::MasterStack, // TODO: get from config
fullscreen_window: None,
})))
}