feat: add tiling variables to cosmic config

This commit is contained in:
Ashley Wulber 2024-02-08 14:25:18 -05:00 committed by GitHub
parent e43c0f648d
commit 5eb5af4675
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 189 additions and 44 deletions

View file

@ -7,13 +7,44 @@ use std::collections::HashMap;
pub mod input; pub mod input;
pub mod workspace; pub mod workspace;
#[derive(Clone, Debug, Default, PartialEq, CosmicConfigEntry)] #[derive(Clone, Debug, PartialEq, CosmicConfigEntry)]
#[version = 1]
pub struct CosmicCompConfig { pub struct CosmicCompConfig {
pub workspaces: workspace::WorkspaceConfig, pub workspaces: workspace::WorkspaceConfig,
pub input_default: input::InputConfig, pub input_default: input::InputConfig,
pub input_touchpad: input::InputConfig, pub input_touchpad: input::InputConfig,
pub input_devices: HashMap<String, input::InputConfig>, pub input_devices: HashMap<String, input::InputConfig>,
pub xkb_config: XkbConfig, pub xkb_config: XkbConfig,
/// Autotiling enabled
pub autotile: bool,
/// Determines the behavior of the autotile variable
/// If set to Global, autotile applies to all windows in all workspaces
/// If set to PerWorkspace, autotile only applies to new windows, and new workspaces
pub autotile_behavior: TileBehavior,
/// Active hint enabled
pub active_hint: bool,
}
impl Default for CosmicCompConfig {
fn default() -> Self {
Self {
workspaces: Default::default(),
input_default: Default::default(),
input_touchpad: Default::default(),
input_devices: Default::default(),
xkb_config: Default::default(),
autotile: Default::default(),
autotile_behavior: Default::default(),
active_hint: true,
}
}
}
#[derive(Debug, Default, Copy, Clone, PartialEq, Deserialize, Serialize)]
pub enum TileBehavior {
#[default]
Global,
PerWorkspace,
} }
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]

View file

@ -578,7 +578,11 @@ where
Vec::new() Vec::new()
}; };
let active_hint = theme.active_hint as u8; let active_hint = if state.config.cosmic_conf.active_hint {
theme.active_hint as u8
} else {
0
};
// overlay redirect windows // overlay redirect windows
// they need to be over sticky windows, because they could be popups of sticky windows, // they need to be over sticky windows, because they could be popups of sticky windows,
@ -664,7 +668,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.workspace.workspace_layout; let layout = state.config.cosmic_conf.workspaces.workspace_layout;
let workspace = state let workspace = state
.shell .shell

View file

