merge: epoch-1.9.0 d'upstream
# Conflicts: # Cargo.lock
This commit is contained in:
commit
51c6cfedf6
11 changed files with 560 additions and 1056 deletions
|
|
@ -2,12 +2,18 @@ use crate::{
|
|||
shell::{CosmicSurface, MinimizedWindow, Shell, Trigger, element::CosmicMapped},
|
||||
state::{Common, State},
|
||||
utils::prelude::*,
|
||||
wayland::handlers::{xdg_shell::PopupGrabData, xwayland_keyboard_grab::XWaylandGrabSeatData},
|
||||
wayland::{
|
||||
handlers::{xdg_shell::PopupGrabData, xwayland_keyboard_grab::XWaylandGrabSeatData},
|
||||
protocols::session_lock_layer::layer_show_on_lock,
|
||||
},
|
||||
};
|
||||
use indexmap::IndexSet;
|
||||
use smithay::{
|
||||
backend::input::InputTime,
|
||||
desktop::{PopupUngrabStrategy, layer_map_for_output},
|
||||
desktop::{
|
||||
LayerSurface, PopupUngrabStrategy, WindowSurfaceType, find_popup_root_surface,
|
||||
layer_map_for_output,
|
||||
},
|
||||
input::{Seat, pointer::MotionEvent},
|
||||
output::Output,
|
||||
reexports::wayland_server::{Resource, protocol::wl_surface::WlSurface},
|
||||
|
|
@ -627,19 +633,42 @@ fn focus_target_is_valid(
|
|||
output: &Output,
|
||||
target: KeyboardFocusTarget,
|
||||
) -> bool {
|
||||
// If a session lock is active, only lock surfaces can be focused
|
||||
// If a session lock is active, only lock surfaces and lock layers can be focused
|
||||
if shell.session_lock.is_some() {
|
||||
if let KeyboardFocusTarget::LayerSurface(layer) = &target {
|
||||
return layer_show_on_lock(layer.wl_surface());
|
||||
} else if let KeyboardFocusTarget::Popup(popup) = &target
|
||||
&& let Ok(root) = find_popup_root_surface(popup)
|
||||
{
|
||||
return layer_show_on_lock(&root);
|
||||
}
|
||||
return matches!(target, KeyboardFocusTarget::LockSurface(_));
|
||||
}
|
||||
|
||||
// If an exclusive layer shell surface exists (on any output), only exclusive
|
||||
// shell surfaces can have focus, on the highest layer with exclusive surfaces.
|
||||
// Popups are judged by their root surface, so an exclusive surface can
|
||||
// still open grabbing popups (menus, dropdowns, context menus).
|
||||
if let Some(layer) = exclusive_layer_surface_layer(shell) {
|
||||
return if let KeyboardFocusTarget::LayerSurface(layer_surface) = target {
|
||||
let is_exclusive_on_layer = |layer_surface: &LayerSurface| {
|
||||
let data = layer_surface.cached_state();
|
||||
(data.keyboard_interactivity, data.layer) == (KeyboardInteractivity::Exclusive, layer)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
return match target {
|
||||
KeyboardFocusTarget::LayerSurface(layer_surface) => {
|
||||
is_exclusive_on_layer(&layer_surface)
|
||||
}
|
||||
KeyboardFocusTarget::Popup(popup) => find_popup_root_surface(&popup)
|
||||
.ok()
|
||||
.and_then(|root| {
|
||||
shell.outputs().find_map(|o| {
|
||||
layer_map_for_output(o)
|
||||
.layer_for_surface(&root, WindowSurfaceType::ALL)
|
||||
.map(&is_exclusive_on_layer)
|
||||
})
|
||||
})
|
||||
.unwrap_or(false),
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ use crate::{
|
|||
prelude::OutputExt,
|
||||
quirks::{WORKSPACE_OVERVIEW_NAMESPACE, workspace_overview_is_open},
|
||||
},
|
||||
wayland::protocols::workspace::WorkspaceHandle,
|
||||
wayland::protocols::{session_lock_layer::layer_show_on_lock, workspace::WorkspaceHandle},
|
||||
};
|
||||
|
||||
pub enum Stage<'a> {
|
||||
|
|
@ -77,6 +77,8 @@ fn render_input_order_internal<R: 'static>(
|
|||
element_filter: ElementFilter,
|
||||
mut callback: impl FnMut(Stage) -> ControlFlow<Result<R, OutputNoMode>, ()>,
|
||||
) -> ControlFlow<Result<R, OutputNoMode>, ()> {
|
||||
// NOTE: Keep in sync with other surface iteration functions
|
||||
|
||||
if shell
|
||||
.zoom_state
|
||||
.as_ref()
|
||||
|
|
@ -87,7 +89,92 @@ fn render_input_order_internal<R: 'static>(
|
|||
|
||||
// Session Lock
|
||||
if let Some(session_lock) = &shell.session_lock {
|
||||
return callback(Stage::SessionLock(session_lock.surfaces.get(output)));
|
||||
for (layer, popup, location) in layer_popups(output, Layer::Overlay, element_filter) {
|
||||
if !layer_show_on_lock(layer.wl_surface()) {
|
||||
continue;
|
||||
}
|
||||
callback(Stage::LayerPopup {
|
||||
layer,
|
||||
popup: &popup,
|
||||
location,
|
||||
workspace_idx: current.1,
|
||||
})?;
|
||||
}
|
||||
for (layer, location) in layer_surfaces(output, Layer::Overlay, element_filter) {
|
||||
if !layer_show_on_lock(layer.wl_surface()) {
|
||||
continue;
|
||||
}
|
||||
callback(Stage::LayerSurface {
|
||||
layer,
|
||||
location,
|
||||
workspace_idx: current.1,
|
||||
})?;
|
||||
}
|
||||
for (layer, popup, location) in layer_popups(output, Layer::Top, element_filter) {
|
||||
if !layer_show_on_lock(layer.wl_surface()) {
|
||||
continue;
|
||||
}
|
||||
callback(Stage::LayerPopup {
|
||||
layer,
|
||||
popup: &popup,
|
||||
location,
|
||||
workspace_idx: current.1,
|
||||
})?;
|
||||
}
|
||||
for (layer, location) in layer_surfaces(output, Layer::Top, element_filter) {
|
||||
if !layer_show_on_lock(layer.wl_surface()) {
|
||||
continue;
|
||||
}
|
||||
callback(Stage::LayerSurface {
|
||||
layer,
|
||||
location,
|
||||
workspace_idx: current.1,
|
||||
})?;
|
||||
}
|
||||
callback(Stage::SessionLock(session_lock.surfaces.get(output)))?;
|
||||
for (layer, popup, location) in layer_popups(output, Layer::Bottom, element_filter) {
|
||||
if !layer_show_on_lock(layer.wl_surface()) {
|
||||
continue;
|
||||
}
|
||||
callback(Stage::LayerPopup {
|
||||
layer,
|
||||
popup: &popup,
|
||||
location,
|
||||
workspace_idx: current.1,
|
||||
})?;
|
||||
}
|
||||
for (layer, popup, location) in layer_popups(output, Layer::Background, element_filter) {
|
||||
if !layer_show_on_lock(layer.wl_surface()) {
|
||||
continue;
|
||||
}
|
||||
callback(Stage::LayerPopup {
|
||||
layer,
|
||||
popup: &popup,
|
||||
location,
|
||||
workspace_idx: current.1,
|
||||
})?;
|
||||
}
|
||||
for (layer, location) in layer_surfaces(output, Layer::Bottom, element_filter) {
|
||||
if !layer_show_on_lock(layer.wl_surface()) {
|
||||
continue;
|
||||
}
|
||||
callback(Stage::LayerSurface {
|
||||
layer,
|
||||
location,
|
||||
workspace_idx: current.1,
|
||||
})?;
|
||||
}
|
||||
for (layer, location) in layer_surfaces(output, Layer::Background, element_filter) {
|
||||
if !layer_show_on_lock(layer.wl_surface()) {
|
||||
continue;
|
||||
}
|
||||
callback(Stage::LayerSurface {
|
||||
layer,
|
||||
location,
|
||||
workspace_idx: current.1,
|
||||
})?;
|
||||
}
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
|
||||
// Overlay-level layer shell
|
||||
|
|
|
|||
|
|
@ -19,7 +19,10 @@ use crate::{
|
|||
utils,
|
||||
wayland::{
|
||||
handlers::data_device::{self, get_dnd_icon},
|
||||
protocols::workspace::{State as WState, WorkspaceCapabilities},
|
||||
protocols::{
|
||||
session_lock_layer::layer_show_on_lock,
|
||||
workspace::{State as WState, WorkspaceCapabilities},
|
||||
},
|
||||
},
|
||||
};
|
||||
use cosmic_comp_config::{
|
||||
|
|
@ -2046,12 +2049,27 @@ impl Shell {
|
|||
}
|
||||
|
||||
pub fn visible_output_for_surface(&self, surface: &WlSurface) -> Option<&Output> {
|
||||
// NOTE: Keep in sync with surface iteration in `render_input_order_internal`
|
||||
|
||||
if let Some(session_lock) = &self.session_lock {
|
||||
return session_lock
|
||||
if let Some((output, _)) = session_lock
|
||||
.surfaces
|
||||
.iter()
|
||||
.find(|(_, v)| v.wl_surface() == surface)
|
||||
.map(|(k, _)| k);
|
||||
{
|
||||
return Some(output);
|
||||
}
|
||||
for o in self.outputs() {
|
||||
let map = layer_map_for_output(o);
|
||||
if let Some(layer_surface) = map.layer_for_surface(surface, WindowSurfaceType::ALL)
|
||||
{
|
||||
if layer_show_on_lock(layer_surface.wl_surface()) {
|
||||
return Some(o);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.outputs()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue