toplevel-info/mgmt: Update to v2/v3
This commit is contained in:
parent
bbda6fb13d
commit
9c7c41c508
11 changed files with 270 additions and 119 deletions
|
|
@ -1,6 +1,9 @@
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
sync::{
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
|
Mutex,
|
||||||
|
},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -84,6 +87,12 @@ impl PartialEq<X11Surface> for CosmicSurface {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct Minimized(AtomicBool);
|
struct Minimized(AtomicBool);
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct Sticky(AtomicBool);
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct GlobalGeometry(pub Mutex<Option<Rectangle<i32, Global>>>);
|
||||||
|
|
||||||
pub const SSD_HEIGHT: i32 = 36;
|
pub const SSD_HEIGHT: i32 = 36;
|
||||||
pub const RESIZE_BORDER: i32 = 10;
|
pub const RESIZE_BORDER: i32 = 10;
|
||||||
|
|
||||||
|
|
@ -130,6 +139,13 @@ impl CosmicSurface {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_geometry(&self, geo: Rectangle<i32, Global>) {
|
pub fn set_geometry(&self, geo: Rectangle<i32, Global>) {
|
||||||
|
*self
|
||||||
|
.0
|
||||||
|
.user_data()
|
||||||
|
.get_or_insert_threadsafe(GlobalGeometry::default)
|
||||||
|
.0
|
||||||
|
.lock()
|
||||||
|
.unwrap() = Some(geo);
|
||||||
match self.0.underlying_surface() {
|
match self.0.underlying_surface() {
|
||||||
WindowSurface::Wayland(toplevel) => {
|
WindowSurface::Wayland(toplevel) => {
|
||||||
toplevel.with_pending_state(|state| state.size = Some(geo.size.as_logical()))
|
toplevel.with_pending_state(|state| state.size = Some(geo.size.as_logical()))
|
||||||
|
|
@ -387,6 +403,22 @@ impl CosmicSurface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_sticky(&self) -> bool {
|
||||||
|
self.0
|
||||||
|
.user_data()
|
||||||
|
.get_or_insert_threadsafe(Sticky::default)
|
||||||
|
.0
|
||||||
|
.load(Ordering::SeqCst)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_sticky(&self, sticky: bool) {
|
||||||
|
self.0
|
||||||
|
.user_data()
|
||||||
|
.get_or_insert_threadsafe(Sticky::default)
|
||||||
|
.0
|
||||||
|
.store(sticky, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_suspended(&self, suspended: bool) {
|
pub fn set_suspended(&self, suspended: bool) {
|
||||||
match self.0.underlying_surface() {
|
match self.0.underlying_surface() {
|
||||||
WindowSurface::Wayland(window) => window.with_pending_state(|state| {
|
WindowSurface::Wayland(window) => window.with_pending_state(|state| {
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@ use smithay::{
|
||||||
utils::{IsAlive, Logical, Point, Rectangle, Serial, Size},
|
utils::{IsAlive, Logical, Point, Rectangle, Serial, Size},
|
||||||
wayland::{
|
wayland::{
|
||||||
compositor::with_states,
|
compositor::with_states,
|
||||||
foreign_toplevel_list::ForeignToplevelListState,
|
|
||||||
seat::WaylandFocus,
|
seat::WaylandFocus,
|
||||||
session_lock::LockSurface,
|
session_lock::LockSurface,
|
||||||
shell::wlr_layer::{KeyboardInteractivity, Layer, LayerSurfaceCachedState},
|
shell::wlr_layer::{KeyboardInteractivity, Layer, LayerSurfaceCachedState},
|
||||||
|
|
@ -61,11 +60,7 @@ use crate::{
|
||||||
utils::{prelude::*, quirks::WORKSPACE_OVERVIEW_NAMESPACE},
|
utils::{prelude::*, quirks::WORKSPACE_OVERVIEW_NAMESPACE},
|
||||||
wayland::{
|
wayland::{
|
||||||
handlers::{
|
handlers::{
|
||||||
foreign_toplevel_list::{
|
toplevel_management::minimize_rectangle, xdg_activation::ActivationContext,
|
||||||
new_foreign_toplevel, refresh_foreign_toplevels, remove_foreign_toplevel,
|
|
||||||
},
|
|
||||||
toplevel_management::minimize_rectangle,
|
|
||||||
xdg_activation::ActivationContext,
|
|
||||||
xdg_shell::popup::get_popup_toplevel,
|
xdg_shell::popup::get_popup_toplevel,
|
||||||
},
|
},
|
||||||
protocols::{
|
protocols::{
|
||||||
|
|
@ -1194,7 +1189,6 @@ impl Common {
|
||||||
);
|
);
|
||||||
self.popups.cleanup();
|
self.popups.cleanup();
|
||||||
self.toplevel_info_state.refresh(&self.workspace_state);
|
self.toplevel_info_state.refresh(&self.workspace_state);
|
||||||
refresh_foreign_toplevels(&self.shell.read().unwrap());
|
|
||||||
self.refresh_idle_inhibit();
|
self.refresh_idle_inhibit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2083,7 +2077,6 @@ impl Shell {
|
||||||
&mut self,
|
&mut self,
|
||||||
window: &CosmicSurface,
|
window: &CosmicSurface,
|
||||||
toplevel_info: &mut ToplevelInfoState<State, CosmicSurface>,
|
toplevel_info: &mut ToplevelInfoState<State, CosmicSurface>,
|
||||||
foreign_toplevel_list: &mut ForeignToplevelListState,
|
|
||||||
workspace_state: &mut WorkspaceState<State>,
|
workspace_state: &mut WorkspaceState<State>,
|
||||||
evlh: &LoopHandle<'static, State>,
|
evlh: &LoopHandle<'static, State>,
|
||||||
) -> Option<KeyboardFocusTarget> {
|
) -> Option<KeyboardFocusTarget> {
|
||||||
|
|
@ -2166,7 +2159,6 @@ impl Shell {
|
||||||
toplevel_info.new_toplevel(&window, workspace_state);
|
toplevel_info.new_toplevel(&window, workspace_state);
|
||||||
toplevel_enter_output(&window, &output);
|
toplevel_enter_output(&window, &output);
|
||||||
toplevel_enter_workspace(&window, &workspace.handle);
|
toplevel_enter_workspace(&window, &workspace.handle);
|
||||||
new_foreign_toplevel(&window, foreign_toplevel_list);
|
|
||||||
|
|
||||||
let mut workspace_state = workspace_state.update();
|
let mut workspace_state = workspace_state.update();
|
||||||
|
|
||||||
|
|
@ -2298,7 +2290,6 @@ impl Shell {
|
||||||
surface: &S,
|
surface: &S,
|
||||||
seat: &Seat<State>,
|
seat: &Seat<State>,
|
||||||
toplevel_info: &mut ToplevelInfoState<State, CosmicSurface>,
|
toplevel_info: &mut ToplevelInfoState<State, CosmicSurface>,
|
||||||
foreign_toplevel_list: &mut ForeignToplevelListState,
|
|
||||||
) where
|
) where
|
||||||
CosmicSurface: PartialEq<S>,
|
CosmicSurface: PartialEq<S>,
|
||||||
{
|
{
|
||||||
|
|
@ -2348,7 +2339,6 @@ impl Shell {
|
||||||
|
|
||||||
if let Some(surface) = surface {
|
if let Some(surface) = surface {
|
||||||
toplevel_info.remove_toplevel(&surface);
|
toplevel_info.remove_toplevel(&surface);
|
||||||
remove_foreign_toplevel(&surface, foreign_toplevel_list);
|
|
||||||
self.pending_windows.push((surface, seat.clone(), None));
|
self.pending_windows.push((surface, seat.clone(), None));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -3619,6 +3609,7 @@ impl Shell {
|
||||||
let handle = workspace.handle;
|
let handle = workspace.handle;
|
||||||
|
|
||||||
for (window, _) in mapped.windows() {
|
for (window, _) in mapped.windows() {
|
||||||
|
window.set_sticky(true);
|
||||||
toplevel_leave_workspace(&window, &handle);
|
toplevel_leave_workspace(&window, &handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3640,6 +3631,7 @@ impl Shell {
|
||||||
let workspace = &mut set.workspaces[set.active];
|
let workspace = &mut set.workspaces[set.active];
|
||||||
for (window, _) in mapped.windows() {
|
for (window, _) in mapped.windows() {
|
||||||
toplevel_enter_workspace(&window, &workspace.handle);
|
toplevel_enter_workspace(&window, &workspace.handle);
|
||||||
|
window.set_sticky(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
match mapped
|
match mapped
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,6 @@ use smithay::{
|
||||||
compositor::{CompositorClientState, CompositorState, SurfaceData},
|
compositor::{CompositorClientState, CompositorState, SurfaceData},
|
||||||
cursor_shape::CursorShapeManagerState,
|
cursor_shape::CursorShapeManagerState,
|
||||||
dmabuf::{DmabufFeedback, DmabufGlobal, DmabufState},
|
dmabuf::{DmabufFeedback, DmabufGlobal, DmabufState},
|
||||||
foreign_toplevel_list::ForeignToplevelListState,
|
|
||||||
fractional_scale::{with_fractional_scale, FractionalScaleManagerState},
|
fractional_scale::{with_fractional_scale, FractionalScaleManagerState},
|
||||||
idle_inhibit::IdleInhibitManagerState,
|
idle_inhibit::IdleInhibitManagerState,
|
||||||
idle_notify::IdleNotifierState,
|
idle_notify::IdleNotifierState,
|
||||||
|
|
@ -195,7 +194,6 @@ pub struct Common {
|
||||||
pub compositor_state: CompositorState,
|
pub compositor_state: CompositorState,
|
||||||
pub data_device_state: DataDeviceState,
|
pub data_device_state: DataDeviceState,
|
||||||
pub dmabuf_state: DmabufState,
|
pub dmabuf_state: DmabufState,
|
||||||
pub foreign_toplevel_list: ForeignToplevelListState,
|
|
||||||
pub fractional_scale_state: FractionalScaleManagerState,
|
pub fractional_scale_state: FractionalScaleManagerState,
|
||||||
pub keyboard_shortcuts_inhibit_state: KeyboardShortcutsInhibitState,
|
pub keyboard_shortcuts_inhibit_state: KeyboardShortcutsInhibitState,
|
||||||
pub output_state: OutputManagerState,
|
pub output_state: OutputManagerState,
|
||||||
|
|
@ -496,8 +494,6 @@ impl State {
|
||||||
let compositor_state = CompositorState::new::<Self>(dh);
|
let compositor_state = CompositorState::new::<Self>(dh);
|
||||||
let data_device_state = DataDeviceState::new::<Self>(dh);
|
let data_device_state = DataDeviceState::new::<Self>(dh);
|
||||||
let dmabuf_state = DmabufState::new();
|
let dmabuf_state = DmabufState::new();
|
||||||
let foreign_toplevel_list =
|
|
||||||
ForeignToplevelListState::new_with_filter::<State>(dh, client_is_privileged);
|
|
||||||
let fractional_scale_state = FractionalScaleManagerState::new::<State>(dh);
|
let fractional_scale_state = FractionalScaleManagerState::new::<State>(dh);
|
||||||
let keyboard_shortcuts_inhibit_state = KeyboardShortcutsInhibitState::new::<Self>(dh);
|
let keyboard_shortcuts_inhibit_state = KeyboardShortcutsInhibitState::new::<Self>(dh);
|
||||||
let output_state = OutputManagerState::new_with_xdg_output::<Self>(dh);
|
let output_state = OutputManagerState::new_with_xdg_output::<Self>(dh);
|
||||||
|
|
@ -595,7 +591,6 @@ impl State {
|
||||||
compositor_state,
|
compositor_state,
|
||||||
data_device_state,
|
data_device_state,
|
||||||
dmabuf_state,
|
dmabuf_state,
|
||||||
foreign_toplevel_list,
|
|
||||||
fractional_scale_state,
|
fractional_scale_state,
|
||||||
idle_notifier_state,
|
idle_notifier_state,
|
||||||
idle_inhibit_manager_state,
|
idle_inhibit_manager_state,
|
||||||
|
|
|
||||||
|
|
@ -265,7 +265,6 @@ impl State {
|
||||||
let res = shell.map_window(
|
let res = shell.map_window(
|
||||||
&window,
|
&window,
|
||||||
&mut self.common.toplevel_info_state,
|
&mut self.common.toplevel_info_state,
|
||||||
&mut self.common.foreign_toplevel_list,
|
|
||||||
&mut self.common.workspace_state,
|
&mut self.common.workspace_state,
|
||||||
&self.common.event_loop_handle,
|
&self.common.event_loop_handle,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,67 +1,13 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use crate::{
|
use crate::{state::State, wayland::protocols::toplevel_info::ToplevelInfoHandler};
|
||||||
shell::{CosmicSurface, Shell},
|
|
||||||
state::State,
|
|
||||||
};
|
|
||||||
use smithay::wayland::foreign_toplevel_list::{
|
use smithay::wayland::foreign_toplevel_list::{
|
||||||
ForeignToplevelHandle, ForeignToplevelListHandler, ForeignToplevelListState,
|
ForeignToplevelListHandler, ForeignToplevelListState,
|
||||||
};
|
};
|
||||||
use std::sync::Mutex;
|
|
||||||
|
|
||||||
impl ForeignToplevelListHandler for State {
|
impl ForeignToplevelListHandler for State {
|
||||||
fn foreign_toplevel_list_state(&mut self) -> &mut ForeignToplevelListState {
|
fn foreign_toplevel_list_state(&mut self) -> &mut ForeignToplevelListState {
|
||||||
&mut self.common.foreign_toplevel_list
|
&mut self.toplevel_info_state_mut().foreign_toplevel_list
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_foreign_toplevel(
|
|
||||||
window: &CosmicSurface,
|
|
||||||
foreign_toplevel_list: &mut ForeignToplevelListState,
|
|
||||||
) {
|
|
||||||
let toplevel_handle =
|
|
||||||
foreign_toplevel_list.new_toplevel::<State>(window.title(), window.app_id());
|
|
||||||
*window
|
|
||||||
.user_data()
|
|
||||||
.get_or_insert::<Mutex<Option<ForeignToplevelHandle>>, _>(Default::default)
|
|
||||||
.lock()
|
|
||||||
.unwrap() = Some(toplevel_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove_foreign_toplevel(
|
|
||||||
window: &CosmicSurface,
|
|
||||||
foreign_toplevel_list: &mut ForeignToplevelListState,
|
|
||||||
) {
|
|
||||||
if let Some(handle) = window
|
|
||||||
.user_data()
|
|
||||||
.get::<Mutex<Option<ForeignToplevelHandle>>>()
|
|
||||||
{
|
|
||||||
if let Some(handle) = handle.lock().unwrap().take() {
|
|
||||||
foreign_toplevel_list.remove_toplevel(&handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn refresh_foreign_toplevels(shell: &Shell) {
|
|
||||||
for (window, _) in shell
|
|
||||||
.workspaces
|
|
||||||
.spaces()
|
|
||||||
.flat_map(|workspace| workspace.mapped())
|
|
||||||
.flat_map(|mapped| mapped.windows())
|
|
||||||
{
|
|
||||||
let foreign_toplevel_handle = window
|
|
||||||
.user_data()
|
|
||||||
.get::<Mutex<Option<ForeignToplevelHandle>>>()
|
|
||||||
.and_then(|handle| handle.lock().unwrap().clone());
|
|
||||||
if let Some(handle) = foreign_toplevel_handle {
|
|
||||||
let app_id = window.app_id();
|
|
||||||
let title = window.title();
|
|
||||||
if handle.app_id() != app_id || handle.title() != title {
|
|
||||||
handle.send_app_id(&app_id);
|
|
||||||
handle.send_title(&title);
|
|
||||||
handle.send_done();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use smithay::utils::user_data::UserDataMap;
|
use smithay::utils::{user_data::UserDataMap, Rectangle};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
shell::CosmicSurface,
|
shell::{element::surface::GlobalGeometry, CosmicSurface},
|
||||||
state::State,
|
state::State,
|
||||||
|
utils::prelude::Global,
|
||||||
wayland::protocols::toplevel_info::{
|
wayland::protocols::toplevel_info::{
|
||||||
delegate_toplevel_info, ToplevelInfoHandler, ToplevelInfoState, Window,
|
delegate_toplevel_info, ToplevelInfoHandler, ToplevelInfoState, Window,
|
||||||
},
|
},
|
||||||
|
|
@ -46,6 +47,20 @@ impl Window for CosmicSurface {
|
||||||
CosmicSurface::is_minimized(self)
|
CosmicSurface::is_minimized(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_sticky(&self) -> bool {
|
||||||
|
CosmicSurface::is_sticky(&self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn global_geometry(&self) -> Option<Rectangle<i32, Global>> {
|
||||||
|
self.user_data()
|
||||||
|
.get_or_insert(GlobalGeometry::default)
|
||||||
|
.0
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.clone()
|
||||||
|
.filter(|_| !self.is_minimized())
|
||||||
|
}
|
||||||
|
|
||||||
fn user_data(&self) -> &UserDataMap {
|
fn user_data(&self) -> &UserDataMap {
|
||||||
CosmicSurface::user_data(self)
|
CosmicSurface::user_data(self)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -228,6 +228,34 @@ impl ToplevelManagementHandler for State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_sticky(&mut self, _dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {
|
||||||
|
if window.is_sticky() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
|
if let Some(mapped) = shell.element_for_surface(window).cloned() {
|
||||||
|
let seat = shell.seats.last_active().clone();
|
||||||
|
shell.toggle_sticky(&seat, &mapped);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unset_sticky(
|
||||||
|
&mut self,
|
||||||
|
_dh: &DisplayHandle,
|
||||||
|
window: &<Self as ToplevelInfoHandler>::Window,
|
||||||
|
) {
|
||||||
|
if !window.is_sticky() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
|
if let Some(mapped) = shell.element_for_surface(window).cloned() {
|
||||||
|
let seat = shell.seats.last_active().clone();
|
||||||
|
shell.toggle_sticky(&seat, &mapped);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ManagementWindow for CosmicSurface {
|
impl ManagementWindow for CosmicSurface {
|
||||||
|
|
|
||||||
|
|
@ -387,7 +387,6 @@ impl XdgShellHandler for State {
|
||||||
surface.wl_surface(),
|
surface.wl_surface(),
|
||||||
&seat,
|
&seat,
|
||||||
&mut self.common.toplevel_info_state,
|
&mut self.common.toplevel_info_state,
|
||||||
&mut self.common.foreign_toplevel_list,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let output = shell
|
let output = shell
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,20 @@ use smithay::{
|
||||||
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, Weak,
|
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, Weak,
|
||||||
},
|
},
|
||||||
utils::{user_data::UserDataMap, IsAlive, Logical, Rectangle},
|
utils::{user_data::UserDataMap, IsAlive, Logical, Rectangle},
|
||||||
|
wayland::foreign_toplevel_list::{
|
||||||
|
ForeignToplevelHandle, ForeignToplevelListHandler, ForeignToplevelListState,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::utils::prelude::{Global, OutputExt, RectGlobalExt};
|
||||||
|
|
||||||
use super::workspace::{WorkspaceHandle, WorkspaceHandler, WorkspaceState};
|
use super::workspace::{WorkspaceHandle, WorkspaceHandler, WorkspaceState};
|
||||||
|
|
||||||
use cosmic_protocols::toplevel_info::v1::server::{
|
use cosmic_protocols::toplevel_info::v1::server::{
|
||||||
zcosmic_toplevel_handle_v1::{self, State as States, ZcosmicToplevelHandleV1},
|
zcosmic_toplevel_handle_v1::{self, State as States, ZcosmicToplevelHandleV1},
|
||||||
zcosmic_toplevel_info_v1::{self, ZcosmicToplevelInfoV1},
|
zcosmic_toplevel_info_v1::{self, ZcosmicToplevelInfoV1},
|
||||||
};
|
};
|
||||||
|
use tracing::error;
|
||||||
|
|
||||||
pub trait Window: IsAlive + Clone + PartialEq + Send {
|
pub trait Window: IsAlive + Clone + PartialEq + Send {
|
||||||
fn title(&self) -> String;
|
fn title(&self) -> String;
|
||||||
|
|
@ -26,6 +32,8 @@ pub trait Window: IsAlive + Clone + PartialEq + Send {
|
||||||
fn is_maximized(&self) -> bool;
|
fn is_maximized(&self) -> bool;
|
||||||
fn is_fullscreen(&self) -> bool;
|
fn is_fullscreen(&self) -> bool;
|
||||||
fn is_minimized(&self) -> bool;
|
fn is_minimized(&self) -> bool;
|
||||||
|
fn is_sticky(&self) -> bool;
|
||||||
|
fn global_geometry(&self) -> Option<Rectangle<i32, Global>>;
|
||||||
fn user_data(&self) -> &UserDataMap;
|
fn user_data(&self) -> &UserDataMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,11 +42,14 @@ pub struct ToplevelInfoState<D, W: Window> {
|
||||||
dh: DisplayHandle,
|
dh: DisplayHandle,
|
||||||
pub(super) toplevels: Vec<W>,
|
pub(super) toplevels: Vec<W>,
|
||||||
instances: Vec<ZcosmicToplevelInfoV1>,
|
instances: Vec<ZcosmicToplevelInfoV1>,
|
||||||
|
dirty: bool,
|
||||||
|
last_dirty: bool,
|
||||||
|
pub(in crate::wayland) foreign_toplevel_list: ForeignToplevelListState,
|
||||||
global: GlobalId,
|
global: GlobalId,
|
||||||
_dispatch_data: std::marker::PhantomData<D>,
|
_dispatch_data: std::marker::PhantomData<D>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ToplevelInfoHandler: WorkspaceHandler + Sized {
|
pub trait ToplevelInfoHandler: ForeignToplevelListHandler + WorkspaceHandler + Sized {
|
||||||
type Window: Window;
|
type Window: Window;
|
||||||
fn toplevel_info_state(&self) -> &ToplevelInfoState<Self, Self::Window>;
|
fn toplevel_info_state(&self) -> &ToplevelInfoState<Self, Self::Window>;
|
||||||
fn toplevel_info_state_mut(&mut self) -> &mut ToplevelInfoState<Self, Self::Window>;
|
fn toplevel_info_state_mut(&mut self) -> &mut ToplevelInfoState<Self, Self::Window>;
|
||||||
|
|
@ -50,6 +61,7 @@ pub struct ToplevelInfoGlobalData {
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(super) struct ToplevelStateInner {
|
pub(super) struct ToplevelStateInner {
|
||||||
|
foreign_handle: Option<ForeignToplevelHandle>,
|
||||||
instances: Vec<ZcosmicToplevelHandleV1>,
|
instances: Vec<ZcosmicToplevelHandleV1>,
|
||||||
outputs: Vec<Output>,
|
outputs: Vec<Output>,
|
||||||
workspaces: Vec<WorkspaceHandle>,
|
workspaces: Vec<WorkspaceHandle>,
|
||||||
|
|
@ -57,8 +69,18 @@ pub(super) struct ToplevelStateInner {
|
||||||
}
|
}
|
||||||
pub(super) type ToplevelState = Mutex<ToplevelStateInner>;
|
pub(super) type ToplevelState = Mutex<ToplevelStateInner>;
|
||||||
|
|
||||||
|
impl ToplevelStateInner {
|
||||||
|
fn from_foreign(foreign_handle: ForeignToplevelHandle) -> Mutex<Self> {
|
||||||
|
Mutex::new(ToplevelStateInner {
|
||||||
|
foreign_handle: Some(foreign_handle),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ToplevelHandleStateInner<W: Window> {
|
pub struct ToplevelHandleStateInner<W: Window> {
|
||||||
outputs: Vec<Output>,
|
outputs: Vec<Output>,
|
||||||
|
geometry: Option<Rectangle<i32, Global>>,
|
||||||
wl_outputs: HashSet<WlOutput>,
|
wl_outputs: HashSet<WlOutput>,
|
||||||
workspaces: Vec<WorkspaceHandle>,
|
workspaces: Vec<WorkspaceHandle>,
|
||||||
title: String,
|
title: String,
|
||||||
|
|
@ -72,6 +94,7 @@ impl<W: Window> ToplevelHandleStateInner<W> {
|
||||||
fn from_window(window: &W) -> ToplevelHandleState<W> {
|
fn from_window(window: &W) -> ToplevelHandleState<W> {
|
||||||
ToplevelHandleState::new(ToplevelHandleStateInner {
|
ToplevelHandleState::new(ToplevelHandleStateInner {
|
||||||
outputs: Vec::new(),
|
outputs: Vec::new(),
|
||||||
|
geometry: None,
|
||||||
wl_outputs: HashSet::new(),
|
wl_outputs: HashSet::new(),
|
||||||
workspaces: Vec::new(),
|
workspaces: Vec::new(),
|
||||||
title: String::new(),
|
title: String::new(),
|
||||||
|
|
@ -119,7 +142,7 @@ where
|
||||||
+ Dispatch<ZcosmicToplevelHandleV1, ToplevelHandleState<W>>
|
+ Dispatch<ZcosmicToplevelHandleV1, ToplevelHandleState<W>>
|
||||||
+ ToplevelInfoHandler<Window = W>
|
+ ToplevelInfoHandler<Window = W>
|
||||||
+ 'static,
|
+ 'static,
|
||||||
W: Window,
|
W: Window + 'static,
|
||||||
{
|
{
|
||||||
fn request(
|
fn request(
|
||||||
state: &mut D,
|
state: &mut D,
|
||||||
|
|
@ -128,14 +151,47 @@ where
|
||||||
request: zcosmic_toplevel_info_v1::Request,
|
request: zcosmic_toplevel_info_v1::Request,
|
||||||
_data: &(),
|
_data: &(),
|
||||||
_dh: &DisplayHandle,
|
_dh: &DisplayHandle,
|
||||||
_data_init: &mut DataInit<'_, D>,
|
data_init: &mut DataInit<'_, D>,
|
||||||
) {
|
) {
|
||||||
match request {
|
match request {
|
||||||
|
zcosmic_toplevel_info_v1::Request::GetCosmicToplevel {
|
||||||
|
cosmic_toplevel,
|
||||||
|
foreign_toplevel,
|
||||||
|
} => {
|
||||||
|
let toplevel_state = state.toplevel_info_state();
|
||||||
|
if let Some(window) = toplevel_state.toplevels.iter().find(|w| {
|
||||||
|
w.user_data().get::<ToplevelState>().and_then(|inner| {
|
||||||
|
inner
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.foreign_handle
|
||||||
|
.as_ref()
|
||||||
|
.map(|handle| handle.identifier())
|
||||||
|
}) == ForeignToplevelHandle::from_resource(&foreign_toplevel)
|
||||||
|
.map(|handle| handle.identifier())
|
||||||
|
}) {
|
||||||
|
let instance = data_init.init(
|
||||||
|
cosmic_toplevel,
|
||||||
|
ToplevelHandleStateInner::from_window(window),
|
||||||
|
);
|
||||||
|
window
|
||||||
|
.user_data()
|
||||||
|
.get::<ToplevelState>()
|
||||||
|
.unwrap()
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.instances
|
||||||
|
.push(instance);
|
||||||
|
} else {
|
||||||
|
error!(?foreign_toplevel, "Toplevel for foreign-toplevel-list not registered for cosmic-toplevel-info.");
|
||||||
|
}
|
||||||
|
}
|
||||||
zcosmic_toplevel_info_v1::Request::Stop => {
|
zcosmic_toplevel_info_v1::Request::Stop => {
|
||||||
state
|
state
|
||||||
.toplevel_info_state_mut()
|
.toplevel_info_state_mut()
|
||||||
.instances
|
.instances
|
||||||
.retain(|i| i != obj);
|
.retain(|i| i != obj);
|
||||||
|
obj.finished();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
@ -216,37 +272,47 @@ where
|
||||||
D: GlobalDispatch<ZcosmicToplevelInfoV1, ToplevelInfoGlobalData>
|
D: GlobalDispatch<ZcosmicToplevelInfoV1, ToplevelInfoGlobalData>
|
||||||
+ Dispatch<ZcosmicToplevelInfoV1, ()>
|
+ Dispatch<ZcosmicToplevelInfoV1, ()>
|
||||||
+ Dispatch<ZcosmicToplevelHandleV1, ToplevelHandleState<W>>
|
+ Dispatch<ZcosmicToplevelHandleV1, ToplevelHandleState<W>>
|
||||||
|
+ ForeignToplevelListHandler
|
||||||
+ ToplevelInfoHandler<Window = W>
|
+ ToplevelInfoHandler<Window = W>
|
||||||
+ 'static,
|
+ 'static,
|
||||||
W: Window + 'static,
|
W: Window + 'static,
|
||||||
{
|
{
|
||||||
pub fn new<F>(dh: &DisplayHandle, client_filter: F) -> ToplevelInfoState<D, W>
|
pub fn new<F>(dh: &DisplayHandle, client_filter: F) -> ToplevelInfoState<D, W>
|
||||||
where
|
where
|
||||||
F: for<'a> Fn(&'a Client) -> bool + Send + Sync + 'static,
|
F: for<'a> Fn(&'a Client) -> bool + Send + Sync + Clone + 'static,
|
||||||
{
|
{
|
||||||
let global = dh.create_global::<D, ZcosmicToplevelInfoV1, _>(
|
let global = dh.create_global::<D, ZcosmicToplevelInfoV1, _>(
|
||||||
1,
|
2,
|
||||||
ToplevelInfoGlobalData {
|
ToplevelInfoGlobalData {
|
||||||
filter: Box::new(client_filter),
|
filter: Box::new(client_filter.clone()),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
let foreign_toplevel_list =
|
||||||
|
ForeignToplevelListState::new_with_filter::<D>(dh, client_filter);
|
||||||
ToplevelInfoState {
|
ToplevelInfoState {
|
||||||
dh: dh.clone(),
|
dh: dh.clone(),
|
||||||
toplevels: Vec::new(),
|
toplevels: Vec::new(),
|
||||||
instances: Vec::new(),
|
instances: Vec::new(),
|
||||||
|
dirty: false,
|
||||||
|
last_dirty: false,
|
||||||
|
foreign_toplevel_list,
|
||||||
global,
|
global,
|
||||||
_dispatch_data: std::marker::PhantomData,
|
_dispatch_data: std::marker::PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_toplevel(&mut self, toplevel: &W, workspace_state: &WorkspaceState<D>) {
|
pub fn new_toplevel(&mut self, toplevel: &W, workspace_state: &WorkspaceState<D>) {
|
||||||
|
let toplevel_handle = self
|
||||||
|
.foreign_toplevel_list
|
||||||
|
.new_toplevel::<D>(toplevel.title(), toplevel.app_id());
|
||||||
toplevel
|
toplevel
|
||||||
.user_data()
|
.user_data()
|
||||||
.insert_if_missing(ToplevelState::default);
|
.insert_if_missing(move || ToplevelStateInner::from_foreign(toplevel_handle));
|
||||||
for instance in &self.instances {
|
for instance in &self.instances {
|
||||||
send_toplevel_to_client::<D, W>(&self.dh, workspace_state, instance, toplevel);
|
send_toplevel_to_client::<D, W>(&self.dh, workspace_state, instance, toplevel);
|
||||||
}
|
}
|
||||||
self.toplevels.push(toplevel.clone());
|
self.toplevels.push(toplevel.clone());
|
||||||
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_toplevel(&mut self, toplevel: &W) {
|
pub fn remove_toplevel(&mut self, toplevel: &W) {
|
||||||
|
|
@ -254,20 +320,27 @@ where
|
||||||
let mut state_inner = state.lock().unwrap();
|
let mut state_inner = state.lock().unwrap();
|
||||||
for handle in &state_inner.instances {
|
for handle in &state_inner.instances {
|
||||||
// don't send events to stopped instances
|
// don't send events to stopped instances
|
||||||
if self
|
if handle.version() < zcosmic_toplevel_info_v1::REQ_GET_COSMIC_TOPLEVEL_SINCE
|
||||||
.instances
|
&& self
|
||||||
.iter()
|
.instances
|
||||||
.any(|i| i.id().same_client_as(&handle.id()))
|
.iter()
|
||||||
|
.any(|i| i.id().same_client_as(&handle.id()))
|
||||||
{
|
{
|
||||||
handle.closed();
|
handle.closed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(handle) = state_inner.foreign_handle.take() {
|
||||||
|
self.foreign_toplevel_list.remove_toplevel(&handle);
|
||||||
|
}
|
||||||
*state_inner = Default::default();
|
*state_inner = Default::default();
|
||||||
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
self.toplevels.retain(|w| w != toplevel);
|
self.toplevels.retain(|w| w != toplevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn refresh(&mut self, workspace_state: &WorkspaceState<D>) {
|
pub fn refresh(&mut self, workspace_state: &WorkspaceState<D>) {
|
||||||
|
let mut dirty = std::mem::replace(&mut self.dirty, false);
|
||||||
|
|
||||||
self.toplevels.retain(|window| {
|
self.toplevels.retain(|window| {
|
||||||
let mut state = window
|
let mut state = window
|
||||||
.user_data()
|
.user_data()
|
||||||
|
|
@ -281,23 +354,41 @@ where
|
||||||
if window.alive() {
|
if window.alive() {
|
||||||
std::mem::drop(state);
|
std::mem::drop(state);
|
||||||
for instance in &self.instances {
|
for instance in &self.instances {
|
||||||
send_toplevel_to_client::<D, W>(&self.dh, workspace_state, instance, window);
|
let changed = send_toplevel_to_client::<D, W>(
|
||||||
|
&self.dh,
|
||||||
|
workspace_state,
|
||||||
|
instance,
|
||||||
|
window,
|
||||||
|
);
|
||||||
|
dirty = dirty || changed;
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
for handle in &state.instances {
|
for handle in &state.instances {
|
||||||
// don't send events to stopped instances
|
// don't send events to stopped instances
|
||||||
if self
|
if handle.version() < zcosmic_toplevel_info_v1::REQ_GET_COSMIC_TOPLEVEL_SINCE
|
||||||
.instances
|
&& self
|
||||||
.iter()
|
.instances
|
||||||
.any(|i| i.id().same_client_as(&handle.id()))
|
.iter()
|
||||||
|
.any(|i| i.id().same_client_as(&handle.id()))
|
||||||
{
|
{
|
||||||
handle.closed();
|
handle.closed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dirty = true;
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if !dirty && self.last_dirty {
|
||||||
|
for instance in &self.instances {
|
||||||
|
if instance.version() >= zcosmic_toplevel_info_v1::EVT_DONE_SINCE {
|
||||||
|
instance.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.last_dirty = dirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn global_id(&self) -> GlobalId {
|
pub fn global_id(&self) -> GlobalId {
|
||||||
|
|
@ -310,7 +401,8 @@ fn send_toplevel_to_client<D, W: 'static>(
|
||||||
workspace_state: &WorkspaceState<D>,
|
workspace_state: &WorkspaceState<D>,
|
||||||
info: &ZcosmicToplevelInfoV1,
|
info: &ZcosmicToplevelInfoV1,
|
||||||
window: &W,
|
window: &W,
|
||||||
) where
|
) -> bool
|
||||||
|
where
|
||||||
D: GlobalDispatch<ZcosmicToplevelInfoV1, ToplevelInfoGlobalData>
|
D: GlobalDispatch<ZcosmicToplevelInfoV1, ToplevelInfoGlobalData>
|
||||||
+ Dispatch<ZcosmicToplevelInfoV1, ()>
|
+ Dispatch<ZcosmicToplevelInfoV1, ()>
|
||||||
+ Dispatch<ZcosmicToplevelHandleV1, ToplevelHandleState<W>>
|
+ Dispatch<ZcosmicToplevelHandleV1, ToplevelHandleState<W>>
|
||||||
|
|
@ -331,22 +423,26 @@ fn send_toplevel_to_client<D, W: 'static>(
|
||||||
{
|
{
|
||||||
Some(i) => i,
|
Some(i) => i,
|
||||||
None => {
|
None => {
|
||||||
if let Ok(client) = dh.get_client(info.id()) {
|
if info.version() < zcosmic_toplevel_info_v1::REQ_GET_COSMIC_TOPLEVEL_SINCE {
|
||||||
if let Ok(toplevel_handle) = client
|
if let Ok(client) = dh.get_client(info.id()) {
|
||||||
.create_resource::<ZcosmicToplevelHandleV1, _, D>(
|
if let Ok(toplevel_handle) = client
|
||||||
dh,
|
.create_resource::<ZcosmicToplevelHandleV1, _, D>(
|
||||||
info.version(),
|
dh,
|
||||||
ToplevelHandleStateInner::from_window(window),
|
info.version(),
|
||||||
)
|
ToplevelHandleStateInner::from_window(window),
|
||||||
{
|
)
|
||||||
info.toplevel(&toplevel_handle);
|
{
|
||||||
state.instances.push(toplevel_handle);
|
info.toplevel(&toplevel_handle);
|
||||||
state.instances.last().unwrap()
|
state.instances.push(toplevel_handle);
|
||||||
|
state.instances.last().unwrap()
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -356,15 +452,27 @@ fn send_toplevel_to_client<D, W: 'static>(
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
let foreign_toplevel_handle = state.foreign_handle.as_ref();
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
|
|
||||||
if handle_state.title != window.title() {
|
if handle_state.title != window.title() {
|
||||||
handle_state.title = window.title();
|
handle_state.title = window.title();
|
||||||
instance.title(handle_state.title.clone());
|
if instance.version() < zcosmic_toplevel_info_v1::REQ_GET_COSMIC_TOPLEVEL_SINCE {
|
||||||
|
instance.title(handle_state.title.clone());
|
||||||
|
}
|
||||||
|
if let Some(handle) = foreign_toplevel_handle {
|
||||||
|
handle.send_title(&handle_state.title);
|
||||||
|
}
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if handle_state.app_id != window.app_id() {
|
if handle_state.app_id != window.app_id() {
|
||||||
handle_state.app_id = window.app_id();
|
handle_state.app_id = window.app_id();
|
||||||
instance.app_id(handle_state.app_id.clone());
|
if instance.version() < zcosmic_toplevel_info_v1::REQ_GET_COSMIC_TOPLEVEL_SINCE {
|
||||||
|
instance.app_id(handle_state.app_id.clone());
|
||||||
|
}
|
||||||
|
if let Some(handle) = foreign_toplevel_handle {
|
||||||
|
handle.send_app_id(&handle_state.app_id);
|
||||||
|
}
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -386,6 +494,11 @@ fn send_toplevel_to_client<D, W: 'static>(
|
||||||
if window.is_minimized() {
|
if window.is_minimized() {
|
||||||
states.push(States::Minimized);
|
states.push(States::Minimized);
|
||||||
}
|
}
|
||||||
|
if instance.version() >= zcosmic_toplevel_info_v1::REQ_GET_COSMIC_TOPLEVEL_SINCE
|
||||||
|
&& window.is_sticky()
|
||||||
|
{
|
||||||
|
states.push(States::Sticky);
|
||||||
|
}
|
||||||
handle_state.states = states.clone();
|
handle_state.states = states.clone();
|
||||||
|
|
||||||
let states: Vec<u8> = {
|
let states: Vec<u8> = {
|
||||||
|
|
@ -400,15 +513,35 @@ fn send_toplevel_to_client<D, W: 'static>(
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let geometry = window.global_geometry();
|
||||||
|
let mut geometry_changed = false;
|
||||||
|
if handle_state.geometry != geometry {
|
||||||
|
handle_state.geometry = geometry;
|
||||||
|
changed = true;
|
||||||
|
geometry_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
if let Ok(client) = dh.get_client(instance.id()) {
|
if let Ok(client) = dh.get_client(instance.id()) {
|
||||||
handle_state.outputs = state.outputs.clone();
|
handle_state.outputs = state.outputs.clone();
|
||||||
|
|
||||||
let handle_state = &mut *handle_state;
|
let handle_state = &mut *handle_state;
|
||||||
for output in &handle_state.outputs {
|
for output in &handle_state.outputs {
|
||||||
|
let geometry = handle_state
|
||||||
|
.geometry
|
||||||
|
.filter(|_| instance.version() >= zcosmic_toplevel_handle_v1::EVT_GEOMETRY_SINCE)
|
||||||
|
.filter(|geo| output.geometry().intersection(*geo).is_some())
|
||||||
|
.map(|geo| geo.to_local(&output));
|
||||||
for wl_output in output.client_outputs(&client) {
|
for wl_output in output.client_outputs(&client) {
|
||||||
if handle_state.wl_outputs.insert(wl_output.clone()) {
|
if handle_state.wl_outputs.insert(wl_output.clone()) {
|
||||||
instance.output_enter(&wl_output);
|
instance.output_enter(&wl_output);
|
||||||
|
if let Some(geo) = geometry {
|
||||||
|
instance.geometry(&wl_output, geo.loc.x, geo.loc.y, geo.size.w, geo.size.h);
|
||||||
|
}
|
||||||
changed = true;
|
changed = true;
|
||||||
|
} else if geometry_changed {
|
||||||
|
if let Some(geo) = geometry {
|
||||||
|
instance.geometry(&wl_output, geo.loc.x, geo.loc.y, geo.size.w, geo.size.h);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -449,8 +582,15 @@ fn send_toplevel_to_client<D, W: 'static>(
|
||||||
handle_state.workspaces = state.workspaces.clone();
|
handle_state.workspaces = state.workspaces.clone();
|
||||||
|
|
||||||
if changed {
|
if changed {
|
||||||
instance.done();
|
if instance.version() < zcosmic_toplevel_info_v1::REQ_GET_COSMIC_TOPLEVEL_SINCE {
|
||||||
|
instance.done();
|
||||||
|
}
|
||||||
|
if let Some(handle) = foreign_toplevel_handle {
|
||||||
|
handle.send_done();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changed
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn window_from_handle<W: Window + 'static>(handle: ZcosmicToplevelHandleV1) -> Option<W> {
|
pub fn window_from_handle<W: Window + 'static>(handle: ZcosmicToplevelHandleV1) -> Option<W> {
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,9 @@ where
|
||||||
fn unmaximize(&mut self, dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {}
|
fn unmaximize(&mut self, dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {}
|
||||||
fn minimize(&mut self, dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {}
|
fn minimize(&mut self, dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {}
|
||||||
fn unminimize(&mut self, dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {}
|
fn unminimize(&mut self, dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {}
|
||||||
|
fn set_sticky(&mut self, dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {}
|
||||||
|
fn unset_sticky(&mut self, dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {
|
||||||
|
}
|
||||||
fn move_to_workspace(
|
fn move_to_workspace(
|
||||||
&mut self,
|
&mut self,
|
||||||
dh: &DisplayHandle,
|
dh: &DisplayHandle,
|
||||||
|
|
@ -113,7 +116,7 @@ impl ToplevelManagementState {
|
||||||
F: for<'a> Fn(&'a Client) -> bool + Send + Sync + 'static,
|
F: for<'a> Fn(&'a Client) -> bool + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
let global = dh.create_global::<D, ZcosmicToplevelManagerV1, _>(
|
let global = dh.create_global::<D, ZcosmicToplevelManagerV1, _>(
|
||||||
2,
|
3,
|
||||||
ToplevelManagerGlobalData {
|
ToplevelManagerGlobalData {
|
||||||
filter: Box::new(client_filter),
|
filter: Box::new(client_filter),
|
||||||
},
|
},
|
||||||
|
|
@ -216,6 +219,14 @@ where
|
||||||
let window = window_from_handle(toplevel).unwrap();
|
let window = window_from_handle(toplevel).unwrap();
|
||||||
state.unminimize(dh, &window);
|
state.unminimize(dh, &window);
|
||||||
}
|
}
|
||||||
|
zcosmic_toplevel_manager_v1::Request::SetSticky { toplevel } => {
|
||||||
|
let window = window_from_handle(toplevel).unwrap();
|
||||||
|
state.set_sticky(dh, &window);
|
||||||
|
}
|
||||||
|
zcosmic_toplevel_manager_v1::Request::UnsetSticky { toplevel } => {
|
||||||
|
let window = window_from_handle(toplevel).unwrap();
|
||||||
|
state.unset_sticky(dh, &window);
|
||||||
|
}
|
||||||
zcosmic_toplevel_manager_v1::Request::SetRectangle {
|
zcosmic_toplevel_manager_v1::Request::SetRectangle {
|
||||||
toplevel,
|
toplevel,
|
||||||
surface,
|
surface,
|
||||||
|
|
|
||||||
|
|
@ -384,7 +384,6 @@ impl XwmHandler for State {
|
||||||
let res = shell.map_window(
|
let res = shell.map_window(
|
||||||
&window,
|
&window,
|
||||||
&mut self.common.toplevel_info_state,
|
&mut self.common.toplevel_info_state,
|
||||||
&mut self.common.foreign_toplevel_list,
|
|
||||||
&mut self.common.workspace_state,
|
&mut self.common.workspace_state,
|
||||||
&self.common.event_loop_handle,
|
&self.common.event_loop_handle,
|
||||||
);
|
);
|
||||||
|
|
@ -414,12 +413,7 @@ impl XwmHandler for State {
|
||||||
shell.override_redirect_windows.retain(|or| or != &window);
|
shell.override_redirect_windows.retain(|or| or != &window);
|
||||||
} else {
|
} else {
|
||||||
let seat = shell.seats.last_active().clone();
|
let seat = shell.seats.last_active().clone();
|
||||||
shell.unmap_surface(
|
shell.unmap_surface(&window, &seat, &mut self.common.toplevel_info_state);
|
||||||
&window,
|
|
||||||
&seat,
|
|
||||||
&mut self.common.toplevel_info_state,
|
|
||||||
&mut self.common.foreign_toplevel_list,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let outputs = if let Some(wl_surface) = window.wl_surface() {
|
let outputs = if let Some(wl_surface) = window.wl_surface() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue