mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2025-01-29 20:34:46 +01:00
Implement session lock
This commit is contained in:
parent
42f3e65255
commit
d708fccf58
11 changed files with 335 additions and 50 deletions
|
@ -33,7 +33,7 @@ use smithay::{
|
|||
use tracing::error;
|
||||
|
||||
use crate::{
|
||||
state::{Pinnacle, State, SurfaceDmabufFeedback},
|
||||
state::{Pinnacle, State, SurfaceDmabufFeedback, WithState},
|
||||
window::WindowElement,
|
||||
};
|
||||
|
||||
|
@ -248,6 +248,16 @@ pub fn post_repaint(
|
|||
if let CursorImageStatus::Surface(surf) = cursor_status {
|
||||
send_frames_surface_tree(surf, output, time, Some(Duration::ZERO), |_, _| None);
|
||||
}
|
||||
|
||||
if let Some(lock_surface) = output.with_state(|state| state.lock_surface.clone()) {
|
||||
send_frames_surface_tree(
|
||||
lock_surface.wl_surface(),
|
||||
output,
|
||||
time,
|
||||
Some(Duration::ZERO),
|
||||
|_, _| None,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl DmabufHandler for State {
|
||||
|
|
|
@ -32,7 +32,10 @@ use smithay::{
|
|||
renderer::{
|
||||
self, damage,
|
||||
element::{
|
||||
self, surface::WaylandSurfaceRenderElement, texture::TextureBuffer, Element,
|
||||
self,
|
||||
surface::{render_elements_from_surface_tree, WaylandSurfaceRenderElement},
|
||||
texture::TextureBuffer,
|
||||
Element,
|
||||
},
|
||||
gles::{GlesRenderbuffer, GlesRenderer},
|
||||
multigpu::{gbm::GbmGlesBackend, GpuManager, MultiRenderer, MultiTexture},
|
||||
|
@ -88,7 +91,7 @@ use tracing::{debug, error, info, trace, warn};
|
|||
use crate::{
|
||||
backend::Backend,
|
||||
config::ConnectorSavedState,
|
||||
output::OutputName,
|
||||
output::{BlankingState, OutputName},
|
||||
render::{
|
||||
pointer::PointerElement, pointer_render_elements, take_presentation_feedback,
|
||||
OutputRenderElement,
|
||||
|
@ -1312,6 +1315,13 @@ impl Udev {
|
|||
flags,
|
||||
);
|
||||
}
|
||||
|
||||
output.with_state_mut(|state| {
|
||||
if let BlankingState::Blanking = state.blanking_state {
|
||||
debug!("Output {} blanked", output.name());
|
||||
state.blanking_state = BlankingState::Blanked;
|
||||
}
|
||||
})
|
||||
}
|
||||
Err(err) => {
|
||||
warn!("Error during rendering: {:?}", err);
|
||||
|
@ -1399,8 +1409,6 @@ impl Udev {
|
|||
texture
|
||||
});
|
||||
|
||||
let windows = pinnacle.space.elements().cloned().collect::<Vec<_>>();
|
||||
|
||||
let pointer_location = pinnacle
|
||||
.seat
|
||||
.get_pointer()
|
||||
|
@ -1434,10 +1442,14 @@ impl Udev {
|
|||
|
||||
let mut output_render_elements = Vec::new();
|
||||
|
||||
let should_blank = pinnacle.lock_state.is_locking()
|
||||
|| (pinnacle.lock_state.is_locked()
|
||||
&& output.with_state(|state| state.lock_surface.is_none()));
|
||||
|
||||
// If there isn't a pending screencopy that doesn't want to overlay the cursor,
|
||||
// render it.
|
||||
match pending_screencopy_with_cursor {
|
||||
Some(include_cursor) => {
|
||||
Some(include_cursor) if !should_blank => {
|
||||
if include_cursor {
|
||||
// HACK: Doing `RenderFrameResult::blit_frame_result` with something on the
|
||||
// | cursor plane causes the cursor to overwrite the pixels underneath it,
|
||||
|
@ -1461,7 +1473,7 @@ impl Udev {
|
|||
output_render_elements.extend(pointer_render_elements);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
_ => {
|
||||
let pointer_render_elements = pointer_render_elements(
|
||||
output,
|
||||
&mut renderer,
|
||||
|
@ -1475,12 +1487,35 @@ impl Udev {
|
|||
}
|
||||
}
|
||||
|
||||
output_render_elements.extend(crate::render::output_render_elements(
|
||||
output,
|
||||
&mut renderer,
|
||||
&pinnacle.space,
|
||||
&windows,
|
||||
));
|
||||
if should_blank {
|
||||
// Don't push any render elements and we get a blank frame
|
||||
output.with_state_mut(|state| {
|
||||
if let BlankingState::NotBlanked = state.blanking_state {
|
||||
debug!("Blanking output {} for session lock", output.name());
|
||||
state.blanking_state = BlankingState::Blanking;
|
||||
}
|
||||
});
|
||||
} else if let Some(lock_surface) = output.with_state(|state| state.lock_surface.clone()) {
|
||||
let elems = render_elements_from_surface_tree(
|
||||
&mut renderer,
|
||||
lock_surface.wl_surface(),
|
||||
(0, 0),
|
||||
output.current_scale().fractional_scale(),
|
||||
1.0,
|
||||
element::Kind::Unspecified,
|
||||
);
|
||||
|
||||
output_render_elements.extend(elems);
|
||||
} else {
|
||||
let windows = pinnacle.space.elements().cloned().collect::<Vec<_>>();
|
||||
|
||||
output_render_elements.extend(crate::render::output_render_elements(
|
||||
output,
|
||||
&mut renderer,
|
||||
&pinnacle.space,
|
||||
&windows,
|
||||
));
|
||||
}
|
||||
|
||||
let result = (|| -> Result<bool, SwapBuffersError> {
|
||||
let render_frame_result = render_frame(
|
||||
|
@ -1496,13 +1531,15 @@ impl Udev {
|
|||
}
|
||||
}
|
||||
|
||||
handle_pending_screencopy(
|
||||
&mut renderer,
|
||||
output,
|
||||
surface,
|
||||
&render_frame_result,
|
||||
&pinnacle.loop_handle,
|
||||
);
|
||||
if pinnacle.lock_state.is_unlocked() {
|
||||
handle_pending_screencopy(
|
||||
&mut renderer,
|
||||
output,
|
||||
surface,
|
||||
&render_frame_result,
|
||||
&pinnacle.loop_handle,
|
||||
);
|
||||
}
|
||||
|
||||
super::post_repaint(
|
||||
output,
|
||||
|
|
|
@ -9,6 +9,7 @@ use smithay::{
|
|||
renderer::{
|
||||
self, buffer_type,
|
||||
damage::{self, OutputDamageTracker, RenderOutputResult},
|
||||
element::{self, surface::render_elements_from_surface_tree},
|
||||
gles::{GlesRenderbuffer, GlesRenderer, GlesTexture},
|
||||
Bind, Blit, BufferType, ExportMem, ImportDma, ImportEgl, ImportMemWl, Offscreen,
|
||||
TextureFilter,
|
||||
|
@ -37,9 +38,10 @@ use smithay::{
|
|||
utils::{IsAlive, Point, Rectangle, Transform},
|
||||
wayland::dmabuf::{self, DmabufFeedback, DmabufFeedbackBuilder, DmabufGlobal, DmabufState},
|
||||
};
|
||||
use tracing::{error, trace, warn};
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
use crate::{
|
||||
output::BlankingState,
|
||||
render::{pointer::PointerElement, pointer_render_elements, take_presentation_feedback},
|
||||
state::{Pinnacle, State, WithState},
|
||||
};
|
||||
|
@ -266,19 +268,20 @@ impl State {
|
|||
|
||||
let mut output_render_elements = Vec::new();
|
||||
|
||||
let pending_screencopy_without_cursor = output.with_state(|state| {
|
||||
state
|
||||
.screencopy
|
||||
.as_ref()
|
||||
.is_some_and(|sc| !sc.overlay_cursor())
|
||||
});
|
||||
let should_blank = self.pinnacle.lock_state.is_locking()
|
||||
|| (self.pinnacle.lock_state.is_locked()
|
||||
&& output.with_state(|state| state.lock_surface.is_none()));
|
||||
|
||||
// If there isn't a pending screencopy that doesn't want to overlay the cursor,
|
||||
// render it.
|
||||
//
|
||||
// This will cause the cursor to disappear for a frame if there is one though,
|
||||
// but it shouldn't meaningfully affect anything.
|
||||
if !pending_screencopy_without_cursor {
|
||||
let should_draw_cursor = !should_blank
|
||||
|| output.with_state(|state| {
|
||||
// Don't draw cursor when screencopy without cursor is pending
|
||||
!state
|
||||
.screencopy
|
||||
.as_ref()
|
||||
.is_some_and(|sc| !sc.overlay_cursor())
|
||||
});
|
||||
|
||||
if should_draw_cursor {
|
||||
let pointer_location = self
|
||||
.pinnacle
|
||||
.seat
|
||||
|
@ -298,12 +301,33 @@ impl State {
|
|||
output_render_elements.extend(pointer_render_elements);
|
||||
}
|
||||
|
||||
output_render_elements.extend(crate::render::output_render_elements(
|
||||
output,
|
||||
winit.backend.renderer(),
|
||||
&self.pinnacle.space,
|
||||
&windows,
|
||||
));
|
||||
if should_blank {
|
||||
// Don't push any render elements and we get a blank frame
|
||||
output.with_state_mut(|state| {
|
||||
if let BlankingState::NotBlanked = state.blanking_state {
|
||||
debug!("Blanking output {} for session lock", output.name());
|
||||
state.blanking_state = BlankingState::Blanking;
|
||||
}
|
||||
});
|
||||
} else if let Some(lock_surface) = output.with_state(|state| state.lock_surface.clone()) {
|
||||
let elems = render_elements_from_surface_tree(
|
||||
winit.backend.renderer(),
|
||||
lock_surface.wl_surface(),
|
||||
(0, 0),
|
||||
output.current_scale().fractional_scale(),
|
||||
1.0,
|
||||
element::Kind::Unspecified,
|
||||
);
|
||||
|
||||
output_render_elements.extend(elems);
|
||||
} else {
|
||||
output_render_elements.extend(crate::render::output_render_elements(
|
||||
output,
|
||||
winit.backend.renderer(),
|
||||
&self.pinnacle.space,
|
||||
&windows,
|
||||
));
|
||||
}
|
||||
|
||||
let render_res = winit.backend.bind().and_then(|_| {
|
||||
let age = if *full_redraw > 0 {
|
||||
|
@ -325,17 +349,30 @@ impl State {
|
|||
|
||||
match render_res {
|
||||
Ok(render_output_result) => {
|
||||
Winit::handle_pending_screencopy(
|
||||
&mut winit.backend,
|
||||
output,
|
||||
&render_output_result,
|
||||
&self.pinnacle.loop_handle,
|
||||
);
|
||||
if self.pinnacle.lock_state.is_unlocked() {
|
||||
Winit::handle_pending_screencopy(
|
||||
&mut winit.backend,
|
||||
output,
|
||||
&render_output_result,
|
||||
&self.pinnacle.loop_handle,
|
||||
);
|
||||
}
|
||||
|
||||
let has_rendered = render_output_result.damage.is_some();
|
||||
if let Some(damage) = render_output_result.damage {
|
||||
if let Err(err) = winit.backend.submit(Some(damage)) {
|
||||
error!("Failed to submit buffer: {}", err);
|
||||
match winit.backend.submit(Some(damage)) {
|
||||
Ok(()) => {
|
||||
output.with_state_mut(|state| {
|
||||
if matches!(state.blanking_state, BlankingState::Blanking) {
|
||||
// TODO: this is probably wrong
|
||||
debug!("Output {} blanked", output.name());
|
||||
state.blanking_state = BlankingState::Blanked;
|
||||
}
|
||||
});
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Failed to submit buffer: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use smithay::{
|
|||
},
|
||||
reexports::wayland_server::{protocol::wl_surface::WlSurface, Resource},
|
||||
utils::{IsAlive, Serial},
|
||||
wayland::seat::WaylandFocus,
|
||||
wayland::{seat::WaylandFocus, session_lock::LockSurface},
|
||||
};
|
||||
|
||||
use crate::{state::State, window::WindowElement};
|
||||
|
@ -18,6 +18,7 @@ pub enum KeyboardFocusTarget {
|
|||
Window(WindowElement),
|
||||
Popup(PopupKind),
|
||||
LayerSurface(LayerSurface),
|
||||
LockSurface(LockSurface),
|
||||
}
|
||||
|
||||
impl KeyboardTarget<State> for KeyboardFocusTarget {
|
||||
|
@ -38,6 +39,9 @@ impl KeyboardTarget<State> for KeyboardFocusTarget {
|
|||
KeyboardFocusTarget::LayerSurface(surf) => {
|
||||
KeyboardTarget::enter(surf.wl_surface(), seat, data, keys, serial);
|
||||
}
|
||||
KeyboardFocusTarget::LockSurface(lock) => {
|
||||
KeyboardTarget::enter(lock.wl_surface(), seat, data, keys, serial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,6 +56,9 @@ impl KeyboardTarget<State> for KeyboardFocusTarget {
|
|||
KeyboardFocusTarget::LayerSurface(surf) => {
|
||||
KeyboardTarget::leave(surf.wl_surface(), seat, data, serial)
|
||||
}
|
||||
KeyboardFocusTarget::LockSurface(lock) => {
|
||||
KeyboardTarget::leave(lock.wl_surface(), seat, data, serial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +67,7 @@ impl KeyboardTarget<State> for KeyboardFocusTarget {
|
|||
seat: &Seat<State>,
|
||||
data: &mut State,
|
||||
key: KeysymHandle<'_>,
|
||||
state: smithay::backend::input::KeyState,
|
||||
state: KeyState,
|
||||
serial: Serial,
|
||||
time: u32,
|
||||
) {
|
||||
|
@ -74,6 +81,9 @@ impl KeyboardTarget<State> for KeyboardFocusTarget {
|
|||
KeyboardFocusTarget::LayerSurface(surf) => {
|
||||
KeyboardTarget::key(surf.wl_surface(), seat, data, key, state, serial, time);
|
||||
}
|
||||
KeyboardFocusTarget::LockSurface(lock) => {
|
||||
KeyboardTarget::key(lock.wl_surface(), seat, data, key, state, serial, time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,7 +91,7 @@ impl KeyboardTarget<State> for KeyboardFocusTarget {
|
|||
&self,
|
||||
seat: &Seat<State>,
|
||||
data: &mut State,
|
||||
modifiers: smithay::input::keyboard::ModifiersState,
|
||||
modifiers: ModifiersState,
|
||||
serial: Serial,
|
||||
) {
|
||||
match self {
|
||||
|
@ -94,6 +104,9 @@ impl KeyboardTarget<State> for KeyboardFocusTarget {
|
|||
KeyboardFocusTarget::LayerSurface(surf) => {
|
||||
KeyboardTarget::modifiers(surf.wl_surface(), seat, data, modifiers, serial);
|
||||
}
|
||||
KeyboardFocusTarget::LockSurface(lock) => {
|
||||
KeyboardTarget::modifiers(lock.wl_surface(), seat, data, modifiers, serial);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,6 +117,7 @@ impl IsAlive for KeyboardFocusTarget {
|
|||
KeyboardFocusTarget::Window(window) => window.alive(),
|
||||
KeyboardFocusTarget::Popup(popup) => popup.alive(),
|
||||
KeyboardFocusTarget::LayerSurface(surf) => surf.alive(),
|
||||
KeyboardFocusTarget::LockSurface(lock) => lock.alive(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -114,6 +128,7 @@ impl WaylandFocus for KeyboardFocusTarget {
|
|||
KeyboardFocusTarget::Window(window) => window.wl_surface(),
|
||||
KeyboardFocusTarget::Popup(popup) => Some(popup.wl_surface().clone()),
|
||||
KeyboardFocusTarget::LayerSurface(surf) => Some(surf.wl_surface().clone()),
|
||||
KeyboardFocusTarget::LockSurface(lock) => Some(lock.wl_surface().clone()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,6 +142,9 @@ impl WaylandFocus for KeyboardFocusTarget {
|
|||
KeyboardFocusTarget::LayerSurface(surf) => {
|
||||
surf.wl_surface().id().same_client_as(object_id)
|
||||
}
|
||||
KeyboardFocusTarget::LockSurface(lock) => {
|
||||
lock.wl_surface().id().same_client_as(object_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -414,6 +414,9 @@ impl From<KeyboardFocusTarget> for PointerFocusTarget {
|
|||
KeyboardFocusTarget::LayerSurface(layer) => {
|
||||
PointerFocusTarget::WlSurface(layer.wl_surface().clone())
|
||||
}
|
||||
KeyboardFocusTarget::LockSurface(lock) => {
|
||||
PointerFocusTarget::WlSurface(lock.wl_surface().clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
pub mod session_lock;
|
||||
mod xdg_shell;
|
||||
mod xwayland;
|
||||
|
||||
|
@ -260,6 +261,21 @@ impl CompositorHandler for State {
|
|||
.cloned()
|
||||
{
|
||||
vec![output] // surface is a layer surface
|
||||
} else if let Some(output) = self
|
||||
.pinnacle
|
||||
.space
|
||||
.outputs()
|
||||
.find(|op| {
|
||||
op.with_state(|state| {
|
||||
state
|
||||
.lock_surface
|
||||
.as_ref()
|
||||
.is_some_and(|lock| lock.wl_surface() == surface)
|
||||
})
|
||||
})
|
||||
.cloned()
|
||||
{
|
||||
vec![output]
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
|
129
src/handlers/session_lock.rs
Normal file
129
src/handlers/session_lock.rs
Normal file
|
@ -0,0 +1,129 @@
|
|||
use smithay::{
|
||||
delegate_session_lock,
|
||||
output::Output,
|
||||
reexports::wayland_server::protocol::wl_output::WlOutput,
|
||||
utils::SERIAL_COUNTER,
|
||||
wayland::session_lock::{
|
||||
LockSurface, SessionLockHandler, SessionLockManagerState, SessionLocker,
|
||||
},
|
||||
};
|
||||
use tracing::{debug, warn};
|
||||
|
||||
use crate::{
|
||||
focus::keyboard::KeyboardFocusTarget,
|
||||
output::BlankingState,
|
||||
state::{State, WithState},
|
||||
};
|
||||
|
||||
/// State of a session lock.
|
||||
#[derive(Default, Debug)]
|
||||
pub enum LockState {
|
||||
/// There is no session lock.
|
||||
#[default]
|
||||
Unlocked,
|
||||
/// A session lock request came in and we are in the process of blanking outputs.
|
||||
Locking(SessionLocker),
|
||||
/// The session is locked.
|
||||
Locked,
|
||||
}
|
||||
|
||||
impl LockState {
|
||||
/// Returns `true` if the lock state is [`Locking`].
|
||||
///
|
||||
/// [`Locking`]: LockState::Locking
|
||||
#[must_use]
|
||||
pub fn is_locking(&self) -> bool {
|
||||
matches!(self, Self::Locking(..))
|
||||
}
|
||||
|
||||
/// Returns `true` if the lock state is [`Unlocked`].
|
||||
///
|
||||
/// [`Unlocked`]: LockState::Unlocked
|
||||
#[must_use]
|
||||
pub fn is_unlocked(&self) -> bool {
|
||||
matches!(self, Self::Unlocked)
|
||||
}
|
||||
|
||||
/// Returns `true` if the lock state is [`Locked`].
|
||||
///
|
||||
/// [`Locked`]: LockState::Locked
|
||||
#[must_use]
|
||||
pub fn is_locked(&self) -> bool {
|
||||
matches!(self, Self::Locked)
|
||||
}
|
||||
}
|
||||
|
||||
impl SessionLockHandler for State {
|
||||
fn lock_state(&mut self) -> &mut SessionLockManagerState {
|
||||
&mut self.pinnacle.session_lock_manager_state
|
||||
}
|
||||
|
||||
fn lock(&mut self, confirmation: SessionLocker) {
|
||||
debug!("Received session lock request");
|
||||
self.pinnacle.lock_state = LockState::Locking(confirmation);
|
||||
self.pinnacle.schedule(
|
||||
|state| {
|
||||
let all_outputs_blanked = state.pinnacle.space.outputs().all(|op| {
|
||||
op.with_state(|st| matches!(st.blanking_state, BlankingState::Blanked))
|
||||
});
|
||||
!state.pinnacle.lock_state.is_locking() || all_outputs_blanked
|
||||
},
|
||||
|state| match std::mem::take(&mut state.pinnacle.lock_state) {
|
||||
LockState::Unlocked => (),
|
||||
LockState::Locking(locker) => {
|
||||
debug!("Locking session");
|
||||
locker.lock();
|
||||
state.pinnacle.lock_state = LockState::Locked;
|
||||
for output in state.pinnacle.space.outputs().cloned().collect::<Vec<_>>() {
|
||||
state.schedule_render(&output);
|
||||
}
|
||||
}
|
||||
LockState::Locked => state.pinnacle.lock_state = LockState::Locked,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn unlock(&mut self) {
|
||||
debug!("Session lock unlocked");
|
||||
for output in self.pinnacle.space.outputs() {
|
||||
output.with_state_mut(|state| {
|
||||
state.lock_surface.take();
|
||||
state.blanking_state = BlankingState::NotBlanked;
|
||||
});
|
||||
}
|
||||
self.pinnacle.lock_state = LockState::Unlocked;
|
||||
}
|
||||
|
||||
fn new_surface(&mut self, surface: LockSurface, output: WlOutput) {
|
||||
let Some(output) = Output::from_resource(&output) else {
|
||||
warn!(
|
||||
"Session lock surface received but output doesn't exist for wl_output {output:?}"
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
||||
debug!("Session lock surface received for output {}", output.name());
|
||||
|
||||
let Some(geo) = self.pinnacle.space.output_geometry(&output) else {
|
||||
return;
|
||||
};
|
||||
|
||||
surface.with_pending_state(|state| {
|
||||
state.size = Some((geo.size.w as u32, geo.size.h as u32).into())
|
||||
});
|
||||
surface.send_configure();
|
||||
|
||||
if let Some(keyboard) = self.pinnacle.seat.get_keyboard() {
|
||||
keyboard.set_focus(
|
||||
self,
|
||||
Some(KeyboardFocusTarget::LockSurface(surface.clone())),
|
||||
SERIAL_COUNTER.next_serial(),
|
||||
);
|
||||
}
|
||||
|
||||
output.with_state_mut(|state| state.lock_surface.replace(surface));
|
||||
|
||||
self.schedule_render(&output);
|
||||
}
|
||||
}
|
||||
delegate_session_lock!(State);
|
|
@ -185,6 +185,13 @@ impl Pinnacle {
|
|||
.output_geometry(output)
|
||||
.expect("called output_geometry on unmapped output");
|
||||
|
||||
if let Some(lock_surface) = output.with_state(|state| state.lock_surface.clone()) {
|
||||
return Some((
|
||||
PointerFocusTarget::WlSurface(lock_surface.wl_surface().clone()),
|
||||
output_geo.loc,
|
||||
));
|
||||
}
|
||||
|
||||
let mut fullscreen_and_up_split_at = 0;
|
||||
|
||||
for (i, win) in self
|
||||
|
|
|
@ -7,6 +7,7 @@ use smithay::{
|
|||
desktop::layer_map_for_output,
|
||||
output::{Mode, Output, Scale},
|
||||
utils::{Logical, Point, Transform},
|
||||
wayland::session_lock::LockSurface,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
@ -34,6 +35,18 @@ impl OutputName {
|
|||
}
|
||||
}
|
||||
|
||||
/// State of an output's blanking status for session lock.
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub enum BlankingState {
|
||||
/// The output is not blanked and is displaying normal content.
|
||||
#[default]
|
||||
NotBlanked,
|
||||
/// A blank frame has been queued up.
|
||||
Blanking,
|
||||
/// A blank frame has been displayed.
|
||||
Blanked,
|
||||
}
|
||||
|
||||
/// The state of an output
|
||||
#[derive(Default, Debug)]
|
||||
pub struct OutputState {
|
||||
|
@ -42,6 +55,8 @@ pub struct OutputState {
|
|||
pub screencopy: Option<Screencopy>,
|
||||
pub serial: Option<NonZeroU32>,
|
||||
pub modes: Vec<Mode>,
|
||||
pub lock_surface: Option<LockSurface>,
|
||||
pub blanking_state: BlankingState,
|
||||
}
|
||||
|
||||
impl WithState for Output {
|
||||
|
|
|
@ -5,6 +5,7 @@ use std::{ops::Deref, sync::Mutex};
|
|||
use smithay::{
|
||||
backend::renderer::{
|
||||
element::{
|
||||
solid::SolidColorRenderElement,
|
||||
surface::WaylandSurfaceRenderElement,
|
||||
utils::{CropRenderElement, RelocateRenderElement, RescaleRenderElement},
|
||||
AsRenderElements, RenderElementStates, Wrap,
|
||||
|
@ -51,6 +52,7 @@ render_elements! {
|
|||
Surface = WaylandSurfaceRenderElement<R>,
|
||||
Pointer = PointerRenderElement<R>,
|
||||
Transform = TransformRenderElement<R, E>,
|
||||
Color = SolidColorRenderElement,
|
||||
}
|
||||
|
||||
impl<R> AsRenderElements<R> for WindowElement
|
||||
|
|
11
src/state.rs
11
src/state.rs
|
@ -7,6 +7,7 @@ use crate::{
|
|||
config::Config,
|
||||
focus::OutputFocusStack,
|
||||
grab::resize_grab::ResizeSurfaceState,
|
||||
handlers::session_lock::LockState,
|
||||
layout::LayoutState,
|
||||
protocol::{
|
||||
foreign_toplevel::{self, ForeignToplevelManagerState},
|
||||
|
@ -41,6 +42,7 @@ use smithay::{
|
|||
data_device::DataDeviceState, primary_selection::PrimarySelectionState,
|
||||
wlr_data_control::DataControlState,
|
||||
},
|
||||
session_lock::SessionLockManagerState,
|
||||
shell::{wlr_layer::WlrLayerShellState, xdg::XdgShellState},
|
||||
shm::ShmState,
|
||||
socket::ListeningSocketSource,
|
||||
|
@ -94,6 +96,9 @@ pub struct Pinnacle {
|
|||
pub relative_pointer_manager_state: RelativePointerManagerState,
|
||||
pub pointer_constraints_state: PointerConstraintsState,
|
||||
pub foreign_toplevel_manager_state: ForeignToplevelManagerState,
|
||||
pub session_lock_manager_state: SessionLockManagerState,
|
||||
|
||||
pub lock_state: LockState,
|
||||
|
||||
/// The state of key and mousebinds along with libinput settings
|
||||
pub input_state: InputState,
|
||||
|
@ -262,6 +267,12 @@ impl Pinnacle {
|
|||
&display_handle,
|
||||
filter_restricted_client,
|
||||
),
|
||||
session_lock_manager_state: SessionLockManagerState::new::<State, _>(
|
||||
&display_handle,
|
||||
filter_restricted_client,
|
||||
),
|
||||
|
||||
lock_state: LockState::default(),
|
||||
|
||||
input_state: InputState::new(),
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue