input: Use render_input_order
This commit is contained in:
parent
51c8588f89
commit
0092dac08c
10 changed files with 712 additions and 387 deletions
423
src/input/mod.rs
423
src/input/mod.rs
|
|
@ -1,6 +1,7 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
backend::render::ElementFilter,
|
||||||
config::{
|
config::{
|
||||||
key_bindings::{
|
key_bindings::{
|
||||||
cosmic_keystate_from_smithay, cosmic_modifiers_eq_smithay,
|
cosmic_keystate_from_smithay, cosmic_modifiers_eq_smithay,
|
||||||
|
|
@ -10,7 +11,11 @@ use crate::{
|
||||||
},
|
},
|
||||||
input::gestures::{GestureState, SwipeAction},
|
input::gestures::{GestureState, SwipeAction},
|
||||||
shell::{
|
shell::{
|
||||||
focus::target::{KeyboardFocusTarget, PointerFocusTarget},
|
focus::{
|
||||||
|
render_input_order,
|
||||||
|
target::{KeyboardFocusTarget, PointerFocusTarget},
|
||||||
|
Stage,
|
||||||
|
},
|
||||||
grabs::{ReleaseMode, ResizeEdge},
|
grabs::{ReleaseMode, ResizeEdge},
|
||||||
layout::{
|
layout::{
|
||||||
floating::ResizeGrabMarker,
|
floating::ResizeGrabMarker,
|
||||||
|
|
@ -39,10 +44,7 @@ use smithay::{
|
||||||
TabletToolButtonEvent, TabletToolEvent, TabletToolProximityEvent, TabletToolTipEvent,
|
TabletToolButtonEvent, TabletToolEvent, TabletToolProximityEvent, TabletToolTipEvent,
|
||||||
TabletToolTipState, TouchEvent,
|
TabletToolTipState, TouchEvent,
|
||||||
},
|
},
|
||||||
desktop::{
|
desktop::{utils::under_from_surface_tree, WindowSurfaceType},
|
||||||
layer_map_for_output, space::SpaceElement, utils::under_from_surface_tree,
|
|
||||||
WindowSurfaceType,
|
|
||||||
},
|
|
||||||
input::{
|
input::{
|
||||||
keyboard::{FilterResult, KeysymHandle, ModifiersState},
|
keyboard::{FilterResult, KeysymHandle, ModifiersState},
|
||||||
pointer::{
|
pointer::{
|
||||||
|
|
@ -58,15 +60,13 @@ use smithay::{
|
||||||
reexports::{
|
reexports::{
|
||||||
input::Device as InputDevice, wayland_server::protocol::wl_shm::Format as ShmFormat,
|
input::Device as InputDevice, wayland_server::protocol::wl_shm::Format as ShmFormat,
|
||||||
},
|
},
|
||||||
utils::{Point, Serial, SERIAL_COUNTER},
|
utils::{Point, Rectangle, Serial, SERIAL_COUNTER},
|
||||||
wayland::{
|
wayland::{
|
||||||
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitorSeat,
|
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitorSeat,
|
||||||
pointer_constraints::{with_pointer_constraint, PointerConstraint},
|
pointer_constraints::{with_pointer_constraint, PointerConstraint},
|
||||||
seat::WaylandFocus,
|
seat::WaylandFocus,
|
||||||
shell::wlr_layer::Layer as WlrLayer,
|
|
||||||
tablet_manager::{TabletDescriptor, TabletSeatTrait},
|
tablet_manager::{TabletDescriptor, TabletSeatTrait},
|
||||||
},
|
},
|
||||||
xwayland::X11Surface,
|
|
||||||
};
|
};
|
||||||
use tracing::{error, trace};
|
use tracing::{error, trace};
|
||||||
use xkbcommon::xkb::{Keycode, Keysym};
|
use xkbcommon::xkb::{Keycode, Keysym};
|
||||||
|
|
@ -76,6 +76,7 @@ use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::HashSet,
|
collections::HashSet,
|
||||||
|
ops::ControlFlow,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -329,9 +330,8 @@ impl State {
|
||||||
} else if self.common.config.cosmic_conf.focus_follows_cursor {
|
} else if self.common.config.cosmic_conf.focus_follows_cursor {
|
||||||
let shell = self.common.shell.read().unwrap();
|
let shell = self.common.shell.read().unwrap();
|
||||||
let old_keyboard_target =
|
let old_keyboard_target =
|
||||||
shell.keyboard_target_from_position(original_position, ¤t_output);
|
State::element_under(original_position, ¤t_output, &*shell);
|
||||||
let new_keyboard_target =
|
let new_keyboard_target = State::element_under(position, &output, &*shell);
|
||||||
shell.keyboard_target_from_position(position, &output);
|
|
||||||
|
|
||||||
if old_keyboard_target != new_keyboard_target
|
if old_keyboard_target != new_keyboard_target
|
||||||
&& new_keyboard_target.is_some()
|
&& new_keyboard_target.is_some()
|
||||||
|
|
@ -497,7 +497,8 @@ impl State {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let shell = self.common.shell.read().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
|
shell.update_pointer_position(position.to_local(&output), &output);
|
||||||
|
|
||||||
if output != current_output {
|
if output != current_output {
|
||||||
for session in cursor_sessions_for_output(&*shell, ¤t_output) {
|
for session in cursor_sessions_for_output(&*shell, ¤t_output) {
|
||||||
|
|
@ -638,15 +639,15 @@ impl State {
|
||||||
|
|
||||||
let global_position =
|
let global_position =
|
||||||
seat.get_pointer().unwrap().current_location().as_global();
|
seat.get_pointer().unwrap().current_location().as_global();
|
||||||
let shell = self.common.shell.write().unwrap();
|
let under = {
|
||||||
let under = shell.keyboard_target_from_position(global_position, &output);
|
let shell = self.common.shell.read().unwrap();
|
||||||
// Don't check override redirect windows, because we don't set keyboard focus to them explicitly.
|
State::element_under(global_position, &output, &shell)
|
||||||
// These cases are handled by the XwaylandKeyboardGrab.
|
};
|
||||||
if let Some(target) = shell.element_under(global_position, &output) {
|
if let Some(target) = under {
|
||||||
if seat.get_keyboard().unwrap().modifier_state().logo
|
if let Some(surface) = target.toplevel().map(Cow::into_owned) {
|
||||||
&& !shortcuts_inhibited
|
if seat.get_keyboard().unwrap().modifier_state().logo
|
||||||
{
|
&& !shortcuts_inhibited
|
||||||
if let Some(surface) = target.toplevel().map(Cow::into_owned) {
|
{
|
||||||
let seat_clone = seat.clone();
|
let seat_clone = seat.clone();
|
||||||
let mouse_button = PointerButtonEvent::button(&event);
|
let mouse_button = PointerButtonEvent::button(&event);
|
||||||
|
|
||||||
|
|
@ -754,10 +755,9 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::mem::drop(shell);
|
Shell::set_focus(self, Some(&target), &seat, Some(serial), false);
|
||||||
Shell::set_focus(self, under.as_ref(), &seat, Some(serial), false);
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
|
|
@ -1814,142 +1814,263 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Try to get rid of the *mutable* Shell references (needed for hovered_stack in floating_layout)
|
pub fn element_under(
|
||||||
|
global_pos: Point<f64, Global>,
|
||||||
|
output: &Output,
|
||||||
|
shell: &Shell,
|
||||||
|
) -> Option<KeyboardFocusTarget> {
|
||||||
|
let (previous_workspace, workspace) = shell.workspaces.active(output);
|
||||||
|
let (previous_idx, idx) = shell.workspaces.active_num(output);
|
||||||
|
let previous_workspace = previous_workspace
|
||||||
|
.zip(previous_idx)
|
||||||
|
.map(|((w, start), idx)| (w.handle, idx, start));
|
||||||
|
let workspace = (workspace.handle, idx);
|
||||||
|
let element_filter = if workspace_overview_is_open(output) {
|
||||||
|
ElementFilter::LayerShellOnly
|
||||||
|
} else {
|
||||||
|
ElementFilter::All
|
||||||
|
};
|
||||||
|
|
||||||
|
render_input_order(
|
||||||
|
shell,
|
||||||
|
output,
|
||||||
|
previous_workspace,
|
||||||
|
workspace,
|
||||||
|
element_filter,
|
||||||
|
|stage| {
|
||||||
|
match stage {
|
||||||
|
Stage::SessionLock(lock_surface) => {
|
||||||
|
return ControlFlow::Break(Ok(lock_surface
|
||||||
|
.cloned()
|
||||||
|
.map(KeyboardFocusTarget::LockSurface)))
|
||||||
|
}
|
||||||
|
Stage::LayerPopup {
|
||||||
|
layer,
|
||||||
|
popup,
|
||||||
|
location,
|
||||||
|
} => {
|
||||||
|
if layer.can_receive_keyboard_focus() {
|
||||||
|
let surface = popup.wl_surface();
|
||||||
|
if under_from_surface_tree(
|
||||||
|
surface,
|
||||||
|
global_pos.as_logical(),
|
||||||
|
location.as_logical(),
|
||||||
|
WindowSurfaceType::POPUP | WindowSurfaceType::SUBSURFACE,
|
||||||
|
)
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
return ControlFlow::Break(Ok(Some(
|
||||||
|
KeyboardFocusTarget::LayerSurface(layer),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Stage::LayerSurface { layer, location } => {
|
||||||
|
if layer.can_receive_keyboard_focus() {
|
||||||
|
if under_from_surface_tree(
|
||||||
|
layer.wl_surface(),
|
||||||
|
global_pos.as_logical(),
|
||||||
|
location.as_logical(),
|
||||||
|
WindowSurfaceType::TOPLEVEL | WindowSurfaceType::SUBSURFACE,
|
||||||
|
)
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
return ControlFlow::Break(Ok(Some(
|
||||||
|
KeyboardFocusTarget::LayerSurface(layer),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Stage::OverrideRedirect { .. } => {
|
||||||
|
// Override redirect windows take a grab on their own via
|
||||||
|
// the Xwayland keyboard grab protocol. Don't focus them via click.
|
||||||
|
}
|
||||||
|
Stage::StickyPopups(layout) => {
|
||||||
|
if let Some(element) =
|
||||||
|
layout.popup_element_under(global_pos.to_local(output))
|
||||||
|
{
|
||||||
|
return ControlFlow::Break(Ok(Some(element)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Stage::Sticky(layout) => {
|
||||||
|
if let Some(element) =
|
||||||
|
layout.toplevel_element_under(global_pos.to_local(output))
|
||||||
|
{
|
||||||
|
return ControlFlow::Break(Ok(Some(element)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Stage::WorkspacePopups { workspace, offset } => {
|
||||||
|
let location = global_pos + offset.as_global().to_f64();
|
||||||
|
let output = workspace.output();
|
||||||
|
let output_geo = output.geometry().to_local(output);
|
||||||
|
if Rectangle::from_loc_and_size(offset.as_local(), output_geo.size)
|
||||||
|
.intersection(output_geo)
|
||||||
|
.is_some_and(|geometry| {
|
||||||
|
geometry.contains(global_pos.to_local(output).to_i32_round())
|
||||||
|
})
|
||||||
|
{
|
||||||
|
if let Some(element) = workspace.popup_element_under(location) {
|
||||||
|
return ControlFlow::Break(Ok(Some(element)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Stage::Workspace { workspace, offset } => {
|
||||||
|
let location = global_pos + offset.as_global().to_f64();
|
||||||
|
let output = workspace.output();
|
||||||
|
let output_geo = output.geometry().to_local(output);
|
||||||
|
if Rectangle::from_loc_and_size(offset.as_local(), output_geo.size)
|
||||||
|
.intersection(output_geo)
|
||||||
|
.is_some_and(|geometry| {
|
||||||
|
geometry.contains(global_pos.to_local(output).to_i32_round())
|
||||||
|
})
|
||||||
|
{
|
||||||
|
if let Some(element) = workspace.toplevel_element_under(location) {
|
||||||
|
return ControlFlow::Break(Ok(Some(element)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ControlFlow::Continue(())
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
.flatten()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn surface_under(
|
pub fn surface_under(
|
||||||
global_pos: Point<f64, Global>,
|
global_pos: Point<f64, Global>,
|
||||||
output: &Output,
|
output: &Output,
|
||||||
shell: &mut Shell,
|
shell: &Shell,
|
||||||
) -> Option<(PointerFocusTarget, Point<f64, Global>)> {
|
) -> Option<(PointerFocusTarget, Point<f64, Global>)> {
|
||||||
let session_lock = shell.session_lock.as_ref();
|
let (previous_workspace, workspace) = shell.workspaces.active(output);
|
||||||
|
let (previous_idx, idx) = shell.workspaces.active_num(output);
|
||||||
|
let previous_workspace = previous_workspace
|
||||||
|
.zip(previous_idx)
|
||||||
|
.map(|((w, start), idx)| (w.handle, idx, start));
|
||||||
|
let workspace = (workspace.handle, idx);
|
||||||
|
|
||||||
|
let element_filter = if workspace_overview_is_open(output) {
|
||||||
|
ElementFilter::LayerShellOnly
|
||||||
|
} else {
|
||||||
|
ElementFilter::All
|
||||||
|
};
|
||||||
|
|
||||||
let relative_pos = global_pos.to_local(output);
|
let relative_pos = global_pos.to_local(output);
|
||||||
let output_geo = output.geometry();
|
let output_geo = output.geometry();
|
||||||
|
let overview = shell.overview_mode().0;
|
||||||
|
|
||||||
if let Some(session_lock) = session_lock {
|
render_input_order(
|
||||||
return session_lock.surfaces.get(output).map(|surface| {
|
shell,
|
||||||
(
|
output,
|
||||||
PointerFocusTarget::WlSurface {
|
previous_workspace,
|
||||||
surface: surface.wl_surface().clone(),
|
workspace,
|
||||||
toplevel: None,
|
element_filter,
|
||||||
},
|
|stage| {
|
||||||
output_geo.loc.to_f64(),
|
match stage {
|
||||||
)
|
Stage::SessionLock(lock_surface) => {
|
||||||
});
|
return ControlFlow::Break(Ok(lock_surface.map(|surface| {
|
||||||
}
|
(
|
||||||
|
PointerFocusTarget::WlSurface {
|
||||||
if let Some(window) = shell.workspaces.active(output).1.get_fullscreen() {
|
surface: surface.wl_surface().clone(),
|
||||||
let layers = layer_map_for_output(output);
|
toplevel: None,
|
||||||
if let Some(layer) = layers.layer_under(WlrLayer::Overlay, relative_pos.as_logical()) {
|
},
|
||||||
let layer_loc = layers.layer_geometry(layer).unwrap().loc;
|
output_geo.loc.to_f64(),
|
||||||
if let Some((wl_surface, surface_loc)) = layer.surface_under(
|
)
|
||||||
relative_pos.as_logical() - layer_loc.to_f64(),
|
})));
|
||||||
WindowSurfaceType::ALL,
|
}
|
||||||
) {
|
Stage::LayerPopup {
|
||||||
return Some((
|
popup, location, ..
|
||||||
PointerFocusTarget::WlSurface {
|
} => {
|
||||||
surface: wl_surface,
|
let surface = popup.wl_surface();
|
||||||
toplevel: None,
|
if let Some((surface, surface_loc)) = under_from_surface_tree(
|
||||||
},
|
surface,
|
||||||
(output_geo.loc + layer_loc.as_global() + surface_loc.as_global()).to_f64(),
|
global_pos.as_logical(),
|
||||||
));
|
location.as_logical(),
|
||||||
}
|
WindowSurfaceType::ALL,
|
||||||
}
|
) {
|
||||||
if let Some((surface, geo)) = shell
|
return ControlFlow::Break(Ok(Some((
|
||||||
.override_redirect_windows
|
PointerFocusTarget::WlSurface {
|
||||||
.iter()
|
surface,
|
||||||
.find(|or| {
|
toplevel: None,
|
||||||
or.is_in_input_region(
|
},
|
||||||
&(global_pos.as_logical() - X11Surface::geometry(*or).loc.to_f64()),
|
surface_loc.as_global().to_f64(),
|
||||||
)
|
))));
|
||||||
})
|
}
|
||||||
.and_then(|or| {
|
}
|
||||||
or.wl_surface()
|
Stage::LayerSurface { layer, location } => {
|
||||||
.map(|surface| (surface, X11Surface::geometry(or).loc.as_global().to_f64()))
|
let surface = layer.wl_surface();
|
||||||
})
|
if let Some((surface, surface_loc)) = under_from_surface_tree(
|
||||||
{
|
surface,
|
||||||
return Some((
|
global_pos.as_logical(),
|
||||||
PointerFocusTarget::WlSurface {
|
location.as_logical(),
|
||||||
surface,
|
WindowSurfaceType::ALL,
|
||||||
toplevel: None,
|
) {
|
||||||
},
|
return ControlFlow::Break(Ok(Some((
|
||||||
geo,
|
PointerFocusTarget::WlSurface {
|
||||||
));
|
surface,
|
||||||
}
|
toplevel: None,
|
||||||
PointerFocusTarget::under_surface(window, relative_pos.as_logical()).map(
|
},
|
||||||
|(target, surface_loc)| {
|
surface_loc.as_global().to_f64(),
|
||||||
(target, (output_geo.loc + surface_loc.as_global()).to_f64())
|
))));
|
||||||
},
|
}
|
||||||
)
|
}
|
||||||
} else {
|
Stage::OverrideRedirect { surface, location } => {
|
||||||
{
|
if let Some(surface) = surface.wl_surface() {
|
||||||
let layers = layer_map_for_output(output);
|
if let Some((surface, surface_loc)) = under_from_surface_tree(
|
||||||
if let Some(layer) = layers
|
&surface,
|
||||||
.layer_under(WlrLayer::Overlay, relative_pos.as_logical())
|
global_pos.as_logical(),
|
||||||
.or_else(|| layers.layer_under(WlrLayer::Top, relative_pos.as_logical()))
|
location.as_logical(),
|
||||||
{
|
WindowSurfaceType::ALL,
|
||||||
let layer_loc = layers.layer_geometry(layer).unwrap().loc;
|
) {
|
||||||
if let Some((wl_surface, surface_loc)) = layer.surface_under(
|
return ControlFlow::Break(Ok(Some((
|
||||||
relative_pos.as_logical() - layer_loc.to_f64(),
|
PointerFocusTarget::WlSurface {
|
||||||
WindowSurfaceType::ALL,
|
surface,
|
||||||
) {
|
toplevel: None,
|
||||||
return Some((
|
},
|
||||||
PointerFocusTarget::WlSurface {
|
surface_loc.as_global().to_f64(),
|
||||||
surface: wl_surface,
|
))));
|
||||||
toplevel: None,
|
}
|
||||||
},
|
}
|
||||||
(output_geo.loc + layer_loc.as_global() + surface_loc.as_global())
|
}
|
||||||
.to_f64(),
|
Stage::StickyPopups(floating_layer) => {
|
||||||
));
|
if let Some(under) = floating_layer
|
||||||
|
.popup_surface_under(relative_pos)
|
||||||
|
.map(|(target, point)| (target, point.to_global(output)))
|
||||||
|
{
|
||||||
|
return ControlFlow::Break(Ok(Some(under)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Stage::Sticky(floating_layer) => {
|
||||||
|
if let Some(under) = floating_layer
|
||||||
|
.toplevel_surface_under(relative_pos)
|
||||||
|
.map(|(target, point)| (target, point.to_global(output)))
|
||||||
|
{
|
||||||
|
return ControlFlow::Break(Ok(Some(under)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Stage::WorkspacePopups { workspace, offset } => {
|
||||||
|
let global_pos = global_pos + offset.to_f64().as_global();
|
||||||
|
if let Some(under) =
|
||||||
|
workspace.popup_surface_under(global_pos, overview.clone())
|
||||||
|
{
|
||||||
|
return ControlFlow::Break(Ok(Some(under)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Stage::Workspace { workspace, offset } => {
|
||||||
|
let global_pos = global_pos + offset.to_f64().as_global();
|
||||||
|
if let Some(under) =
|
||||||
|
workspace.toplevel_surface_under(global_pos, overview.clone())
|
||||||
|
{
|
||||||
|
return ControlFlow::Break(Ok(Some(under)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if let Some((surface, geo)) = shell
|
ControlFlow::Continue(())
|
||||||
.override_redirect_windows
|
},
|
||||||
.iter()
|
)
|
||||||
.find(|or| {
|
.ok()
|
||||||
or.is_in_input_region(
|
.flatten()
|
||||||
&(global_pos.as_logical() - X11Surface::geometry(*or).loc.to_f64()),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.and_then(|or| {
|
|
||||||
or.wl_surface()
|
|
||||||
.map(|surface| (surface, X11Surface::geometry(or).loc.as_global().to_f64()))
|
|
||||||
})
|
|
||||||
{
|
|
||||||
return Some((
|
|
||||||
PointerFocusTarget::WlSurface {
|
|
||||||
surface,
|
|
||||||
toplevel: None,
|
|
||||||
},
|
|
||||||
geo,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if let Some((target, loc)) = shell.surface_under(global_pos, output) {
|
|
||||||
return Some((target, loc));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
let layers = layer_map_for_output(output);
|
|
||||||
if let Some(layer) = layers
|
|
||||||
.layer_under(WlrLayer::Bottom, relative_pos.as_logical())
|
|
||||||
.or_else(|| layers.layer_under(WlrLayer::Background, relative_pos.as_logical()))
|
|
||||||
{
|
|
||||||
let layer_loc = layers.layer_geometry(layer).unwrap().loc;
|
|
||||||
if let Some((wl_surface, surface_loc)) = layer.surface_under(
|
|
||||||
relative_pos.as_logical() - layer_loc.to_f64(),
|
|
||||||
WindowSurfaceType::ALL,
|
|
||||||
) {
|
|
||||||
return Some((
|
|
||||||
PointerFocusTarget::WlSurface {
|
|
||||||
surface: wl_surface,
|
|
||||||
toplevel: None,
|
|
||||||
},
|
|
||||||
(output_geo.loc + layer_loc.as_global() + surface_loc.as_global())
|
|
||||||
.to_f64(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -302,10 +302,11 @@ impl CosmicMapped {
|
||||||
pub fn focus_under(
|
pub fn focus_under(
|
||||||
&self,
|
&self,
|
||||||
relative_pos: Point<f64, Logical>,
|
relative_pos: Point<f64, Logical>,
|
||||||
|
surface_type: WindowSurfaceType,
|
||||||
) -> Option<(PointerFocusTarget, Point<f64, Logical>)> {
|
) -> Option<(PointerFocusTarget, Point<f64, Logical>)> {
|
||||||
match &self.element {
|
match &self.element {
|
||||||
CosmicMappedInternal::Stack(stack) => stack.focus_under(relative_pos),
|
CosmicMappedInternal::Stack(stack) => stack.focus_under(relative_pos, surface_type),
|
||||||
CosmicMappedInternal::Window(window) => window.focus_under(relative_pos),
|
CosmicMappedInternal::Window(window) => window.focus_under(relative_pos, surface_type),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -420,48 +420,52 @@ impl CosmicStack {
|
||||||
pub fn focus_under(
|
pub fn focus_under(
|
||||||
&self,
|
&self,
|
||||||
mut relative_pos: Point<f64, Logical>,
|
mut relative_pos: Point<f64, Logical>,
|
||||||
|
surface_type: WindowSurfaceType,
|
||||||
) -> Option<(PointerFocusTarget, Point<f64, Logical>)> {
|
) -> Option<(PointerFocusTarget, Point<f64, Logical>)> {
|
||||||
self.0.with_program(|p| {
|
self.0.with_program(|p| {
|
||||||
let mut stack_ui = None;
|
let mut stack_ui = None;
|
||||||
let geo = p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].geometry();
|
let geo = p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].geometry();
|
||||||
|
|
||||||
let point_i32 = relative_pos.to_i32_round::<i32>();
|
if surface_type.contains(WindowSurfaceType::TOPLEVEL) {
|
||||||
if (point_i32.x - geo.loc.x >= -RESIZE_BORDER && point_i32.x - geo.loc.x < 0)
|
let point_i32 = relative_pos.to_i32_round::<i32>();
|
||||||
|| (point_i32.y - geo.loc.y >= -RESIZE_BORDER && point_i32.y - geo.loc.y < 0)
|
if (point_i32.x - geo.loc.x >= -RESIZE_BORDER && point_i32.x - geo.loc.x < 0)
|
||||||
|| (point_i32.x - geo.loc.x >= geo.size.w
|
|| (point_i32.y - geo.loc.y >= -RESIZE_BORDER && point_i32.y - geo.loc.y < 0)
|
||||||
&& point_i32.x - geo.loc.x < geo.size.w + RESIZE_BORDER)
|
|| (point_i32.x - geo.loc.x >= geo.size.w
|
||||||
|| (point_i32.y - geo.loc.y >= geo.size.h
|
&& point_i32.x - geo.loc.x < geo.size.w + RESIZE_BORDER)
|
||||||
&& point_i32.y - geo.loc.y < geo.size.h + TAB_HEIGHT + RESIZE_BORDER)
|
|| (point_i32.y - geo.loc.y >= geo.size.h
|
||||||
{
|
&& point_i32.y - geo.loc.y < geo.size.h + TAB_HEIGHT + RESIZE_BORDER)
|
||||||
stack_ui = Some((
|
{
|
||||||
PointerFocusTarget::StackUI(self.clone()),
|
stack_ui = Some((
|
||||||
Point::from((0., 0.)),
|
PointerFocusTarget::StackUI(self.clone()),
|
||||||
));
|
Point::from((0., 0.)),
|
||||||
}
|
));
|
||||||
|
}
|
||||||
|
|
||||||
if point_i32.y - geo.loc.y < TAB_HEIGHT {
|
if point_i32.y - geo.loc.y < TAB_HEIGHT {
|
||||||
stack_ui = Some((
|
stack_ui = Some((
|
||||||
PointerFocusTarget::StackUI(self.clone()),
|
PointerFocusTarget::StackUI(self.clone()),
|
||||||
Point::from((0., 0.)),
|
Point::from((0., 0.)),
|
||||||
));
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
relative_pos.y -= TAB_HEIGHT as f64;
|
relative_pos.y -= TAB_HEIGHT as f64;
|
||||||
|
|
||||||
let active_window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)];
|
let active_window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)];
|
||||||
active_window
|
stack_ui.or_else(|| {
|
||||||
.0
|
active_window
|
||||||
.surface_under(relative_pos, WindowSurfaceType::ALL)
|
.0
|
||||||
.map(|(surface, surface_offset)| {
|
.surface_under(relative_pos, surface_type)
|
||||||
(
|
.map(|(surface, surface_offset)| {
|
||||||
PointerFocusTarget::WlSurface {
|
(
|
||||||
surface,
|
PointerFocusTarget::WlSurface {
|
||||||
toplevel: Some(active_window.clone().into()),
|
surface,
|
||||||
},
|
toplevel: Some(active_window.clone().into()),
|
||||||
surface_offset.to_f64() + Point::from((0., TAB_HEIGHT as f64)),
|
},
|
||||||
)
|
surface_offset.to_f64() + Point::from((0., TAB_HEIGHT as f64)),
|
||||||
})
|
)
|
||||||
.or(stack_ui)
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1034,7 +1038,7 @@ impl SpaceElement for CosmicStack {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn is_in_input_region(&self, point: &Point<f64, Logical>) -> bool {
|
fn is_in_input_region(&self, point: &Point<f64, Logical>) -> bool {
|
||||||
self.focus_under(*point).is_some()
|
self.focus_under(*point, WindowSurfaceType::ALL).is_some()
|
||||||
}
|
}
|
||||||
fn set_activate(&self, activated: bool) {
|
fn set_activate(&self, activated: bool) {
|
||||||
SpaceElement::set_activate(&self.0, activated);
|
SpaceElement::set_activate(&self.0, activated);
|
||||||
|
|
|
||||||
|
|
@ -243,11 +243,12 @@ impl CosmicWindow {
|
||||||
pub fn focus_under(
|
pub fn focus_under(
|
||||||
&self,
|
&self,
|
||||||
mut relative_pos: Point<f64, Logical>,
|
mut relative_pos: Point<f64, Logical>,
|
||||||
|
surface_type: WindowSurfaceType,
|
||||||
) -> Option<(PointerFocusTarget, Point<f64, Logical>)> {
|
) -> Option<(PointerFocusTarget, Point<f64, Logical>)> {
|
||||||
self.0.with_program(|p| {
|
self.0.with_program(|p| {
|
||||||
let mut offset = Point::from((0., 0.));
|
let mut offset = Point::from((0., 0.));
|
||||||
let mut window_ui = None;
|
let mut window_ui = None;
|
||||||
if p.has_ssd(false) {
|
if p.has_ssd(false) && surface_type.contains(WindowSurfaceType::TOPLEVEL) {
|
||||||
let geo = p.window.geometry();
|
let geo = p.window.geometry();
|
||||||
|
|
||||||
let point_i32 = relative_pos.to_i32_round::<i32>();
|
let point_i32 = relative_pos.to_i32_round::<i32>();
|
||||||
|
|
@ -275,19 +276,19 @@ impl CosmicWindow {
|
||||||
offset.y += SSD_HEIGHT as f64;
|
offset.y += SSD_HEIGHT as f64;
|
||||||
}
|
}
|
||||||
|
|
||||||
p.window
|
window_ui.or_else(|| {
|
||||||
.0
|
p.window.0.surface_under(relative_pos, surface_type).map(
|
||||||
.surface_under(relative_pos, WindowSurfaceType::ALL)
|
|(surface, surface_offset)| {
|
||||||
.map(|(surface, surface_offset)| {
|
(
|
||||||
(
|
PointerFocusTarget::WlSurface {
|
||||||
PointerFocusTarget::WlSurface {
|
surface,
|
||||||
surface,
|
toplevel: Some(p.window.clone().into()),
|
||||||
toplevel: Some(p.window.clone().into()),
|
},
|
||||||
},
|
(offset + surface_offset.to_f64()),
|
||||||
(offset + surface_offset.to_f64()),
|
)
|
||||||
)
|
},
|
||||||
})
|
)
|
||||||
.or(window_ui)
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -561,7 +562,7 @@ impl SpaceElement for CosmicWindow {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn is_in_input_region(&self, point: &Point<f64, Logical>) -> bool {
|
fn is_in_input_region(&self, point: &Point<f64, Logical>) -> bool {
|
||||||
self.focus_under(*point).is_some()
|
self.focus_under(*point, WindowSurfaceType::ALL).is_some()
|
||||||
}
|
}
|
||||||
fn set_activate(&self, activated: bool) {
|
fn set_activate(&self, activated: bool) {
|
||||||
if self
|
if self
|
||||||
|
|
|
||||||
|
|
@ -232,8 +232,8 @@ fn update_focus_state(
|
||||||
if should_update_cursor && state.common.config.cosmic_conf.cursor_follows_focus {
|
if should_update_cursor && state.common.config.cosmic_conf.cursor_follows_focus {
|
||||||
if target.is_some() {
|
if target.is_some() {
|
||||||
//need to borrow mutably for surface under
|
//need to borrow mutably for surface under
|
||||||
let mut shell = state.common.shell.write().unwrap();
|
let shell = state.common.shell.read().unwrap();
|
||||||
// get geometry of the target element
|
// get the top left corner of the target element
|
||||||
let geometry = shell.focused_geometry(target.unwrap());
|
let geometry = shell.focused_geometry(target.unwrap());
|
||||||
if let Some(geometry) = geometry {
|
if let Some(geometry) = geometry {
|
||||||
// get the center of the target element
|
// get the center of the target element
|
||||||
|
|
@ -247,10 +247,9 @@ fn update_focus_state(
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or(seat.active_output());
|
.unwrap_or(seat.active_output());
|
||||||
|
|
||||||
let focus = shell
|
let focus = State::surface_under(new_pos, &output, &*shell)
|
||||||
.surface_under(new_pos, &output)
|
|
||||||
.map(|(focus, loc)| (focus, loc.as_logical()));
|
.map(|(focus, loc)| (focus, loc.as_logical()));
|
||||||
//drop here to avoid multiple mutable borrows
|
//drop here to avoid multiple borrows
|
||||||
mem::drop(shell);
|
mem::drop(shell);
|
||||||
seat.get_pointer().unwrap().motion(
|
seat.get_pointer().unwrap().motion(
|
||||||
state,
|
state,
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ use smithay::{
|
||||||
ImportAll, ImportMem, Renderer,
|
ImportAll, ImportMem, Renderer,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
desktop::{layer_map_for_output, space::SpaceElement},
|
desktop::{layer_map_for_output, space::SpaceElement, WindowSurfaceType},
|
||||||
input::{
|
input::{
|
||||||
pointer::{
|
pointer::{
|
||||||
AxisFrame, ButtonEvent, CursorIcon, GestureHoldBeginEvent, GestureHoldEndEvent,
|
AxisFrame, ButtonEvent, CursorIcon, GestureHoldBeginEvent, GestureHoldEndEvent,
|
||||||
|
|
@ -864,7 +864,7 @@ impl Drop for MoveGrab {
|
||||||
let current_location = pointer.current_location();
|
let current_location = pointer.current_location();
|
||||||
|
|
||||||
if let Some((target, offset)) =
|
if let Some((target, offset)) =
|
||||||
mapped.focus_under(current_location - position.as_logical().to_f64())
|
mapped.focus_under(current_location - position.as_logical().to_f64(), WindowSurfaceType::ALL)
|
||||||
{
|
{
|
||||||
pointer.motion(
|
pointer.motion(
|
||||||
state,
|
state,
|
||||||
|
|
|
||||||
|
|
@ -728,16 +728,115 @@ impl FloatingLayout {
|
||||||
self.space.element_geometry(elem).map(RectExt::as_local)
|
self.space.element_geometry(elem).map(RectExt::as_local)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn element_under(&self, location: Point<f64, Local>) -> Option<KeyboardFocusTarget> {
|
pub fn popup_element_under(&self, location: Point<f64, Local>) -> Option<KeyboardFocusTarget> {
|
||||||
self.space
|
self.space
|
||||||
.element_under(location.as_logical())
|
.elements()
|
||||||
.map(|(mapped, _)| mapped.clone().into())
|
.rev()
|
||||||
|
.map(|e| (e, self.space.element_location(e).unwrap() - e.geometry().loc))
|
||||||
|
.filter(|(e, render_location)| {
|
||||||
|
let mut bbox = e.bbox();
|
||||||
|
bbox.loc += *render_location;
|
||||||
|
bbox.to_f64().contains(location.as_logical())
|
||||||
|
})
|
||||||
|
.find_map(|(e, render_location)| {
|
||||||
|
let render_location = render_location
|
||||||
|
.as_local()
|
||||||
|
.to_f64();
|
||||||
|
let point = location - render_location;
|
||||||
|
if e.focus_under(point.as_logical(), WindowSurfaceType::POPUP | WindowSurfaceType::SUBSURFACE).is_some() {
|
||||||
|
Some(e.clone().into())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toplevel_element_under(&self, location: Point<f64, Local>) -> Option<KeyboardFocusTarget> {
|
||||||
|
self.space
|
||||||
|
.elements()
|
||||||
|
.rev()
|
||||||
|
.map(|e| (e, self.space.element_location(e).unwrap() - e.geometry().loc))
|
||||||
|
.filter(|(e, render_location)| {
|
||||||
|
let mut bbox = e.bbox();
|
||||||
|
bbox.loc += *render_location;
|
||||||
|
bbox.to_f64().contains(location.as_logical())
|
||||||
|
})
|
||||||
|
.find_map(|(e, render_location)| {
|
||||||
|
let render_location = render_location
|
||||||
|
.as_local()
|
||||||
|
.to_f64();
|
||||||
|
let point = location - render_location;
|
||||||
|
if e.focus_under(point.as_logical(), WindowSurfaceType::TOPLEVEL | WindowSurfaceType::SUBSURFACE).is_some() {
|
||||||
|
Some(e.clone().into())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn surface_under(
|
pub fn popup_surface_under(
|
||||||
&mut self,
|
&self,
|
||||||
location: Point<f64, Local>,
|
location: Point<f64, Local>,
|
||||||
) -> Option<(PointerFocusTarget, Point<f64, Local>)> {
|
) -> Option<(PointerFocusTarget, Point<f64, Local>)> {
|
||||||
|
self.space
|
||||||
|
.elements()
|
||||||
|
.rev()
|
||||||
|
.map(|e| (e, self.space.element_location(e).unwrap() - e.geometry().loc))
|
||||||
|
.filter(|(e, render_location)| {
|
||||||
|
let mut bbox = e.bbox();
|
||||||
|
bbox.loc += *render_location;
|
||||||
|
bbox.to_f64().contains(location.as_logical())
|
||||||
|
})
|
||||||
|
.find_map(|(e, render_location)| {
|
||||||
|
let render_location = render_location
|
||||||
|
.as_local()
|
||||||
|
.to_f64();
|
||||||
|
let point = location - render_location;
|
||||||
|
e.focus_under(
|
||||||
|
point.as_logical(),
|
||||||
|
WindowSurfaceType::POPUP | WindowSurfaceType::SUBSURFACE,
|
||||||
|
)
|
||||||
|
.map(|(surface, surface_offset)| {
|
||||||
|
(surface, render_location + surface_offset.as_local())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toplevel_surface_under(
|
||||||
|
&self,
|
||||||
|
location: Point<f64, Local>,
|
||||||
|
) -> Option<(PointerFocusTarget, Point<f64, Local>)> {
|
||||||
|
self.space
|
||||||
|
.elements()
|
||||||
|
.rev()
|
||||||
|
.map(|e| (e, self.space.element_location(e).unwrap() - e.geometry().loc))
|
||||||
|
.filter(|(e, render_location)| {
|
||||||
|
let mut bbox = e.bbox();
|
||||||
|
bbox.loc += *render_location;
|
||||||
|
bbox.to_f64().contains(location.as_logical())
|
||||||
|
})
|
||||||
|
.find_map(|(e, render_location)| {
|
||||||
|
let render_location = render_location.as_local().to_f64();
|
||||||
|
let point = location - render_location;
|
||||||
|
e.focus_under(
|
||||||
|
point.as_logical(),
|
||||||
|
WindowSurfaceType::TOPLEVEL | WindowSurfaceType::SUBSURFACE,
|
||||||
|
)
|
||||||
|
.map(|(surface, surface_offset)| {
|
||||||
|
(
|
||||||
|
surface,
|
||||||
|
render_location + surface_offset.as_local(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_pointer_position(&mut self, location: Option<Point<f64, Local>>) {
|
||||||
|
let Some(location) = location else {
|
||||||
|
self.hovered_stack.take();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
let res = self
|
let res = self
|
||||||
.space
|
.space
|
||||||
.element_under(location.as_logical())
|
.element_under(location.as_logical())
|
||||||
|
|
@ -754,15 +853,6 @@ impl FloatingLayout {
|
||||||
} else {
|
} else {
|
||||||
self.hovered_stack.take();
|
self.hovered_stack.take();
|
||||||
}
|
}
|
||||||
|
|
||||||
res.and_then(|(element, space_offset)| {
|
|
||||||
let point = location - space_offset.to_f64();
|
|
||||||
element
|
|
||||||
.focus_under(point.as_logical())
|
|
||||||
.map(|(surface, surface_offset)| {
|
|
||||||
(surface, space_offset.to_f64() + surface_offset.as_local())
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stacking_indicator(&self) -> Option<Rectangle<i32, Local>> {
|
pub fn stacking_indicator(&self) -> Option<Rectangle<i32, Local>> {
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ use smithay::{
|
||||||
glow::GlowRenderer,
|
glow::GlowRenderer,
|
||||||
ImportAll, ImportMem, Renderer,
|
ImportAll, ImportMem, Renderer,
|
||||||
},
|
},
|
||||||
desktop::{layer_map_for_output, space::SpaceElement, PopupKind},
|
desktop::{layer_map_for_output, space::SpaceElement, PopupKind, WindowSurfaceType},
|
||||||
input::Seat,
|
input::Seat,
|
||||||
output::Output,
|
output::Output,
|
||||||
reexports::wayland_server::Client,
|
reexports::wayland_server::Client,
|
||||||
|
|
@ -3104,17 +3104,38 @@ impl TilingLayout {
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn element_under(&self, location_f64: Point<f64, Local>) -> Option<KeyboardFocusTarget> {
|
pub fn popup_element_under(&self, location_f64: Point<f64, Local>) -> Option<KeyboardFocusTarget> {
|
||||||
let location = location_f64.to_i32_round();
|
let location = location_f64.to_i32_round();
|
||||||
|
|
||||||
for (mapped, geo) in self.mapped() {
|
for (mapped, geo) in self.mapped() {
|
||||||
if !mapped.bbox().contains((location - geo.loc).as_logical()) {
|
if !mapped.bbox().contains((location - geo.loc).as_logical()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if mapped.is_in_input_region(
|
|
||||||
&((location_f64 - geo.loc.to_f64()).as_logical() + mapped.geometry().loc.to_f64()),
|
if mapped.focus_under(
|
||||||
) {
|
(location_f64 - geo.loc.to_f64()).as_logical() + mapped.geometry().loc.to_f64(),
|
||||||
|
WindowSurfaceType::POPUP | WindowSurfaceType::SUBSURFACE,
|
||||||
|
).is_some() {
|
||||||
|
return Some(mapped.clone().into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toplevel_element_under(&self, location_f64: Point<f64, Local>) -> Option<KeyboardFocusTarget> {
|
||||||
|
let location = location_f64.to_i32_round();
|
||||||
|
|
||||||
|
for (mapped, geo) in self.mapped() {
|
||||||
|
if !mapped.bbox().contains((location - geo.loc).as_logical()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if mapped.focus_under(
|
||||||
|
(location_f64 - geo.loc.to_f64()).as_logical() + mapped.geometry().loc.to_f64(),
|
||||||
|
WindowSurfaceType::TOPLEVEL | WindowSurfaceType::SUBSURFACE,
|
||||||
|
).is_some() {
|
||||||
return Some(mapped.clone().into());
|
return Some(mapped.clone().into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3122,34 +3143,13 @@ impl TilingLayout {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn surface_under(
|
pub fn popup_surface_under(
|
||||||
&mut self,
|
&self,
|
||||||
location_f64: Point<f64, Local>,
|
location_f64: Point<f64, Local>,
|
||||||
overview: OverviewMode,
|
overview: OverviewMode,
|
||||||
) -> Option<(PointerFocusTarget, Point<f64, Local>)> {
|
) -> Option<(PointerFocusTarget, Point<f64, Local>)> {
|
||||||
let gaps = self.gaps();
|
|
||||||
let last_overview_hover = &mut self.last_overview_hover;
|
|
||||||
let placeholder_id = &self.placeholder_id;
|
|
||||||
let tree = &self.queue.trees.back().unwrap().0;
|
|
||||||
let root = tree.root_node_id()?;
|
|
||||||
let location = location_f64.to_i32_round();
|
let location = location_f64.to_i32_round();
|
||||||
|
|
||||||
{
|
|
||||||
let output_geo =
|
|
||||||
Rectangle::from_loc_and_size((0, 0), self.output.geometry().size.as_logical())
|
|
||||||
.as_local();
|
|
||||||
if !output_geo.contains(location) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !matches!(
|
|
||||||
overview,
|
|
||||||
OverviewMode::Started(_, _) | OverviewMode::Active(_)
|
|
||||||
) {
|
|
||||||
last_overview_hover.take();
|
|
||||||
}
|
|
||||||
|
|
||||||
if matches!(overview, OverviewMode::None) {
|
if matches!(overview, OverviewMode::None) {
|
||||||
for (mapped, geo) in self.mapped() {
|
for (mapped, geo) in self.mapped() {
|
||||||
if !mapped.bbox().contains((location - geo.loc).as_logical()) {
|
if !mapped.bbox().contains((location - geo.loc).as_logical()) {
|
||||||
|
|
@ -3157,6 +3157,37 @@ impl TilingLayout {
|
||||||
}
|
}
|
||||||
if let Some((target, surface_offset)) = mapped.focus_under(
|
if let Some((target, surface_offset)) = mapped.focus_under(
|
||||||
(location_f64 - geo.loc.to_f64()).as_logical() + mapped.geometry().loc.to_f64(),
|
(location_f64 - geo.loc.to_f64()).as_logical() + mapped.geometry().loc.to_f64(),
|
||||||
|
WindowSurfaceType::POPUP | WindowSurfaceType::SUBSURFACE,
|
||||||
|
) {
|
||||||
|
return Some((
|
||||||
|
target,
|
||||||
|
geo.loc.to_f64() - mapped.geometry().loc.as_local().to_f64()
|
||||||
|
+ surface_offset.as_local(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toplevel_surface_under(
|
||||||
|
&self,
|
||||||
|
location_f64: Point<f64, Local>,
|
||||||
|
overview: OverviewMode,
|
||||||
|
) -> Option<(PointerFocusTarget, Point<f64, Local>)> {
|
||||||
|
let tree = &self.queue.trees.back().unwrap().0;
|
||||||
|
let root = tree.root_node_id()?;
|
||||||
|
let location = location_f64.to_i32_round();
|
||||||
|
|
||||||
|
if matches!(overview, OverviewMode::None) {
|
||||||
|
for (mapped, geo) in self.mapped() {
|
||||||
|
if !mapped.bbox().contains((location - geo.loc).as_logical()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Some((target, surface_offset)) = mapped.focus_under(
|
||||||
|
(location_f64 - geo.loc.to_f64()).as_logical() + mapped.geometry().loc.to_f64(),
|
||||||
|
WindowSurfaceType::TOPLEVEL | WindowSurfaceType::SUBSURFACE,
|
||||||
) {
|
) {
|
||||||
return Some((
|
return Some((
|
||||||
target,
|
target,
|
||||||
|
|
@ -3204,7 +3235,10 @@ impl TilingLayout {
|
||||||
+ mapped.geometry().loc.to_f64().as_local())
|
+ mapped.geometry().loc.to_f64().as_local())
|
||||||
.as_logical();
|
.as_logical();
|
||||||
mapped
|
mapped
|
||||||
.focus_under(test_point)
|
.focus_under(
|
||||||
|
test_point,
|
||||||
|
WindowSurfaceType::TOPLEVEL | WindowSurfaceType::SUBSURFACE,
|
||||||
|
)
|
||||||
.map(|(surface, surface_offset)| {
|
.map(|(surface, surface_offset)| {
|
||||||
(
|
(
|
||||||
surface,
|
surface,
|
||||||
|
|
@ -3257,7 +3291,37 @@ impl TilingLayout {
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
} else if matches!(
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_pointer_position(
|
||||||
|
&mut self,
|
||||||
|
location_f64: Option<Point<f64, Local>>,
|
||||||
|
overview: OverviewMode,
|
||||||
|
) {
|
||||||
|
let gaps = self.gaps();
|
||||||
|
let last_overview_hover = &mut self.last_overview_hover;
|
||||||
|
let placeholder_id = &self.placeholder_id;
|
||||||
|
let tree = &self.queue.trees.back().unwrap().0;
|
||||||
|
let Some(root) = tree.root_node_id() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if !matches!(
|
||||||
|
overview,
|
||||||
|
OverviewMode::Started(_, _) | OverviewMode::Active(_)
|
||||||
|
) || location_f64.is_none()
|
||||||
|
{
|
||||||
|
last_overview_hover.take();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let location_f64 = location_f64.unwrap();
|
||||||
|
let location = location_f64.to_i32_round();
|
||||||
|
|
||||||
|
if matches!(
|
||||||
overview.active_trigger(),
|
overview.active_trigger(),
|
||||||
Some(Trigger::Pointer(_) | Trigger::Touch(_))
|
Some(Trigger::Pointer(_) | Trigger::Touch(_))
|
||||||
) {
|
) {
|
||||||
|
|
@ -3319,7 +3383,9 @@ impl TilingLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(res_id) = result {
|
if let Some(res_id) = result {
|
||||||
let mut last_geometry = *geometries.get(&res_id)?;
|
let Some(mut last_geometry) = geometries.get(&res_id).copied() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
let node = tree.get(&res_id).unwrap();
|
let node = tree.get(&res_id).unwrap();
|
||||||
let data = node.data().clone();
|
let data = node.data().clone();
|
||||||
|
|
||||||
|
|
@ -3716,10 +3782,6 @@ impl TilingLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
144
src/shell/mod.rs
144
src/shell/mod.rs
|
|
@ -54,8 +54,6 @@ use smithay::{
|
||||||
xwayland::X11Surface,
|
xwayland::X11Surface,
|
||||||
};
|
};
|
||||||
|
|
||||||
use smithay::wayland::shell::wlr_layer::Layer as WlrLayer;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::render::animations::spring::{Spring, SpringParams},
|
backend::render::animations::spring::{Spring, SpringParams},
|
||||||
config::Config,
|
config::Config,
|
||||||
|
|
@ -1532,97 +1530,6 @@ impl Shell {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Derives a keyboard focus target from a global position, and indicates whether the
|
|
||||||
/// the shell should start a move request event. Used during cursor related focus checks
|
|
||||||
pub fn keyboard_target_from_position(
|
|
||||||
&self,
|
|
||||||
global_position: Point<f64, Global>,
|
|
||||||
output: &Output,
|
|
||||||
) -> Option<KeyboardFocusTarget> {
|
|
||||||
let relative_pos = global_position.to_local(output);
|
|
||||||
|
|
||||||
let mut under: Option<KeyboardFocusTarget> = None;
|
|
||||||
// if the lockscreen is active
|
|
||||||
if let Some(session_lock) = self.session_lock.as_ref() {
|
|
||||||
under = session_lock
|
|
||||||
.surfaces
|
|
||||||
.get(output)
|
|
||||||
.map(|lock| lock.clone().into());
|
|
||||||
// if the output can receive keyboard focus
|
|
||||||
} else if let Some(window) = self.active_space(output).get_fullscreen() {
|
|
||||||
let layers = layer_map_for_output(output);
|
|
||||||
if let Some(layer) = layers.layer_under(WlrLayer::Overlay, relative_pos.as_logical()) {
|
|
||||||
let layer_loc = layers.layer_geometry(layer).unwrap().loc;
|
|
||||||
if layer.can_receive_keyboard_focus()
|
|
||||||
&& layer
|
|
||||||
.surface_under(
|
|
||||||
relative_pos.as_logical() - layer_loc.to_f64(),
|
|
||||||
WindowSurfaceType::ALL,
|
|
||||||
)
|
|
||||||
.is_some()
|
|
||||||
{
|
|
||||||
under = Some(layer.clone().into());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
under = Some(window.clone().into());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let done = {
|
|
||||||
let layers = layer_map_for_output(output);
|
|
||||||
if let Some(layer) = layers
|
|
||||||
.layer_under(WlrLayer::Overlay, relative_pos.as_logical())
|
|
||||||
.or_else(|| layers.layer_under(WlrLayer::Top, relative_pos.as_logical()))
|
|
||||||
{
|
|
||||||
let layer_loc = layers.layer_geometry(layer).unwrap().loc;
|
|
||||||
if layer.can_receive_keyboard_focus()
|
|
||||||
&& layer
|
|
||||||
.surface_under(
|
|
||||||
relative_pos.as_logical() - layer_loc.to_f64(),
|
|
||||||
WindowSurfaceType::ALL,
|
|
||||||
)
|
|
||||||
.is_some()
|
|
||||||
{
|
|
||||||
under = Some(layer.clone().into());
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if !done {
|
|
||||||
// Don't check override redirect windows, because we don't set keyboard focus to them explicitly.
|
|
||||||
// These cases are handled by the XwaylandKeyboardGrab.
|
|
||||||
if let Some(target) = self.element_under(global_position, output) {
|
|
||||||
under = Some(target);
|
|
||||||
} else {
|
|
||||||
let layers = layer_map_for_output(output);
|
|
||||||
if let Some(layer) = layers
|
|
||||||
.layer_under(WlrLayer::Bottom, relative_pos.as_logical())
|
|
||||||
.or_else(|| {
|
|
||||||
layers.layer_under(WlrLayer::Background, relative_pos.as_logical())
|
|
||||||
})
|
|
||||||
{
|
|
||||||
let layer_loc = layers.layer_geometry(layer).unwrap().loc;
|
|
||||||
if layer.can_receive_keyboard_focus()
|
|
||||||
&& layer
|
|
||||||
.surface_under(
|
|
||||||
relative_pos.as_logical() - layer_loc.to_f64(),
|
|
||||||
WindowSurfaceType::ALL,
|
|
||||||
)
|
|
||||||
.is_some()
|
|
||||||
{
|
|
||||||
under = Some(layer.clone().into());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
under
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Coerce a keyboard focus target into a CosmicMapped element. This is useful when performing window specific
|
/// Coerce a keyboard focus target into a CosmicMapped element. This is useful when performing window specific
|
||||||
/// actions, such as closing a window
|
/// actions, such as closing a window
|
||||||
pub fn focused_element(&self, focus_target: &KeyboardFocusTarget) -> Option<CosmicMapped> {
|
pub fn focused_element(&self, focus_target: &KeyboardFocusTarget) -> Option<CosmicMapped> {
|
||||||
|
|
@ -2053,6 +1960,26 @@ impl Shell {
|
||||||
self.pending_windows.retain(|(s, _, _)| s.alive());
|
self.pending_windows.retain(|(s, _, _)| s.alive());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_pointer_position(&mut self, location: Point<f64, Local>, output: &Output) {
|
||||||
|
for (o, set) in self.workspaces.sets.iter_mut() {
|
||||||
|
if o == output {
|
||||||
|
set.sticky_layer.update_pointer_position(Some(location));
|
||||||
|
for (i, workspace) in set.workspaces.iter_mut().enumerate() {
|
||||||
|
if i == set.active {
|
||||||
|
workspace.update_pointer_position(Some(location), self.overview_mode.clone());
|
||||||
|
} else {
|
||||||
|
workspace.update_pointer_position(None, self.overview_mode.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
set.sticky_layer.update_pointer_position(None);
|
||||||
|
for workspace in &mut set.workspaces {
|
||||||
|
workspace.update_pointer_position(None, self.overview_mode.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn remap_unfullscreened_window(
|
pub fn remap_unfullscreened_window(
|
||||||
&mut self,
|
&mut self,
|
||||||
mapped: CosmicMapped,
|
mapped: CosmicMapped,
|
||||||
|
|
@ -2382,33 +2309,6 @@ impl Shell {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn element_under(
|
|
||||||
&self,
|
|
||||||
location: Point<f64, Global>,
|
|
||||||
output: &Output,
|
|
||||||
) -> Option<KeyboardFocusTarget> {
|
|
||||||
self.workspaces.sets.get(output).and_then(|set| {
|
|
||||||
set.sticky_layer
|
|
||||||
.space
|
|
||||||
.element_under(location.to_local(output).as_logical())
|
|
||||||
.map(|(mapped, _)| mapped.clone().into())
|
|
||||||
.or_else(|| set.workspaces[set.active].element_under(location))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
pub fn surface_under(
|
|
||||||
&mut self,
|
|
||||||
location: Point<f64, Global>,
|
|
||||||
output: &Output,
|
|
||||||
) -> Option<(PointerFocusTarget, Point<f64, Global>)> {
|
|
||||||
let overview = self.overview_mode.clone();
|
|
||||||
self.workspaces.sets.get_mut(output).and_then(|set| {
|
|
||||||
set.sticky_layer
|
|
||||||
.surface_under(location.to_local(output))
|
|
||||||
.map(|(target, offset)| (target, offset.to_global(output)))
|
|
||||||
.or_else(|| set.workspaces[set.active].surface_under(location, overview))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn move_window(
|
pub fn move_window(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
@ -2782,7 +2682,7 @@ impl Shell {
|
||||||
let mapped = if move_out_of_stack {
|
let mapped = if move_out_of_stack {
|
||||||
let new_mapped: CosmicMapped =
|
let new_mapped: CosmicMapped =
|
||||||
CosmicWindow::new(window.clone(), evlh.clone(), self.theme.clone()).into();
|
CosmicWindow::new(window.clone(), evlh.clone(), self.theme.clone()).into();
|
||||||
start_data.set_focus(new_mapped.focus_under((0., 0.).into()));
|
start_data.set_focus(new_mapped.focus_under((0., 0.).into(), WindowSurfaceType::ALL));
|
||||||
new_mapped
|
new_mapped
|
||||||
} else {
|
} else {
|
||||||
old_mapped.clone()
|
old_mapped.clone()
|
||||||
|
|
@ -3250,7 +3150,7 @@ impl Shell {
|
||||||
|
|
||||||
let element_offset = (new_loc - geometry.loc).as_logical();
|
let element_offset = (new_loc - geometry.loc).as_logical();
|
||||||
let focus = mapped
|
let focus = mapped
|
||||||
.focus_under(element_offset.to_f64())
|
.focus_under(element_offset.to_f64(), WindowSurfaceType::ALL)
|
||||||
.map(|(target, surface_offset)| (target, (surface_offset + element_offset.to_f64())));
|
.map(|(target, surface_offset)| (target, (surface_offset + element_offset.to_f64())));
|
||||||
start_data.set_location(new_loc.as_logical().to_f64());
|
start_data.set_location(new_loc.as_logical().to_f64());
|
||||||
start_data.set_focus(focus.clone());
|
start_data.set_focus(focus.clone());
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ use smithay::{
|
||||||
utils::{DamageSet, OpaqueRegions},
|
utils::{DamageSet, OpaqueRegions},
|
||||||
ImportAll, ImportMem, Renderer,
|
ImportAll, ImportMem, Renderer,
|
||||||
},
|
},
|
||||||
desktop::{layer_map_for_output, space::SpaceElement},
|
desktop::{layer_map_for_output, space::SpaceElement, WindowSurfaceType},
|
||||||
input::Seat,
|
input::Seat,
|
||||||
output::Output,
|
output::Output,
|
||||||
reexports::wayland_server::{Client, Resource},
|
reexports::wayland_server::{Client, Resource},
|
||||||
|
|
@ -434,6 +434,27 @@ impl Workspace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fullscreen_geometry(&self) -> Option<Rectangle<i32, Local>> {
|
||||||
|
self.fullscreen.as_ref().map(|fullscreen| {
|
||||||
|
let bbox = fullscreen.surface.bbox().as_local();
|
||||||
|
|
||||||
|
let mut full_geo =
|
||||||
|
Rectangle::from_loc_and_size((0, 0), self.output.geometry().size.as_local());
|
||||||
|
if bbox != full_geo {
|
||||||
|
if bbox.size.w < full_geo.size.w {
|
||||||
|
full_geo.loc.x += (full_geo.size.w - bbox.size.w) / 2;
|
||||||
|
full_geo.size.w = bbox.size.w;
|
||||||
|
}
|
||||||
|
if bbox.size.h < full_geo.size.h {
|
||||||
|
full_geo.loc.y += (full_geo.size.h - bbox.size.h) / 2;
|
||||||
|
full_geo.size.h = bbox.size.h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
full_geo
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn element_for_surface<S>(&self, surface: &S) -> Option<&CosmicMapped>
|
pub fn element_for_surface<S>(&self, surface: &S) -> Option<&CosmicMapped>
|
||||||
where
|
where
|
||||||
CosmicSurface: PartialEq<S>,
|
CosmicSurface: PartialEq<S>,
|
||||||
|
|
@ -445,25 +466,151 @@ impl Workspace {
|
||||||
.find(|e| e.windows().any(|(w, _)| &w == surface))
|
.find(|e| e.windows().any(|(w, _)| &w == surface))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn element_under(&self, location: Point<f64, Global>) -> Option<KeyboardFocusTarget> {
|
pub fn popup_element_under(&self, location: Point<f64, Global>) -> Option<KeyboardFocusTarget> {
|
||||||
|
if !self.output.geometry().contains(location.to_i32_round()) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let location = location.to_local(&self.output);
|
let location = location.to_local(&self.output);
|
||||||
|
|
||||||
|
if let Some(fullscreen) = self.fullscreen.as_ref() {
|
||||||
|
if !fullscreen.is_animating() {
|
||||||
|
let geometry = self.fullscreen_geometry().unwrap();
|
||||||
|
return fullscreen
|
||||||
|
.surface
|
||||||
|
.0
|
||||||
|
.surface_under(
|
||||||
|
(location + geometry.loc.to_f64()).as_logical(),
|
||||||
|
WindowSurfaceType::POPUP | WindowSurfaceType::SUBSURFACE,
|
||||||
|
)
|
||||||
|
.is_some()
|
||||||
|
.then(|| KeyboardFocusTarget::Fullscreen(fullscreen.surface.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.floating_layer
|
self.floating_layer
|
||||||
.element_under(location)
|
.popup_element_under(location)
|
||||||
.or_else(|| self.tiling_layer.element_under(location))
|
.or_else(|| self.tiling_layer.popup_element_under(location))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn surface_under(
|
pub fn toplevel_element_under(
|
||||||
&mut self,
|
&self,
|
||||||
|
location: Point<f64, Global>,
|
||||||
|
) -> Option<KeyboardFocusTarget> {
|
||||||
|
if !self.output.geometry().contains(location.to_i32_round()) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let location = location.to_local(&self.output);
|
||||||
|
|
||||||
|
if let Some(fullscreen) = self.fullscreen.as_ref() {
|
||||||
|
if !fullscreen.is_animating() {
|
||||||
|
let geometry = self.fullscreen_geometry().unwrap();
|
||||||
|
return fullscreen
|
||||||
|
.surface
|
||||||
|
.0
|
||||||
|
.surface_under(
|
||||||
|
(location + geometry.loc.to_f64()).as_logical(),
|
||||||
|
WindowSurfaceType::TOPLEVEL | WindowSurfaceType::SUBSURFACE,
|
||||||
|
)
|
||||||
|
.is_some()
|
||||||
|
.then(|| KeyboardFocusTarget::Fullscreen(fullscreen.surface.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.floating_layer
|
||||||
|
.toplevel_element_under(location)
|
||||||
|
.or_else(|| self.tiling_layer.toplevel_element_under(location))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn popup_surface_under(
|
||||||
|
&self,
|
||||||
location: Point<f64, Global>,
|
location: Point<f64, Global>,
|
||||||
overview: OverviewMode,
|
overview: OverviewMode,
|
||||||
) -> Option<(PointerFocusTarget, Point<f64, Global>)> {
|
) -> Option<(PointerFocusTarget, Point<f64, Global>)> {
|
||||||
|
if !self.output.geometry().contains(location.to_i32_round()) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let location = location.to_local(&self.output);
|
let location = location.to_local(&self.output);
|
||||||
|
|
||||||
|
if let Some(fullscreen) = self.fullscreen.as_ref() {
|
||||||
|
if !fullscreen.is_animating() {
|
||||||
|
let geometry = self.fullscreen_geometry().unwrap();
|
||||||
|
return fullscreen
|
||||||
|
.surface
|
||||||
|
.0
|
||||||
|
.surface_under(
|
||||||
|
(location + geometry.loc.to_f64()).as_logical(),
|
||||||
|
WindowSurfaceType::POPUP | WindowSurfaceType::SUBSURFACE,
|
||||||
|
)
|
||||||
|
.map(|(surface, surface_offset)| {
|
||||||
|
(
|
||||||
|
PointerFocusTarget::WlSurface {
|
||||||
|
surface,
|
||||||
|
toplevel: Some(fullscreen.surface.clone().into()),
|
||||||
|
},
|
||||||
|
(geometry.loc + surface_offset.as_local())
|
||||||
|
.to_global(&self.output)
|
||||||
|
.to_f64(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.floating_layer
|
self.floating_layer
|
||||||
.surface_under(location)
|
.popup_surface_under(location)
|
||||||
.or_else(|| self.tiling_layer.surface_under(location, overview))
|
.or_else(|| self.tiling_layer.popup_surface_under(location, overview))
|
||||||
.map(|(m, p)| (m, p.to_global(&self.output)))
|
.map(|(m, p)| (m, p.to_global(&self.output)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn toplevel_surface_under(
|
||||||
|
&self,
|
||||||
|
location: Point<f64, Global>,
|
||||||
|
overview: OverviewMode,
|
||||||
|
) -> Option<(PointerFocusTarget, Point<f64, Global>)> {
|
||||||
|
if !self.output.geometry().contains(location.to_i32_round()) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let location = location.to_local(&self.output);
|
||||||
|
|
||||||
|
if let Some(fullscreen) = self.fullscreen.as_ref() {
|
||||||
|
if !fullscreen.is_animating() {
|
||||||
|
let geometry = self.fullscreen_geometry().unwrap();
|
||||||
|
return fullscreen
|
||||||
|
.surface
|
||||||
|
.0
|
||||||
|
.surface_under(
|
||||||
|
(location + geometry.loc.to_f64()).as_logical(),
|
||||||
|
WindowSurfaceType::TOPLEVEL | WindowSurfaceType::SUBSURFACE,
|
||||||
|
)
|
||||||
|
.map(|(surface, surface_offset)| {
|
||||||
|
(
|
||||||
|
PointerFocusTarget::WlSurface {
|
||||||
|
surface,
|
||||||
|
toplevel: Some(fullscreen.surface.clone().into()),
|
||||||
|
},
|
||||||
|
(geometry.loc + surface_offset.as_local())
|
||||||
|
.to_global(&self.output)
|
||||||
|
.to_f64(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.floating_layer
|
||||||
|
.toplevel_surface_under(location)
|
||||||
|
.or_else(|| self.tiling_layer.toplevel_surface_under(location, overview))
|
||||||
|
.map(|(m, p)| (m, p.to_global(&self.output)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_pointer_position(
|
||||||
|
&mut self,
|
||||||
|
location: Option<Point<f64, Local>>,
|
||||||
|
overview: OverviewMode,
|
||||||
|
) {
|
||||||
|
self.floating_layer.update_pointer_position(location);
|
||||||
|
self.tiling_layer
|
||||||
|
.update_pointer_position(location, overview);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn element_geometry(&self, elem: &CosmicMapped) -> Option<Rectangle<i32, Local>> {
|
pub fn element_geometry(&self, elem: &CosmicMapped) -> Option<Rectangle<i32, Local>> {
|
||||||
self.floating_layer
|
self.floating_layer
|
||||||
.element_geometry(elem)
|
.element_geometry(elem)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue