diff --git a/Cargo.lock b/Cargo.lock
index 4e864e81..4dd69a13 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -904,6 +904,34 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
+[[package]]
+name = "cookie"
+version = "0.18.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
+dependencies = [
+ "percent-encoding",
+ "time",
+ "version_check",
+]
+
+[[package]]
+name = "cookie_store"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4934e6b7e8419148b6ef56950d277af8561060b56afd59e2aadf98b59fce6baa"
+dependencies = [
+ "cookie",
+ "idna 0.5.0",
+ "log",
+ "publicsuffix",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "time",
+ "url",
+]
+
[[package]]
name = "core-foundation"
version = "0.7.0"
@@ -1100,6 +1128,12 @@ dependencies = [
"syn 2.0.68",
]
+[[package]]
+name = "data-url"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a"
+
[[package]]
name = "deranged"
version = "0.3.11"
@@ -1972,6 +2006,25 @@ dependencies = [
"syn 2.0.68",
]
+[[package]]
+name = "h2"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab"
+dependencies = [
+ "atomic-waker",
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "http",
+ "indexmap 2.2.6",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
[[package]]
name = "half"
version = "2.4.1"
@@ -2096,6 +2149,7 @@ dependencies = [
"bytes",
"futures-channel",
"futures-util",
+ "h2",
"http",
"http-body",
"httparse",
@@ -2183,6 +2237,16 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+[[package]]
+name = "idna"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
[[package]]
name = "idna"
version = "0.5.0"
@@ -3617,6 +3681,12 @@ dependencies = [
"syn 2.0.68",
]
+[[package]]
+name = "psl-types"
+version = "2.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac"
+
[[package]]
name = "ptr_meta"
version = "0.1.4"
@@ -3637,6 +3707,16 @@ dependencies = [
"syn 1.0.109",
]
+[[package]]
+name = "publicsuffix"
+version = "2.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96a8c1bda5ae1af7f99a2962e49df150414a43d62404644d98dd5c3a93d07457"
+dependencies = [
+ "idna 0.3.0",
+ "psl-types",
+]
+
[[package]]
name = "qoi"
version = "0.4.1"
@@ -3976,8 +4056,12 @@ checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37"
dependencies = [
"base64 0.22.1",
"bytes",
+ "cookie",
+ "cookie_store",
+ "encoding_rs",
"futures-core",
"futures-util",
+ "h2",
"http",
"http-body",
"http-body-util",
@@ -3999,6 +4083,7 @@ dependencies = [
"serde_json",
"serde_urlencoded",
"sync_wrapper",
+ "system-configuration",
"tokio",
"tokio-rustls",
"tokio-util",
@@ -4285,6 +4370,7 @@ dependencies = [
"tauri-plugin-deep-link",
"tauri-plugin-dialog",
"tauri-plugin-fs",
+ "tauri-plugin-http",
"tauri-plugin-log",
"tauri-plugin-process",
"tauri-plugin-shell",
@@ -4772,6 +4858,27 @@ dependencies = [
"windows 0.52.0",
]
+[[package]]
+name = "system-configuration"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
+dependencies = [
+ "bitflags 1.3.2",
+ "core-foundation 0.9.4",
+ "system-configuration-sys",
+]
+
+[[package]]
+name = "system-configuration-sys"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
+dependencies = [
+ "core-foundation-sys 0.8.6",
+ "libc",
+]
+
[[package]]
name = "system-deps"
version = "6.2.2"
@@ -5061,6 +5168,28 @@ dependencies = [
"uuid",
]
+[[package]]
+name = "tauri-plugin-http"
+version = "2.0.0-rc.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1eef17218eaa8bd0fc6cafb7831c63d82ef83b3950d59dc817d92d5320c4f20c"
+dependencies = [
+ "data-url",
+ "http",
+ "regex",
+ "reqwest",
+ "schemars",
+ "serde",
+ "serde_json",
+ "tauri",
+ "tauri-plugin",
+ "tauri-plugin-fs",
+ "thiserror",
+ "tokio",
+ "url",
+ "urlpattern",
+]
+
[[package]]
name = "tauri-plugin-log"
version = "2.0.0-rc.0"
@@ -5372,10 +5501,22 @@ dependencies = [
"pin-project-lite",
"signal-hook-registry",
"socket2",
+ "tokio-macros",
"tracing",
"windows-sys 0.48.0",
]
+[[package]]
+name = "tokio-macros"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.68",
+]
+
[[package]]
name = "tokio-rustls"
version = "0.26.0"
@@ -5709,7 +5850,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
dependencies = [
"form_urlencoded",
- "idna",
+ "idna 0.5.0",
"percent-encoding",
"serde",
]
diff --git a/Cargo.toml b/Cargo.toml
index ec3eeba6..224de042 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -37,6 +37,7 @@ tauri-plugin-process = "2.0.0-beta.2"
tauri-plugin-log = "2.0.0-beta.2"
tauri-plugin-updater = "2.0.0-beta.2"
tauri-plugin-deep-link = "2.0.0-beta.10"
+tauri-plugin-http = "2.0.0-beta.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_yaml = "0.9.34"
diff --git a/changelog.md b/changelog.md
index 6167a043..0b4d9039 100644
--- a/changelog.md
+++ b/changelog.md
@@ -3,6 +3,7 @@
## [Unreleased]
### features
- .slu and uri now are loaded correctly on seelen ui.
+- allow change wallpaper from seelen settings.
### enhancements
- add file associations for .slu files
diff --git a/src/apps/settings/components/SettingsBox/index.module.css b/src/apps/settings/components/SettingsBox/index.module.css
index 08732743..ef928702 100644
--- a/src/apps/settings/components/SettingsBox/index.module.css
+++ b/src/apps/settings/components/SettingsBox/index.module.css
@@ -5,6 +5,10 @@
overflow: hidden;
position: relative;
+ &:last-child {
+ margin-bottom: 10px;
+ }
+
> div {
position: absolute; /* for noise and blur */
top: 0;
diff --git a/src/apps/settings/components/monitor/index.module.css b/src/apps/settings/components/monitor/index.module.css
new file mode 100644
index 00000000..c22ddd05
--- /dev/null
+++ b/src/apps/settings/components/monitor/index.module.css
@@ -0,0 +1,28 @@
+.monitor {
+ height: 144px;
+ width: 256px;
+ border-radius: 12px;
+ background-color: var(--color-persist-gray-800);
+ padding: 8px;
+
+ .screen {
+ position: relative;
+ border-radius: 8px;
+ background: linear-gradient(
+ 40deg,
+ var(--color-blue-500) 2%,
+ var(--color-blue-300) 60%,
+ var(--color-blue-100) 100%
+ );
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+
+ .wallpaper {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ position: absolute;
+ }
+ }
+}
diff --git a/src/apps/settings/components/monitor/index.tsx b/src/apps/settings/components/monitor/index.tsx
new file mode 100644
index 00000000..d2f9f3c8
--- /dev/null
+++ b/src/apps/settings/components/monitor/index.tsx
@@ -0,0 +1,22 @@
+import { convertFileSrc } from '@tauri-apps/api/core';
+import { PropsWithChildren } from 'react';
+import { useSelector } from 'react-redux';
+
+import { newSelectors } from '../../modules/shared/store/app/reducer';
+
+import cs from './index.module.css';
+
+interface Props extends PropsWithChildren {}
+
+export function Monitor({ children }: Props) {
+ const wallpaper = useSelector(newSelectors.wallpaper);
+
+ return (
+
+
+ {wallpaper ?
![]({convertFileSrc(wallpaper)})
: null}
+ {children}
+
+
+ );
+}
diff --git a/src/apps/settings/i18n/translations/en.yml b/src/apps/settings/i18n/translations/en.yml
index f743d2cc..5afdb97d 100644
--- a/src/apps/settings/i18n/translations/en.yml
+++ b/src/apps/settings/i18n/translations/en.yml
@@ -44,6 +44,8 @@ general:
selected: Selected
icon_pack:
label: Icon Packs
+ wallpaper:
+ select: Select Wallpaper
accent_color: Accent Color
toolbar:
enable: Enable Fancy Toolbar
diff --git a/src/apps/settings/modules/general/main/infra/Wallpaper.tsx b/src/apps/settings/modules/general/main/infra/Wallpaper.tsx
new file mode 100644
index 00000000..b22f8a16
--- /dev/null
+++ b/src/apps/settings/modules/general/main/infra/Wallpaper.tsx
@@ -0,0 +1,38 @@
+import { Monitor } from '../../../../components/monitor';
+import { SettingsOption } from '../../../../components/SettingsBox';
+import { invoke } from '@tauri-apps/api/core';
+import { Button } from 'antd';
+import { useTranslation } from 'react-i18next';
+import { useDispatch } from 'react-redux';
+
+import { dialog } from '../../../shared/tauri/infra';
+
+import { RootActions } from '../../../shared/store/app/reducer';
+
+export function Wallpaper() {
+ const { t } = useTranslation();
+ const dispatch = useDispatch();
+
+ async function loadWallpaper() {
+ const file = await dialog.open({
+ title: t('general.wallpaper.select'),
+ filters: [{ name: 'images', extensions: ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'tif', 'tiff'] }],
+ });
+
+ if (!file) {
+ return;
+ }
+
+ await invoke('state_set_wallpaper', { path: file.path });
+ dispatch(RootActions.setWallpaper(file.path));
+ }
+
+ return (
+ <>
+
+
+
+
+ >
+ );
+}
diff --git a/src/apps/settings/modules/general/main/infra/index.tsx b/src/apps/settings/modules/general/main/infra/index.tsx
index ca5a53ac..6d921a22 100644
--- a/src/apps/settings/modules/general/main/infra/index.tsx
+++ b/src/apps/settings/modules/general/main/infra/index.tsx
@@ -2,6 +2,7 @@ import { LanguageList } from '../../../../../shared/lang';
import { SettingsGroup, SettingsOption } from '../../../../components/SettingsBox';
import { Colors } from './Colors';
import { Themes } from './Themes';
+import { Wallpaper } from './Wallpaper';
import { Select, Switch } from 'antd';
import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
@@ -35,9 +36,6 @@ export function General() {
{t('general.startup')}
-
-
-
{t('general.language')}:
+
+
+
+
{t('general.theme.label')}
diff --git a/src/apps/settings/modules/shared/store/app/StateBridge.ts b/src/apps/settings/modules/shared/store/app/StateBridge.ts
index 1f9b7dd9..a124b117 100644
--- a/src/apps/settings/modules/shared/store/app/StateBridge.ts
+++ b/src/apps/settings/modules/shared/store/app/StateBridge.ts
@@ -38,11 +38,12 @@ export const StaticSettingsToState = (
userSettings: UserSettings,
state: RootState,
): RootState => {
- const { jsonSettings, yamlSettings, themes, layouts, placeholders } = userSettings;
+ const { jsonSettings, yamlSettings, themes, layouts, placeholders, wallpaper } = userSettings;
return {
...state,
...jsonSettings,
+ wallpaper,
availableThemes: themes,
availableLayouts: layouts,
availablePlaceholders: placeholders,
diff --git a/src/apps/settings/modules/shared/store/app/reducer.ts b/src/apps/settings/modules/shared/store/app/reducer.ts
index 7dd13750..cf154c64 100644
--- a/src/apps/settings/modules/shared/store/app/reducer.ts
+++ b/src/apps/settings/modules/shared/store/app/reducer.ts
@@ -44,6 +44,7 @@ const initialState: RootState = {
accent_lightest: '#000000',
complement: null,
},
+ wallpaper: null,
};
export const RootSlice = createSlice({
diff --git a/src/apps/settings/modules/shared/store/domain.ts b/src/apps/settings/modules/shared/store/domain.ts
index 5651850d..62599c89 100644
--- a/src/apps/settings/modules/shared/store/domain.ts
+++ b/src/apps/settings/modules/shared/store/domain.ts
@@ -29,4 +29,5 @@ export interface RootState extends ISettings {
availablePlaceholders: Placeholder[];
autostart: boolean;
colors: UIColors;
+ wallpaper: string | null;
}
diff --git a/src/apps/settings/modules/shared/store/infra.ts b/src/apps/settings/modules/shared/store/infra.ts
index 76fe3cf3..b312dc40 100644
--- a/src/apps/settings/modules/shared/store/infra.ts
+++ b/src/apps/settings/modules/shared/store/infra.ts
@@ -58,8 +58,6 @@ export async function registerStoreEvents() {
IsSavingSettings.current = false;
return;
}
- console.log('SETTINGS CHANGED', event.payload);
-
const currentState = store.getState();
const newState: RootState = {
...currentState,
@@ -80,6 +78,7 @@ export const LoadSettingsToStore = async (customPath?: string) => {
.withLayouts()
.withPlaceholders()
.withUserApps()
+ .withWallpaper()
.load(customPath);
const currentState = store.getState();
diff --git a/src/apps/settings/modules/shared/store/storeApi.ts b/src/apps/settings/modules/shared/store/storeApi.ts
index 76fabef6..273544ef 100644
--- a/src/apps/settings/modules/shared/store/storeApi.ts
+++ b/src/apps/settings/modules/shared/store/storeApi.ts
@@ -98,6 +98,7 @@ export class UserSettingsLoader {
private _withLayouts: boolean = false;
private _withPlaceholders: boolean = false;
private _withThemes: boolean = true;
+ private _withWallpaper: boolean = true;
withUserApps() {
this._withUserApps = true;
@@ -114,6 +115,11 @@ export class UserSettingsLoader {
return this;
}
+ withWallpaper() {
+ this._withWallpaper = true;
+ return this;
+ }
+
withThemes(value: boolean) {
this._withThemes = value;
return this;
@@ -127,6 +133,7 @@ export class UserSettingsLoader {
layouts: [],
placeholders: [],
env: await invoke('get_user_envs'),
+ wallpaper: null,
};
let data =
@@ -152,6 +159,10 @@ export class UserSettingsLoader {
await loadUserPlaceholders(userSettings);
}
+ if (this._withWallpaper) {
+ userSettings.wallpaper = await invoke('state_get_wallpaper');
+ }
+
return userSettings;
}
}
diff --git a/src/background/error_handler.rs b/src/background/error_handler.rs
index e68b0ff1..eb8a2e82 100644
--- a/src/background/error_handler.rs
+++ b/src/background/error_handler.rs
@@ -37,6 +37,8 @@ define_app_errors!(
Battery(battery::Error);
FileNotify(notify::Error);
Base64Decode(base64::DecodeError);
+ WideStringNull(widestring::error::MissingNulTerminator);
+ Reqwest(tauri_plugin_http::reqwest::Error);
);
impl From<&str> for AppError {
diff --git a/src/background/exposed.rs b/src/background/exposed.rs
index 9314e868..f29cbf08 100644
--- a/src/background/exposed.rs
+++ b/src/background/exposed.rs
@@ -184,6 +184,8 @@ pub fn register_invoke_handler(app_builder: Builder
) -> Builder {
state_get_weg_items,
state_get_settings,
state_get_specific_apps_configurations,
+ state_get_wallpaper,
+ state_set_wallpaper,
// Media
media_prev,
media_toggle_play_pause,
diff --git a/src/background/modules/cli/domain.rs b/src/background/modules/cli/domain.rs
index 4b001a87..f34aabf3 100644
--- a/src/background/modules/cli/domain.rs
+++ b/src/background/modules/cli/domain.rs
@@ -5,6 +5,8 @@ use crate::state::domain::{Placeholder, Theme};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Resource {
pub id: String,
+ /// Url of wallpaper
+ pub wallpaper: Option,
pub resources: ResourceItems,
}
diff --git a/src/background/modules/tray/application.rs b/src/background/modules/tray/application.rs
index 4e2231da..398d50bf 100644
--- a/src/background/modules/tray/application.rs
+++ b/src/background/modules/tray/application.rs
@@ -1,7 +1,6 @@
use itertools::Itertools;
use windows::Win32::{
Foundation::{HWND, POINT, RECT},
- System::Registry,
UI::{
Accessibility::{
CUIAutomation, IUIAutomation, IUIAutomationCondition, IUIAutomationElement,
@@ -11,7 +10,10 @@ use windows::Win32::{
WindowsAndMessaging::{FindWindowA, FindWindowExA, GetCursorPos, SW_SHOW},
},
};
-use winreg::{enums::HKEY_CURRENT_USER, RegKey};
+use winreg::{
+ enums::{HKEY_CURRENT_USER, KEY_ALL_ACCESS},
+ RegKey,
+};
use crate::{
error_handler::Result,
@@ -230,8 +232,7 @@ impl TrayIcon {
});
for id in ids {
- let key =
- settings.open_subkey_with_flags(id.to_string(), Registry::KEY_ALL_ACCESS.0)?;
+ let key = settings.open_subkey_with_flags(id.to_string(), KEY_ALL_ACCESS)?;
let promoted: u32 = key.get_value("IsPromoted").unwrap_or_default();
if promoted == 1 && WindowsApi::is_elevated()? {
diff --git a/src/background/plugins.rs b/src/background/plugins.rs
index 621b101d..d887e52b 100644
--- a/src/background/plugins.rs
+++ b/src/background/plugins.rs
@@ -58,4 +58,5 @@ pub fn register_plugins(app_builder: Builder) -> Builder {
))
.plugin(log_plugin_builder.build())
.plugin(tauri_plugin_deep_link::init())
+ .plugin(tauri_plugin_http::init())
}
diff --git a/src/background/seelen.rs b/src/background/seelen.rs
index 5caa1343..01a192cc 100644
--- a/src/background/seelen.rs
+++ b/src/background/seelen.rs
@@ -208,6 +208,7 @@ impl Seelen {
std::fs::create_dir_all(data_path.join("themes"))?;
std::fs::create_dir_all(data_path.join("layouts"))?;
std::fs::create_dir_all(data_path.join("icons"))?;
+ std::fs::create_dir_all(data_path.join("wallpapers"))?;
Ok(())
}
diff --git a/src/background/state/application/mod.rs b/src/background/state/application/mod.rs
index ee19e3de..7ae720c9 100644
--- a/src/background/state/application/mod.rs
+++ b/src/background/state/application/mod.rs
@@ -6,7 +6,7 @@ use notify::{RecursiveMode, Watcher};
use parking_lot::Mutex;
use std::{
collections::{HashMap, VecDeque},
- path::PathBuf,
+ path::{Path, PathBuf},
sync::{
atomic::{AtomicBool, Ordering},
Arc,
@@ -16,7 +16,7 @@ use tauri::{AppHandle, Emitter, Manager};
use crate::{
error_handler::Result, log_error, modules::cli::domain::Resource, seelen::get_app_handle,
- trace_lock,
+ trace_lock, windows_api::WindowsApi,
};
use super::{
@@ -346,10 +346,25 @@ impl FullState {
Ok(())
}
+ async fn set_wallpaper(url: &str, path: &Path) -> Result<()> {
+ let response = tauri_plugin_http::reqwest::get(url).await?;
+ let contents = response.bytes().await?;
+ std::fs::write(path, &contents)?;
+ WindowsApi::set_wallpaper(path.to_string_lossy().to_string())?;
+ Ok(())
+ }
+
pub fn load_resource(&mut self, resource: Resource) -> Result<()> {
log::trace!("Loading resource: {}", resource.id);
let id = resource.id;
+ if let Some(image_url) = resource.wallpaper {
+ let path = self.data_dir.join(format!("wallpapers/{id}.png"));
+ tauri::async_runtime::spawn(async move {
+ log_error!(Self::set_wallpaper(&image_url, &path).await);
+ });
+ }
+
if let Some(theme) = resource.resources.theme {
let filename = format!("{id}.yml");
std::fs::write(
diff --git a/src/background/state/infrastructure.rs b/src/background/state/infrastructure.rs
index de75e544..9e798e3b 100644
--- a/src/background/state/infrastructure.rs
+++ b/src/background/state/infrastructure.rs
@@ -1,6 +1,8 @@
+use std::path::PathBuf;
+
use itertools::Itertools;
-use crate::trace_lock;
+use crate::{error_handler::Result, trace_lock, windows_api::WindowsApi};
use super::{
application::FULL_STATE,
@@ -43,3 +45,13 @@ pub fn state_get_specific_apps_configurations() -> Vec {
.cloned()
.collect_vec()
}
+
+#[tauri::command]
+pub fn state_get_wallpaper() -> Result {
+ WindowsApi::get_wallpaper()
+}
+
+#[tauri::command]
+pub fn state_set_wallpaper(path: String) -> Result<()> {
+ WindowsApi::set_wallpaper(path)
+}
diff --git a/src/background/windows_api/mod.rs b/src/background/windows_api/mod.rs
index b1b2e90a..46718fe9 100644
--- a/src/background/windows_api/mod.rs
+++ b/src/background/windows_api/mod.rs
@@ -5,6 +5,7 @@ mod iterator;
pub use app_bar::*;
pub use com::*;
pub use iterator::*;
+use itertools::Itertools;
use widestring::U16CStr;
use std::{ffi::c_void, path::PathBuf, thread::sleep, time::Duration};
@@ -20,7 +21,7 @@ use windows::{
GetNumberOfPhysicalMonitorsFromHMONITOR, GetPhysicalMonitorsFromHMONITOR,
PHYSICAL_MONITOR,
},
- Foundation::{CloseHandle, HANDLE, HMODULE, HWND, LPARAM, LUID, RECT},
+ Foundation::{CloseHandle, HANDLE, HMODULE, HWND, LPARAM, LUID, MAX_PATH, RECT},
Graphics::{
Dwm::{
DwmGetWindowAttribute, DWMWA_CLOAKED, DWMWA_EXTENDED_FRAME_BOUNDS,
@@ -59,8 +60,9 @@ use windows::{
IsWindow, IsWindowVisible, IsZoomed, SetWindowPos, ShowWindow, ShowWindowAsync,
SystemParametersInfoW, ANIMATIONINFO, EVENT_SYSTEM_FOREGROUND, GWL_EXSTYLE,
GWL_STYLE, SET_WINDOW_POS_FLAGS, SHOW_WINDOW_CMD, SPIF_SENDCHANGE,
- SPI_GETANIMATION, SPI_SETANIMATION, SWP_ASYNCWINDOWPOS, SWP_NOACTIVATE, SWP_NOMOVE,
- SWP_NOSIZE, SWP_NOZORDER, SW_MINIMIZE, SW_NORMAL, SW_RESTORE,
+ SPIF_UPDATEINIFILE, SPI_GETANIMATION, SPI_GETDESKWALLPAPER, SPI_SETANIMATION,
+ SPI_SETDESKWALLPAPER, SWP_ASYNCWINDOWPOS, SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOSIZE,
+ SWP_NOZORDER, SW_MINIMIZE, SW_NORMAL, SW_RESTORE,
SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS, WINDOW_EX_STYLE, WINDOW_STYLE, WNDENUMPROC,
},
},
@@ -71,6 +73,7 @@ use crate::{
error_handler::{AppError, Result},
hook::HOOK_MANAGER,
log_error, trace_lock,
+ utils::is_windows_11,
winevent::WinEvent,
};
@@ -528,6 +531,46 @@ impl WindowsApi {
Ok(desktop_id)
}
+ pub fn get_wallpaper() -> Result {
+ let mut path = [0_u16; MAX_PATH as usize];
+ unsafe {
+ SystemParametersInfoW(
+ SPI_GETDESKWALLPAPER,
+ MAX_PATH,
+ Some(path.as_mut_ptr() as _),
+ SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS(0),
+ )?;
+ }
+ Ok(PathBuf::from(
+ U16CStr::from_slice_truncate(&path)?
+ .to_ustring()
+ .to_string_lossy(),
+ ))
+ }
+
+ pub fn set_wallpaper(path: String) -> Result<()> {
+ if !PathBuf::from(&path).exists() {
+ return Err("File not found".into());
+ }
+
+ if is_windows_11() {
+ for v_desktop in winvd::get_desktops()? {
+ v_desktop.set_wallpaper(&path)?;
+ }
+ }
+
+ let mut path = path.encode_utf16().chain(Some(0)).collect_vec();
+ unsafe {
+ SystemParametersInfoW(
+ SPI_SETDESKWALLPAPER,
+ MAX_PATH,
+ Some(path.as_mut_ptr() as _),
+ SPIF_SENDCHANGE | SPIF_UPDATEINIFILE,
+ )?;
+ }
+ Ok(())
+ }
+
pub fn get_min_animation_info() -> Result {
let mut anim_info: ANIMATIONINFO = unsafe { core::mem::zeroed() };
anim_info.cbSize = core::mem::size_of::() as u32;
diff --git a/src/shared.interfaces.ts b/src/shared.interfaces.ts
index 8ec2d8be..89d7f7ec 100644
--- a/src/shared.interfaces.ts
+++ b/src/shared.interfaces.ts
@@ -14,6 +14,7 @@ export interface UserSettings {
layouts: Layout[];
placeholders: Placeholder[];
env: Record;
+ wallpaper: string | null;
}
const _defaultLayout = LayoutSchema.parse({});
diff --git a/tauri.conf.json b/tauri.conf.json
index 629686d4..047e22df 100644
--- a/tauri.conf.json
+++ b/tauri.conf.json
@@ -10,7 +10,14 @@
"scope": [
"$RESOURCE/**/*",
"$TEMP/**/*",
- "$DATA/**/*"
+ "$DATA/**/*",
+ "**/*.jpg",
+ "**/*.jpeg",
+ "**/*.png",
+ "**/*.gif",
+ "**/*.bmp",
+ "**/*.tif",
+ "**/*.tiff"
]
}
}
@@ -52,7 +59,9 @@
"homepage": "https://github.com/eythaann/Seelen-UI",
"fileAssociations": [
{
- "ext": [".slu"],
+ "ext": [
+ ".slu"
+ ],
"name": "seelen-ui.file",
"description": "Seelen UI File",
"mimeType": "text/plain",
@@ -70,7 +79,9 @@
"deep-link": {
"mobile": [],
"desktop": {
- "schemes": ["seelen-ui.uri"]
+ "schemes": [
+ "seelen-ui.uri"
+ ]
}
}
}