Use cosmic-config for dynamic workspace settings

`WorkspaceAmount`, `WorkspaceMode`, and `WorkspaceLayout` can all be
changed dynamically now.
This commit is contained in:
Ian Douglas Scott 2023-09-07 13:28:08 -07:00
parent 25f5edd6cf
commit 81efd42dd5
9 changed files with 88 additions and 51 deletions

View file

@ -81,8 +81,5 @@
(modifiers: [], key: "XF86MonBrightnessUp"): Spawn("busctl --user call com.system76.CosmicSettingsDaemon /com/system76/CosmicSettingsDaemon com.system76.CosmicSettingsDaemon IncreaseDisplayBrightness"), (modifiers: [], key: "XF86MonBrightnessUp"): Spawn("busctl --user call com.system76.CosmicSettingsDaemon /com/system76/CosmicSettingsDaemon com.system76.CosmicSettingsDaemon IncreaseDisplayBrightness"),
(modifiers: [], key: "XF86MonBrightnessDown"): Spawn("busctl --user call com.system76.CosmicSettingsDaemon /com/system76/CosmicSettingsDaemon com.system76.CosmicSettingsDaemon DecreaseDisplayBrightness"), (modifiers: [], key: "XF86MonBrightnessDown"): Spawn("busctl --user call com.system76.CosmicSettingsDaemon /com/system76/CosmicSettingsDaemon com.system76.CosmicSettingsDaemon DecreaseDisplayBrightness"),
}, },
workspace_mode: OutputBound,
workspace_amount: Dynamic,
workspace_layout: Vertical,
tiling_enabled: false, tiling_enabled: false,
) )

View file

@ -3,6 +3,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
pub mod input; pub mod input;
pub mod workspace;
#[derive(Debug, Clone, Deserialize, Serialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
pub struct XkbConfig { pub struct XkbConfig {

View file

@ -0,0 +1,43 @@
// SPDX-License-Identifier: GPL-3.0-only
use serde::{Deserialize, Serialize};
fn default_workspace_layout() -> WorkspaceLayout {
WorkspaceLayout::Vertical
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkspaceConfig {
pub workspace_mode: WorkspaceMode,
pub workspace_amount: WorkspaceAmount,
#[serde(default = "default_workspace_layout")]
pub workspace_layout: WorkspaceLayout,
}
impl Default for WorkspaceConfig {
fn default() -> Self {
Self {
workspace_mode: WorkspaceMode::OutputBound,
workspace_amount: WorkspaceAmount::Dynamic,
workspace_layout: WorkspaceLayout::Vertical,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum WorkspaceAmount {
Dynamic,
Static(u8),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum WorkspaceMode {
OutputBound,
Global,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum WorkspaceLayout {
Vertical,
Horizontal,
}

View file

@ -11,7 +11,6 @@ use std::{
#[cfg(feature = "debug")] #[cfg(feature = "debug")]
use crate::debug::{fps_ui, profiler_ui}; use crate::debug::{fps_ui, profiler_ui};
use crate::{ use crate::{
config::WorkspaceLayout,
shell::{ shell::{
focus::target::WindowGroup, grabs::SeatMoveGrabState, layout::tiling::ANIMATION_DURATION, focus::target::WindowGroup, grabs::SeatMoveGrabState, layout::tiling::ANIMATION_DURATION,
CosmicMapped, CosmicMappedRenderElement, OverviewMode, Trigger, WorkspaceRenderElement, CosmicMapped, CosmicMappedRenderElement, OverviewMode, Trigger, WorkspaceRenderElement,
@ -32,6 +31,7 @@ use crate::{
}, },
}; };
use cosmic_comp_config::workspace::WorkspaceLayout;
use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::FailureReason; use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::FailureReason;
use keyframe::{ease, functions::EaseInOutCubic}; use keyframe::{ease, functions::EaseInOutCubic};
use smithay::{ use smithay::{
@ -557,7 +557,7 @@ where
let offset = match previous.as_ref() { let offset = match previous.as_ref() {
Some((previous, previous_idx, start)) => { Some((previous, previous_idx, start)) => {
let layout = state.config.static_conf.workspace_layout; let layout = state.config.workspace.workspace_layout;
let workspace = state let workspace = state
.shell .shell

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use crate::shell::{focus::FocusDirection, grabs::ResizeEdge, Direction, ResizeDirection}; use crate::shell::{focus::FocusDirection, grabs::ResizeEdge, Direction, ResizeDirection};
use cosmic_comp_config::workspace::WorkspaceLayout;
use serde::Deserialize; use serde::Deserialize;
use smithay::{ use smithay::{
backend::input::KeyState, backend::input::KeyState,
@ -8,7 +9,7 @@ use smithay::{
}; };
use std::collections::HashMap; use std::collections::HashMap;
use super::{types::*, WorkspaceLayout}; use super::types::*;
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
pub enum KeyModifier { pub enum KeyModifier {

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use crate::{ use crate::{
shell::{Shell, WorkspaceAmount}, shell::Shell,
state::{BackendData, State}, state::{BackendData, State},
wayland::protocols::output_configuration::OutputConfigurationState, wayland::protocols::output_configuration::OutputConfigurationState,
}; };
@ -29,7 +29,11 @@ mod key_bindings;
pub use key_bindings::{Action, KeyModifier, KeyModifiers, KeyPattern}; pub use key_bindings::{Action, KeyModifier, KeyModifiers, KeyPattern};
mod types; mod types;
pub use self::types::*; pub use self::types::*;
use cosmic_comp_config::{input::InputConfig, XkbConfig}; use cosmic_comp_config::{
input::InputConfig,
workspace::{WorkspaceConfig, WorkspaceLayout},
XkbConfig,
};
#[derive(Debug)] #[derive(Debug)]
pub struct Config { pub struct Config {
@ -40,30 +44,15 @@ pub struct Config {
pub input_default: InputConfig, pub input_default: InputConfig,
pub input_touchpad: InputConfig, pub input_touchpad: InputConfig,
pub input_devices: HashMap<String, InputConfig>, pub input_devices: HashMap<String, InputConfig>,
pub workspace: WorkspaceConfig,
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct StaticConfig { pub struct StaticConfig {
pub key_bindings: HashMap<key_bindings::KeyPattern, key_bindings::Action>, pub key_bindings: HashMap<key_bindings::KeyPattern, key_bindings::Action>,
pub workspace_mode: WorkspaceMode,
pub workspace_amount: WorkspaceAmount,
#[serde(default = "default_workspace_layout")]
pub workspace_layout: WorkspaceLayout,
pub tiling_enabled: bool, pub tiling_enabled: bool,
} }
#[derive(Debug, Deserialize, Clone, Copy, PartialEq, Eq)]
pub enum WorkspaceMode {
OutputBound,
Global,
}
#[derive(Debug, Deserialize, Clone, Copy, PartialEq, Eq)]
pub enum WorkspaceLayout {
Vertical,
Horizontal,
}
#[derive(Debug)] #[derive(Debug)]
pub struct DynamicConfig { pub struct DynamicConfig {
outputs: (Option<PathBuf>, OutputsConfig), outputs: (Option<PathBuf>, OutputsConfig),
@ -96,10 +85,6 @@ fn default_enabled() -> bool {
true true
} }
fn default_workspace_layout() -> WorkspaceLayout {
WorkspaceLayout::Vertical
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] #[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
pub struct OutputConfig { pub struct OutputConfig {
pub mode: ((i32, i32), Option<u32>), pub mode: ((i32, i32), Option<u32>),
@ -155,18 +140,23 @@ impl Config {
}) })
.expect("Failed to add cosmic-config to the event loop"); .expect("Failed to add cosmic-config to the event loop");
let xdg = xdg::BaseDirectories::new().ok(); let xdg = xdg::BaseDirectories::new().ok();
let workspace = get_config::<WorkspaceConfig>(&config, "workspaces");
Config { Config {
static_conf: Self::load_static(xdg.as_ref()), static_conf: Self::load_static(xdg.as_ref(), workspace.workspace_layout),
dynamic_conf: Self::load_dynamic(xdg.as_ref()), dynamic_conf: Self::load_dynamic(xdg.as_ref()),
xkb: get_config(&config, "xkb-config"), xkb: get_config(&config, "xkb-config"),
input_default: get_config(&config, "input-default"), input_default: get_config(&config, "input-default"),
input_touchpad: get_config(&config, "input-touchpad"), input_touchpad: get_config(&config, "input-touchpad"),
input_devices: get_config(&config, "input-devices"), input_devices: get_config(&config, "input-devices"),
workspace,
config, config,
} }
} }
fn load_static(xdg: Option<&xdg::BaseDirectories>) -> StaticConfig { fn load_static(
xdg: Option<&xdg::BaseDirectories>,
workspace_layout: WorkspaceLayout,
) -> StaticConfig {
let mut locations = if let Some(base) = xdg { let mut locations = if let Some(base) = xdg {
vec![ vec![
base.get_config_file("cosmic-comp.ron"), base.get_config_file("cosmic-comp.ron"),
@ -192,10 +182,7 @@ impl Config {
ron::de::from_reader(OpenOptions::new().read(true).open(path).unwrap()) ron::de::from_reader(OpenOptions::new().read(true).open(path).unwrap())
.expect("Malformed config file"); .expect("Malformed config file");
key_bindings::add_default_bindings( key_bindings::add_default_bindings(&mut config.key_bindings, workspace_layout);
&mut config.key_bindings,
config.workspace_layout,
);
return config; return config;
} }
@ -203,9 +190,6 @@ impl Config {
StaticConfig { StaticConfig {
key_bindings: HashMap::new(), key_bindings: HashMap::new(),
workspace_mode: WorkspaceMode::Global,
workspace_amount: WorkspaceAmount::Dynamic,
workspace_layout: WorkspaceLayout::Vertical,
tiling_enabled: false, tiling_enabled: false,
} }
} }
@ -516,6 +500,11 @@ fn config_changed(config: cosmic_config::Config, keys: Vec<String>, state: &mut
state.common.config.input_devices = value; state.common.config.input_devices = value;
update_input(state); update_input(state);
} }
"workspaces" => {
state.common.config.workspace =
get_config::<WorkspaceConfig>(&config, "workspaces");
state.common.shell.update_config(&state.common.config);
}
_ => {} _ => {}
} }
} }

View file

@ -2,7 +2,7 @@
use crate::{ use crate::{
backend::render::cursor::CursorState, backend::render::cursor::CursorState,
config::{xkb_config_to_wl, Action, Config, KeyPattern, WorkspaceLayout}, config::{xkb_config_to_wl, Action, Config, KeyPattern},
shell::{ shell::{
focus::{target::PointerFocusTarget, FocusDirection}, focus::{target::PointerFocusTarget, FocusDirection},
grabs::{ResizeEdge, SeatMoveGrabState}, grabs::{ResizeEdge, SeatMoveGrabState},
@ -18,6 +18,7 @@ use crate::{
wayland::{handlers::screencopy::ScreencopySessions, protocols::screencopy::Session}, wayland::{handlers::screencopy::ScreencopySessions, protocols::screencopy::Session},
}; };
use calloop::{timer::Timer, RegistrationToken}; use calloop::{timer::Timer, RegistrationToken};
use cosmic_comp_config::workspace::WorkspaceLayout;
use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::InputType; use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::InputType;
#[allow(deprecated)] #[allow(deprecated)]
use smithay::{ use smithay::{
@ -1518,7 +1519,7 @@ impl State {
match result { match result {
FocusResult::None => { FocusResult::None => {
match (focus, self.common.config.static_conf.workspace_layout) { match (focus, self.common.config.workspace.workspace_layout) {
(FocusDirection::Left, WorkspaceLayout::Horizontal) (FocusDirection::Left, WorkspaceLayout::Horizontal)
| (FocusDirection::Up, WorkspaceLayout::Vertical) => self | (FocusDirection::Up, WorkspaceLayout::Vertical) => self
.handle_action( .handle_action(
@ -1574,7 +1575,7 @@ impl State {
match workspace.move_current_element(direction, seat) { match workspace.move_current_element(direction, seat) {
MoveResult::MoveFurther(_move_further) => { MoveResult::MoveFurther(_move_further) => {
match (direction, self.common.config.static_conf.workspace_layout) { match (direction, self.common.config.workspace.workspace_layout) {
(Direction::Left, WorkspaceLayout::Horizontal) (Direction::Left, WorkspaceLayout::Horizontal)
| (Direction::Up, WorkspaceLayout::Vertical) => self.handle_action( | (Direction::Up, WorkspaceLayout::Vertical) => self.handle_action(
Action::MoveToPreviousWorkspace, Action::MoveToPreviousWorkspace,

View file

@ -1,6 +1,5 @@
use calloop::LoopHandle; use calloop::LoopHandle;
use indexmap::IndexMap; use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use std::{ use std::{
collections::HashMap, collections::HashMap,
sync::atomic::{AtomicBool, Ordering}, sync::atomic::{AtomicBool, Ordering},
@ -8,6 +7,7 @@ use std::{
}; };
use wayland_backend::server::ClientId; use wayland_backend::server::ClientId;
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;
use keyframe::{ease, functions::EaseInOutCubic}; use keyframe::{ease, functions::EaseInOutCubic};
use smithay::{ use smithay::{
@ -35,7 +35,7 @@ use smithay::{
}; };
use crate::{ use crate::{
config::{Config, KeyModifiers, KeyPattern, WorkspaceMode}, config::{Config, KeyModifiers, KeyPattern},
state::client_has_security_context, state::client_has_security_context,
utils::prelude::*, utils::prelude::*,
wayland::protocols::{ wayland::protocols::{
@ -189,12 +189,6 @@ pub struct WorkspaceSet {
pub(crate) workspaces: Vec<Workspace>, pub(crate) workspaces: Vec<Workspace>,
} }
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum WorkspaceAmount {
Dynamic,
Static(u8),
}
fn create_workspace( fn create_workspace(
state: &mut WorkspaceUpdateGuard<'_, State>, state: &mut WorkspaceUpdateGuard<'_, State>,
output: &Output, output: &Output,
@ -466,8 +460,8 @@ impl Workspaces {
Workspaces { Workspaces {
sets: IndexMap::new(), sets: IndexMap::new(),
backup_set: None, backup_set: None,
amount: config.static_conf.workspace_amount, amount: config.workspace.workspace_amount,
mode: config.static_conf.workspace_mode, mode: config.workspace.workspace_mode,
tiling_enabled: config.static_conf.tiling_enabled, tiling_enabled: config.static_conf.tiling_enabled,
theme, theme,
} }
@ -592,11 +586,16 @@ impl Workspaces {
workspace_state: &mut WorkspaceUpdateGuard<'_, State>, workspace_state: &mut WorkspaceUpdateGuard<'_, State>,
toplevel_info_state: &mut ToplevelInfoState<State, CosmicSurface>, toplevel_info_state: &mut ToplevelInfoState<State, CosmicSurface>,
) { ) {
let old_mode = self.mode;
self.mode = config.workspace.workspace_mode;
self.amount = config.workspace.workspace_amount;
if self.sets.len() <= 1 { if self.sets.len() <= 1 {
return; return;
} }
match (self.mode, config.static_conf.workspace_mode) { match (old_mode, self.mode) {
(WorkspaceMode::Global, WorkspaceMode::OutputBound) => { (WorkspaceMode::Global, WorkspaceMode::OutputBound) => {
// We basically just unlink the existing spaces, so nothing needs to be updated // We basically just unlink the existing spaces, so nothing needs to be updated
} }

View file

@ -70,6 +70,7 @@ pub struct WorkspaceGroupHandle {
pub struct WorkspaceGroupDataInner { pub struct WorkspaceGroupDataInner {
outputs: Vec<Output>, outputs: Vec<Output>,
capabilities: Vec<GroupCapabilities>, capabilities: Vec<GroupCapabilities>,
workspace_count: usize,
} }
pub type WorkspaceGroupData = Mutex<WorkspaceGroupDataInner>; pub type WorkspaceGroupData = Mutex<WorkspaceGroupDataInner>;
@ -870,6 +871,11 @@ where
changed = true; changed = true;
} }
if handle_state.workspace_count != group.workspaces.len() {
changed = true;
}
handle_state.workspace_count = group.workspaces.len();
for workspace in &mut group.workspaces { for workspace in &mut group.workspaces {
if send_workspace_to_client::<D>(dh, instance, workspace) { if send_workspace_to_client::<D>(dh, instance, workspace) {
changed = true; changed = true;