fmt commit

This commit is contained in:
Victoria Brekenfeld 2022-08-30 13:28:36 +02:00
parent 352c526e9e
commit 9e0a6e1b5f
25 changed files with 787 additions and 499 deletions

View file

@ -207,7 +207,8 @@ impl CompositorHandler for State {
// schedule a new render
for output in self.common.shell.outputs_for_surface(surface) {
self.backend.schedule_render(&self.common.event_loop_handle, &output);
self.backend
.schedule_render(&self.common.event_loop_handle, &output);
}
}
}

View file

@ -4,13 +4,13 @@ use crate::state::State;
use smithay::{
delegate_data_device,
reexports::wayland_server::protocol::{wl_data_source::WlDataSource, wl_surface::WlSurface},
utils::IsAlive,
wayland::{
data_device::{
ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler,
},
seat::Seat,
},
utils::IsAlive
};
use std::cell::RefCell;

View file

@ -2,66 +2,65 @@
use anyhow::{anyhow, Context, Result};
use std::{
cell::RefCell,
time::Instant,
};
use std::{cell::RefCell, time::Instant};
use smithay::{
backend::{
drm::{DrmNode, NodeType},
egl::EGLDevice,
renderer::{
Bind,
Offscreen,
ExportDma,
ImportAll,
Renderer,
gles2::{Gles2Renderer, Gles2Renderbuffer, Gles2Error},
gles2::{Gles2Error, Gles2Renderbuffer, Gles2Renderer},
utils::with_renderer_surface_state,
Bind, ExportDma, ImportAll, Offscreen, Renderer,
},
},
desktop::{space::RenderElement, Kind, Window, draw_window, draw_window_popups},
desktop::{draw_window, draw_window_popups, space::RenderElement, Kind, Window},
reexports::wayland_server::{protocol::wl_output::WlOutput, DisplayHandle, Resource},
utils::{IsAlive, Size, Transform},
wayland::{
compositor::{get_children, with_states, SurfaceAttributes},
dmabuf::get_dmabuf,
output::Output,
seat::CursorImageStatus,
},
reexports::{
wayland_server::{DisplayHandle, Resource, protocol::wl_output::WlOutput},
},
utils::{IsAlive, Size, Transform},
};
use crate::{
backend::render::{render_output, render_workspace, cursor::draw_cursor, AsGles2Renderer, CustomElem},
backend::render::{
cursor::draw_cursor, render_output, render_workspace, AsGles2Renderer, CustomElem,
},
state::{BackendData, ClientState, Common},
utils::prelude::*,
wayland::protocols::{
export_dmabuf::{
delegate_export_dmabuf, ExportDmabufHandler, Capture, CaptureError,
},
export_dmabuf::{delegate_export_dmabuf, Capture, CaptureError, ExportDmabufHandler},
workspace::WorkspaceHandle,
},
};
impl ExportDmabufHandler for State {
fn capture_output(&mut self, _dh: &DisplayHandle, output: WlOutput, overlay_cursor: bool) -> Result<Capture, CaptureError> {
fn capture_output(
&mut self,
_dh: &DisplayHandle,
output: WlOutput,
overlay_cursor: bool,
) -> Result<Capture, CaptureError> {
let output = Output::from_resource(&output)
.ok_or(CaptureError::Permanent(anyhow!("Output is gone").into()))?;
let renderer = match self.backend {
BackendData::Kms(ref mut kms) => {
// the kms backend just keeps its dmabufs easily accessible for capture.
return kms.capture_output(&output)
return kms
.capture_output(&output)
.map(|(device, dmabuf, presentation_time)| Capture {
device,
dmabuf,
presentation_time,
})
.ok_or(CaptureError::Temporary(anyhow!("Surface not initialized yet").into()));
},
.ok_or(CaptureError::Temporary(
anyhow!("Surface not initialized yet").into(),
));
}
BackendData::Winit(ref mut winit) => winit.backend.renderer(),
BackendData::X11(ref mut x11) => &mut x11.renderer,
_ => unreachable!(),
@ -70,14 +69,20 @@ impl ExportDmabufHandler for State {
.context("Failed to find DrmNode")
.map_err(|err| CaptureError::Permanent(err.into()))?;
let size = output.geometry().size.to_f64().to_buffer(
output.current_scale().fractional_scale(),
output.current_transform().into()
).to_i32_round();
let size = output
.geometry()
.size
.to_f64()
.to_buffer(
output.current_scale().fractional_scale(),
output.current_transform().into(),
)
.to_i32_round();
let buffer = Offscreen::<Gles2Renderbuffer>::create_buffer(renderer, size)
.context("Failed to create render buffer for offscreen capture")
.map_err(|err| CaptureError::Temporary(err.into()))?;
renderer.bind(buffer)
renderer
.bind(buffer)
.context("Failed to bind render buffer for offscreen capture")
.map_err(|err| CaptureError::Temporary(err.into()))?;
render_output(
@ -90,9 +95,10 @@ impl ExportDmabufHandler for State {
#[cfg(feature = "debug")]
None,
)
.context("Failed to render desktop for offscreen capture")
.map_err(|err| CaptureError::Temporary(err.into()))?;
let dmabuf = renderer.export_framebuffer(size)
.context("Failed to render desktop for offscreen capture")
.map_err(|err| CaptureError::Temporary(err.into()))?;
let dmabuf = renderer
.export_framebuffer(size)
.context("Failed to export buffer for offscreen capture")
.map_err(|err| CaptureError::Temporary(err.into()))?;
@ -103,10 +109,21 @@ impl ExportDmabufHandler for State {
})
}
fn capture_workspace(&mut self, _dh: &DisplayHandle, workspace: WorkspaceHandle, wl_output: WlOutput, overlay_cursor: bool) -> Result<Capture, CaptureError> {
fn capture_workspace(
&mut self,
_dh: &DisplayHandle,
workspace: WorkspaceHandle,
wl_output: WlOutput,
overlay_cursor: bool,
) -> Result<Capture, CaptureError> {
let output = Output::from_resource(&wl_output)
.ok_or(CaptureError::Permanent(anyhow!("Output is gone").into()))?;
let workspace = self.common.shell.spaces.iter().find(|w| w.handle == workspace)
let workspace = self
.common
.shell
.spaces
.iter()
.find(|w| w.handle == workspace)
.ok_or(CaptureError::Permanent(anyhow!("Workspace is gone").into()))?
.idx;
if self.common.shell.active_space(&output).idx == workspace {
@ -117,50 +134,66 @@ impl ExportDmabufHandler for State {
let device = device_from_renderer(winit.backend.renderer())
.context("Failed to find DrmNode")
.map_err(|err| CaptureError::Permanent(err.into()))?;
capture_workspace(device, winit.backend.renderer(), &output, workspace, &mut self.common)
},
capture_workspace(
device,
winit.backend.renderer(),
&output,
workspace,
&mut self.common,
)
}
BackendData::X11(ref mut x11) => {
let device = device_from_renderer(&x11.renderer)
.context("Failed to find DrmNode")
.map_err(|err| CaptureError::Permanent(err.into()))?;
capture_workspace(device, &mut x11.renderer, &output, workspace, &mut self.common)
},
capture_workspace(
device,
&mut x11.renderer,
&output,
workspace,
&mut self.common,
)
}
BackendData::Kms(ref mut kms) => {
let node = kms.target_node_for_output(&output)
let node = kms
.target_node_for_output(&output)
.unwrap_or(kms.primary)
.node_with_type(NodeType::Render)
.with_context(|| "Unable to find node")
.map_err(|x| CaptureError::Permanent(x.into()))?
.map_err(|x| CaptureError::Permanent(x.into()))?;
let mut renderer = kms.api.renderer::<Gles2Renderbuffer>(&node, &node)
let mut renderer = kms
.api
.renderer::<Gles2Renderbuffer>(&node, &node)
.with_context(|| format!("Failed to optain renderer for {:?}", node))
.map_err(|x| CaptureError::Permanent(x.into()))?;
capture_workspace(
node,
&mut renderer,
&output,
workspace,
&mut self.common,
)
},
capture_workspace(node, &mut renderer, &output, workspace, &mut self.common)
}
BackendData::Unset => unreachable!(),
}
}
}
fn capture_toplevel(&mut self, dh: &DisplayHandle, window: Window, overlay_cursor: bool) -> Result<Capture, CaptureError> {
fn capture_toplevel(
&mut self,
dh: &DisplayHandle,
window: Window,
overlay_cursor: bool,
) -> Result<Capture, CaptureError> {
let Kind::Xdg(xdg) = window.toplevel();
let surface = xdg.wl_surface();
let window_transform = with_states(surface, |states| states
.cached_state
.current::<SurfaceAttributes>()
.buffer_transform
.into()
);
let window_transform = with_states(surface, |states| {
states
.cached_state
.current::<SurfaceAttributes>()
.buffer_transform
.into()
});
let workspace = self.common.shell.space_for_window(surface);
let pointers = if overlay_cursor && workspace.is_some() {
self.common.seats
self.common
.seats
.iter()
.filter_map(|seat| {
let cursor_status = seat
@ -181,14 +214,22 @@ impl ExportDmabufHandler for State {
let workspace = workspace.as_deref()?;
let loc = seat.get_pointer().map(|ptr| ptr.current_location())?;
let output = active_output(seat, &self.common);
if self.common.shell.active_space(&output).idx == workspace.idx {
let relative = self.common.shell.space_relative_output_geometry(loc, &output);
let relative = self
.common
.shell
.space_relative_output_geometry(loc, &output);
// unwrap is safe, because we got this workspace from `space_for_window`. It has to contain the window.
let bbox = workspace.space.window_bbox(&window).unwrap();
bbox.contains(relative.to_i32_round()).then_some((seat, (relative - bbox.loc.to_f64()).to_i32_round()))
} else { None }
} else { None }
bbox.contains(relative.to_i32_round())
.then_some((seat, (relative - bbox.loc.to_f64()).to_i32_round()))
} else {
None
}
} else {
None
}
})
.collect::<Vec<_>>()
} else {
@ -198,7 +239,8 @@ impl ExportDmabufHandler for State {
let device = match self.backend {
BackendData::Winit(ref mut winit) => device_from_renderer(winit.backend.renderer()),
BackendData::X11(ref x11) => device_from_renderer(&x11.renderer),
BackendData::Kms(ref kms) => Ok(dh.get_client(window.toplevel().wl_surface().id())
BackendData::Kms(ref kms) => Ok(dh
.get_client(window.toplevel().wl_surface().id())
.ok()
.with_context(|| "Unable to find matching wayland client")
.map_err(|x| CaptureError::Permanent(x.into()))?
@ -209,12 +251,18 @@ impl ExportDmabufHandler for State {
.unwrap_or_else(|| kms.primary.clone())),
_ => unreachable!(),
}
.context("Failed to find DrmNode")
.map_err(|err| CaptureError::Permanent(err.into()))?;
.context("Failed to find DrmNode")
.map_err(|err| CaptureError::Permanent(err.into()))?;
// first lets check, if we can just send a dmabuf from the client directly
if pointers.is_empty() && window_transform == Transform::Normal && get_children(surface).is_empty() && self.common.shell.popups.find_popup(surface).is_none() {
let dmabuf = with_renderer_surface_state(surface, |state| state.wl_buffer().and_then(|buf| get_dmabuf(buf).ok()));
if pointers.is_empty()
&& window_transform == Transform::Normal
&& get_children(surface).is_empty()
&& self.common.shell.popups.find_popup(surface).is_none()
{
let dmabuf = with_renderer_surface_state(surface, |state| {
state.wl_buffer().and_then(|buf| get_dmabuf(buf).ok())
});
if let Some(dmabuf) = dmabuf {
return Ok(Capture {
device,
@ -230,47 +278,77 @@ impl ExportDmabufHandler for State {
BackendData::Winit(ref mut winit) => winit.backend.renderer(),
BackendData::X11(ref mut x11) => &mut x11.renderer,
BackendData::Kms(ref mut kms) => {
_tmp_multirenderer = Some(kms.api.renderer::<Gles2Renderbuffer>(&device, &device)
.with_context(|| format!("Failed to optain renderer for {:?}", device))
.map_err(|x| CaptureError::Permanent(x.into()))?);
_tmp_multirenderer = Some(
kms.api
.renderer::<Gles2Renderbuffer>(&device, &device)
.with_context(|| format!("Failed to optain renderer for {:?}", device))
.map_err(|x| CaptureError::Permanent(x.into()))?,
);
_tmp_multirenderer.as_mut().unwrap().as_gles2()
},
}
BackendData::Unset => unreachable!(),
};
let bbox = window.bbox_with_popups();
let size = bbox.size + Size::from((-bbox.loc.x, -bbox.loc.y));
let buffer = Offscreen::<Gles2Renderbuffer>::create_buffer(renderer, size.to_buffer(1, window_transform))
.context("Failed to create render buffer for offscreen capture")
.map_err(|err| CaptureError::Temporary(err.into()))?;
renderer.bind(buffer)
let buffer = Offscreen::<Gles2Renderbuffer>::create_buffer(
renderer,
size.to_buffer(1, window_transform),
)
.context("Failed to create render buffer for offscreen capture")
.map_err(|err| CaptureError::Temporary(err.into()))?;
renderer
.bind(buffer)
.context("Failed to bind render buffer for offscreen capture")
.map_err(|err| CaptureError::Temporary(err.into()))?;
renderer.render(size.to_physical(1), Transform::Normal, |renderer, frame| {
let log = slog_scope::logger();
let damage = &[window.physical_bbox_with_popups((0.0, 0.0), 1.0)];
draw_window(renderer, frame, &window, 1.0, (0.0, 0.0), damage, &log)?;
draw_window_popups(renderer, frame, &window, 1.0, (0.0, 0.0), damage, &log)?;
for (seat, loc) in pointers.into_iter() {
if let Some(cursor_elem) = draw_cursor::<_, CustomElem>(renderer, seat, loc, &self.common.start_time, true) {
let damage = RenderElement::<Gles2Renderer>::accumulated_damage(&cursor_elem, 1.0, None);
cursor_elem.draw(renderer, frame, 1.0, loc.to_physical(1.0), &damage, &log)?;
renderer
.render(size.to_physical(1), Transform::Normal, |renderer, frame| {
let log = slog_scope::logger();
let damage = &[window.physical_bbox_with_popups((0.0, 0.0), 1.0)];
draw_window(renderer, frame, &window, 1.0, (0.0, 0.0), damage, &log)?;
draw_window_popups(renderer, frame, &window, 1.0, (0.0, 0.0), damage, &log)?;
for (seat, loc) in pointers.into_iter() {
if let Some(cursor_elem) = draw_cursor::<_, CustomElem>(
renderer,
seat,
loc,
&self.common.start_time,
true,
) {
let damage = RenderElement::<Gles2Renderer>::accumulated_damage(
&cursor_elem,
1.0,
None,
);
cursor_elem.draw(
renderer,
frame,
1.0,
loc.to_physical(1.0),
&damage,
&log,
)?;
}
}
}
Result::<(), Gles2Error>::Ok(())
})
Result::<(), Gles2Error>::Ok(())
})
.context("Failed to render window for offscreen capture")
.map_err(|err| CaptureError::Temporary(err.into()))?
.context("Failed to render window for offscreen capture")
.map_err(|err| CaptureError::Temporary(err.into()))?;
let dmabuf = renderer.export_framebuffer(size.to_buffer(1, window_transform))
let dmabuf = renderer
.export_framebuffer(size.to_buffer(1, window_transform))
.context("Failed to export buffer for offscreen capture")
.map_err(|err| CaptureError::Temporary(err.into()))?;
Ok(Capture { device, dmabuf, presentation_time: Instant::now() })
Ok(Capture {
device,
dmabuf,
presentation_time: Instant::now(),
})
}
fn start_time(&mut self) -> Instant {
self.common.start_time
}
@ -286,22 +364,28 @@ fn capture_workspace<E, T, R>(
where
E: std::error::Error + Send + Sync + 'static,
T: Clone + 'static,
R: Renderer<Error=E, TextureId=T>
+ ImportAll
+ AsGles2Renderer
+ Offscreen<Gles2Renderbuffer>
+ Bind<Gles2Renderbuffer>
+ ExportDma,
R: Renderer<Error = E, TextureId = T>
+ ImportAll
+ AsGles2Renderer
+ Offscreen<Gles2Renderbuffer>
+ Bind<Gles2Renderbuffer>
+ ExportDma,
CustomElem: RenderElement<R>,
{
let size = output.geometry().size.to_f64().to_buffer(
output.current_scale().fractional_scale(),
output.current_transform().into()
).to_i32_round();
let size = output
.geometry()
.size
.to_f64()
.to_buffer(
output.current_scale().fractional_scale(),
output.current_transform().into(),
)
.to_i32_round();
let buffer = Offscreen::<Gles2Renderbuffer>::create_buffer(renderer, size)
.context("Failed to create render buffer for offscreen capture")
.map_err(|err| CaptureError::Temporary(err.into()))?;
renderer.bind(buffer)
renderer
.bind(buffer)
.context("Failed to bind render buffer for offscreen capture")
.map_err(|err| CaptureError::Temporary(err.into()))?;
render_workspace(
@ -315,19 +399,26 @@ where
#[cfg(feature = "debug")]
None,
)
.map_err(|err| anyhow!("Failed to render desktop for offscreen capture: {:?}", err)) // meh..
.map_err(|err| CaptureError::Temporary(err.into()))?;
let dmabuf = renderer.export_framebuffer(size)
.map_err(|err| anyhow!("Failed to render desktop for offscreen capture: {:?}", err)) // meh..
.map_err(|err| CaptureError::Temporary(err.into()))?;
let dmabuf = renderer
.export_framebuffer(size)
.context("Failed to export buffer for offscreen capture")
.map_err(|err| CaptureError::Temporary(err.into()))?;
Ok(Capture { device: gpu, dmabuf, presentation_time: Instant::now() })
Ok(Capture {
device: gpu,
dmabuf,
presentation_time: Instant::now(),
})
}
fn device_from_renderer(renderer: &Gles2Renderer) -> Result<DrmNode> {
EGLDevice::device_for_display(renderer.egl_context().display())?
.try_get_render_node()?
.ok_or(anyhow!("No node associated with context (software context?)"))
.ok_or(anyhow!(
"No node associated with context (software context?)"
))
}
delegate_export_dmabuf!(State);
delegate_export_dmabuf!(State);

View file

@ -19,18 +19,19 @@ impl ToplevelManagementHandler for State {
}
fn activate(&mut self, dh: &DisplayHandle, window: &Window, seat: Option<Seat<Self>>) {
if let Some(idx) = self.common.shell.space_for_window(window.toplevel().wl_surface()).map(|w| w.idx) {
if let Some(idx) = self
.common
.shell
.space_for_window(window.toplevel().wl_surface())
.map(|w| w.idx)
{
let seat = seat.unwrap_or(self.common.last_active_seat.clone());
let output = active_output(&seat, &self.common);
if self.common.shell.active_space(&output).idx != idx {
self.common.shell.activate(&seat, &output, idx as usize);
}
self.common.set_focus(
dh,
Some(window.toplevel().wl_surface()),
&seat,
None,
);
self.common
.set_focus(dh, Some(window.toplevel().wl_surface()), &seat, None);
}
}

View file

@ -181,7 +181,9 @@ impl XdgShellHandler for State {
.unwrap()
.clone();
self.common.shell.move_request(&window, &seat, serial, start_data);
self.common
.shell
.move_request(&window, &seat, serial, start_data);
}
}

View file

@ -87,7 +87,12 @@ fn unconstrain_xdg_popup(
if let Some(output_rect) = space
.outputs_for_window(window)
.into_iter()
.find(|o| space.output_geometry(o).map(|rect| rect.contains(anchor_point)).unwrap_or(false))
.find(|o| {
space
.output_geometry(o)
.map(|rect| rect.contains(anchor_point))
.unwrap_or(false)
})
.map(|o| space.output_geometry(&o).unwrap())
{
// the output_rect represented relative to the parents coordinate system

View file

@ -26,8 +26,8 @@ use smithay::{
Format, Fourcc, Modifier,
},
reexports::wayland_server::{
backend::GlobalId, protocol::wl_buffer::WlBuffer, Client, DataInit,
Dispatch, DisplayHandle, GlobalDispatch, New, Resource,
backend::GlobalId, protocol::wl_buffer::WlBuffer, Client, DataInit, Dispatch,
DisplayHandle, GlobalDispatch, New, Resource,
},
wayland::{
buffer::BufferHandler,

View file

@ -1,46 +1,33 @@
// SPDX-License-Identifier: GPL-3.0-only
use smithay::{
backend::{
allocator::{dmabuf::Dmabuf, Buffer},
drm::DrmNode,
},
desktop::Window,
reexports::wayland_server::{
self, backend::GlobalId, protocol::wl_output::WlOutput, Client, Dispatch, DisplayHandle,
GlobalDispatch,
},
};
use std::{
fs::File,
io::{Seek, SeekFrom},
os::unix::io::{FromRawFd, IntoRawFd},
time::Instant,
};
use smithay::{
backend::{
allocator::{
Buffer,
dmabuf::Dmabuf,
},
drm::DrmNode,
},
desktop::Window,
reexports::{
wayland_server::{
self,
Client,
Dispatch,
GlobalDispatch,
DisplayHandle,
backend::GlobalId,
protocol::wl_output::WlOutput,
},
},
};
use cosmic_protocols::{
export_dmabuf::v1::server::{
zcosmic_export_dmabuf_manager_v1::{self, ZcosmicExportDmabufManagerV1},
zcosmic_export_dmabuf_frame_v1::{self, CancelReason, Flags, ZcosmicExportDmabufFrameV1},
},
use cosmic_protocols::export_dmabuf::v1::server::{
zcosmic_export_dmabuf_frame_v1::{self, CancelReason, Flags, ZcosmicExportDmabufFrameV1},
zcosmic_export_dmabuf_manager_v1::{self, ZcosmicExportDmabufManagerV1},
};
use crate::wayland::protocols::{
toplevel_info::{ToplevelInfoHandler, window_from_handle},
toplevel_info::{window_from_handle, ToplevelInfoHandler},
workspace::{WorkspaceHandle, WorkspaceHandler},
};
/// Export Dmabuf global state
#[derive(Debug)]
pub struct ExportDmabufState {
@ -63,9 +50,12 @@ impl ExportDmabufState {
F: for<'a> Fn(&'a Client) -> bool + Send + Sync + 'static,
{
ExportDmabufState {
global: display.create_global::<D, ZcosmicExportDmabufManagerV1, _>(1, ExportDmabufGlobalData {
filter: Box::new(client_filter),
}),
global: display.create_global::<D, ZcosmicExportDmabufManagerV1, _>(
1,
ExportDmabufGlobalData {
filter: Box::new(client_filter),
},
),
}
}
@ -88,18 +78,35 @@ pub struct Capture {
}
pub trait ExportDmabufHandler {
fn capture_output(&mut self, dh: &DisplayHandle, output: WlOutput, overlay_cursor: bool) -> Result<Capture, CaptureError>;
fn capture_workspace(&mut self, dh: &DisplayHandle, workspace: WorkspaceHandle, output: WlOutput, overlay_cursor: bool) -> Result<Capture, CaptureError>;
fn capture_toplevel(&mut self, dh: &DisplayHandle, toplevel: Window, overlay_cursor: bool) -> Result<Capture, CaptureError>;
fn capture_output(
&mut self,
dh: &DisplayHandle,
output: WlOutput,
overlay_cursor: bool,
) -> Result<Capture, CaptureError>;
fn capture_workspace(
&mut self,
dh: &DisplayHandle,
workspace: WorkspaceHandle,
output: WlOutput,
overlay_cursor: bool,
) -> Result<Capture, CaptureError>;
fn capture_toplevel(
&mut self,
dh: &DisplayHandle,
toplevel: Window,
overlay_cursor: bool,
) -> Result<Capture, CaptureError>;
fn start_time(&mut self) -> Instant;
}
impl<D> GlobalDispatch<ZcosmicExportDmabufManagerV1, ExportDmabufGlobalData, D> for ExportDmabufState
impl<D> GlobalDispatch<ZcosmicExportDmabufManagerV1, ExportDmabufGlobalData, D>
for ExportDmabufState
where
D: GlobalDispatch<ZcosmicExportDmabufManagerV1, ExportDmabufGlobalData>
+ Dispatch<ZcosmicExportDmabufManagerV1, ()>
+ Dispatch<ZcosmicExportDmabufFrameV1, ()>
+ ExportDmabufHandler,
+ Dispatch<ZcosmicExportDmabufManagerV1, ()>
+ Dispatch<ZcosmicExportDmabufFrameV1, ()>
+ ExportDmabufHandler,
{
fn bind(
_state: &mut D,
@ -120,11 +127,11 @@ where
impl<D> Dispatch<ZcosmicExportDmabufManagerV1, (), D> for ExportDmabufState
where
D: GlobalDispatch<ZcosmicExportDmabufManagerV1, ExportDmabufGlobalData>
+ Dispatch<ZcosmicExportDmabufManagerV1, ()>
+ Dispatch<ZcosmicExportDmabufFrameV1, ()>
+ ExportDmabufHandler
+ WorkspaceHandler
+ ToplevelInfoHandler
+ Dispatch<ZcosmicExportDmabufManagerV1, ()>
+ Dispatch<ZcosmicExportDmabufFrameV1, ()>
+ ExportDmabufHandler
+ WorkspaceHandler
+ ToplevelInfoHandler,
{
fn request(
state: &mut D,
@ -147,7 +154,7 @@ where
Ok(capture) => handle_capture(capture, frame, start_time),
Err(err) => frame.cancel(err.into()),
}
},
}
zcosmic_export_dmabuf_manager_v1::Request::CaptureWorkspace {
frame,
overlay_cursor,
@ -157,14 +164,19 @@ where
let frame = data_init.init(frame, ());
match state.workspace_state().workspace_handle(&workspace) {
Some(workspace) => {
match state.capture_workspace(dhandle, workspace, output, overlay_cursor != 0) {
match state.capture_workspace(
dhandle,
workspace,
output,
overlay_cursor != 0,
) {
Ok(capture) => handle_capture(capture, frame, start_time),
Err(err) => frame.cancel(err.into()),
}
},
}
None => frame.cancel(CancelReason::Permanent),
}
},
}
zcosmic_export_dmabuf_manager_v1::Request::CaptureToplevel {
frame,
overlay_cursor,
@ -177,36 +189,38 @@ where
Ok(capture) => handle_capture(capture, frame, start_time),
Err(err) => frame.cancel(err.into()),
}
},
}
None => frame.cancel(CancelReason::Permanent),
}
},
zcosmic_export_dmabuf_manager_v1::Request::Destroy => {},
_ => {},
}
zcosmic_export_dmabuf_manager_v1::Request::Destroy => {}
_ => {}
}
}
}
impl From<CaptureError> for CancelReason {
fn from(err: CaptureError) -> Self {
match err {
match err {
CaptureError::Temporary(err) => {
slog_scope::debug!("Temporary Capture Error: {}", err);
CancelReason::Temporary
},
}
CaptureError::Permanent(err) => {
slog_scope::warn!("Permanent Capture Error: {}", err);
CancelReason::Permanent
},
CaptureError::Resizing => {
CancelReason::Resizing
}
}
CaptureError::Resizing => CancelReason::Resizing,
}
}
}
fn handle_capture(capture: Capture, frame: ZcosmicExportDmabufFrameV1, start_time: Instant) {
let Capture { device, dmabuf, presentation_time } = capture;
let Capture {
device,
dmabuf,
presentation_time,
} = capture;
let format = dmabuf.format();
let modifier: u64 = format.modifier.into();
@ -224,7 +238,11 @@ fn handle_capture(capture: Capture, frame: ZcosmicExportDmabufFrameV1, start_tim
dmabuf.num_planes() as u32,
);
for (i, (handle, (offset, stride))) in dmabuf.handles().zip(dmabuf.offsets().zip(dmabuf.strides())).enumerate() {
for (i, (handle, (offset, stride))) in dmabuf
.handles()
.zip(dmabuf.offsets().zip(dmabuf.strides()))
.enumerate()
{
let mut file = unsafe { File::from_raw_fd(handle) };
let size = match file.seek(SeekFrom::End(0)) {
Ok(size) => size,
@ -240,31 +258,20 @@ fn handle_capture(capture: Capture, frame: ZcosmicExportDmabufFrameV1, start_tim
return;
}
let handle = file.into_raw_fd();
frame.object(
i as u32,
handle,
size as u32,
offset,
stride,
i as u32,
);
frame.object(i as u32, handle, size as u32, offset, stride, i as u32);
}
let duration = presentation_time.duration_since(start_time);
let (tv_sec, tv_nsec) = (duration.as_secs(), duration.subsec_nanos());
frame.ready(
(tv_sec >> 32) as u32,
(tv_sec & 0xFFFFFFFF) as u32,
tv_nsec,
);
frame.ready((tv_sec >> 32) as u32, (tv_sec & 0xFFFFFFFF) as u32, tv_nsec);
}
impl<D> Dispatch<ZcosmicExportDmabufFrameV1, (), D> for ExportDmabufState
where
D: GlobalDispatch<ZcosmicExportDmabufManagerV1, ExportDmabufGlobalData>
+ Dispatch<ZcosmicExportDmabufManagerV1, ()>
+ Dispatch<ZcosmicExportDmabufFrameV1, ()>
+ ExportDmabufHandler,
+ Dispatch<ZcosmicExportDmabufManagerV1, ()>
+ Dispatch<ZcosmicExportDmabufFrameV1, ()>
+ ExportDmabufHandler,
{
fn request(
_state: &mut D,
@ -276,8 +283,8 @@ where
_data_init: &mut wayland_server::DataInit<'_, D>,
) {
match request {
zcosmic_export_dmabuf_frame_v1::Request::Destroy => {},
_ => {},
zcosmic_export_dmabuf_frame_v1::Request::Destroy => {}
_ => {}
}
}
}

View file

@ -12,8 +12,7 @@ use smithay::{
wayland_server::{
backend::{ClientId, GlobalId, ObjectId},
protocol::wl_output::WlOutput,
Client, DataInit, Dispatch, DisplayHandle,
GlobalDispatch, New, Resource,
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource,
},
},
utils::{Logical, Physical, Point, Size, Transform},
@ -133,8 +132,7 @@ struct OutputStateInner {
}
type OutputState = Mutex<OutputStateInner>;
impl<D> GlobalDispatch<ZwlrOutputManagerV1, OutputMngrGlobalData, D>
for OutputConfigurationState<D>
impl<D> GlobalDispatch<ZwlrOutputManagerV1, OutputMngrGlobalData, D> for OutputConfigurationState<D>
where
D: GlobalDispatch<ZwlrOutputManagerV1, OutputMngrGlobalData>
+ Dispatch<ZwlrOutputManagerV1, OutputMngrInstanceData>
@ -176,8 +174,7 @@ where
}
}
impl<D> Dispatch<ZwlrOutputManagerV1, OutputMngrInstanceData, D>
for OutputConfigurationState<D>
impl<D> Dispatch<ZwlrOutputManagerV1, OutputMngrInstanceData, D> for OutputConfigurationState<D>
where
D: GlobalDispatch<ZwlrOutputManagerV1, OutputMngrGlobalData>
+ Dispatch<ZwlrOutputManagerV1, OutputMngrInstanceData>
@ -279,8 +276,7 @@ where
}
}
impl<D> Dispatch<ZwlrOutputConfigurationV1, PendingConfiguration, D>
for OutputConfigurationState<D>
impl<D> Dispatch<ZwlrOutputConfigurationV1, PendingConfiguration, D> for OutputConfigurationState<D>
where
D: GlobalDispatch<ZwlrOutputManagerV1, OutputMngrGlobalData>
+ Dispatch<ZwlrOutputManagerV1, OutputMngrInstanceData>

View file

@ -1,9 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
use std::{
collections::HashMap,
sync::Mutex,
};
use std::{collections::HashMap, sync::Mutex};
use smithay::{
desktop::Window,
@ -12,11 +9,10 @@ use smithay::{
wayland_server::{
backend::{ClientId, GlobalId, ObjectId},
protocol::wl_surface::WlSurface,
Client, DataInit, Dispatch, DisplayHandle,
GlobalDispatch, New, Resource,
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource,
},
},
utils::{IsAlive, Rectangle, Logical},
utils::{IsAlive, Logical, Rectangle},
wayland::{
compositor::with_states, output::Output, shell::xdg::XdgToplevelSurfaceRoleAttributes,
},
@ -68,21 +64,18 @@ pub type ToplevelHandleState = Mutex<ToplevelHandleStateInner>;
impl ToplevelHandleStateInner {
fn from_window(window: &Window) -> ToplevelHandleState {
ToplevelHandleState::new(
ToplevelHandleStateInner {
outputs: Vec::new(),
workspaces: Vec::new(),
title: String::new(),
app_id: String::new(),
states: Vec::new(),
window: window.clone(),
}
)
ToplevelHandleState::new(ToplevelHandleStateInner {
outputs: Vec::new(),
workspaces: Vec::new(),
title: String::new(),
app_id: String::new(),
states: Vec::new(),
window: window.clone(),
})
}
}
impl<D> GlobalDispatch<ZcosmicToplevelInfoV1, ToplevelInfoGlobalData, D>
for ToplevelInfoState<D>
impl<D> GlobalDispatch<ZcosmicToplevelInfoV1, ToplevelInfoGlobalData, D> for ToplevelInfoState<D>
where
D: GlobalDispatch<ZcosmicToplevelInfoV1, ToplevelInfoGlobalData>
+ Dispatch<ZcosmicToplevelInfoV1, ()>
@ -256,8 +249,7 @@ where
.unwrap()
.lock()
.unwrap();
state.rectangles
.retain(|_, (surface, _)| surface.alive());
state.rectangles.retain(|_, (surface, _)| surface.alive());
if window.alive() {
std::mem::drop(state);
for instance in &self.instances {
@ -476,13 +468,7 @@ fn send_toplevel_to_client<D>(
pub fn window_from_handle(handle: ZcosmicToplevelHandleV1) -> Option<Window> {
handle
.data::<ToplevelHandleState>()
.map(|state|
state
.lock()
.unwrap()
.window
.clone()
)
.map(|state| state.lock().unwrap().window.clone())
}
macro_rules! delegate_toplevel_info {

View file

@ -2,29 +2,21 @@
use smithay::{
desktop::Window,
reexports::{
wayland_server::{
backend::{ClientId, GlobalId, ObjectId},
protocol::wl_surface::WlSurface,
Client, DataInit, Dispatch, DisplayHandle,
GlobalDispatch, New, Resource,
},
reexports::wayland_server::{
backend::{ClientId, GlobalId, ObjectId},
protocol::wl_surface::WlSurface,
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource,
},
utils::{Logical, Rectangle},
wayland::{
output::Output,
seat::Seat,
},
wayland::{output::Output, seat::Seat},
};
use cosmic_protocols::toplevel_management::v1::server::{
zcosmic_toplevel_manager_v1::{self, ZcosmicToplevelManagerV1},
};
pub use cosmic_protocols::toplevel_management::v1::server::zcosmic_toplevel_manager_v1::ZcosmicToplelevelManagementCapabilitiesV1 as ManagementCapabilities;
use cosmic_protocols::toplevel_management::v1::server::zcosmic_toplevel_manager_v1::{
self, ZcosmicToplevelManagerV1,
};
use super::toplevel_info::{ToplevelInfoHandler, ToplevelState, window_from_handle};
use super::toplevel_info::{window_from_handle, ToplevelInfoHandler, ToplevelState};
pub struct ToplevelManagementState {
instances: Vec<ZcosmicToplevelManagerV1>,
@ -52,13 +44,17 @@ pub struct ToplevelManagerGlobalData {
}
impl ToplevelManagementState {
pub fn new<D, F>(dh: &DisplayHandle, capabilities: Vec<ManagementCapabilities>, client_filter: F) -> ToplevelManagementState
pub fn new<D, F>(
dh: &DisplayHandle,
capabilities: Vec<ManagementCapabilities>,
client_filter: F,
) -> ToplevelManagementState
where
D: GlobalDispatch<ZcosmicToplevelManagerV1, ToplevelManagerGlobalData>
+ Dispatch<ZcosmicToplevelManagerV1, ()>
+ ToplevelManagementHandler
+ 'static,
F: for<'a> Fn(&'a Client) -> bool + Send + Sync + 'static
F: for<'a> Fn(&'a Client) -> bool + Send + Sync + 'static,
{
let global = dh.create_global::<D, ZcosmicToplevelManagerV1, _>(
1,
@ -73,7 +69,11 @@ impl ToplevelManagementState {
}
}
pub fn rectangle_for(&mut self, window: &Window, client: &ClientId) -> Option<(WlSurface, Rectangle<i32, Logical>)> {
pub fn rectangle_for(
&mut self,
window: &Window,
client: &ClientId,
) -> Option<(WlSurface, Rectangle<i32, Logical>)> {
if let Some(state) = window.user_data().get::<ToplevelState>() {
state.lock().unwrap().rectangles.get(client).cloned()
} else {
@ -86,12 +86,13 @@ impl ToplevelManagementState {
}
}
impl<D> GlobalDispatch<ZcosmicToplevelManagerV1, ToplevelManagerGlobalData, D> for ToplevelManagementState
impl<D> GlobalDispatch<ZcosmicToplevelManagerV1, ToplevelManagerGlobalData, D>
for ToplevelManagementState
where
D: GlobalDispatch<ZcosmicToplevelManagerV1, ToplevelManagerGlobalData>
+ Dispatch<ZcosmicToplevelManagerV1, ()>
+ ToplevelManagementHandler
+ 'static
+ 'static,
{
fn bind(
state: &mut D,
@ -120,13 +121,12 @@ where
}
}
impl<D> Dispatch<ZcosmicToplevelManagerV1, (), D> for ToplevelManagementState
where
D: GlobalDispatch<ZcosmicToplevelManagerV1, ToplevelManagerGlobalData>
+ Dispatch<ZcosmicToplevelManagerV1, ()>
+ ToplevelManagementHandler
+ 'static
+ 'static,
{
fn request(
state: &mut D,
@ -141,36 +141,43 @@ where
zcosmic_toplevel_manager_v1::Request::Activate { toplevel, seat } => {
let window = window_from_handle(toplevel).unwrap();
state.activate(dh, &window, Seat::from_resource(&seat));
},
}
zcosmic_toplevel_manager_v1::Request::Close { toplevel } => {
let window = window_from_handle(toplevel).unwrap();
state.close(dh, &window);
},
}
zcosmic_toplevel_manager_v1::Request::SetFullscreen { toplevel, output } => {
let window = window_from_handle(toplevel).unwrap();
state.fullscreen(dh, &window, output.as_ref().and_then(Output::from_resource))
},
}
zcosmic_toplevel_manager_v1::Request::UnsetFullscreen { toplevel } => {
let window = window_from_handle(toplevel).unwrap();
state.unfullscreen(dh, &window);
},
}
zcosmic_toplevel_manager_v1::Request::SetMaximized { toplevel } => {
let window = window_from_handle(toplevel).unwrap();
state.maximize(dh, &window);
},
}
zcosmic_toplevel_manager_v1::Request::UnsetMaximized { toplevel } => {
let window = window_from_handle(toplevel).unwrap();
state.unmaximize(dh, &window);
},
}
zcosmic_toplevel_manager_v1::Request::SetMinimized { toplevel } => {
let window = window_from_handle(toplevel).unwrap();
state.minimize(dh, &window);
},
}
zcosmic_toplevel_manager_v1::Request::UnsetMinimized { toplevel } => {
let window = window_from_handle(toplevel).unwrap();
state.unminimize(dh, &window);
},
zcosmic_toplevel_manager_v1::Request::SetRectangle { toplevel, surface, x, y, width, height } => {
}
zcosmic_toplevel_manager_v1::Request::SetRectangle {
toplevel,
surface,
x,
y,
width,
height,
} => {
let window = window_from_handle(toplevel).unwrap();
if let Some(toplevel_state) = window.user_data().get::<ToplevelState>() {
let mut toplevel_state = toplevel_state.lock().unwrap();
@ -178,11 +185,17 @@ where
if width == 0 && height == 0 {
toplevel_state.rectangles.remove(&client);
} else {
toplevel_state.rectangles.insert(client, (surface, Rectangle::from_loc_and_size((x, y), (width, height))));
toplevel_state.rectangles.insert(
client,
(
surface,
Rectangle::from_loc_and_size((x, y), (width, height)),
),
);
}
}
}
},
}
_ => unreachable!(),
}
}
@ -190,7 +203,11 @@ where
fn destroyed(state: &mut D, client: ClientId, resource: ObjectId, _data: &()) {
let mng_state = state.toplevel_management_state();
mng_state.instances.retain(|i| i.id() != resource);
if !mng_state.instances.iter().any(|i| i.client_id().map(|c| c == client).unwrap_or(false)) {
if !mng_state
.instances
.iter()
.any(|i| i.client_id().map(|c| c == client).unwrap_or(false))
{
for toplevel in state.toplevel_info_state_mut().toplevels.iter() {
if let Some(toplevel_state) = toplevel.user_data().get::<ToplevelState>() {
toplevel_state.lock().unwrap().rectangles.remove(&client);

View file

@ -1,15 +1,11 @@
// SPDX-License-Identifier: GPL-3.0-only
use std::{
collections::HashSet,
sync::Mutex,
};
use std::{collections::HashSet, sync::Mutex};
use smithay::{
reexports::wayland_server::{
backend::{ClientData, ClientId, GlobalId, ObjectId},
Client, DataInit, Dispatch, DisplayHandle,
GlobalDispatch, New, Resource,
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource,
},
wayland::output::Output,
};
@ -142,8 +138,7 @@ pub trait WorkspaceClientHandler {
fn workspace_state(&self) -> &WorkspaceClientState;
}
impl<D> GlobalDispatch<ZcosmicWorkspaceManagerV1, WorkspaceGlobalData, D>
for WorkspaceState<D>
impl<D> GlobalDispatch<ZcosmicWorkspaceManagerV1, WorkspaceGlobalData, D> for WorkspaceState<D>
where
D: GlobalDispatch<ZcosmicWorkspaceManagerV1, WorkspaceGlobalData>
+ Dispatch<ZcosmicWorkspaceManagerV1, ()>
@ -477,7 +472,7 @@ where
.map(|w| w.states.iter())
})
}
pub fn group_handle(
&self,
group: &ZcosmicWorkspaceGroupHandleV1,
@ -493,7 +488,11 @@ where
) -> Option<WorkspaceHandle> {
self.groups
.iter()
.find_map(|g| g.workspaces.iter().find(|w| w.instances.contains(workspace)))
.find_map(|g| {
g.workspaces
.iter()
.find(|w| w.instances.contains(workspace))
})
.map(|w| WorkspaceHandle { id: w.id })
}