@ -5,7 +5,7 @@ use crate::{
state::{BackendData, State}, state::{BackendData, State},
wayland::protocols::output_configuration::OutputConfigurationState, wayland::protocols::output_configuration::OutputConfigurationState,
}; };
use cosmic_config::ConfigGet; use cosmic_config::{ConfigGet, CosmicConfigEntry};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use smithay::input::Seat; use smithay::input::Seat;
pub use smithay::{ pub use smithay::{
@ -32,25 +32,20 @@ pub use self::types::*;
use cosmic_comp_config::{ use cosmic_comp_config::{
input::InputConfig, input::InputConfig,
workspace::{WorkspaceConfig, WorkspaceLayout}, workspace::{WorkspaceConfig, WorkspaceLayout},
XkbConfig, CosmicCompConfig, TileBehavior, XkbConfig,
}; };
#[derive(Debug)] #[derive(Debug)]
pub struct Config { pub struct Config {
pub static_conf: StaticConfig, pub static_conf: StaticConfig,
pub dynamic_conf: DynamicConfig, pub dynamic_conf: DynamicConfig,
pub config: cosmic_config::Config, pub cosmic_helper: cosmic_config::Config,
pub xkb: XkbConfig, pub cosmic_conf: CosmicCompConfig,
pub input_default: InputConfig,
pub input_touchpad: 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 tiling_enabled: bool,
pub data_control_enabled: bool, pub data_control_enabled: bool,
} }
@ -172,15 +167,18 @@ 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"); let workspace = get_config::<WorkspaceConfig>(&config, "workspaces");
let cosmic_comp_config =
CosmicCompConfig::get_entry(&config).unwrap_or_else(|(errs, c)| {
for err in errs {
error!(?err, "");
}
c
});
Config { Config {
static_conf: Self::load_static(xdg.as_ref(), workspace.workspace_layout), 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"), cosmic_conf: cosmic_comp_config,
input_default: get_config(&config, "input_default"), cosmic_helper: config,
input_touchpad: get_config(&config, "input_touchpad"),
input_devices: get_config(&config, "input_devices"),
workspace,
config,
} }
} }
@ -221,7 +219,6 @@ impl Config {
StaticConfig { StaticConfig {
key_bindings: HashMap::new(), key_bindings: HashMap::new(),
tiling_enabled: false,
data_control_enabled: false, data_control_enabled: false,
} }
} }
@ -410,7 +407,7 @@ impl Config {
} }
pub fn xkb_config(&self) -> XkbConfig { pub fn xkb_config(&self) -> XkbConfig {
self.xkb.clone() self.cosmic_conf.xkb_config.clone()
} }
pub fn read_device(&self, device: &mut InputDevice) { pub fn read_device(&self, device: &mut InputDevice) {
@ -438,11 +435,11 @@ impl Config {
fn get_device_config(&self, device: &InputDevice) -> (Option<&InputConfig>, &InputConfig) { fn get_device_config(&self, device: &InputDevice) -> (Option<&InputConfig>, &InputConfig) {
let default_config = if device.config_tap_finger_count() > 0 { let default_config = if device.config_tap_finger_count() > 0 {
&self.input_touchpad &self.cosmic_conf.input_touchpad
} else { } else {
&self.input_default &self.cosmic_conf.input_default
}; };
let device_config = self.input_devices.get(device.name()); let device_config = self.cosmic_conf.input_devices.get(device.name());
(device_config, default_config) (device_config, default_config)
} }
} }
@ -525,28 +522,61 @@ fn config_changed(config: cosmic_config::Config, keys: Vec<String>, state: &mut
} }
} }
} }
state.common.config.xkb = value; state.common.config.cosmic_conf.xkb_config = value;
} }
"input_default" => { "input_default" => {
let value = get_config::<InputConfig>(&config, "input_default"); let value = get_config::<InputConfig>(&config, "input_default");
state.common.config.input_default = value; state.common.config.cosmic_conf.input_default = value;
update_input(state); update_input(state);
} }
"input_touchpad" => { "input_touchpad" => {
let value = get_config::<InputConfig>(&config, "input_touchpad"); let value = get_config::<InputConfig>(&config, "input_touchpad");
state.common.config.input_touchpad = value; state.common.config.cosmic_conf.input_touchpad = value;
update_input(state); update_input(state);
} }
"input_devices" => { "input_devices" => {
let value = get_config::<HashMap<String, InputConfig>>(&config, "input_devices"); let value = get_config::<HashMap<String, InputConfig>>(&config, "input_devices");
state.common.config.input_devices = value; state.common.config.cosmic_conf.input_devices = value;
update_input(state); update_input(state);
} }
"workspaces" => { "workspaces" => {
state.common.config.workspace = state.common.config.cosmic_conf.workspaces =
get_config::<WorkspaceConfig>(&config, "workspaces"); get_config::<WorkspaceConfig>(&config, "workspaces");
state.common.shell.update_config(&state.common.config); state.common.shell.update_config(&state.common.config);
} }
"autotile" => {
let new = get_config::<bool>(&config, "autotile");
if new != state.common.config.cosmic_conf.autotile {
state.common.config.cosmic_conf.autotile = new;
let seats: Vec<_> = state.common.seats().cloned().collect();
let mut guard = state.common.shell.workspace_state.update();
state
.common
.shell
.workspaces
.update_autotile(new, &mut guard, seats);
}
}
"autotile_behavior" => {
let new = get_config::<TileBehavior>(&config, "autotile_behavior");
if new != state.common.config.cosmic_conf.autotile_behavior {
state.common.config.cosmic_conf.autotile_behavior = new;
let seats: Vec<_> = state.common.seats().cloned().collect();
let mut guard = state.common.shell.workspace_state.update();
state
.common
.shell
.workspaces
.update_autotile_behavior(new, &mut guard, seats);
}
}
"active_hint" => {
let new = get_config::<bool>(&config, "active_hint");
if new != state.common.config.cosmic_conf.active_hint {
state.common.config.cosmic_conf.active_hint = new;
state.common.shell.update_config(&state.common.config);
}
}
_ => {} _ => {}
} }
} }

View file

@ -20,7 +20,8 @@ use crate::{
}, },
}; };
use calloop::{timer::Timer, RegistrationToken}; use calloop::{timer::Timer, RegistrationToken};
use cosmic_comp_config::workspace::WorkspaceLayout; use cosmic_comp_config::{workspace::WorkspaceLayout, TileBehavior};
use cosmic_config::ConfigSet;
use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::InputType; use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::InputType;
use smithay::{ use smithay::{
backend::input::{ backend::input::{
@ -61,6 +62,7 @@ use std::{
any::Any, any::Any,
cell::RefCell, cell::RefCell,
collections::HashMap, collections::HashMap,
thread,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
@ -1651,7 +1653,10 @@ impl State {
_ => {} _ => {}
} }
} else if propagate { } else if propagate {
match (direction, self.common.config.workspace.workspace_layout) { match (
direction,
self.common.config.cosmic_conf.workspaces.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::PreviousWorkspace, Action::PreviousWorkspace,
@ -1786,7 +1791,10 @@ impl State {
} }
} }
} else if propagate { } else if propagate {
match (direction, self.common.config.workspace.workspace_layout) { match (
direction,
self.common.config.cosmic_conf.workspaces.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,
@ -2048,10 +2056,31 @@ impl State {
} }
} }
Action::ToggleTiling => { Action::ToggleTiling => {
let output = seat.active_output(); if matches!(
let workspace = self.common.shell.workspaces.active_mut(&output); self.common.config.cosmic_conf.autotile_behavior,
let mut guard = self.common.shell.workspace_state.update(); TileBehavior::Global
workspace.toggle_tiling(seat, &mut guard); ) {
let autotile = !self.common.config.cosmic_conf.autotile;
self.common.config.cosmic_conf.autotile = autotile;
let seats: Vec<_> = self.common.seats().cloned().collect();
let mut guard = self.common.shell.workspace_state.update();
self.common.shell.workspaces.update_autotile(
self.common.config.cosmic_conf.autotile,
&mut guard,
seats,
);
let config = self.common.config.cosmic_helper.clone();
thread::spawn(move || {
if let Err(err) = config.set("autotile", autotile) {
error!(?err, "Failed to update autotile key");
}
});
} else {
let output = seat.active_output();
let workspace = self.common.shell.workspaces.active_mut(&output);
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

@ -7,7 +7,7 @@ use std::{
}; };
use wayland_backend::server::ClientId; use wayland_backend::server::ClientId;
use cosmic_comp_config::workspace::WorkspaceMode; use cosmic_comp_config::{workspace::WorkspaceMode, TileBehavior};
use cosmic_protocols::workspace::v1::server::zcosmic_workspace_handle_v1::{ use cosmic_protocols::workspace::v1::server::zcosmic_workspace_handle_v1::{
State as WState, TilingState, State as WState, TilingState,
}; };
@ -27,7 +27,10 @@ use smithay::{
ext::session_lock::v1::server::ext_session_lock_v1::ExtSessionLockV1, ext::session_lock::v1::server::ext_session_lock_v1::ExtSessionLockV1,
xdg::shell::server::xdg_toplevel::WmCapabilities, xdg::shell::server::xdg_toplevel::WmCapabilities,
}, },
wayland_server::{protocol::wl_surface::WlSurface, Client, DisplayHandle}, wayland_server::{
protocol::{wl_seat::WlSeat, wl_surface::WlSurface},
Client, DisplayHandle,
},
}, },
utils::{Logical, Point, Rectangle, Serial, Size, SERIAL_COUNTER}, utils::{Logical, Point, Rectangle, Serial, Size, SERIAL_COUNTER},
wayland::{ wayland::{
@ -477,7 +480,8 @@ pub struct Workspaces {
pub sets: IndexMap<Output, WorkspaceSet>, pub sets: IndexMap<Output, WorkspaceSet>,
backup_set: Option<WorkspaceSet>, backup_set: Option<WorkspaceSet>,
mode: WorkspaceMode, mode: WorkspaceMode,
tiling_enabled: bool, autotile: bool,
autotile_behavior: TileBehavior,
theme: cosmic::Theme, theme: cosmic::Theme,
} }
@ -486,8 +490,9 @@ impl Workspaces {
Workspaces { Workspaces {
sets: IndexMap::new(), sets: IndexMap::new(),
backup_set: None, backup_set: None,
mode: config.workspace.workspace_mode, mode: config.cosmic_conf.workspaces.workspace_mode,
tiling_enabled: config.static_conf.tiling_enabled, autotile: config.cosmic_conf.autotile,
autotile_behavior: config.cosmic_conf.autotile_behavior,
theme, theme,
} }
} }
@ -515,7 +520,7 @@ impl Workspaces {
workspace_state, workspace_state,
&output, &output,
self.sets.len(), self.sets.len(),
self.tiling_enabled, self.autotile,
self.theme.clone(), self.theme.clone(),
) )
}); });
@ -659,7 +664,7 @@ impl Workspaces {
xdg_activation_state: &XdgActivationState, xdg_activation_state: &XdgActivationState,
) { ) {
let old_mode = self.mode; let old_mode = self.mode;
self.mode = config.workspace.workspace_mode; self.mode = config.cosmic_conf.workspaces.workspace_mode;
if self.sets.len() <= 1 { if self.sets.len() <= 1 {
return; return;
@ -704,7 +709,7 @@ impl Workspaces {
output, output,
&set.group, &set.group,
false, false,
config.static_conf.tiling_enabled, config.cosmic_conf.autotile,
self.theme.clone(), self.theme.clone(),
), ),
); );
@ -917,6 +922,48 @@ impl Workspaces {
} }
} }
} }
pub fn update_autotile_behavior(
&mut self,
behavior: TileBehavior,
guard: &mut WorkspaceUpdateGuard<'_, State>,
seats: Vec<Seat<State>>,
) {
self.autotile_behavior = behavior;
self.apply_tile_change(guard, seats);
}
fn apply_tile_change(
&mut self,
guard: &mut WorkspaceUpdateGuard<'_, State>,
seats: Vec<Seat<State>>,
) {
if matches!(self.autotile_behavior, TileBehavior::Global) {
// must apply change to all workspaces now
for (_, set) in &mut self.sets {
set.tiling_enabled = self.autotile;
for w in &mut set.workspaces {
if w.tiling_enabled == self.autotile {
continue;
}
for s in &seats {
w.toggle_tiling(s, guard);
}
}
}
}
}
pub fn update_autotile(
&mut self,
autotile: bool,
guard: &mut WorkspaceUpdateGuard<'_, State>,
seats: Vec<Seat<State>>,
) {
self.autotile = autotile;
self.apply_tile_change(guard, seats);
}
} }
#[derive(Debug)] #[derive(Debug)]
@ -2139,7 +2186,11 @@ impl Shell {
}; };
let button = start_data.button; let button = start_data.button;
let active_hint = state.common.theme.cosmic().active_hint as u8; let active_hint = if state.common.config.cosmic_conf.active_hint {
state.common.theme.cosmic().active_hint as u8
} else {
0
};
let pointer = seat.get_pointer().unwrap(); let pointer = seat.get_pointer().unwrap();
let pos = pointer.current_location().as_global(); let pos = pointer.current_location().as_global();