Skip to content

Commit a217c40

Browse files
authored
Merge pull request #406 from dwall-rs/main
0.1.22
2 parents 9ecd38b + 4772be9 commit a217c40

File tree

139 files changed

+2995
-3264
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

139 files changed

+2995
-3264
lines changed

Cargo.lock

Lines changed: 244 additions & 246 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ members = ["daemon", "src-tauri"]
44

55
[workspace.package]
66
authors = ["thep0y"]
7-
version = "0.1.21"
7+
version = "0.1.22"
88
# homepage = ""
99
repository = "https://github.com/dwall-rs/dwall"
1010
license = "AGPL-3.0"

bun.lockb

10.2 KB
Binary file not shown.

daemon/src/color_mode.rs

Lines changed: 55 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,13 @@
11
use std::fmt;
22

33
use serde::Deserialize;
4-
use windows::{
5-
core::PCWSTR,
6-
Win32::{
7-
Foundation::{ERROR_SUCCESS, LPARAM, WPARAM},
8-
System::Registry::{
9-
RegCloseKey, RegOpenKeyExW, RegQueryValueExW, RegSetValueExW, HKEY, HKEY_CURRENT_USER,
10-
KEY_QUERY_VALUE, KEY_SET_VALUE, REG_DWORD, REG_SAM_FLAGS,
11-
},
12-
UI::WindowsAndMessaging::{SendNotifyMessageW, HWND_BROADCAST, WM_SETTINGCHANGE},
13-
},
4+
use windows::Win32::{
5+
Foundation::{LPARAM, WPARAM},
6+
System::Registry::{KEY_QUERY_VALUE, KEY_SET_VALUE, REG_DWORD},
7+
UI::WindowsAndMessaging::{SendNotifyMessageW, HWND_BROADCAST, WM_SETTINGCHANGE},
148
};
159

16-
use crate::{error::DwallResult, utils::string::WideStringExt};
17-
18-
/// Custom error types for registry operations
19-
#[derive(thiserror::Error, Debug)]
20-
pub enum ColorModeRegistryError {
21-
#[error("Registry operation failed: Open key {0}")]
22-
Open(u32),
23-
24-
#[error("Registry operation failed: Query value {0}")]
25-
Query(u32),
26-
27-
#[error("Registry operation failed: Set value {0}")]
28-
Set(u32),
29-
30-
#[error("Registry operation failed: Close key {0}")]
31-
Close(u32),
32-
}
10+
use crate::{error::DwallResult, registry::RegistryKey, utils::string::WideStringExt};
3311

3412
#[derive(Debug, PartialEq, Deserialize)]
3513
#[serde(rename_all = "UPPERCASE")]
@@ -38,78 +16,23 @@ pub enum ColorMode {
3816
Dark,
3917
}
4018

41-
impl fmt::Display for ColorMode {
42-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19+
impl ColorMode {
20+
fn as_u32(&self) -> u32 {
4321
match self {
44-
ColorMode::Light => write!(f, "Light"),
45-
ColorMode::Dark => write!(f, "Dark"),
46-
}
47-
}
48-
}
49-
50-
/// RAII wrapper for Windows registry key handles
51-
/// Automatically closes the key handle when dropped
52-
struct RegistryKey {
53-
hkey: HKEY,
54-
path: String,
55-
}
56-
57-
impl RegistryKey {
58-
/// Open a registry key with specified access rights
59-
fn open(path: &str, access: REG_SAM_FLAGS) -> DwallResult<Self> {
60-
debug!(path = path, "Attempting to open registry key");
61-
let wide_path = Vec::from_str(path);
62-
let mut hkey = HKEY::default();
63-
64-
unsafe {
65-
let result = RegOpenKeyExW(
66-
HKEY_CURRENT_USER,
67-
PCWSTR(wide_path.as_ptr()),
68-
None,
69-
access,
70-
&mut hkey,
71-
);
72-
73-
match result {
74-
ERROR_SUCCESS => {
75-
info!(path = path, "Successfully opened registry key");
76-
Ok(Self {
77-
hkey,
78-
path: path.to_string(),
79-
})
80-
}
81-
err => {
82-
error!(
83-
path = path,
84-
error_code = err.0,
85-
"Failed to open registry key"
86-
);
87-
Err(ColorModeRegistryError::Open(err.0).into())
88-
}
89-
}
22+
ColorMode::Light => 1,
23+
ColorMode::Dark => 0,
9024
}
9125
}
92-
93-
/// Get the raw HKEY handle
94-
fn as_raw(&self) -> HKEY {
95-
self.hkey
26+
fn to_le_bytes(&self) -> [u8; 4] {
27+
self.as_u32().to_le_bytes()
9628
}
9729
}
9830

99-
impl Drop for RegistryKey {
100-
fn drop(&mut self) {
101-
trace!(path = self.path, "Automatically closing registry key");
102-
unsafe {
103-
let err = RegCloseKey(self.hkey);
104-
if err != ERROR_SUCCESS {
105-
warn!(
106-
path = self.path,
107-
error_code = err.0,
108-
"Failed to close registry key on drop"
109-
);
110-
} else {
111-
debug!(path = self.path, "Successfully closed registry key");
112-
}
31+
impl fmt::Display for ColorMode {
32+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33+
match self {
34+
ColorMode::Light => write!(f, "Light"),
35+
ColorMode::Dark => write!(f, "Dark"),
11336
}
11437
}
11538
}
@@ -132,41 +55,26 @@ impl ColorModeManager {
13255
info!("Retrieving current system color mode");
13356
let registry_key = RegistryKey::open(Self::PERSONALIZE_KEY_PATH, KEY_QUERY_VALUE)?;
13457

135-
let value_name = Vec::from_str(Self::APPS_THEME_VALUE);
136-
let mut value: u32 = 0;
137-
let mut size = std::mem::size_of::<u32>() as u32;
138-
139-
unsafe {
140-
let result = RegQueryValueExW(
141-
registry_key.as_raw(),
142-
PCWSTR(value_name.as_ptr()),
143-
None,
144-
None,
145-
Some(&mut value as *mut u32 as *mut u8),
146-
Some(&mut size),
147-
);
148-
149-
match result {
150-
ERROR_SUCCESS => {
151-
let mode = if value == 1 {
152-
debug!("Current color mode is Light");
153-
ColorMode::Light
154-
} else {
155-
debug!("Current color mode is Dark");
156-
ColorMode::Dark
157-
};
158-
Ok(mode)
159-
}
160-
err => {
161-
error!(
162-
value_name = Self::APPS_THEME_VALUE,
163-
error_code = err.0,
164-
"Failed to query color mode value"
165-
);
166-
Err(ColorModeRegistryError::Query(err.0).into())
167-
}
168-
}
169-
}
58+
let mut data: u32 = 0;
59+
let mut data_size = std::mem::size_of_val(&data) as u32;
60+
let mut data_type = REG_DWORD;
61+
62+
registry_key.query(
63+
Self::APPS_THEME_VALUE,
64+
Some(std::ptr::addr_of_mut!(data_type)),
65+
Some(std::ptr::addr_of_mut!(data) as *mut u8),
66+
Some(&mut data_size),
67+
)?;
68+
debug!(value = data, "Retrieved app theme value from registry");
69+
70+
let mode = if data == 1 {
71+
debug!("Current color mode is Light");
72+
ColorMode::Light
73+
} else {
74+
debug!("Current color mode is Dark");
75+
ColorMode::Dark
76+
};
77+
Ok(mode)
17078
}
17179

17280
/// Set the system color mode in the registry
@@ -181,51 +89,25 @@ impl ColorModeManager {
18189
info!(mode = %mode, "Setting system color mode");
18290
let registry_key = RegistryKey::open(Self::PERSONALIZE_KEY_PATH, KEY_SET_VALUE)?;
18391

184-
let value = match mode {
185-
ColorMode::Light => [1u8, 0, 0, 0],
186-
ColorMode::Dark => [0u8, 0, 0, 0],
187-
};
188-
189-
let apps_value = Vec::from_str(Self::APPS_THEME_VALUE);
190-
let system_value = Vec::from_str(Self::SYSTEM_THEME_VALUE);
191-
192-
unsafe {
193-
let set_apps_result = RegSetValueExW(
194-
registry_key.as_raw(),
195-
PCWSTR(apps_value.as_ptr()),
196-
None,
197-
REG_DWORD,
198-
Some(&value),
199-
);
200-
201-
let set_system_result = RegSetValueExW(
202-
registry_key.as_raw(),
203-
PCWSTR(system_value.as_ptr()),
204-
None,
205-
REG_DWORD,
206-
Some(&value),
207-
);
208-
209-
match (set_apps_result, set_system_result) {
210-
(ERROR_SUCCESS, ERROR_SUCCESS) => {
211-
info!(mode = %mode, "Successfully set color mode");
212-
}
213-
_ => {
214-
error!(
215-
mode = %mode,
216-
apps_result = set_apps_result.0,
217-
system_result = set_system_result.0,
218-
"Failed to set color mode"
219-
);
220-
return Err(ColorModeRegistryError::Set(
221-
set_apps_result.0 | set_system_result.0,
222-
)
223-
.into());
224-
}
225-
};
226-
227-
notify_theme_change()?;
228-
}
92+
let value = mode.to_le_bytes();
93+
94+
registry_key
95+
.set(Self::APPS_THEME_VALUE, REG_DWORD, &value)
96+
.map_err(|e| {
97+
error!(error =?e, "Failed to set apps theme value");
98+
e
99+
})?;
100+
info!(mode = %mode, "Successfully set apps theme value");
101+
102+
registry_key
103+
.set(Self::SYSTEM_THEME_VALUE, REG_DWORD, &value)
104+
.map_err(|e| {
105+
error!(error =?e, "Failed to set system theme value");
106+
e
107+
})?;
108+
info!(mode = %mode, "Successfully set system theme value");
109+
110+
notify_theme_change()?;
229111

230112
Ok(())
231113
}

daemon/src/config.rs

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
77
use serde_valid::Validate;
88
use thiserror::Error;
99

10-
use crate::{error::DwallResult, lazy::DWALL_CONFIG_DIR, theme::ThemeError};
10+
use crate::{error::DwallResult, lazy::DWALL_CONFIG_DIR};
1111

1212
#[derive(Error, Debug)]
1313
pub enum ConfigError {
@@ -77,16 +77,38 @@ impl CoordinateSource {
7777
}
7878
}
7979

80+
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
81+
#[serde(untagged)]
82+
pub enum MonitorSpecificWallpapers {
83+
All(String),
84+
Specific(HashMap<String, String>),
85+
}
86+
87+
impl MonitorSpecificWallpapers {
88+
pub fn is_all(&self) -> bool {
89+
matches!(self, MonitorSpecificWallpapers::All(_))
90+
}
91+
92+
pub fn is_empty(&self) -> bool {
93+
match self {
94+
MonitorSpecificWallpapers::All(_) => false,
95+
MonitorSpecificWallpapers::Specific(wallpapers) => wallpapers.is_empty(),
96+
}
97+
}
98+
99+
pub fn get(&self, monitor_id: &str) -> Option<&String> {
100+
match self {
101+
MonitorSpecificWallpapers::All(theme_id) => Some(theme_id),
102+
MonitorSpecificWallpapers::Specific(wallpapers) => wallpapers.get(monitor_id),
103+
}
104+
}
105+
}
106+
80107
#[derive(Debug, Serialize, Deserialize, Validate, Clone, PartialEq)]
81108
pub struct Config {
82109
#[serde(skip_serializing_if = "Option::is_none")]
83110
github_mirror_template: Option<String>,
84111

85-
/// When `monitor_specific_wallpapers` is not set, `selected_theme_id` will be applied to all monitors.
86-
/// Otherwise, `selected_theme_id` will not take effect, and wallpapers will be set according to `monitor_specific_wallpapers`.
87-
#[serde(skip_serializing_if = "Option::is_none")]
88-
selected_theme_id: Option<String>,
89-
90112
#[serde(default = "default_image_format")]
91113
image_format: ImageFormat,
92114

@@ -104,7 +126,7 @@ pub struct Config {
104126

105127
/// Wallpapers specific to each monitor, using monitor ID as key
106128
#[serde(default = "default_monitor_specific_wallpapers")]
107-
monitor_specific_wallpapers: HashMap<String, String>,
129+
monitor_specific_wallpapers: MonitorSpecificWallpapers,
108130

109131
/// Time interval for detecting solar altitude angle and azimuth angle
110132
/// Measured in seconds, range: [1, 600]
@@ -138,8 +160,8 @@ fn default_themes_directory() -> PathBuf {
138160
DWALL_CONFIG_DIR.join("themes")
139161
}
140162

141-
fn default_monitor_specific_wallpapers() -> HashMap<String, String> {
142-
HashMap::new()
163+
fn default_monitor_specific_wallpapers() -> MonitorSpecificWallpapers {
164+
MonitorSpecificWallpapers::Specific(HashMap::new())
143165
}
144166

145167
impl Config {
@@ -160,13 +182,6 @@ impl Config {
160182
Ok(())
161183
}
162184

163-
/// Returns the default theme ID or an error if not set
164-
pub fn default_theme_id(&self) -> DwallResult<&str> {
165-
self.selected_theme_id
166-
.as_deref()
167-
.ok_or(ThemeError::MissingDefaultTheme.into())
168-
}
169-
170185
/// Returns the themes directory path
171186
pub fn themes_directory(&self) -> &Path {
172187
&self.themes_directory
@@ -205,7 +220,7 @@ impl Config {
205220
}
206221

207222
/// Returns the monitor-specific wallpapers map
208-
pub fn monitor_specific_wallpapers(&self) -> &HashMap<String, String> {
223+
pub fn monitor_specific_wallpapers(&self) -> &MonitorSpecificWallpapers {
209224
&self.monitor_specific_wallpapers
210225
}
211226

@@ -239,11 +254,10 @@ impl Default for Config {
239254
image_format: Default::default(),
240255
coordinate_source: Default::default(),
241256
github_mirror_template: Default::default(),
242-
selected_theme_id: Default::default(),
243257
auto_detect_color_mode: default_auto_detect_color_mode(),
244258
themes_directory: default_themes_directory(),
245259
lock_screen_wallpaper_enabled: default_lock_screen_wallpaper_enabled(),
246-
monitor_specific_wallpapers: Default::default(),
260+
monitor_specific_wallpapers: default_monitor_specific_wallpapers(),
247261
// On the equator, an azimuth change of 0.1 degrees takes
248262
// approximately 12 seconds, and an altitude change of 0.1
249263
// degrees takes about 24 seconds.

0 commit comments

Comments
 (0)