workspace: Add tiling_state

This commit is contained in:
Victoria Brekenfeld 2024-01-03 17:11:50 +00:00 committed by Victoria Brekenfeld
parent ec822e421f
commit 226bf7f49d
4 changed files with 133 additions and 25 deletions

View file

@ -2049,8 +2049,9 @@ impl State {
} }
Action::ToggleTiling => { Action::ToggleTiling => {
let output = seat.active_output(); let output = seat.active_output();
let workspace = self.common.shell.active_space_mut(&output); let workspace = self.common.shell.workspaces.active_mut(&output);
workspace.toggle_tiling(seat); let mut guard = self.common.shell.workspace_state.update();
workspace.toggle_tiling(seat, &mut guard);
} }
Action::ToggleWindowFloating => { Action::ToggleWindowFloating => {
let output = seat.active_output(); let output = seat.active_output();

View file

@ -8,7 +8,9 @@ use std::{
use wayland_backend::server::ClientId; use wayland_backend::server::ClientId;
use cosmic_comp_config::workspace::{WorkspaceAmount, WorkspaceMode}; use cosmic_comp_config::workspace::{WorkspaceAmount, WorkspaceMode};
use cosmic_protocols::workspace::v1::server::zcosmic_workspace_handle_v1::State as WState; use cosmic_protocols::workspace::v1::server::zcosmic_workspace_handle_v1::{
State as WState, TilingState,
};
use keyframe::{ease, functions::EaseInOutCubic}; use keyframe::{ease, functions::EaseInOutCubic};
use smithay::{ use smithay::{
desktop::{ desktop::{
@ -238,7 +240,16 @@ fn create_workspace(
tiling: bool, tiling: bool,
theme: cosmic::Theme, theme: cosmic::Theme,
) -> Workspace { ) -> Workspace {
let workspace_handle = state.create_workspace(&group_handle).unwrap(); let workspace_handle = state
.create_workspace(
&group_handle,
if tiling {
TilingState::TilingEnabled
} else {
TilingState::FloatingOnly
},
)
.unwrap();
if active { if active {
state.add_workspace_state(&workspace_handle, WState::Active); state.add_workspace_state(&workspace_handle, WState::Active);
} }
@ -256,7 +267,16 @@ fn move_workspace_to_group(
toplevel_info_state: &mut ToplevelInfoState<State, CosmicSurface>, toplevel_info_state: &mut ToplevelInfoState<State, CosmicSurface>,
) { ) {
let old_workspace_handle = workspace.handle; let old_workspace_handle = workspace.handle;
workspace.handle = workspace_state.create_workspace(group).unwrap(); workspace.handle = workspace_state
.create_workspace(
group,
if workspace.tiling_enabled {
TilingState::TilingEnabled
} else {
TilingState::FloatingOnly
},
)
.unwrap();
workspace_state.set_workspace_capabilities( workspace_state.set_workspace_capabilities(
&workspace.handle, &workspace.handle,
[WorkspaceCapabilities::Activate].into_iter(), [WorkspaceCapabilities::Activate].into_iter(),
@ -515,15 +535,6 @@ impl WorkspaceSet {
workspace_set_idx(state, i as u8 + 1, idx, &workspace.handle); workspace_set_idx(state, i as u8 + 1, idx, &workspace.handle);
} }
} }
fn update_tiling_status(&mut self, seat: &Seat<State>, tiling_enabled: bool) {
self.tiling_enabled = tiling_enabled;
for workspace in &mut self.workspaces {
if workspace.tiling_enabled != tiling_enabled {
workspace.toggle_tiling(seat);
}
}
}
} }
#[derive(Debug)] #[derive(Debug)]
@ -1001,12 +1012,6 @@ impl Workspaces {
) )
} }
pub fn update_tiling_status(&mut self, seat: &Seat<State>, tiling: bool) {
for set in self.sets.values_mut() {
set.update_tiling_status(seat, tiling)
}
}
pub fn set_theme(&mut self, theme: cosmic::Theme, xdg_activation_state: &XdgActivationState) { pub fn set_theme(&mut self, theme: cosmic::Theme, xdg_activation_state: &XdgActivationState) {
for (_, s) in &mut self.sets { for (_, s) in &mut self.sets {
s.theme = theme.clone(); s.theme = theme.clone();

View file

@ -14,12 +14,13 @@ use crate::{
protocols::{ protocols::{
screencopy::{BufferParams, Session as ScreencopySession}, screencopy::{BufferParams, Session as ScreencopySession},
toplevel_info::ToplevelInfoState, toplevel_info::ToplevelInfoState,
workspace::WorkspaceHandle, workspace::{WorkspaceHandle, WorkspaceUpdateGuard},
}, },
}, },
}; };
use cosmic::theme::CosmicTheme; use cosmic::theme::CosmicTheme;
use cosmic_protocols::workspace::v1::server::zcosmic_workspace_handle_v1::TilingState;
use id_tree::Tree; use id_tree::Tree;
use indexmap::IndexSet; use indexmap::IndexSet;
use keyframe::{ease, functions::EaseInOutCubic}; use keyframe::{ease, functions::EaseInOutCubic};
@ -612,7 +613,11 @@ impl Workspace {
} }
} }
pub fn toggle_tiling(&mut self, seat: &Seat<State>) { pub fn toggle_tiling(
&mut self,
seat: &Seat<State>,
workspace_state: &mut WorkspaceUpdateGuard<'_, State>,
) {
if self.tiling_enabled { if self.tiling_enabled {
for window in self for window in self
.tiling_layer .tiling_layer
@ -624,6 +629,7 @@ impl Workspace {
self.tiling_layer.unmap(&window); self.tiling_layer.unmap(&window);
self.floating_layer.map(window, None); self.floating_layer.map(window, None);
} }
workspace_state.set_workspace_tiling_state(&self.handle, TilingState::FloatingOnly);
self.tiling_enabled = false; self.tiling_enabled = false;
} else { } else {
let focus_stack = self.focus_stack.get(seat); let focus_stack = self.focus_stack.get(seat);
@ -638,6 +644,7 @@ impl Workspace {
self.tiling_layer self.tiling_layer
.map(window, Some(focus_stack.iter()), None) .map(window, Some(focus_stack.iter()), None)
} }
workspace_state.set_workspace_tiling_state(&self.handle, TilingState::TilingEnabled);
self.tiling_enabled = true; self.tiling_enabled = true;
} }
} }

