overlap-notify: Implementation fixes
This commit is contained in:
parent
81b9fb179b
commit
895261c2bf
1 changed files with 78 additions and 42 deletions
|
|
@ -12,7 +12,6 @@ use cosmic_protocols::{
|
||||||
zcosmic_toplevel_info_v1::ZcosmicToplevelInfoV1,
|
zcosmic_toplevel_info_v1::ZcosmicToplevelInfoV1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use rand::distributions::{Alphanumeric, DistString};
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
desktop::{layer_map_for_output, LayerSurface},
|
desktop::{layer_map_for_output, LayerSurface},
|
||||||
output::Output,
|
output::Output,
|
||||||
|
|
@ -29,7 +28,7 @@ use smithay::{
|
||||||
shell::wlr_layer::{ExclusiveZone, Layer},
|
shell::wlr_layer::{ExclusiveZone, Layer},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use wayland_backend::server::GlobalId;
|
use wayland_backend::server::{GlobalId, ObjectId};
|
||||||
|
|
||||||
use crate::utils::prelude::{RectExt, RectGlobalExt, RectLocalExt};
|
use crate::utils::prelude::{RectExt, RectGlobalExt, RectLocalExt};
|
||||||
|
|
||||||
|
|
@ -94,14 +93,18 @@ impl OverlapNotifyState {
|
||||||
if inner.has_active_notifications() {
|
if inner.has_active_notifications() {
|
||||||
let mut new_snapshot = OverlapSnapshot::default();
|
let mut new_snapshot = OverlapSnapshot::default();
|
||||||
|
|
||||||
let layer_geo = layer_surface.bbox().as_local().to_global(output);
|
let layer_geo = map
|
||||||
|
.layer_geometry(layer_surface)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.as_local()
|
||||||
|
.to_global(&output);
|
||||||
|
|
||||||
for window in state.toplevel_info_state().registered_toplevels() {
|
for window in state.toplevel_info_state().registered_toplevels() {
|
||||||
if let Some(window_geo) = window.global_geometry() {
|
if let Some(window_geo) = window.global_geometry() {
|
||||||
if let Some(intersection) = layer_geo.intersection(window_geo) {
|
if let Some(intersection) = layer_geo.intersection(window_geo) {
|
||||||
// relative to window location
|
// relative to layer location
|
||||||
let region = Rectangle::from_loc_and_size(
|
let region = Rectangle::from_loc_and_size(
|
||||||
intersection.loc - window_geo.loc,
|
intersection.loc - layer_geo.loc,
|
||||||
intersection.size,
|
intersection.size,
|
||||||
)
|
)
|
||||||
.as_logical();
|
.as_logical();
|
||||||
|
|
@ -111,11 +114,18 @@ impl OverlapNotifyState {
|
||||||
}
|
}
|
||||||
|
|
||||||
for other_surface in map.layers().filter(|s| *s != layer_surface) {
|
for other_surface in map.layers().filter(|s| *s != layer_surface) {
|
||||||
let other_geo = other_surface.bbox().as_local().to_global(output);
|
if other_surface.wl_surface().id() == layer_surface.wl_surface().id() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let other_geo = map
|
||||||
|
.layer_geometry(other_surface)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.as_local()
|
||||||
|
.to_global(&output);
|
||||||
if let Some(intersection) = layer_geo.intersection(other_geo) {
|
if let Some(intersection) = layer_geo.intersection(other_geo) {
|
||||||
// relative to window location
|
// relative to layer location
|
||||||
let region = Rectangle::from_loc_and_size(
|
let region = Rectangle::from_loc_and_size(
|
||||||
intersection.loc - other_geo.loc,
|
intersection.loc - layer_geo.loc,
|
||||||
intersection.size,
|
intersection.size,
|
||||||
)
|
)
|
||||||
.as_logical();
|
.as_logical();
|
||||||
|
|
@ -156,20 +166,26 @@ impl LayerOverlapNotificationDataInternal {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_notification(&mut self, new_notification: ZcosmicOverlapNotificationV1) {
|
pub fn add_notification(&mut self, new_notification: ZcosmicOverlapNotificationV1) {
|
||||||
for (toplevel, overlap) in &self.last_snapshot.toplevel_overlaps {
|
if let Some(client) = new_notification.client() {
|
||||||
if let Ok(toplevel) = toplevel.upgrade() {
|
for (toplevel, overlap) in &self.last_snapshot.toplevel_overlaps {
|
||||||
new_notification.toplevel_enter(
|
if let Some(toplevel) = toplevel
|
||||||
&toplevel,
|
.upgrade()
|
||||||
overlap.loc.x,
|
.ok()
|
||||||
overlap.loc.y,
|
.filter(|handle| handle.client().is_some_and(|c| c == client))
|
||||||
overlap.size.w,
|
{
|
||||||
overlap.size.h,
|
new_notification.toplevel_enter(
|
||||||
);
|
&toplevel,
|
||||||
|
overlap.loc.x,
|
||||||
|
overlap.loc.y,
|
||||||
|
overlap.size.w,
|
||||||
|
overlap.size.h,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (layer_surface, (exclusive, layer, overlap)) in &self.last_snapshot.layer_overlaps {
|
for (_, (identifier, exclusive, layer, overlap)) in &self.last_snapshot.layer_overlaps {
|
||||||
new_notification.layer_enter(
|
new_notification.layer_enter(
|
||||||
layer_surface.clone(),
|
identifier.clone(),
|
||||||
if *exclusive { 1 } else { 0 },
|
if *exclusive { 1 } else { 0 },
|
||||||
match layer {
|
match layer {
|
||||||
Layer::Background => WlrLayer::Background,
|
Layer::Background => WlrLayer::Background,
|
||||||
|
|
@ -196,44 +212,61 @@ impl LayerOverlapNotificationDataInternal {
|
||||||
for toplevel in self.last_snapshot.toplevel_overlaps.keys() {
|
for toplevel in self.last_snapshot.toplevel_overlaps.keys() {
|
||||||
if !new_snapshot.toplevel_overlaps.contains_key(toplevel) {
|
if !new_snapshot.toplevel_overlaps.contains_key(toplevel) {
|
||||||
if let Ok(toplevel) = toplevel.upgrade() {
|
if let Ok(toplevel) = toplevel.upgrade() {
|
||||||
for notification in ¬ifications {
|
if let Some(client) = toplevel.client() {
|
||||||
notification.toplevel_leave(&toplevel);
|
for notification in notifications
|
||||||
|
.iter()
|
||||||
|
.filter(|n| n.client().is_some_and(|c| c == client))
|
||||||
|
{
|
||||||
|
notification.toplevel_leave(&toplevel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (toplevel, overlap) in &new_snapshot.toplevel_overlaps {
|
for (toplevel, overlap) in &new_snapshot.toplevel_overlaps {
|
||||||
if !self.last_snapshot.toplevel_overlaps.contains_key(toplevel) {
|
if !self
|
||||||
|
.last_snapshot
|
||||||
|
.toplevel_overlaps
|
||||||
|
.get(toplevel)
|
||||||
|
.is_some_and(|old_overlap| old_overlap == overlap)
|
||||||
|
{
|
||||||
if let Ok(toplevel) = toplevel.upgrade() {
|
if let Ok(toplevel) = toplevel.upgrade() {
|
||||||
for notification in ¬ifications {
|
if let Some(client) = toplevel.client() {
|
||||||
notification.toplevel_enter(
|
for notification in notifications
|
||||||
&toplevel,
|
.iter()
|
||||||
overlap.loc.x,
|
.filter(|n| n.client().is_some_and(|c| c == client))
|
||||||
overlap.loc.y,
|
{
|
||||||
overlap.size.w,
|
notification.toplevel_enter(
|
||||||
overlap.size.h,
|
&toplevel,
|
||||||
);
|
overlap.loc.x,
|
||||||
|
overlap.loc.y,
|
||||||
|
overlap.size.w,
|
||||||
|
overlap.size.h,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for layer_surface in self.last_snapshot.layer_overlaps.keys() {
|
for (layer_surface, (identifier, ..)) in &self.last_snapshot.layer_overlaps {
|
||||||
if new_snapshot.layer_overlaps.contains_key(layer_surface) {
|
if !new_snapshot.layer_overlaps.contains_key(layer_surface) {
|
||||||
for notification in ¬ifications {
|
for notification in ¬ifications {
|
||||||
notification.layer_leave(layer_surface.clone());
|
notification.layer_leave(identifier.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (layer_surface, (exclusive, layer, overlap)) in &new_snapshot.layer_overlaps {
|
for (layer_surface, (identifier, exclusive, layer, overlap)) in &new_snapshot.layer_overlaps
|
||||||
|
{
|
||||||
if !self
|
if !self
|
||||||
.last_snapshot
|
.last_snapshot
|
||||||
.layer_overlaps
|
.layer_overlaps
|
||||||
.contains_key(layer_surface)
|
.get(layer_surface)
|
||||||
|
.is_some_and(|(_, _, _, old_overlap)| old_overlap == overlap)
|
||||||
{
|
{
|
||||||
for notification in ¬ifications {
|
for notification in ¬ifications {
|
||||||
notification.layer_enter(
|
notification.layer_enter(
|
||||||
layer_surface.clone(),
|
identifier.clone(),
|
||||||
if *exclusive { 1 } else { 0 },
|
if *exclusive { 1 } else { 0 },
|
||||||
match layer {
|
match layer {
|
||||||
Layer::Background => WlrLayer::Background,
|
Layer::Background => WlrLayer::Background,
|
||||||
|
|
@ -257,7 +290,7 @@ impl LayerOverlapNotificationDataInternal {
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
struct OverlapSnapshot {
|
struct OverlapSnapshot {
|
||||||
toplevel_overlaps: HashMap<Weak<ExtForeignToplevelHandleV1>, Rectangle<i32, Logical>>,
|
toplevel_overlaps: HashMap<Weak<ExtForeignToplevelHandleV1>, Rectangle<i32, Logical>>,
|
||||||
layer_overlaps: HashMap<String, (bool, Layer, Rectangle<i32, Logical>)>,
|
layer_overlaps: HashMap<ObjectId, (String, bool, Layer, Rectangle<i32, Logical>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OverlapSnapshot {
|
impl OverlapSnapshot {
|
||||||
|
|
@ -283,18 +316,21 @@ impl OverlapSnapshot {
|
||||||
ExclusiveZone::Exclusive(_)
|
ExclusiveZone::Exclusive(_)
|
||||||
);
|
);
|
||||||
let layer = layer_surface.layer();
|
let layer = layer_surface.layer();
|
||||||
let identifier = layer_surface.user_data().get_or_insert(Identifier::default);
|
let id = layer_surface.wl_surface().id();
|
||||||
|
let identifier = layer_surface
|
||||||
|
.user_data()
|
||||||
|
.get_or_insert(|| Identifier::from(id.clone()));
|
||||||
|
|
||||||
self.layer_overlaps
|
self.layer_overlaps
|
||||||
.insert(identifier.0.clone(), (exclusive, layer, overlap));
|
.insert(id, (identifier.0.clone(), exclusive, layer, overlap));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Identifier(String);
|
struct Identifier(String);
|
||||||
|
|
||||||
impl Default for Identifier {
|
impl From<ObjectId> for Identifier {
|
||||||
fn default() -> Self {
|
fn from(value: ObjectId) -> Self {
|
||||||
Identifier(Alphanumeric.sample_string(&mut rand::thread_rng(), 32))
|
Identifier(value.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue