refactor(output config): move to config crate
this allows the greeter to easily sync to the user config
This commit is contained in:
parent
4a385d5535
commit
416b66b776
17 changed files with 283 additions and 194 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
|
@ -828,6 +828,7 @@ dependencies = [
|
|||
"cosmic-text",
|
||||
"egui",
|
||||
"egui_plot",
|
||||
"futures",
|
||||
"i18n-embed",
|
||||
"i18n-embed-fl",
|
||||
"iced_tiny_skia",
|
||||
|
|
@ -880,7 +881,9 @@ dependencies = [
|
|||
"cosmic-config",
|
||||
"input",
|
||||
"libdisplay-info",
|
||||
"ron 0.9.0",
|
||||
"serde",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ reis = { version = "0.5", features = ["calloop"] }
|
|||
clap_lex = "0.7"
|
||||
parking_lot = "0.12.4"
|
||||
logind-zbus = { version = "5.3.2", optional = true }
|
||||
futures = "0.3.31"
|
||||
|
||||
[dependencies.id_tree]
|
||||
branch = "feature/copy_clone"
|
||||
|
|
|
|||
|
|
@ -8,3 +8,12 @@ cosmic-config = { git = "https://github.com/pop-os/libcosmic/" }
|
|||
input = "0.9.0"
|
||||
libdisplay-info = { version = "0.2.0", optional = true }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
ron = { version = "0.9.0-alpha.0", optional = true }
|
||||
tracing = { version = "0.1.37", features = [
|
||||
"max_level_debug",
|
||||
"release_max_level_info",
|
||||
], optional = true }
|
||||
|
||||
[features]
|
||||
default = ["output"]
|
||||
output = ["ron", "tracing"]
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use std::collections::HashMap;
|
|||
use crate::input::TouchpadOverride;
|
||||
|
||||
pub mod input;
|
||||
#[cfg(feature = "output")]
|
||||
pub mod output;
|
||||
pub mod workspace;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::HashMap, fs::OpenOptions, path::Path};
|
||||
use tracing::{error, warn};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct EdidProduct {
|
||||
|
|
@ -25,3 +27,133 @@ impl From<libdisplay_info::edid::VendorProduct> for EdidProduct {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum OutputState {
|
||||
#[serde(rename = "true")]
|
||||
Enabled,
|
||||
#[serde(rename = "false")]
|
||||
Disabled,
|
||||
Mirroring(String),
|
||||
}
|
||||
|
||||
fn default_state() -> OutputState {
|
||||
OutputState::Enabled
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum AdaptiveSync {
|
||||
#[serde(rename = "true")]
|
||||
Enabled,
|
||||
#[serde(rename = "false")]
|
||||
Disabled,
|
||||
Force,
|
||||
}
|
||||
|
||||
fn default_sync() -> AdaptiveSync {
|
||||
AdaptiveSync::Enabled
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct OutputsConfig {
|
||||
pub config: HashMap<Vec<OutputInfo>, Vec<OutputConfig>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
|
||||
pub struct OutputConfig {
|
||||
pub mode: ((i32, i32), Option<u32>),
|
||||
#[serde(default = "default_sync")]
|
||||
pub vrr: AdaptiveSync,
|
||||
pub scale: f64,
|
||||
pub transform: TransformDef,
|
||||
pub position: (u32, u32),
|
||||
#[serde(default = "default_state")]
|
||||
pub enabled: OutputState,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub max_bpc: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub xwayland_primary: bool,
|
||||
}
|
||||
|
||||
impl Default for OutputConfig {
|
||||
fn default() -> OutputConfig {
|
||||
OutputConfig {
|
||||
mode: ((0, 0), None),
|
||||
vrr: AdaptiveSync::Enabled,
|
||||
scale: 1.0,
|
||||
transform: TransformDef::Normal,
|
||||
position: (0, 0),
|
||||
enabled: OutputState::Enabled,
|
||||
max_bpc: None,
|
||||
xwayland_primary: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct OutputInfo {
|
||||
pub connector: String,
|
||||
pub make: String,
|
||||
pub model: String,
|
||||
}
|
||||
|
||||
pub fn load_outputs(path: Option<impl AsRef<Path>>) -> OutputsConfig {
|
||||
if let Some(path) = path.as_ref() {
|
||||
let path: &Path = path.as_ref();
|
||||
if path.exists() {
|
||||
match ron::de::from_reader::<_, OutputsConfig>(
|
||||
OpenOptions::new().read(true).open(path).unwrap(),
|
||||
) {
|
||||
Ok(mut config) => {
|
||||
for (info, config) in config.config.iter_mut() {
|
||||
let config_clone = config.clone();
|
||||
for conf in config.iter_mut() {
|
||||
if let OutputState::Mirroring(conn) = &conf.enabled {
|
||||
if let Some((j, _)) = info
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, info)| &info.connector == conn)
|
||||
{
|
||||
if config_clone[j].enabled != OutputState::Enabled {
|
||||
warn!("Invalid Mirroring tag, overriding with `Enabled` instead");
|
||||
conf.enabled = OutputState::Enabled;
|
||||
}
|
||||
} else {
|
||||
warn!(
|
||||
"Invalid Mirroring tag, overriding with `Enabled` instead"
|
||||
);
|
||||
conf.enabled = OutputState::Enabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return config;
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(?err, "Failed to read output_config, resetting..");
|
||||
if let Err(err) = std::fs::remove_file(path) {
|
||||
error!(?err, "Failed to remove output_config.");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
OutputsConfig {
|
||||
config: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum TransformDef {
|
||||
Normal,
|
||||
_90,
|
||||
_180,
|
||||
_270,
|
||||
Flipped,
|
||||
Flipped90,
|
||||
Flipped180,
|
||||
Flipped270,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@ use crate::{
|
|||
kms::render::gles::GbmGlowBackend,
|
||||
render::{init_shaders, output_elements, CursorMode, GlMultiRenderer, CLEAR_COLOR},
|
||||
},
|
||||
config::{AdaptiveSync, EdidProduct, OutputConfig, OutputState, ScreenFilter},
|
||||
config::{CompTransformDef, EdidProduct, ScreenFilter},
|
||||
shell::Shell,
|
||||
utils::{env::dev_list_var, prelude::*},
|
||||
wayland::handlers::screencopy::PendingImageCopyData,
|
||||
};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use cosmic_comp_config::output::{AdaptiveSync, OutputConfig, OutputState};
|
||||
use libc::dev_t;
|
||||
use smithay::{
|
||||
backend::{
|
||||
|
|
@ -1008,7 +1009,7 @@ fn populate_modes(
|
|||
position,
|
||||
max_bpc,
|
||||
scale,
|
||||
transform,
|
||||
transform: CompTransformDef::from(transform).0,
|
||||
// Try opportunistic VRR by default,
|
||||
// if not supported this will be turned off on `resume`,
|
||||
// when we have the `Surface` to actually check for support.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::{
|
||||
config::{AdaptiveSync, OutputState, ScreenFilter},
|
||||
config::{CompOutputConfig, ScreenFilter},
|
||||
shell::Shell,
|
||||
state::BackendData,
|
||||
utils::{env::dev_var, prelude::*},
|
||||
|
|
@ -9,6 +9,7 @@ use crate::{
|
|||
|
||||
use anyhow::{Context, Result};
|
||||
use calloop::LoopSignal;
|
||||
use cosmic_comp_config::output::{AdaptiveSync, OutputState};
|
||||
use indexmap::IndexMap;
|
||||
use render::gles::GbmGlowBackend;
|
||||
use smithay::{
|
||||
|
|
@ -798,7 +799,7 @@ impl<'a> KmsGuard<'a> {
|
|||
|
||||
// reconfigure existing
|
||||
for (crtc, surface) in device.inner.surfaces.iter_mut() {
|
||||
let output_config = surface.output.config();
|
||||
let output_config = CompOutputConfig(surface.output.config());
|
||||
|
||||
let drm = &mut device.drm;
|
||||
let conn = surface.connector;
|
||||
|
|
@ -814,7 +815,7 @@ impl<'a> KmsGuard<'a> {
|
|||
// and then select the closest refresh rate (e.g. to match 59.98 as 60)
|
||||
.min_by_key(|mode| {
|
||||
let refresh_rate = drm_helpers::calculate_refresh_rate(**mode);
|
||||
(output_config.mode.1.unwrap() as i32 - refresh_rate as i32).abs()
|
||||
(output_config.0.mode.1.unwrap() as i32 - refresh_rate as i32).abs()
|
||||
})
|
||||
.ok_or(anyhow::anyhow!("Unable to find matching mode"))?;
|
||||
|
||||
|
|
@ -876,7 +877,7 @@ impl<'a> KmsGuard<'a> {
|
|||
compositor
|
||||
};
|
||||
|
||||
if let Some(bpc) = output_config.max_bpc {
|
||||
if let Some(bpc) = output_config.0.max_bpc {
|
||||
if let Err(err) = drm_helpers::set_max_bpc(drm.device(), conn, bpc) {
|
||||
warn!(
|
||||
?bpc,
|
||||
|
|
@ -887,7 +888,7 @@ impl<'a> KmsGuard<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
let vrr = output_config.vrr;
|
||||
let vrr = output_config.0.vrr;
|
||||
std::mem::drop(output_config);
|
||||
|
||||
let compositor_ref = drm.compositors().get(crtc).unwrap().lock().unwrap();
|
||||
|
|
@ -928,7 +929,7 @@ impl<'a> KmsGuard<'a> {
|
|||
surface.output.set_adaptive_sync(AdaptiveSync::Disabled);
|
||||
}
|
||||
} else {
|
||||
let vrr = output_config.vrr;
|
||||
let vrr = output_config.0.vrr;
|
||||
std::mem::drop(output_config);
|
||||
if vrr != surface.output.adaptive_sync() {
|
||||
if match surface.output.adaptive_sync_support() {
|
||||
|
|
@ -1030,7 +1031,7 @@ impl<'a> KmsGuard<'a> {
|
|||
Some(
|
||||
all_outputs
|
||||
.iter()
|
||||
.find(|output| &output.name() == conn)
|
||||
.find(|output| output.name() == *conn)
|
||||
.cloned()
|
||||
.ok_or(anyhow::anyhow!("Unable to find mirroring output"))?,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use crate::{
|
|||
init_shaders, output_elements, CursorMode, GlMultiError, GlMultiRenderer,
|
||||
PostprocessOutputConfig, PostprocessShader, PostprocessState, CLEAR_COLOR,
|
||||
},
|
||||
config::{AdaptiveSync, ScreenFilter},
|
||||
config::ScreenFilter,
|
||||
shell::Shell,
|
||||
state::SurfaceDmabufFeedback,
|
||||
utils::prelude::*,
|
||||
|
|
@ -23,6 +23,7 @@ use crate::{
|
|||
|
||||
use anyhow::{Context, Result};
|
||||
use calloop::channel::Channel;
|
||||
use cosmic_comp_config::output::AdaptiveSync;
|
||||
use smithay::{
|
||||
backend::{
|
||||
allocator::{
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@
|
|||
|
||||
use crate::{
|
||||
backend::render,
|
||||
config::{OutputConfig, ScreenFilter},
|
||||
config::ScreenFilter,
|
||||
shell::{Devices, SeatExt},
|
||||
state::{BackendData, Common},
|
||||
utils::prelude::*,
|
||||
};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use cosmic_comp_config::output::{OutputConfig, TransformDef};
|
||||
use smithay::{
|
||||
backend::{
|
||||
drm::NodeType,
|
||||
|
|
@ -167,7 +168,7 @@ pub fn init_backend(
|
|||
output.user_data().insert_if_missing(|| {
|
||||
RefCell::new(OutputConfig {
|
||||
mode: ((size.w, size.h), None),
|
||||
transform: Transform::Flipped180.into(),
|
||||
transform: TransformDef::Flipped180,
|
||||
..Default::default()
|
||||
})
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@
|
|||
|
||||
use crate::{
|
||||
backend::render,
|
||||
config::{OutputConfig, ScreenFilter},
|
||||
config::ScreenFilter,
|
||||
shell::{Devices, SeatExt},
|
||||
state::{BackendData, Common},
|
||||
utils::prelude::*,
|
||||
};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use cosmic_comp_config::output::OutputConfig;
|
||||
use smithay::{
|
||||
backend::{
|
||||
allocator::{
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ pub use smithay::{
|
|||
utils::{Logical, Physical, Point, Size, Transform, SERIAL_COUNTER},
|
||||
};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
cell::{Ref, RefCell},
|
||||
collections::{BTreeMap, HashMap},
|
||||
fs::OpenOptions,
|
||||
io::Write,
|
||||
|
|
@ -39,17 +39,19 @@ use tracing::{error, warn};
|
|||
|
||||
mod input_config;
|
||||
pub mod key_bindings;
|
||||
pub use key_bindings::{Action, PrivateAction};
|
||||
mod types;
|
||||
pub use self::types::*;
|
||||
|
||||
use cosmic::config::CosmicTk;
|
||||
pub use cosmic_comp_config::output::EdidProduct;
|
||||
use cosmic_comp_config::{
|
||||
input::{DeviceState as InputDeviceState, InputConfig, TouchpadOverride},
|
||||
output::{load_outputs, OutputConfig, OutputInfo, OutputState, OutputsConfig, TransformDef},
|
||||
workspace::WorkspaceConfig,
|
||||
CosmicCompConfig, KeyboardConfig, TileBehavior, XkbConfig, XwaylandDescaling,
|
||||
XwaylandEavesdropping, ZoomConfig,
|
||||
};
|
||||
pub use key_bindings::{Action, PrivateAction};
|
||||
use types::WlXkbConfig;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Config {
|
||||
|
|
@ -74,105 +76,24 @@ pub struct DynamicConfig {
|
|||
accessibility_filter: (Option<PathBuf>, ScreenFilter),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct OutputsConfig {
|
||||
pub config: HashMap<Vec<OutputInfo>, Vec<OutputConfig>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct OutputInfo {
|
||||
pub connector: String,
|
||||
pub make: String,
|
||||
pub model: String,
|
||||
}
|
||||
|
||||
impl From<Output> for OutputInfo {
|
||||
fn from(o: Output) -> OutputInfo {
|
||||
let physical = o.physical_properties();
|
||||
OutputInfo {
|
||||
connector: o.name(),
|
||||
make: physical.make,
|
||||
model: physical.model,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Deserialize, Serialize)]
|
||||
pub struct NumlockStateConfig {
|
||||
pub last_state: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum OutputState {
|
||||
#[serde(rename = "true")]
|
||||
Enabled,
|
||||
#[serde(rename = "false")]
|
||||
Disabled,
|
||||
Mirroring(String),
|
||||
}
|
||||
pub struct CompOutputConfig<'a>(pub Ref<'a, OutputConfig>);
|
||||
|
||||
fn default_state() -> OutputState {
|
||||
OutputState::Enabled
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum AdaptiveSync {
|
||||
#[serde(rename = "true")]
|
||||
Enabled,
|
||||
#[serde(rename = "false")]
|
||||
Disabled,
|
||||
Force,
|
||||
}
|
||||
|
||||
fn default_sync() -> AdaptiveSync {
|
||||
AdaptiveSync::Enabled
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
|
||||
pub struct OutputConfig {
|
||||
pub mode: ((i32, i32), Option<u32>),
|
||||
#[serde(default = "default_sync")]
|
||||
pub vrr: AdaptiveSync,
|
||||
pub scale: f64,
|
||||
#[serde(with = "TransformDef")]
|
||||
pub transform: Transform,
|
||||
pub position: (u32, u32),
|
||||
#[serde(default = "default_state")]
|
||||
pub enabled: OutputState,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub max_bpc: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub xwayland_primary: bool,
|
||||
}
|
||||
|
||||
impl Default for OutputConfig {
|
||||
fn default() -> OutputConfig {
|
||||
OutputConfig {
|
||||
mode: ((0, 0), None),
|
||||
vrr: AdaptiveSync::Enabled,
|
||||
scale: 1.0,
|
||||
transform: Transform::Normal,
|
||||
position: (0, 0),
|
||||
enabled: OutputState::Enabled,
|
||||
max_bpc: None,
|
||||
xwayland_primary: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OutputConfig {
|
||||
impl<'a> CompOutputConfig<'a> {
|
||||
pub fn mode_size(&self) -> Size<i32, Physical> {
|
||||
self.mode.0.into()
|
||||
self.0.mode.0.into()
|
||||
}
|
||||
|
||||
pub fn mode_refresh(&self) -> u32 {
|
||||
self.mode.1.unwrap_or(60_000)
|
||||
self.0.mode.1.unwrap_or(60_000)
|
||||
}
|
||||
|
||||
pub fn transformed_size(&self) -> Size<i32, Physical> {
|
||||
self.transform.transform_size(self.mode_size())
|
||||
self.transform().transform_size(self.mode_size())
|
||||
}
|
||||
|
||||
pub fn output_mode(&self) -> Mode {
|
||||
|
|
@ -181,6 +102,57 @@ impl OutputConfig {
|
|||
refresh: self.mode_refresh() as i32,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transform(&self) -> Transform {
|
||||
Transform::from(CompTransformDef(self.0.transform))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CompTransformDef(pub TransformDef);
|
||||
|
||||
impl From<Transform> for CompTransformDef {
|
||||
fn from(transform: Transform) -> Self {
|
||||
let def = match transform {
|
||||
Transform::Normal => TransformDef::Normal,
|
||||
Transform::_90 => TransformDef::_90,
|
||||
Transform::_180 => TransformDef::_180,
|
||||
Transform::_270 => TransformDef::_270,
|
||||
Transform::Flipped => TransformDef::Flipped,
|
||||
Transform::Flipped90 => TransformDef::Flipped90,
|
||||
Transform::Flipped180 => TransformDef::Flipped180,
|
||||
Transform::Flipped270 => TransformDef::Flipped270,
|
||||
};
|
||||
CompTransformDef(def)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CompTransformDef> for Transform {
|
||||
fn from(comp_transform: CompTransformDef) -> Self {
|
||||
match comp_transform.0 {
|
||||
TransformDef::Normal => Transform::Normal,
|
||||
TransformDef::_90 => Transform::_90,
|
||||
TransformDef::_180 => Transform::_180,
|
||||
TransformDef::_270 => Transform::_270,
|
||||
TransformDef::Flipped => Transform::Flipped,
|
||||
TransformDef::Flipped90 => Transform::Flipped90,
|
||||
TransformDef::Flipped180 => Transform::Flipped180,
|
||||
TransformDef::Flipped270 => Transform::Flipped270,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "libdisplay-info")]
|
||||
impl From<libdisplay_info::edid::VendorProduct> for EdidProduct {
|
||||
fn from(vp: libdisplay_info::edid::VendorProduct) -> Self {
|
||||
Self {
|
||||
manufacturer: vp.manufacturer,
|
||||
product: vp.product,
|
||||
serial: vp.serial,
|
||||
manufacture_week: vp.manufacture_week,
|
||||
manufacture_year: vp.manufacture_year,
|
||||
model_year: vp.model_year,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq)]
|
||||
|
|
@ -355,7 +327,7 @@ impl Config {
|
|||
|
||||
fn load_dynamic(xdg: &xdg::BaseDirectories) -> DynamicConfig {
|
||||
let output_path = xdg.place_state_file("cosmic-comp/outputs.ron").ok();
|
||||
let outputs = Self::load_outputs(&output_path);
|
||||
let outputs = load_outputs(output_path.as_ref());
|
||||
let numlock_path = xdg.place_state_file("cosmic-comp/numlock.ron").ok();
|
||||
let numlock = Self::load_numlock(&numlock_path);
|
||||
|
||||
|
|
@ -371,54 +343,6 @@ impl Config {
|
|||
}
|
||||
}
|
||||
|
||||
fn load_outputs(path: &Option<PathBuf>) -> OutputsConfig {
|
||||
if let Some(path) = path.as_ref() {
|
||||
if path.exists() {
|
||||
match ron::de::from_reader::<_, OutputsConfig>(
|
||||
OpenOptions::new().read(true).open(path).unwrap(),
|
||||
) {
|
||||
Ok(mut config) => {
|
||||
for (info, config) in config.config.iter_mut() {
|
||||
let config_clone = config.clone();
|
||||
for conf in config.iter_mut() {
|
||||
if let OutputState::Mirroring(conn) = &conf.enabled {
|
||||
if let Some((j, _)) = info
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, info)| &info.connector == conn)
|
||||
{
|
||||
if config_clone[j].enabled != OutputState::Enabled {
|
||||
warn!(
|
||||
"Invalid Mirroring tag, overriding with `Enabled` instead"
|
||||
);
|
||||
conf.enabled = OutputState::Enabled;
|
||||
}
|
||||
} else {
|
||||
warn!(
|
||||
"Invalid Mirroring tag, overriding with `Enabled` instead"
|
||||
);
|
||||
conf.enabled = OutputState::Enabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return config;
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(?err, "Failed to read output_config, resetting..");
|
||||
if let Err(err) = std::fs::remove_file(path) {
|
||||
error!(?err, "Failed to remove output_config.");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
OutputsConfig {
|
||||
config: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn load_numlock(path: &Option<PathBuf>) -> NumlockStateConfig {
|
||||
path.as_deref()
|
||||
.filter(|path| path.exists())
|
||||
|
|
@ -479,7 +403,8 @@ impl Config {
|
|||
let mut infos = outputs
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(Into::<crate::config::OutputInfo>::into)
|
||||
.map(Into::<crate::config::CompOutputInfo>::into)
|
||||
.map(|i| i.0)
|
||||
.collect::<Vec<_>>();
|
||||
infos.sort();
|
||||
|
||||
|
|
@ -657,7 +582,7 @@ impl Config {
|
|||
.map(|o| {
|
||||
let o = o.borrow();
|
||||
(
|
||||
Into::<crate::config::OutputInfo>::into(o.clone()),
|
||||
Into::<CompOutputInfo>::into(o.clone()).0,
|
||||
o.user_data()
|
||||
.get::<RefCell<OutputConfig>>()
|
||||
.unwrap()
|
||||
|
|
@ -801,6 +726,16 @@ impl DynamicConfig {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn xkb_config_to_wl(config: &XkbConfig) -> WlXkbConfig<'_> {
|
||||
WlXkbConfig {
|
||||
rules: &config.rules,
|
||||
model: &config.model,
|
||||
layout: &config.layout,
|
||||
variant: &config.variant,
|
||||
options: config.options.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_config<T: Default + serde::de::DeserializeOwned>(
|
||||
config: &cosmic_config::Config,
|
||||
key: &str,
|
||||
|
|
@ -1002,12 +937,16 @@ fn config_changed(config: cosmic_config::Config, keys: Vec<String>, state: &mut
|
|||
}
|
||||
}
|
||||
|
||||
pub fn xkb_config_to_wl(config: &XkbConfig) -> WlXkbConfig<'_> {
|
||||
WlXkbConfig {
|
||||
rules: &config.rules,
|
||||
model: &config.model,
|
||||
layout: &config.layout,
|
||||
variant: &config.variant,
|
||||
options: config.options.clone(),
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct CompOutputInfo(OutputInfo);
|
||||
|
||||
impl From<Output> for CompOutputInfo {
|
||||
fn from(o: Output) -> CompOutputInfo {
|
||||
let physical = o.physical_properties();
|
||||
CompOutputInfo(OutputInfo {
|
||||
connector: o.name(),
|
||||
make: physical.make,
|
||||
model: physical.model,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
pub use smithay::{input::keyboard::XkbConfig as WlXkbConfig, utils::Transform};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "Transform")]
|
||||
pub enum TransformDef {
|
||||
Normal,
|
||||
_90,
|
||||
_180,
|
||||
_270,
|
||||
Flipped,
|
||||
Flipped90,
|
||||
Flipped180,
|
||||
Flipped270,
|
||||
}
|
||||
pub use smithay::input::keyboard::XkbConfig as WlXkbConfig;
|
||||
|
|
|
|||
25
src/state.rs
25
src/state.rs
|
|
@ -7,7 +7,7 @@ use crate::{
|
|||
winit::WinitState,
|
||||
x11::X11State,
|
||||
},
|
||||
config::{Config, OutputConfig, OutputState, ScreenFilter},
|
||||
config::{CompOutputConfig, Config, ScreenFilter},
|
||||
input::{gestures::GestureState, PointerFocusState},
|
||||
shell::{grabs::SeatMoveGrabState, CosmicSurface, SeatExt, Shell},
|
||||
utils::prelude::OutputExt,
|
||||
|
|
@ -31,6 +31,7 @@ use crate::{
|
|||
};
|
||||
use anyhow::Context;
|
||||
use calloop::RegistrationToken;
|
||||
use cosmic_comp_config::output::{OutputConfig, OutputState};
|
||||
use i18n_embed::{
|
||||
fluent::{fluent_language_loader, FluentLanguageLoader},
|
||||
DesktopLanguageRequester,
|
||||
|
|
@ -455,28 +456,30 @@ impl<'a> LockedBackend<'a> {
|
|||
// update outputs, so that `OutputModeSource`s are correct
|
||||
for output in &all_outputs {
|
||||
// apply to Output
|
||||
let final_config = output
|
||||
.user_data()
|
||||
.get::<RefCell<OutputConfig>>()
|
||||
.unwrap()
|
||||
.borrow();
|
||||
let final_config = CompOutputConfig(
|
||||
output
|
||||
.user_data()
|
||||
.get::<RefCell<OutputConfig>>()
|
||||
.unwrap()
|
||||
.borrow(),
|
||||
);
|
||||
|
||||
let mode = Some(final_config.output_mode()).filter(|m| match output.current_mode() {
|
||||
None => true,
|
||||
Some(c_m) => m.size != c_m.size || m.refresh != c_m.refresh,
|
||||
});
|
||||
let transform =
|
||||
Some(final_config.transform.into()).filter(|x| *x != output.current_transform());
|
||||
let scale = Some(final_config.scale)
|
||||
Some(final_config.transform()).filter(|x| *x != output.current_transform());
|
||||
let scale = Some(final_config.0.scale)
|
||||
.filter(|x| *x != output.current_scale().fractional_scale());
|
||||
let location = Some(Point::from((
|
||||
final_config.position.0 as i32,
|
||||
final_config.position.1 as i32,
|
||||
final_config.0.position.0 as i32,
|
||||
final_config.0.position.1 as i32,
|
||||
)))
|
||||
.filter(|x| *x != output.current_location());
|
||||
output.change_current_state(mode, transform, scale.map(Scale::Fractional), location);
|
||||
|
||||
output.set_adaptive_sync(final_config.vrr);
|
||||
output.set_adaptive_sync(final_config.0.vrr);
|
||||
}
|
||||
|
||||
match self {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use cosmic_comp_config::output::{AdaptiveSync, OutputConfig, OutputState};
|
||||
use smithay::{
|
||||
backend::drm::VrrSupport as Support,
|
||||
output::{Output, WeakOutput},
|
||||
|
|
@ -8,10 +9,7 @@ pub use super::geometry::*;
|
|||
pub use crate::shell::{SeatExt, Shell, Workspace};
|
||||
pub use crate::state::{Common, State};
|
||||
pub use crate::wayland::handlers::xdg_shell::popup::update_reactive_popups;
|
||||
use crate::{
|
||||
config::{AdaptiveSync, EdidProduct, OutputConfig, OutputState},
|
||||
shell::zoom::OutputZoomState,
|
||||
};
|
||||
use crate::{config::EdidProduct, shell::zoom::OutputZoomState};
|
||||
|
||||
use std::{
|
||||
cell::{Ref, RefCell, RefMut},
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use cosmic_comp_config::output::{OutputConfig, OutputState, TransformDef};
|
||||
use smithay::{output::Output, utils::Point};
|
||||
use tracing::{error, warn};
|
||||
|
||||
use crate::{
|
||||
config::{OutputConfig, OutputState},
|
||||
state::State,
|
||||
utils::prelude::OutputExt,
|
||||
wayland::protocols::output_configuration::{
|
||||
|
|
@ -123,7 +123,16 @@ impl State {
|
|||
current_config.scale = *scale;
|
||||
}
|
||||
if let Some(transform) = transform {
|
||||
current_config.transform = *transform;
|
||||
current_config.transform = match transform {
|
||||
smithay::utils::Transform::Normal => TransformDef::Normal,
|
||||
smithay::utils::Transform::_90 => TransformDef::_90,
|
||||
smithay::utils::Transform::_180 => TransformDef::_180,
|
||||
smithay::utils::Transform::_270 => TransformDef::_270,
|
||||
smithay::utils::Transform::Flipped => TransformDef::Flipped,
|
||||
smithay::utils::Transform::Flipped90 => TransformDef::Flipped90,
|
||||
smithay::utils::Transform::Flipped180 => TransformDef::Flipped180,
|
||||
smithay::utils::Transform::Flipped270 => TransformDef::Flipped270,
|
||||
}
|
||||
}
|
||||
if let Some(position) = position {
|
||||
current_config.position = (position.x as u32, position.y as u32);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ use smithay::{
|
|||
},
|
||||
};
|
||||
|
||||
use cosmic_comp_config::output::OutputState as EnabledState;
|
||||
|
||||
use cosmic_protocols::output_management::v1::server::{
|
||||
zcosmic_output_configuration_head_v1::{self, ZcosmicOutputConfigurationHeadV1},
|
||||
zcosmic_output_configuration_v1::{self, ZcosmicOutputConfigurationV1},
|
||||
|
|
@ -21,7 +23,7 @@ use cosmic_protocols::output_management::v1::server::{
|
|||
zcosmic_output_manager_v1::{self, ZcosmicOutputManagerV1},
|
||||
};
|
||||
|
||||
use crate::{config::OutputState as EnabledState, wayland::protocols::output_configuration::*};
|
||||
use crate::wayland::protocols::output_configuration::*;
|
||||
|
||||
impl<D> GlobalDispatch<ZcosmicOutputManagerV1, OutputMngrGlobalData, D>
|
||||
for OutputConfigurationState<D>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use calloop::{
|
|||
timer::{TimeoutAction, Timer},
|
||||
LoopHandle,
|
||||
};
|
||||
use cosmic_comp_config::output::AdaptiveSync;
|
||||
use cosmic_protocols::output_management::v1::server::{
|
||||
zcosmic_output_configuration_head_v1::ZcosmicOutputConfigurationHeadV1,
|
||||
zcosmic_output_configuration_v1::ZcosmicOutputConfigurationV1,
|
||||
|
|
@ -580,4 +581,4 @@ macro_rules! delegate_output_configuration {
|
|||
}
|
||||
pub(crate) use delegate_output_configuration;
|
||||
|
||||
use crate::{config::AdaptiveSync, utils::prelude::OutputExt};
|
||||
use crate::utils::prelude::OutputExt;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue