Start on wlr-layer-shell

This commit is contained in:
Ottatop 2023-08-04 18:48:10 -05:00 committed by Ottatop
parent a552c3abda
commit a053c55f82
6 changed files with 222 additions and 127 deletions

View file

@ -1,6 +1,22 @@
// SPDX-License-Identifier: GPL-3.0-or-later
use smithay::{output::Output, reexports::wayland_server::protocol::wl_surface::WlSurface};
use std::time::Duration;
use smithay::{
backend::renderer::element::{
default_primary_scanout_output_compare, utils::select_dmabuf_feedback, RenderElementStates,
},
desktop::{
layer_map_for_output,
utils::{surface_primary_scanout_output, update_surface_primary_scanout_output},
Space,
},
output::Output,
reexports::wayland_server::protocol::wl_surface::WlSurface,
wayland::fractional_scale::with_fractional_scale,
};
use crate::{state::SurfaceDmabufFeedback, window::WindowElement};
pub mod udev;
pub mod winit;
@ -13,3 +29,84 @@ pub trait Backend: 'static {
// INFO: only for udev in anvil, maybe shouldn't be a trait fn?
fn early_import(&mut self, surface: &WlSurface);
}
pub fn post_repaint(
output: &Output,
render_element_states: &RenderElementStates,
space: &Space<WindowElement>,
dmabuf_feedback: Option<SurfaceDmabufFeedback<'_>>,
time: Duration,
) {
let throttle = Some(Duration::from_secs(1));
space.elements().for_each(|window| {
window.with_surfaces(|surface, states_inner| {
let primary_scanout_output = update_surface_primary_scanout_output(
surface,
output,
states_inner,
render_element_states,
default_primary_scanout_output_compare,
);
if let Some(output) = primary_scanout_output {
with_fractional_scale(states_inner, |fraction_scale| {
fraction_scale.set_preferred_scale(output.current_scale().fractional_scale());
});
}
});
if space.outputs_for_element(window).contains(output) {
window.send_frame(output, time, throttle, surface_primary_scanout_output);
if let Some(dmabuf_feedback) = dmabuf_feedback {
window.send_dmabuf_feedback(
output,
surface_primary_scanout_output,
|surface, _| {
select_dmabuf_feedback(
surface,
render_element_states,
dmabuf_feedback.render_feedback,
dmabuf_feedback.scanout_feedback,
)
},
);
}
}
});
let map = layer_map_for_output(output);
for layer_surface in map.layers() {
layer_surface.with_surfaces(|surface, states| {
let primary_scanout_output = update_surface_primary_scanout_output(
surface,
output,
states,
render_element_states,
default_primary_scanout_output_compare,
);
if let Some(output) = primary_scanout_output {
with_fractional_scale(states, |fraction_scale| {
fraction_scale.set_preferred_scale(output.current_scale().fractional_scale());
});
}
});
layer_surface.send_frame(output, time, throttle, surface_primary_scanout_output);
if let Some(dmabuf_feedback) = dmabuf_feedback {
layer_surface.send_dmabuf_feedback(
output,
surface_primary_scanout_output,
|surface, _| {
select_dmabuf_feedback(
surface,
render_element_states,
dmabuf_feedback.render_feedback,
dmabuf_feedback.scanout_feedback,
)
},
);
}
}
}

View file

@ -32,8 +32,7 @@ use smithay::{
renderer::{
damage::{self, OutputDamageTracker},
element::{
self, texture::TextureBuffer, utils::select_dmabuf_feedback, AsRenderElements,
RenderElement, RenderElementStates,
texture::TextureBuffer, AsRenderElements, RenderElement, RenderElementStates,
},
gles::{GlesRenderer, GlesTexture},
multigpu::{gbm::GbmGlesBackend, GpuManager, MultiRenderer, MultiTexture},
@ -52,10 +51,7 @@ use smithay::{
delegate_dmabuf,
desktop::{
space::{self, SurfaceTree},
utils::{
self, send_frames_surface_tree, surface_primary_scanout_output,
OutputPresentationFeedback,
},
utils::{send_frames_surface_tree, OutputPresentationFeedback},
Space,
},
input::pointer::{CursorImageAttributes, CursorImageStatus},
@ -91,7 +87,6 @@ use smithay::{
DmabufFeedback, DmabufFeedbackBuilder, DmabufGlobal, DmabufHandler, DmabufState,
ImportError,
},
fractional_scale,
input_method::{InputMethodHandle, InputMethodSeat},
},
};
@ -1588,8 +1583,6 @@ fn render_surface<'a>(
// post_repaint
{
let throttle = Some(Duration::from_secs(1));
let time = clock.now();
// We need to send frames to the cursor surface so that xwayland windows will properly
@ -1598,56 +1591,19 @@ fn render_surface<'a>(
send_frames_surface_tree(surf, output, time, Some(Duration::ZERO), |_, _| None);
}
space.elements().for_each(|window| {
window.with_surfaces(|surface, states_inner| {
let primary_scanout_output = utils::update_surface_primary_scanout_output(
surface,
output,
states_inner,
&res.states,
element::default_primary_scanout_output_compare,
);
if let Some(output) = primary_scanout_output {
fractional_scale::with_fractional_scale(states_inner, |fraction_scale| {
fraction_scale
.set_preferred_scale(output.current_scale().fractional_scale());
});
}
});
if space.outputs_for_element(window).contains(output) {
window.send_frame(
output,
time,
throttle,
utils::surface_primary_scanout_output,
);
if let Some(dmabuf_feedback) =
surface
.dmabuf_feedback
.as_ref()
.map(|feedback| SurfaceDmabufFeedback {
render_feedback: &feedback.render_feedback,
scanout_feedback: &feedback.scanout_feedback,
})
{
window.send_dmabuf_feedback(
output,
surface_primary_scanout_output,
|surface, _| {
select_dmabuf_feedback(
surface,
&res.states,
dmabuf_feedback.render_feedback,
dmabuf_feedback.scanout_feedback,
)
},
);
}
}
});
super::post_repaint(
output,
&res.states,
space,
surface
.dmabuf_feedback
.as_ref()
.map(|feedback| SurfaceDmabufFeedback {
render_feedback: &feedback.render_feedback,
scanout_feedback: &feedback.scanout_feedback,
}),
time.into(),
)
}
if res.rendered {

View file

@ -8,23 +8,14 @@ use smithay::{
egl::EGLDevice,
renderer::{
damage::{self, OutputDamageTracker},
element::{
default_primary_scanout_output_compare, surface::WaylandSurfaceRenderElement,
AsRenderElements,
},
element::{surface::WaylandSurfaceRenderElement, AsRenderElements},
gles::{GlesRenderer, GlesTexture},
ImportDma, ImportEgl, ImportMemWl,
},
winit::{WinitError, WinitEvent, WinitGraphicsBackend},
},
delegate_dmabuf,
desktop::{
space,
utils::{
send_frames_surface_tree, surface_primary_scanout_output,
update_surface_primary_scanout_output,
},
},
desktop::{space, utils::send_frames_surface_tree},
input::pointer::{CursorImageAttributes, CursorImageStatus},
output::{Output, Subpixel},
reexports::{
@ -42,7 +33,6 @@ use smithay::{
DmabufFeedback, DmabufFeedbackBuilder, DmabufGlobal, DmabufHandler, DmabufState,
ImportError,
},
fractional_scale::with_fractional_scale,
},
};
@ -357,11 +347,9 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
.window()
.set_cursor_visible(cursor_visible);
let throttle = Some(Duration::from_secs(1));
// let throttle = Some(Duration::ZERO);
let time = state.clock.now();
// Send frames to the cursor surface so it updates in xwayland
if let CursorImageStatus::Surface(surf) = &state.cursor_status {
if let Some(op) = state.focus_state.focused_output.as_ref() {
send_frames_surface_tree(
@ -374,35 +362,13 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
}
}
state.space.elements().for_each(|window| {
window.with_surfaces(|surface, states_inner| {
let primary_scanout_output = update_surface_primary_scanout_output(
surface,
&output,
states_inner,
&render_output_result.states,
default_primary_scanout_output_compare,
);
if let Some(output) = primary_scanout_output {
with_fractional_scale(states_inner, |fraction_scale| {
fraction_scale.set_preferred_scale(
output.current_scale().fractional_scale(),
);
});
}
});
if state.space.outputs_for_element(window).contains(&output) {
window.send_frame(
&output,
time,
throttle,
surface_primary_scanout_output,
);
// TODO: dmabuf_feedback
}
});
super::post_repaint(
&output,
&render_output_result.states,
&state.space,
None,
time.into(),
);
if has_rendered {
let mut output_presentation_feedback = take_presentation_feedback(
@ -432,11 +398,11 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
.flush_clients()
.expect("failed to flush client buffers");
TimeoutAction::ToDuration(Duration::from_millis(6))
TimeoutAction::ToDuration(Duration::from_millis(1))
})?;
event_loop.run(
Some(Duration::from_millis(6)),
Some(Duration::from_millis(1)),
&mut CalloopData { display, state },
|_data| {
// println!("{}", _data.state.space.elements().count());

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
use smithay::{
desktop::PopupKind,
desktop::{LayerSurface, PopupKind},
input::{
keyboard::KeyboardTarget,
pointer::{MotionEvent, PointerTarget},
@ -49,7 +49,7 @@ impl FocusState {
pub enum FocusTarget {
Window(WindowElement),
Popup(PopupKind),
// TODO: LayerSurface
LayerSurface(LayerSurface),
}
impl IsAlive for FocusTarget {
@ -57,6 +57,7 @@ impl IsAlive for FocusTarget {
match self {
FocusTarget::Window(window) => window.alive(),
FocusTarget::Popup(popup) => popup.alive(),
FocusTarget::LayerSurface(surf) => surf.alive(),
}
}
}
@ -77,6 +78,7 @@ impl<B: Backend> PointerTarget<State<B>> for FocusTarget {
FocusTarget::Popup(popup) => {
PointerTarget::enter(popup.wl_surface(), seat, data, event);
}
FocusTarget::LayerSurface(surf) => PointerTarget::enter(surf, seat, data, event),
}
}
@ -86,6 +88,7 @@ impl<B: Backend> PointerTarget<State<B>> for FocusTarget {
FocusTarget::Popup(popup) => {
PointerTarget::motion(popup.wl_surface(), seat, data, event);
}
FocusTarget::LayerSurface(surf) => PointerTarget::motion(surf, seat, data, event),
}
}
@ -102,6 +105,9 @@ impl<B: Backend> PointerTarget<State<B>> for FocusTarget {
FocusTarget::Popup(popup) => {
PointerTarget::relative_motion(popup.wl_surface(), seat, data, event);
}
FocusTarget::LayerSurface(surf) => {
PointerTarget::relative_motion(surf, seat, data, event);
}
}
}
@ -116,6 +122,7 @@ impl<B: Backend> PointerTarget<State<B>> for FocusTarget {
FocusTarget::Popup(popup) => {
PointerTarget::button(popup.wl_surface(), seat, data, event);
}
FocusTarget::LayerSurface(surf) => PointerTarget::button(surf, seat, data, event),
}
}
@ -128,6 +135,7 @@ impl<B: Backend> PointerTarget<State<B>> for FocusTarget {
match self {
FocusTarget::Window(window) => PointerTarget::axis(window, seat, data, frame),
FocusTarget::Popup(popup) => PointerTarget::axis(popup.wl_surface(), seat, data, frame),
FocusTarget::LayerSurface(surf) => PointerTarget::axis(surf, seat, data, frame),
}
}
@ -144,6 +152,7 @@ impl<B: Backend> PointerTarget<State<B>> for FocusTarget {
FocusTarget::Popup(popup) => {
PointerTarget::leave(popup.wl_surface(), seat, data, serial, time);
}
FocusTarget::LayerSurface(surf) => PointerTarget::leave(surf, seat, data, serial, time),
}
}
}
@ -161,6 +170,9 @@ impl<B: Backend> KeyboardTarget<State<B>> for FocusTarget {
FocusTarget::Popup(popup) => {
KeyboardTarget::enter(popup.wl_surface(), seat, data, keys, serial);
}
FocusTarget::LayerSurface(surf) => {
KeyboardTarget::enter(surf, seat, data, keys, serial);
}
}
}
@ -170,6 +182,7 @@ impl<B: Backend> KeyboardTarget<State<B>> for FocusTarget {
FocusTarget::Popup(popup) => {
KeyboardTarget::leave(popup.wl_surface(), seat, data, serial);
}
FocusTarget::LayerSurface(surf) => KeyboardTarget::leave(surf, seat, data, serial),
}
}
@ -189,6 +202,9 @@ impl<B: Backend> KeyboardTarget<State<B>> for FocusTarget {
FocusTarget::Popup(popup) => {
KeyboardTarget::key(popup.wl_surface(), seat, data, key, state, serial, time);
}
FocusTarget::LayerSurface(surf) => {
KeyboardTarget::key(surf, seat, data, key, state, serial, time);
}
}
}
@ -206,6 +222,9 @@ impl<B: Backend> KeyboardTarget<State<B>> for FocusTarget {
FocusTarget::Popup(popup) => {
KeyboardTarget::modifiers(popup.wl_surface(), seat, data, modifiers, serial);
}
FocusTarget::LayerSurface(surf) => {
KeyboardTarget::modifiers(surf, seat, data, modifiers, serial);
}
}
}
}
@ -215,6 +234,7 @@ impl WaylandFocus for FocusTarget {
match self {
FocusTarget::Window(window) => window.wl_surface(),
FocusTarget::Popup(popup) => Some(popup.wl_surface().clone()),
FocusTarget::LayerSurface(surf) => Some(surf.wl_surface().clone()),
}
}
@ -226,6 +246,7 @@ impl WaylandFocus for FocusTarget {
FocusTarget::Window(WindowElement::Wayland(window)) => window.same_client_as(object_id),
FocusTarget::Window(WindowElement::X11(surface)) => surface.same_client_as(object_id),
FocusTarget::Popup(popup) => popup.wl_surface().id().same_client_as(object_id),
FocusTarget::LayerSurface(surf) => surf.wl_surface().id().same_client_as(object_id),
}
}
}
@ -241,3 +262,9 @@ impl From<PopupKind> for FocusTarget {
FocusTarget::Popup(value)
}
}
impl From<LayerSurface> for FocusTarget {
fn from(value: LayerSurface) -> Self {
FocusTarget::LayerSurface(value)
}
}

View file

@ -6,24 +6,25 @@ use std::time::Duration;
use smithay::{
backend::renderer::utils,
delegate_compositor, delegate_data_device, delegate_fractional_scale, delegate_output,
delegate_presentation, delegate_primary_selection, delegate_relative_pointer, delegate_seat,
delegate_shm, delegate_viewporter, delegate_xdg_shell,
delegate_compositor, delegate_data_device, delegate_fractional_scale, delegate_layer_shell,
delegate_output, delegate_presentation, delegate_primary_selection, delegate_relative_pointer,
delegate_seat, delegate_shm, delegate_viewporter, delegate_xdg_shell,
desktop::{
find_popup_root_surface, utils::surface_primary_scanout_output, PopupKeyboardGrab,
PopupKind, PopupPointerGrab, PopupUngrabStrategy, Window,
self, find_popup_root_surface, layer_map_for_output, utils::surface_primary_scanout_output,
PopupKeyboardGrab, PopupKind, PopupPointerGrab, PopupUngrabStrategy, Window,
},
input::{
pointer::{CursorImageStatus, Focus},
Seat, SeatHandler, SeatState,
},
output::Output,
reexports::{
calloop::Interest,
wayland_protocols::xdg::shell::server::xdg_toplevel::{self, ResizeEdge},
wayland_server::{
protocol::{
wl_buffer::WlBuffer, wl_data_source::WlDataSource, wl_seat::WlSeat,
wl_surface::WlSurface,
wl_buffer::WlBuffer, wl_data_source::WlDataSource, wl_output::WlOutput,
wl_seat::WlSeat, wl_surface::WlSurface,
},
Client, Resource,
},
@ -45,9 +46,12 @@ use smithay::{
self, set_primary_focus, PrimarySelectionHandler, PrimarySelectionState,
},
seat::WaylandFocus,
shell::xdg::{
Configure, PopupSurface, PositionerState, ToplevelSurface, XdgPopupSurfaceData,
XdgShellHandler, XdgShellState, XdgToplevelSurfaceData,
shell::{
wlr_layer::{self, Layer, WlrLayerShellHandler, WlrLayerShellState},
xdg::{
Configure, PopupSurface, PositionerState, ToplevelSurface, XdgPopupSurfaceData,
XdgShellHandler, XdgShellState, XdgToplevelSurfaceData,
},
},
shm::{ShmHandler, ShmState},
},
@ -640,18 +644,16 @@ impl<B: Backend> FractionalScaleHandler for State<B> {
compositor::with_states(&surface, |states| {
let primary_scanout_output =
smithay::desktop::utils::surface_primary_scanout_output(&surface, states)
desktop::utils::surface_primary_scanout_output(&surface, states)
.or_else(|| {
if root != surface {
compositor::with_states(&root, |states| {
smithay::desktop::utils::surface_primary_scanout_output(
&root, states,
)
.or_else(|| {
self.window_for_surface(&root).and_then(|window| {
self.space.outputs_for_element(&window).first().cloned()
desktop::utils::surface_primary_scanout_output(&root, states)
.or_else(|| {
self.window_for_surface(&root).and_then(|window| {
self.space.outputs_for_element(&window).first().cloned()
})
})
})
})
} else {
self.window_for_surface(&root).and_then(|window| {
@ -674,3 +676,45 @@ delegate_fractional_scale!(@<B: Backend> State<B>);
delegate_relative_pointer!(@<B: Backend> State<B>);
delegate_presentation!(@<B: Backend> State<B>);
impl<B: Backend> WlrLayerShellHandler for State<B> {
fn shell_state(&mut self) -> &mut WlrLayerShellState {
&mut self.layer_shell_state
}
fn new_layer_surface(
&mut self,
surface: wlr_layer::LayerSurface,
output: Option<WlOutput>,
_layer: Layer,
namespace: String,
) {
let output = output
.as_ref()
.and_then(Output::from_resource)
.or_else(|| self.space.outputs().next().cloned());
let Some(output) = output else {
tracing::error!("New layer surface, but there was no output to map it on");
return;
};
let mut map = layer_map_for_output(&output);
map.map_layer(&desktop::LayerSurface::new(surface, namespace))
.expect("failed to map layer surface");
}
fn layer_destroyed(&mut self, surface: wlr_layer::LayerSurface) {
if let Some((mut map, layer)) = self.space.outputs().find_map(|o| {
let map = layer_map_for_output(o);
let layer = map
.layers()
.find(|&layer| layer.layer_surface() == &surface)
.cloned();
layer.map(|layer| (map, layer))
}) {
map.unmap_layer(&layer);
}
}
}
delegate_layer_shell!(@<B: Backend> State<B>);

View file

@ -58,7 +58,10 @@ use smithay::{
fractional_scale::FractionalScaleManagerState,
output::OutputManagerState,
primary_selection::PrimarySelectionState,
shell::xdg::{XdgShellState, XdgToplevelSurfaceData},
shell::{
wlr_layer::WlrLayerShellState,
xdg::{XdgShellState, XdgToplevelSurfaceData},
},
shm::ShmState,
socket::ListeningSocketSource,
viewporter::ViewporterState,
@ -92,6 +95,7 @@ pub struct State<B: Backend> {
pub viewporter_state: ViewporterState,
pub fractional_scale_manager_state: FractionalScaleManagerState,
pub primary_selection_state: PrimarySelectionState,
pub layer_shell_state: WlrLayerShellState,
pub input_state: InputState,
pub api_state: ApiState,
@ -960,6 +964,7 @@ impl<B: Backend> State<B> {
&display_handle,
),
primary_selection_state: PrimarySelectionState::new::<Self>(&display_handle),
layer_shell_state: WlrLayerShellState::new::<Self>(&display_handle),
input_state: InputState::new(),
api_state: ApiState::new(),