2022-07-04 15:26:26 +02:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
|
|
2022-08-30 13:28:36 +02:00
|
|
|
use std::{collections::HashMap, sync::Mutex};
|
2022-07-04 15:26:26 +02:00
|
|
|
|
|
|
|
|
use smithay::{
|
2022-09-09 20:00:00 -07:00
|
|
|
output::Output,
|
2023-01-16 15:12:25 +01:00
|
|
|
reexports::wayland_server::{
|
|
|
|
|
backend::{ClientId, GlobalId, ObjectId},
|
|
|
|
|
protocol::wl_surface::WlSurface,
|
|
|
|
|
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource,
|
2022-07-04 15:26:26 +02:00
|
|
|
},
|
2023-01-16 15:12:25 +01:00
|
|
|
utils::{user_data::UserDataMap, IsAlive, Logical, Rectangle},
|
2022-07-04 15:26:26 +02:00
|
|
|
};
|
|
|
|
|
|
2022-07-04 16:00:29 +02:00
|
|
|
use super::workspace::{WorkspaceHandle, WorkspaceHandler, WorkspaceState};
|
2022-07-04 15:26:26 +02:00
|
|
|
|
2022-07-04 16:00:29 +02:00
|
|
|
use cosmic_protocols::toplevel_info::v1::server::{
|
|
|
|
|
zcosmic_toplevel_handle_v1::{self, State as States, ZcosmicToplevelHandleV1},
|
|
|
|
|
zcosmic_toplevel_info_v1::{self, ZcosmicToplevelInfoV1},
|
2022-07-04 15:26:26 +02:00
|
|
|
};
|
|
|
|
|
|
2023-01-16 15:12:25 +01:00
|
|
|
pub trait Window: IsAlive + Clone + Send {
|
|
|
|
|
fn title(&self) -> String;
|
|
|
|
|
fn app_id(&self) -> String;
|
|
|
|
|
fn is_activated(&self) -> bool;
|
|
|
|
|
fn is_maximized(&self) -> bool;
|
|
|
|
|
fn is_fullscreen(&self) -> bool;
|
|
|
|
|
fn is_minimized(&self) -> bool;
|
|
|
|
|
fn user_data(&self) -> &UserDataMap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct ToplevelInfoState<D, W: Window> {
|
2022-07-04 15:26:26 +02:00
|
|
|
dh: DisplayHandle,
|
2023-01-16 15:12:25 +01:00
|
|
|
pub(super) toplevels: Vec<W>,
|
2022-07-04 15:26:26 +02:00
|
|
|
instances: Vec<ZcosmicToplevelInfoV1>,
|
|
|
|
|
global: GlobalId,
|
|
|
|
|
_dispatch_data: std::marker::PhantomData<D>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub trait ToplevelInfoHandler: WorkspaceHandler + Sized {
|
2023-01-16 15:12:25 +01:00
|
|
|
type Window: Window;
|
|
|
|
|
fn toplevel_info_state(&self) -> &ToplevelInfoState<Self, Self::Window>;
|
|
|
|
|
fn toplevel_info_state_mut(&mut self) -> &mut ToplevelInfoState<Self, Self::Window>;
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct ToplevelInfoGlobalData {
|
|
|
|
|
filter: Box<dyn for<'a> Fn(&'a Client) -> bool + Send + Sync>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Default)]
|
2022-07-18 21:26:02 +02:00
|
|
|
pub(super) struct ToplevelStateInner {
|
2022-07-04 15:26:26 +02:00
|
|
|
instances: Vec<ZcosmicToplevelHandleV1>,
|
|
|
|
|
outputs: Vec<Output>,
|
|
|
|
|
workspaces: Vec<WorkspaceHandle>,
|
2022-07-18 21:26:02 +02:00
|
|
|
pub(super) rectangles: HashMap<ClientId, (WlSurface, Rectangle<i32, Logical>)>,
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
2022-07-18 21:26:02 +02:00
|
|
|
pub(super) type ToplevelState = Mutex<ToplevelStateInner>;
|
2022-07-04 15:26:26 +02:00
|
|
|
|
2023-01-16 15:12:25 +01:00
|
|
|
pub struct ToplevelHandleStateInner<W: Window> {
|
2022-07-04 15:26:26 +02:00
|
|
|
outputs: Vec<Output>,
|
|
|
|
|
workspaces: Vec<WorkspaceHandle>,
|
|
|
|
|
title: String,
|
|
|
|
|
app_id: String,
|
|
|
|
|
states: Vec<States>,
|
2023-01-16 15:12:25 +01:00
|
|
|
pub(super) window: W,
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
2023-01-16 15:12:25 +01:00
|
|
|
pub type ToplevelHandleState<W> = Mutex<ToplevelHandleStateInner<W>>;
|
2022-07-04 15:26:26 +02:00
|
|
|
|
2023-01-16 15:12:25 +01:00
|
|
|
impl<W: Window> ToplevelHandleStateInner<W> {
|
|
|
|
|
fn from_window(window: &W) -> ToplevelHandleState<W> {
|
2022-08-30 13:28:36 +02:00
|
|
|
ToplevelHandleState::new(ToplevelHandleStateInner {
|
|
|
|
|
outputs: Vec::new(),
|
|
|
|
|
workspaces: Vec::new(),
|
|
|
|
|
title: String::new(),
|
|
|
|
|
app_id: String::new(),
|
|
|
|
|
states: Vec::new(),
|
|
|
|
|
window: window.clone(),
|
|
|
|
|
})
|
2022-07-18 21:26:02 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-16 15:12:25 +01:00
|
|
|
impl<D, W> GlobalDispatch<ZcosmicToplevelInfoV1, ToplevelInfoGlobalData, D>
|
|
|
|
|
for ToplevelInfoState<D, W>
|
2022-07-04 15:26:26 +02:00
|
|
|
where
|
|
|
|
|
D: GlobalDispatch<ZcosmicToplevelInfoV1, ToplevelInfoGlobalData>
|
|
|
|
|
+ Dispatch<ZcosmicToplevelInfoV1, ()>
|
2023-01-16 15:12:25 +01:00
|
|
|
+ Dispatch<ZcosmicToplevelHandleV1, ToplevelHandleState<W>>
|
|
|
|
|
+ ToplevelInfoHandler<Window = W>
|
2022-07-04 16:00:29 +02:00
|
|
|
+ 'static,
|
2023-01-16 15:12:25 +01:00
|
|
|
W: Window + 'static,
|
2022-07-04 15:26:26 +02:00
|
|
|
{
|
|
|
|
|
fn bind(
|
|
|
|
|
state: &mut D,
|
|
|
|
|
dh: &DisplayHandle,
|
|
|
|
|
_client: &Client,
|
|
|
|
|
resource: New<ZcosmicToplevelInfoV1>,
|
|
|
|
|
_global_data: &ToplevelInfoGlobalData,
|
|
|
|
|
data_init: &mut DataInit<'_, D>,
|
|
|
|
|
) {
|
|
|
|
|
let instance = data_init.init(resource, ());
|
|
|
|
|
for window in &state.toplevel_info_state().toplevels {
|
2023-01-16 15:12:25 +01:00
|
|
|
send_toplevel_to_client::<D, W>(dh, Some(state.workspace_state()), &instance, window);
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
2022-07-18 21:26:02 +02:00
|
|
|
state.toplevel_info_state_mut().instances.push(instance);
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn can_view(client: Client, global_data: &ToplevelInfoGlobalData) -> bool {
|
|
|
|
|
(global_data.filter)(&client)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-16 15:12:25 +01:00
|
|
|
impl<D, W> Dispatch<ZcosmicToplevelInfoV1, (), D> for ToplevelInfoState<D, W>
|
2022-07-04 15:26:26 +02:00
|
|
|
where
|
|
|
|
|
D: GlobalDispatch<ZcosmicToplevelInfoV1, ToplevelInfoGlobalData>
|
|
|
|
|
+ Dispatch<ZcosmicToplevelInfoV1, ()>
|
2023-01-16 15:12:25 +01:00
|
|
|
+ Dispatch<ZcosmicToplevelHandleV1, ToplevelHandleState<W>>
|
|
|
|
|
+ ToplevelInfoHandler<Window = W>
|
2022-07-04 16:00:29 +02:00
|
|
|
+ 'static,
|
2023-01-16 15:12:25 +01:00
|
|
|
W: Window,
|
2022-07-04 15:26:26 +02:00
|
|
|
{
|
|
|
|
|
fn request(
|
|
|
|
|
state: &mut D,
|
|
|
|
|
_client: &Client,
|
|
|
|
|
obj: &ZcosmicToplevelInfoV1,
|
|
|
|
|
request: zcosmic_toplevel_info_v1::Request,
|
|
|
|
|
_data: &(),
|
|
|
|
|
_dh: &DisplayHandle,
|
|
|
|
|
_data_init: &mut DataInit<'_, D>,
|
|
|
|
|
) {
|
|
|
|
|
match request {
|
|
|
|
|
zcosmic_toplevel_info_v1::Request::Stop => {
|
2022-07-04 16:00:29 +02:00
|
|
|
state
|
|
|
|
|
.toplevel_info_state_mut()
|
|
|
|
|
.instances
|
|
|
|
|
.retain(|i| i != obj);
|
|
|
|
|
}
|
|
|
|
|
_ => {}
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-04 16:00:29 +02:00
|
|
|
fn destroyed(state: &mut D, _client: ClientId, resource: ObjectId, _data: &()) {
|
|
|
|
|
state
|
|
|
|
|
.toplevel_info_state_mut()
|
|
|
|
|
.instances
|
|
|
|
|
.retain(|i| i.id() != resource);
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-16 15:12:25 +01:00
|
|
|
impl<D, W> Dispatch<ZcosmicToplevelHandleV1, ToplevelHandleState<W>, D> for ToplevelInfoState<D, W>
|
2022-07-04 15:26:26 +02:00
|
|
|
where
|
|
|
|
|
D: GlobalDispatch<ZcosmicToplevelInfoV1, ToplevelInfoGlobalData>
|
|
|
|
|
+ Dispatch<ZcosmicToplevelInfoV1, ()>
|
2023-01-16 15:12:25 +01:00
|
|
|
+ Dispatch<ZcosmicToplevelHandleV1, ToplevelHandleState<W>>
|
|
|
|
|
+ ToplevelInfoHandler<Window = W>
|
2022-07-04 16:00:29 +02:00
|
|
|
+ 'static,
|
2023-01-16 15:12:25 +01:00
|
|
|
W: Window,
|
2022-07-04 15:26:26 +02:00
|
|
|
{
|
|
|
|
|
fn request(
|
|
|
|
|
_state: &mut D,
|
|
|
|
|
_client: &Client,
|
|
|
|
|
_obj: &ZcosmicToplevelHandleV1,
|
|
|
|
|
request: zcosmic_toplevel_handle_v1::Request,
|
2023-01-16 15:12:25 +01:00
|
|
|
_data: &ToplevelHandleState<W>,
|
2022-07-04 15:26:26 +02:00
|
|
|
_dh: &DisplayHandle,
|
|
|
|
|
_data_init: &mut DataInit<'_, D>,
|
|
|
|
|
) {
|
|
|
|
|
match request {
|
2022-07-04 16:00:29 +02:00
|
|
|
zcosmic_toplevel_handle_v1::Request::Destroy => {}
|
|
|
|
|
_ => {}
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn destroyed(
|
2022-07-04 16:00:29 +02:00
|
|
|
state: &mut D,
|
|
|
|
|
_client: ClientId,
|
|
|
|
|
resource: ObjectId,
|
2023-01-16 15:12:25 +01:00
|
|
|
_data: &ToplevelHandleState<W>,
|
2022-07-04 15:26:26 +02:00
|
|
|
) {
|
|
|
|
|
for toplevel in &state.toplevel_info_state_mut().toplevels {
|
|
|
|
|
if let Some(state) = toplevel.user_data().get::<ToplevelState>() {
|
2022-07-04 16:00:29 +02:00
|
|
|
state
|
|
|
|
|
.lock()
|
|
|
|
|
.unwrap()
|
|
|
|
|
.instances
|
|
|
|
|
.retain(|i| i.id() != resource);
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-16 15:12:25 +01:00
|
|
|
impl<D, W> ToplevelInfoState<D, W>
|
2022-07-04 15:26:26 +02:00
|
|
|
where
|
|
|
|
|
D: GlobalDispatch<ZcosmicToplevelInfoV1, ToplevelInfoGlobalData>
|
|
|
|
|
+ Dispatch<ZcosmicToplevelInfoV1, ()>
|
2023-01-16 15:12:25 +01:00
|
|
|
+ Dispatch<ZcosmicToplevelHandleV1, ToplevelHandleState<W>>
|
|
|
|
|
+ ToplevelInfoHandler<Window = W>
|
2022-07-04 15:26:26 +02:00
|
|
|
+ 'static,
|
2023-01-16 15:12:25 +01:00
|
|
|
W: Window + 'static,
|
2022-07-04 15:26:26 +02:00
|
|
|
{
|
2023-01-16 15:12:25 +01:00
|
|
|
pub fn new<F>(dh: &DisplayHandle, client_filter: F) -> ToplevelInfoState<D, W>
|
2022-07-04 15:26:26 +02:00
|
|
|
where
|
2022-07-04 16:00:29 +02:00
|
|
|
F: for<'a> Fn(&'a Client) -> bool + Send + Sync + 'static,
|
2022-07-04 15:26:26 +02:00
|
|
|
{
|
2022-07-04 16:00:29 +02:00
|
|
|
let global = dh.create_global::<D, ZcosmicToplevelInfoV1, _>(
|
|
|
|
|
1,
|
|
|
|
|
ToplevelInfoGlobalData {
|
|
|
|
|
filter: Box::new(client_filter),
|
|
|
|
|
},
|
|
|
|
|
);
|
2022-07-04 15:26:26 +02:00
|
|
|
ToplevelInfoState {
|
|
|
|
|
dh: dh.clone(),
|
|
|
|
|
toplevels: Vec::new(),
|
|
|
|
|
instances: Vec::new(),
|
|
|
|
|
global,
|
|
|
|
|
_dispatch_data: std::marker::PhantomData,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-16 15:12:25 +01:00
|
|
|
pub fn new_toplevel(&mut self, toplevel: &W) {
|
2022-07-04 16:00:29 +02:00
|
|
|
toplevel
|
|
|
|
|
.user_data()
|
|
|
|
|
.insert_if_missing(ToplevelState::default);
|
2022-07-04 15:26:26 +02:00
|
|
|
for instance in &self.instances {
|
2023-01-16 15:12:25 +01:00
|
|
|
send_toplevel_to_client::<D, W>(&self.dh, None, instance, toplevel);
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
|
|
|
|
self.toplevels.push(toplevel.clone());
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-16 15:12:25 +01:00
|
|
|
pub fn toplevel_enter_output(&mut self, toplevel: &W, output: &Output) {
|
2022-07-04 15:26:26 +02:00
|
|
|
if let Some(state) = toplevel.user_data().get::<ToplevelState>() {
|
|
|
|
|
state.lock().unwrap().outputs.push(output.clone());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-16 15:12:25 +01:00
|
|
|
pub fn toplevel_leave_output(&mut self, toplevel: &W, output: &Output) {
|
2022-07-04 15:26:26 +02:00
|
|
|
if let Some(state) = toplevel.user_data().get::<ToplevelState>() {
|
|
|
|
|
state.lock().unwrap().outputs.retain(|o| o != output);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-16 15:12:25 +01:00
|
|
|
pub fn toplevel_enter_workspace(&mut self, toplevel: &W, workspace: &WorkspaceHandle) {
|
2022-07-04 15:26:26 +02:00
|
|
|
if let Some(state) = toplevel.user_data().get::<ToplevelState>() {
|
|
|
|
|
state.lock().unwrap().workspaces.push(workspace.clone());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-16 15:12:25 +01:00
|
|
|
pub fn toplevel_leave_workspace(&mut self, toplevel: &W, workspace: &WorkspaceHandle) {
|
2022-07-04 15:26:26 +02:00
|
|
|
if let Some(state) = toplevel.user_data().get::<ToplevelState>() {
|
|
|
|
|
state.lock().unwrap().workspaces.retain(|w| w != workspace);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn refresh(&mut self, workspace_state: Option<&WorkspaceState<D>>) {
|
|
|
|
|
self.toplevels.retain(|window| {
|
2022-07-18 21:26:02 +02:00
|
|
|
let mut state = window
|
|
|
|
|
.user_data()
|
|
|
|
|
.get::<ToplevelState>()
|
|
|
|
|
.unwrap()
|
|
|
|
|
.lock()
|
|
|
|
|
.unwrap();
|
2022-08-30 13:28:36 +02:00
|
|
|
state.rectangles.retain(|_, (surface, _)| surface.alive());
|
2022-07-04 15:26:26 +02:00
|
|
|
if window.alive() {
|
2022-07-18 21:26:02 +02:00
|
|
|
std::mem::drop(state);
|
2022-07-04 15:26:26 +02:00
|
|
|
for instance in &self.instances {
|
2023-01-16 15:12:25 +01:00
|
|
|
send_toplevel_to_client::<D, W>(&self.dh, workspace_state, instance, window);
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
|
|
|
|
true
|
|
|
|
|
} else {
|
|
|
|
|
for handle in &state.instances {
|
|
|
|
|
// don't send events to stopped instances
|
2022-07-04 16:00:29 +02:00
|
|
|
if self
|
|
|
|
|
.instances
|
|
|
|
|
.iter()
|
|
|
|
|
.any(|i| i.id().same_client_as(&handle.id()))
|
|
|
|
|
{
|
2022-07-04 15:26:26 +02:00
|
|
|
handle.closed();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn global_id(&self) -> GlobalId {
|
|
|
|
|
self.global.clone()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-16 15:12:25 +01:00
|
|
|
fn send_toplevel_to_client<D, W: 'static>(
|
2022-07-04 16:00:29 +02:00
|
|
|
dh: &DisplayHandle,
|
|
|
|
|
workspace_state: Option<&WorkspaceState<D>>,
|
|
|
|
|
info: &ZcosmicToplevelInfoV1,
|
2023-01-16 15:12:25 +01:00
|
|
|
window: &W,
|
2022-07-04 16:00:29 +02:00
|
|
|
) where
|
2022-07-04 15:26:26 +02:00
|
|
|
D: GlobalDispatch<ZcosmicToplevelInfoV1, ToplevelInfoGlobalData>
|
|
|
|
|
+ Dispatch<ZcosmicToplevelInfoV1, ()>
|
2023-01-16 15:12:25 +01:00
|
|
|
+ Dispatch<ZcosmicToplevelHandleV1, ToplevelHandleState<W>>
|
|
|
|
|
+ ToplevelInfoHandler<Window = W>
|
2022-07-04 15:26:26 +02:00
|
|
|
+ 'static,
|
2023-01-16 15:12:25 +01:00
|
|
|
W: Window,
|
2022-07-04 15:26:26 +02:00
|
|
|
{
|
2022-07-04 16:00:29 +02:00
|
|
|
let mut state = window
|
|
|
|
|
.user_data()
|
|
|
|
|
.get::<ToplevelState>()
|
|
|
|
|
.unwrap()
|
|
|
|
|
.lock()
|
|
|
|
|
.unwrap();
|
|
|
|
|
let instance = match state
|
|
|
|
|
.instances
|
|
|
|
|
.iter()
|
|
|
|
|
.find(|i| i.id().same_client_as(&info.id()))
|
|
|
|
|
{
|
2022-07-04 15:26:26 +02:00
|
|
|
Some(i) => i,
|
|
|
|
|
None => {
|
|
|
|
|
if let Ok(client) = dh.get_client(info.id()) {
|
2022-07-04 16:00:29 +02:00
|
|
|
if let Ok(toplevel_handle) = client
|
|
|
|
|
.create_resource::<ZcosmicToplevelHandleV1, _, D>(
|
|
|
|
|
dh,
|
|
|
|
|
info.version(),
|
2022-07-18 21:26:02 +02:00
|
|
|
ToplevelHandleStateInner::from_window(window),
|
2022-07-04 16:00:29 +02:00
|
|
|
)
|
|
|
|
|
{
|
2022-07-19 19:30:06 +02:00
|
|
|
info.toplevel(&toplevel_handle);
|
2022-07-04 15:26:26 +02:00
|
|
|
state.instances.push(toplevel_handle);
|
|
|
|
|
state.instances.last().unwrap()
|
|
|
|
|
} else {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2022-07-04 16:00:29 +02:00
|
|
|
let mut handle_state = instance
|
2023-01-16 15:12:25 +01:00
|
|
|
.data::<ToplevelHandleState<W>>()
|
2022-07-04 16:00:29 +02:00
|
|
|
.unwrap()
|
|
|
|
|
.lock()
|
|
|
|
|
.unwrap();
|
2022-07-04 15:26:26 +02:00
|
|
|
let mut changed = false;
|
2023-01-16 15:12:25 +01:00
|
|
|
if handle_state.title != window.title() {
|
|
|
|
|
handle_state.title = window.title();
|
|
|
|
|
instance.title(handle_state.title.clone());
|
|
|
|
|
changed = true;
|
|
|
|
|
}
|
|
|
|
|
if handle_state.app_id != window.app_id() {
|
|
|
|
|
handle_state.app_id = window.app_id();
|
|
|
|
|
instance.app_id(handle_state.app_id.clone());
|
|
|
|
|
changed = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (handle_state.states.contains(&States::Maximized) != window.is_maximized())
|
|
|
|
|
|| (handle_state.states.contains(&States::Fullscreen) != window.is_fullscreen())
|
|
|
|
|
|| (handle_state.states.contains(&States::Activated) != window.is_activated())
|
|
|
|
|
|| (handle_state.states.contains(&States::Minimized) != window.is_minimized())
|
|
|
|
|
{
|
|
|
|
|
let mut states = Vec::new();
|
|
|
|
|
if window.is_maximized() {
|
|
|
|
|
states.push(States::Maximized);
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
2023-01-16 15:12:25 +01:00
|
|
|
if window.is_fullscreen() {
|
|
|
|
|
states.push(States::Fullscreen);
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
2023-01-16 15:12:25 +01:00
|
|
|
if window.is_activated() {
|
|
|
|
|
states.push(States::Activated);
|
2022-07-04 15:26:26 +02:00
|
|
|
}
|
2023-01-16 15:12:25 +01:00
|
|
|
if window.is_minimized() {
|
|
|
|
|
states.push(States::Minimized);
|
|
|
|
|
}
|
|
|
|
|
handle_state.states = states.clone();
|
|
|
|
|
|
|
|
|
|
let states: Vec<u8> = {
|
|
|
|
|
let ratio = std::mem::size_of::<States>() / std::mem::size_of::<u8>();
|
|
|
|
|
let ptr = states.as_mut_ptr() as *mut u8;
|
|
|
|
|
let len = states.len() * ratio;
|
|
|
|
|
let cap = states.capacity() * ratio;
|
|
|
|
|
std::mem::forget(states);
|
|
|
|
|
unsafe { Vec::from_raw_parts(ptr, len, cap) }
|
|
|
|
|
};
|
|
|
|
|
instance.state(states);
|
|
|
|
|
changed = true;
|
|
|
|
|
}
|
2022-07-04 15:26:26 +02:00
|
|
|
|
|
|
|
|
if let Ok(client) = dh.get_client(instance.id()) {
|
2022-07-04 16:00:29 +02:00
|
|
|
for new_output in state
|
|
|
|
|
.outputs
|
|
|
|
|
.iter()
|
|
|
|
|
.filter(|o| !handle_state.outputs.contains(o))
|
|
|
|
|
{
|
2022-11-03 18:51:27 +01:00
|
|
|
for wl_output in new_output.client_outputs(&client) {
|
|
|
|
|
instance.output_enter(&wl_output);
|
|
|
|
|
}
|
2022-07-04 15:26:26 +02:00
|
|
|
changed = true;
|
|
|
|
|
}
|
2022-07-04 16:00:29 +02:00
|
|
|
for old_output in handle_state
|
|
|
|
|
.outputs
|
|
|
|
|
.iter()
|
|
|
|
|
.filter(|o| !state.outputs.contains(o))
|
|
|
|
|
{
|
2022-11-03 18:51:27 +01:00
|
|
|
for wl_output in old_output.client_outputs(&client) {
|
|
|
|
|
instance.output_leave(&wl_output);
|
|
|
|
|
}
|
2022-07-04 15:26:26 +02:00
|
|
|
changed = true;
|
|
|
|
|
}
|
|
|
|
|
handle_state.outputs = state.outputs.clone();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let Some(workspace_state) = workspace_state {
|
2022-07-04 16:00:29 +02:00
|
|
|
for new_workspace in state
|
|
|
|
|
.workspaces
|
|
|
|
|
.iter()
|
|
|
|
|
.filter(|w| !handle_state.workspaces.contains(w))
|
|
|
|
|
{
|
|
|
|
|
if let Some(handle) =
|
|
|
|
|
workspace_state.raw_workspace_handle(&new_workspace, &instance.id())
|
|
|
|
|
{
|
2022-07-04 15:26:26 +02:00
|
|
|
instance.workspace_enter(&handle);
|
|
|
|
|
changed = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-07-04 16:00:29 +02:00
|
|
|
for old_workspace in handle_state
|
|
|
|
|
.workspaces
|
|
|
|
|
.iter()
|
|
|
|
|
.filter(|w| !state.workspaces.contains(w))
|
|
|
|
|
{
|
|
|
|
|
if let Some(handle) =
|
|
|
|
|
workspace_state.raw_workspace_handle(&old_workspace, &instance.id())
|
|
|
|
|
{
|
2022-07-04 15:26:26 +02:00
|
|
|
instance.workspace_leave(&handle);
|
|
|
|
|
changed = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
handle_state.workspaces = state.workspaces.clone();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if changed {
|
|
|
|
|
instance.done();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-16 15:12:25 +01:00
|
|
|
pub fn window_from_handle<W: Window + 'static>(handle: ZcosmicToplevelHandleV1) -> Option<W> {
|
2022-07-18 21:26:02 +02:00
|
|
|
handle
|
2023-01-16 15:12:25 +01:00
|
|
|
.data::<ToplevelHandleState<W>>()
|
2022-08-30 13:28:36 +02:00
|
|
|
.map(|state| state.lock().unwrap().window.clone())
|
2022-07-18 21:26:02 +02:00
|
|
|
}
|
|
|
|
|
|
2022-07-04 15:26:26 +02:00
|
|
|
macro_rules! delegate_toplevel_info {
|
2023-01-16 15:12:25 +01:00
|
|
|
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty, $window: ty) => {
|
2022-07-04 15:26:26 +02:00
|
|
|
smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
|
|
|
|
|
cosmic_protocols::toplevel_info::v1::server::zcosmic_toplevel_info_v1::ZcosmicToplevelInfoV1: $crate::wayland::protocols::toplevel_info::ToplevelInfoGlobalData
|
2023-01-16 15:12:25 +01:00
|
|
|
] => $crate::wayland::protocols::toplevel_info::ToplevelInfoState<Self, $window>);
|
2022-07-04 15:26:26 +02:00
|
|
|
smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
|
|
|
|
|
cosmic_protocols::toplevel_info::v1::server::zcosmic_toplevel_info_v1::ZcosmicToplevelInfoV1: ()
|
2023-01-16 15:12:25 +01:00
|
|
|
] => $crate::wayland::protocols::toplevel_info::ToplevelInfoState<Self, $window>);
|
2022-07-04 15:26:26 +02:00
|
|
|
smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
|
2023-01-16 15:12:25 +01:00
|
|
|
cosmic_protocols::toplevel_info::v1::server::zcosmic_toplevel_handle_v1::ZcosmicToplevelHandleV1: $crate::wayland::protocols::toplevel_info::ToplevelHandleState<$window>
|
|
|
|
|
] => $crate::wayland::protocols::toplevel_info::ToplevelInfoState<Self, $window>);
|
2022-07-04 15:26:26 +02:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
pub(crate) use delegate_toplevel_info;
|