Handle session lock surfaces in visible_outputs_for_surface

Fixes issue with re-draw not being queued on initial surface commit
until cursor is moved.
This commit is contained in:
Ian Douglas Scott 2023-11-14 13:13:42 -08:00 committed by Victoria Brekenfeld
parent 14867a0893
commit 440cd03371
6 changed files with 49 additions and 41 deletions

View file

@ -13,9 +13,10 @@ use crate::debug::{fps_ui, profiler_ui};
use crate::{ use crate::{
shell::{ shell::{
focus::target::WindowGroup, grabs::SeatMoveGrabState, layout::tiling::ANIMATION_DURATION, focus::target::WindowGroup, grabs::SeatMoveGrabState, layout::tiling::ANIMATION_DURATION,
CosmicMapped, CosmicMappedRenderElement, OverviewMode, Trigger, WorkspaceRenderElement, CosmicMapped, CosmicMappedRenderElement, OverviewMode, SessionLock, Trigger,
WorkspaceRenderElement,
}, },
state::{Common, Fps, SessionLock}, state::{Common, Fps},
utils::prelude::*, utils::prelude::*,
wayland::{ wayland::{
handlers::{ handlers::{
@ -487,7 +488,7 @@ where
} }
// If session locked, only show session lock surfaces // If session locked, only show session lock surfaces
if let Some(session_lock) = &state.session_lock { if let Some(session_lock) = &state.shell.session_lock {
elements.extend( elements.extend(
session_lock_elements(renderer, output, session_lock) session_lock_elements(renderer, output, session_lock)
.into_iter() .into_iter()

View file

@ -10,10 +10,10 @@ use crate::{
floating::ResizeGrabMarker, floating::ResizeGrabMarker,
tiling::{SwapWindowGrab, TilingLayout}, tiling::{SwapWindowGrab, TilingLayout},
}, },
Direction, FocusResult, MoveResult, OverviewMode, ResizeDirection, ResizeMode, Trigger, Direction, FocusResult, MoveResult, OverviewMode, ResizeDirection, ResizeMode, SessionLock,
Workspace, Trigger, Workspace,
}, },
state::{Common, SessionLock}, state::Common,
utils::prelude::*, utils::prelude::*,
wayland::{ wayland::{
handlers::{screencopy::ScreencopySessions, xdg_activation::ActivationContext}, handlers::{screencopy::ScreencopySessions, xdg_activation::ActivationContext},
@ -569,7 +569,7 @@ impl State {
&self.common.shell.override_redirect_windows, &self.common.shell.override_redirect_windows,
overview.0.clone(), overview.0.clone(),
workspace, workspace,
self.common.session_lock.as_ref(), self.common.shell.session_lock.as_ref(),
) )
.map(|(target, pos)| (target, pos.as_logical())); .map(|(target, pos)| (target, pos.as_logical()));
@ -651,7 +651,7 @@ impl State {
&self.common.shell.override_redirect_windows, &self.common.shell.override_redirect_windows,
overview.0, overview.0,
workspace, workspace,
self.common.session_lock.as_ref(), self.common.shell.session_lock.as_ref(),
) )
.map(|(target, pos)| (target, pos.as_logical())); .map(|(target, pos)| (target, pos.as_logical()));
@ -777,7 +777,7 @@ impl State {
&self.common.shell.override_redirect_windows, &self.common.shell.override_redirect_windows,
overview.0, overview.0,
workspace, workspace,
self.common.session_lock.as_ref(), self.common.shell.session_lock.as_ref(),
) )
.map(|(target, pos)| (target, pos.as_logical())); .map(|(target, pos)| (target, pos.as_logical()));
@ -843,18 +843,20 @@ impl State {
&& !seat.get_keyboard().map(|k| k.is_grabbed()).unwrap_or(false) && !seat.get_keyboard().map(|k| k.is_grabbed()).unwrap_or(false)
{ {
let output = seat.active_output(); let output = seat.active_output();
let pos = seat.get_pointer().unwrap().current_location().as_global(); let pos = seat.get_pointer().unwrap().current_location().as_global();
let relative_pos = pos.to_local(&output); let relative_pos = pos.to_local(&output);
let overview = self.common.shell.overview_mode(); let overview = self.common.shell.overview_mode();
let workspace = self.common.shell.active_space_mut(&output);
let mut under = None; let mut under = None;
if let Some(session_lock) = self.common.session_lock.as_ref() { if let Some(session_lock) = self.common.shell.session_lock.as_ref() {
under = session_lock under = session_lock
.surfaces .surfaces
.get(&output) .get(&output)
.map(|lock| lock.clone().into()); .map(|lock| lock.clone().into());
} else if let Some(window) = workspace.get_fullscreen() { } else if let Some(window) =
self.common.shell.active_space(&output).get_fullscreen()
{
let layers = layer_map_for_output(&output); let layers = layer_map_for_output(&output);
if let Some(layer) = if let Some(layer) =
layers.layer_under(WlrLayer::Overlay, relative_pos.as_logical()) layers.layer_under(WlrLayer::Overlay, relative_pos.as_logical())
@ -874,6 +876,7 @@ impl State {
under = Some(window.clone().into()); under = Some(window.clone().into());
} }
} else { } else {
let workspace = self.common.shell.active_space_mut(&output);
let done = { let done = {
let layers = layer_map_for_output(&output); let layers = layer_map_for_output(&output);
if let Some(layer) = layers if let Some(layer) = layers
@ -1157,7 +1160,7 @@ impl State {
) { ) {
// TODO: Detect if started from login manager or tty, and only allow // TODO: Detect if started from login manager or tty, and only allow
// `Terminate` if it will return to login manager. // `Terminate` if it will return to login manager.
if self.common.session_lock.is_some() if self.common.shell.session_lock.is_some()
&& !matches!(action, Action::Terminate | Action::Debug) && !matches!(action, Action::Terminate | Action::Debug)
{ {
return; return;

View file

@ -308,7 +308,7 @@ fn focus_target_is_valid(
target: KeyboardFocusTarget, target: KeyboardFocusTarget,
) -> bool { ) -> bool {
// If a session lock is active, only lock surfaces can be focused // If a session lock is active, only lock surfaces can be focused
if state.common.session_lock.is_some() { if state.common.shell.session_lock.is_some() {
return matches!(target, KeyboardFocusTarget::LockSurface(_)); return matches!(target, KeyboardFocusTarget::LockSurface(_));
} }
@ -361,7 +361,7 @@ fn update_focus_target(
seat: &Seat<State>, seat: &Seat<State>,
output: &Output, output: &Output,
) -> Option<KeyboardFocusTarget> { ) -> Option<KeyboardFocusTarget> {
if let Some(session_lock) = &state.common.session_lock { if let Some(session_lock) = &state.common.shell.session_lock {
session_lock session_lock
.surfaces .surfaces
.get(output) .get(output)

View file

@ -19,11 +19,15 @@ use smithay::{
Seat, Seat,
}, },
output::Output, output::Output,
reexports::wayland_server::{protocol::wl_surface::WlSurface, Client, DisplayHandle}, reexports::{
wayland_protocols::ext::session_lock::v1::server::ext_session_lock_v1::ExtSessionLockV1,
wayland_server::{protocol::wl_surface::WlSurface, Client, DisplayHandle},
},
utils::{Point, Rectangle, Serial, SERIAL_COUNTER}, utils::{Point, Rectangle, Serial, SERIAL_COUNTER},
wayland::{ wayland::{
compositor::with_states, compositor::with_states,
seat::WaylandFocus, seat::WaylandFocus,
session_lock::LockSurface,
shell::{ shell::{
wlr_layer::{ wlr_layer::{
KeyboardInteractivity, Layer, LayerSurfaceCachedState, WlrLayerShellState, KeyboardInteractivity, Layer, LayerSurfaceCachedState, WlrLayerShellState,
@ -175,6 +179,7 @@ pub struct Shell {
pub pending_layers: Vec<(LayerSurface, Output, Seat<State>)>, pub pending_layers: Vec<(LayerSurface, Output, Seat<State>)>,
pub pending_activations: HashMap<ActivationKey, ActivationContext>, pub pending_activations: HashMap<ActivationKey, ActivationContext>,
pub override_redirect_windows: Vec<X11Surface>, pub override_redirect_windows: Vec<X11Surface>,
pub session_lock: Option<SessionLock>,
// wayland_state // wayland_state
pub layer_shell_state: WlrLayerShellState, pub layer_shell_state: WlrLayerShellState,
@ -199,6 +204,12 @@ pub struct Shell {
resize_indicator: Option<ResizeIndicator>, resize_indicator: Option<ResizeIndicator>,
} }
#[derive(Debug)]
pub struct SessionLock {
pub ext_session_lock: ExtSessionLockV1,
pub surfaces: HashMap<Output, LockSurface>,
}
#[derive(Debug)] #[derive(Debug)]
pub struct WorkspaceSet { pub struct WorkspaceSet {
previously_active: Option<(usize, Instant)>, previously_active: Option<(usize, Instant)>,
@ -916,6 +927,7 @@ impl Shell {
pending_layers: Vec::new(), pending_layers: Vec::new(),
pending_activations: HashMap::new(), pending_activations: HashMap::new(),
override_redirect_windows: Vec::new(), override_redirect_windows: Vec::new(),
session_lock: None,
layer_shell_state, layer_shell_state,
toplevel_info_state, toplevel_info_state,
@ -1015,6 +1027,15 @@ impl Shell {
&'a self, &'a self,
surface: &'a WlSurface, surface: &'a WlSurface,
) -> impl Iterator<Item = Output> + 'a { ) -> impl Iterator<Item = Output> + 'a {
if let Some(session_lock) = &self.session_lock {
let output = session_lock
.surfaces
.iter()
.find(|(_, v)| v.wl_surface() == surface)
.map(|(k, _)| k.clone());
return Box::new(output.into_iter()) as Box<dyn Iterator<Item = Output>>;
}
match self match self
.outputs() .outputs()
.find(|o| { .find(|o| {

View file

@ -50,7 +50,6 @@ use smithay::{
output::{Mode as OutputMode, Output, Scale}, output::{Mode as OutputMode, Output, Scale},
reexports::{ reexports::{
calloop::{LoopHandle, LoopSignal}, calloop::{LoopHandle, LoopSignal},
wayland_protocols::ext::session_lock::v1::server::ext_session_lock_v1::ExtSessionLockV1,
wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration_manager::Mode, wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration_manager::Mode,
wayland_server::{ wayland_server::{
backend::{ClientData, ClientId, DisconnectReason}, backend::{ClientData, ClientId, DisconnectReason},
@ -75,7 +74,7 @@ use smithay::{
data_device::DataDeviceState, primary_selection::PrimarySelectionState, data_device::DataDeviceState, primary_selection::PrimarySelectionState,
wlr_data_control::DataControlState, wlr_data_control::DataControlState,
}, },
session_lock::{LockSurface, SessionLockManagerState}, session_lock::SessionLockManagerState,
shell::{kde::decoration::KdeDecorationState, xdg::decoration::XdgDecorationState}, shell::{kde::decoration::KdeDecorationState, xdg::decoration::XdgDecorationState},
shm::ShmState, shm::ShmState,
text_input::TextInputManagerState, text_input::TextInputManagerState,
@ -87,10 +86,7 @@ use smithay::{
use tracing::error; use tracing::error;
use std::{cell::RefCell, ffi::OsString, time::Duration}; use std::{cell::RefCell, ffi::OsString, time::Duration};
use std::{ use std::{collections::VecDeque, time::Instant};
collections::{HashMap, VecDeque},
time::Instant,
};
#[derive(RustEmbed)] #[derive(RustEmbed)]
#[folder = "resources/i18n"] #[folder = "resources/i18n"]
@ -173,8 +169,6 @@ pub struct Common {
pub kde_decoration_state: KdeDecorationState, pub kde_decoration_state: KdeDecorationState,
pub xdg_decoration_state: XdgDecorationState, pub xdg_decoration_state: XdgDecorationState,
pub session_lock: Option<SessionLock>,
// xwayland state // xwayland state
pub xwayland_state: Option<XWaylandState>, pub xwayland_state: Option<XWaylandState>,
} }
@ -195,12 +189,6 @@ pub struct SurfaceDmabufFeedback {
pub scanout_feedback: DmabufFeedback, pub scanout_feedback: DmabufFeedback,
} }
#[derive(Debug)]
pub struct SessionLock {
pub ext_session_lock: ExtSessionLockV1,
pub surfaces: HashMap<Output, LockSurface>,
}
impl BackendData { impl BackendData {
pub fn kms(&mut self) -> &mut KmsState { pub fn kms(&mut self) -> &mut KmsState {
match self { match self {
@ -414,8 +402,6 @@ impl State {
kde_decoration_state, kde_decoration_state,
xdg_decoration_state, xdg_decoration_state,
session_lock: None,
xwayland_state: None, xwayland_state: None,
}, },
backend: BackendData::Unset, backend: BackendData::Unset,
@ -515,7 +501,7 @@ impl Common {
let time = self.clock.now(); let time = self.clock.now();
let throttle = Some(Duration::from_secs(1)); let throttle = Some(Duration::from_secs(1));
if let Some(session_lock) = self.session_lock.as_ref() { if let Some(session_lock) = self.shell.session_lock.as_ref() {
if let Some(lock_surface) = session_lock.surfaces.get(output) { if let Some(lock_surface) = session_lock.surfaces.get(output) {
with_surfaces_surface_tree(lock_surface.wl_surface(), |_surface, states| { with_surfaces_surface_tree(lock_surface.wl_surface(), |_surface, states| {
with_fractional_scale(states, |fraction_scale| { with_fractional_scale(states, |fraction_scale| {

View file

@ -1,9 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use crate::{ use crate::{shell::SessionLock, state::State, utils::prelude::*};
state::{SessionLock, State},
utils::prelude::*,
};
use smithay::{ use smithay::{
delegate_session_lock, delegate_session_lock,
output::Output, output::Output,
@ -22,7 +19,7 @@ impl SessionLockHandler for State {
fn lock(&mut self, locker: SessionLocker) { fn lock(&mut self, locker: SessionLocker) {
// Reject lock if sesion lock exists and is still valid // Reject lock if sesion lock exists and is still valid
if let Some(session_lock) = self.common.session_lock.as_ref() { if let Some(session_lock) = self.common.shell.session_lock.as_ref() {
if self if self
.common .common
.display_handle .display_handle
@ -35,18 +32,18 @@ impl SessionLockHandler for State {
let ext_session_lock = locker.ext_session_lock().clone(); let ext_session_lock = locker.ext_session_lock().clone();
locker.lock(); locker.lock();
self.common.session_lock = Some(SessionLock { self.common.shell.session_lock = Some(SessionLock {
ext_session_lock, ext_session_lock,
surfaces: HashMap::new(), surfaces: HashMap::new(),
}); });
} }
fn unlock(&mut self) { fn unlock(&mut self) {
self.common.session_lock = None; self.common.shell.session_lock = None;
} }
fn new_surface(&mut self, lock_surface: LockSurface, wl_output: WlOutput) { fn new_surface(&mut self, lock_surface: LockSurface, wl_output: WlOutput) {
if let Some(session_lock) = &mut self.common.session_lock { if let Some(session_lock) = &mut self.common.shell.session_lock {
if let Some(output) = Output::from_resource(&wl_output) { if let Some(output) = Output::from_resource(&wl_output) {
lock_surface.with_pending_state(|states| { lock_surface.with_pending_state(|states| {
let size = output.geometry().size; let size = output.geometry().size;