View file

@ -9,6 +9,7 @@ use smithay::{
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource,
}, },
}; };
use wayland_backend::protocol::WEnum;
use cosmic_protocols::workspace::v1::server::{ use cosmic_protocols::workspace::v1::server::{
zcosmic_workspace_group_handle_v1::{self, ZcosmicWorkspaceGroupHandleV1}, zcosmic_workspace_group_handle_v1::{self, ZcosmicWorkspaceGroupHandleV1},
@ -74,7 +75,7 @@ pub struct WorkspaceGroupDataInner {
} }
pub type WorkspaceGroupData = Mutex<WorkspaceGroupDataInner>; pub type WorkspaceGroupData = Mutex<WorkspaceGroupDataInner>;
#[derive(Debug, Default)] #[derive(Debug)]
pub struct Workspace { pub struct Workspace {
id: usize, id: usize,
instances: Vec<ZcosmicWorkspaceHandleV1>, instances: Vec<ZcosmicWorkspaceHandleV1>,
@ -83,6 +84,7 @@ pub struct Workspace {
capabilities: Vec<WorkspaceCapabilities>, capabilities: Vec<WorkspaceCapabilities>,
coordinates: Vec<u32>, coordinates: Vec<u32>,
states: HashSet<zcosmic_workspace_handle_v1::State>, states: HashSet<zcosmic_workspace_handle_v1::State>,
tiling: zcosmic_workspace_handle_v1::TilingState,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -96,6 +98,7 @@ pub struct WorkspaceDataInner {
capabilities: Vec<WorkspaceCapabilities>, capabilities: Vec<WorkspaceCapabilities>,
coordinates: Vec<u32>, coordinates: Vec<u32>,
states: HashSet<zcosmic_workspace_handle_v1::State>, states: HashSet<zcosmic_workspace_handle_v1::State>,
tiling: Option<zcosmic_workspace_handle_v1::TilingState>,
} }
pub type WorkspaceData = Mutex<WorkspaceDataInner>; pub type WorkspaceData = Mutex<WorkspaceDataInner>;
@ -124,6 +127,14 @@ pub enum Request {
Activate(WorkspaceHandle), Activate(WorkspaceHandle),
Deactivate(WorkspaceHandle), Deactivate(WorkspaceHandle),
Remove(WorkspaceHandle), Remove(WorkspaceHandle),
Rename {
workspace: WorkspaceHandle,
name: String,
},
SetTilingState {
workspace: WorkspaceHandle,
state: WEnum<zcosmic_workspace_handle_v1::TilingState>,
},
Create { Create {
in_group: WorkspaceGroupHandle, in_group: WorkspaceGroupHandle,
name: String, name: String,
@ -339,6 +350,36 @@ where
state.requests.push(Request::Remove(workspace_handle)); state.requests.push(Request::Remove(workspace_handle));
} }
} }
zcosmic_workspace_handle_v1::Request::Rename { name } => {
if let Some(workspace_handle) = state.workspace_state().get_workspace_handle(obj) {
let mut state = client
.get_data::<<D as WorkspaceHandler>::Client>()
.unwrap()
.workspace_state()
.lock()
.unwrap();
state.requests.push(Request::Rename {
workspace: workspace_handle,
name,
});
}
}
zcosmic_workspace_handle_v1::Request::SetTilingState {
state: tiling_state,
} => {
if let Some(workspace_handle) = state.workspace_state().get_workspace_handle(obj) {
let mut state = client
.get_data::<<D as WorkspaceHandler>::Client>()
.unwrap()
.workspace_state()
.lock()
.unwrap();
state.requests.push(Request::SetTilingState {
workspace: workspace_handle,
state: tiling_state,
});
}
}
zcosmic_workspace_handle_v1::Request::Destroy => { zcosmic_workspace_handle_v1::Request::Destroy => {
for group in &mut state.workspace_state_mut().groups { for group in &mut state.workspace_state_mut().groups {
for workspace in &mut group.workspaces { for workspace in &mut group.workspaces {
@ -468,6 +509,18 @@ where
}) })
} }
pub fn workspace_tiling_state(
&self,
workspace: &WorkspaceHandle,
) -> Option<zcosmic_workspace_handle_v1::TilingState> {
self.groups.iter().find_map(|g| {
g.workspaces
.iter()
.find(|w| w.id == workspace.id)
.map(|w| w.tiling)
})
}
pub fn group_handle( pub fn group_handle(
&self, &self,
group: &ZcosmicWorkspaceGroupHandleV1, group: &ZcosmicWorkspaceGroupHandleV1,
@ -569,12 +622,21 @@ where
WorkspaceGroupHandle { id } WorkspaceGroupHandle { id }
} }
pub fn create_workspace(&mut self, group: &WorkspaceGroupHandle) -> Option<WorkspaceHandle> { pub fn create_workspace(
&mut self,
group: &WorkspaceGroupHandle,
tiling: zcosmic_workspace_handle_v1::TilingState,
) -> Option<WorkspaceHandle> {
if let Some(group) = self.0.groups.iter_mut().find(|g| g.id == group.id) { if let Some(group) = self.0.groups.iter_mut().find(|g| g.id == group.id) {
let id = next_workspace_id(); let id = next_workspace_id();
let workspace = Workspace { let workspace = Workspace {
id, id,
..Default::default() tiling,
instances: Default::default(),
name: Default::default(),
capabilities: Default::default(),
coordinates: Default::default(),
states: Default::default(),
}; };
group.workspaces.push(workspace); group.workspaces.push(workspace);
Some(WorkspaceHandle { id }) Some(WorkspaceHandle { id })
@ -758,6 +820,28 @@ where
workspace.states.remove(&state); workspace.states.remove(&state);
} }
} }
pub fn workspace_tiling_state(
&self,
workspace: &WorkspaceHandle,
) -> Option<zcosmic_workspace_handle_v1::TilingState> {
self.0.workspace_tiling_state(workspace)
}
pub fn set_workspace_tiling_state(
&mut self,
workspace: &WorkspaceHandle,
state: zcosmic_workspace_handle_v1::TilingState,
) {
if let Some(workspace) = self
.0
.groups
.iter_mut()
.find_map(|g| g.workspaces.iter_mut().find(|w| w.id == workspace.id))
{
workspace.tiling = state;
}
}
} }
impl<'a, D> Drop for WorkspaceUpdateGuard<'a, D> impl<'a, D> Drop for WorkspaceUpdateGuard<'a, D>
@ -963,6 +1047,17 @@ where
handle_state.states = workspace.states.clone(); handle_state.states = workspace.states.clone();
changed = true; changed = true;
} }
if instance.version() >= zcosmic_workspace_handle_v1::EVT_TILING_STATE_SINCE {
if handle_state
.tiling
.map(|state| state != workspace.tiling)
.unwrap_or(true)
{
instance.tiling_state(workspace.tiling);
handle_state.tiling = Some(workspace.tiling);
changed = true;
}
}
changed changed
} }