More work on fullscreen

This commit is contained in:
Ottatop 2023-08-08 18:33:47 -05:00
parent a2887567a3
commit 7a8fc983a9
2 changed files with 148 additions and 21 deletions

View file

@ -8,7 +8,7 @@ use smithay::{
egl::EGLDevice,
renderer::{
damage::{self, OutputDamageTracker},
element::{surface::WaylandSurfaceRenderElement, AsRenderElements},
element::{self, surface::WaylandSurfaceRenderElement, AsRenderElements},
gles::{GlesRenderer, GlesTexture},
ImportDma, ImportEgl, ImportMemWl,
},
@ -38,7 +38,7 @@ use smithay::{
use crate::{
render::{pointer::PointerElement, CustomRenderElements, OutputRenderElements},
state::{take_presentation_feedback, CalloopData, State},
state::{take_presentation_feedback, CalloopData, State, WithState},
};
use super::Backend;
@ -294,6 +294,70 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
));
}
let active_tag_with_fullscreen = {
output.with_state(|state| {
state
.tags
.iter()
.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 mut output_render_elements = Vec::<
OutputRenderElements<
GlesRenderer,
WaylandSurfaceRenderElement<GlesRenderer>,
>,
>::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);
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 {
let space_render_elements =
space::space_render_elements(renderer, [&state.space], &output, 1.0)
.expect("Failed to get render elements");
let mut output_render_elements = Vec::<
OutputRenderElements<
GlesRenderer,
WaylandSurfaceRenderElement<GlesRenderer>,
>,
>::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 render_res = state.backend_data.backend.bind().and_then(|_| {
let age = if *full_redraw > 0 {
0
@ -304,24 +368,6 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
let renderer = state.backend_data.backend.renderer();
// render_output()
let space_render_elements =
space::space_render_elements(renderer, [&state.space], &output, 1.0)
.expect("Failed to get render elements");
let mut output_render_elements = Vec::<
OutputRenderElements<GlesRenderer, WaylandSurfaceRenderElement<GlesRenderer>>,
>::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),
);
state
.backend_data

View file

@ -8,10 +8,11 @@ use smithay::{
WindowSurfaceType,
},
input::{pointer::Focus, Seat},
output::Output,
reexports::{
wayland_protocols::xdg::shell::server::xdg_toplevel::{self, ResizeEdge},
wayland_server::{
protocol::{wl_seat::WlSeat, wl_surface::WlSurface},
protocol::{wl_output::WlOutput, wl_seat::WlSeat, wl_surface::WlSurface},
Resource,
},
},
@ -301,6 +302,86 @@ impl<B: Backend> XdgShellHandler for State<B> {
}
}
fn fullscreen_request(&mut self, surface: ToplevelSurface, mut wl_output: Option<WlOutput>) {
if !surface
.current_state()
.capabilities
.contains(xdg_toplevel::WmCapabilities::Fullscreen)
{
return;
}
let wl_surface = surface.wl_surface();
let output = wl_output
.as_ref()
.and_then(Output::from_resource)
.or_else(|| {
self.window_for_surface(wl_surface)
.and_then(|window| self.space.outputs_for_element(&window).get(0).cloned())
});
if let Some(output) = output {
let Some(geometry) = self.space.output_geometry(&output) else {
surface.send_configure();
return;
};
let client = self
.display_handle
.get_client(wl_surface.id())
.expect("wl_surface had no client");
for output in output.client_outputs(&client) {
wl_output = Some(output);
}
surface.with_pending_state(|state| {
state.states.set(xdg_toplevel::State::Fullscreen);
state.size = Some(geometry.size);
state.fullscreen_output = wl_output;
});
let Some(window) = self.window_for_surface(wl_surface) else {
tracing::error!("wl_surface had no window");
return;
};
window.with_state(|state| {
let tags = state.tags.iter();
for tag in tags {
tag.set_fullscreen_window(window.clone());
}
});
}
surface.send_configure();
}
fn unfullscreen_request(&mut self, surface: ToplevelSurface) {
if !surface
.current_state()
.states
.contains(xdg_toplevel::State::Fullscreen)
{
return;
}
surface.with_pending_state(|state| {
state.states.unset(xdg_toplevel::State::Fullscreen);
state.size = None;
state.fullscreen_output.take();
});
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);
}
});
}
surface.send_pending_configure();
}
// fn minimize_request(&mut self, surface: ToplevelSurface) {
// if let Some(window) = self.window_for_surface(surface.wl_surface()) {
// self.space.unmap_elem(&window);