aboutsummaryrefslogtreecommitdiffstats
path: root/src/wayland.rs
diff options
context:
space:
mode:
authorPetri Hienonen <petri.hienonen@gmail.com>2025-10-18 14:24:04 +0300
committerPetri Hienonen <petri.hienonen@gmail.com>2025-10-18 14:24:04 +0300
commit0396d313791af347f31d004bbf2842fb11244fac (patch)
tree2cae5a5b55e610b7e3d19667032fefeb8018f4de /src/wayland.rs
downloadwallpaper-0396d313791af347f31d004bbf2842fb11244fac.tar.zst
Update
Diffstat (limited to '')
-rw-r--r--src/wayland.rs176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/wayland.rs b/src/wayland.rs
new file mode 100644
index 0000000..afb1486
--- /dev/null
+++ b/src/wayland.rs
@@ -0,0 +1,176 @@
+use anyhow::{Result, anyhow};
+use log::{info, warn};
+use std::process::Command;
+
+/// Hyprland-specific window configuration for better integration
+pub struct HyprlandConfig {
+ pub floating: bool,
+ pub pin: bool,
+ pub no_focus: bool,
+}
+
+impl Default for HyprlandConfig {
+ fn default() -> Self {
+ Self {
+ floating: true,
+ pin: true,
+ no_focus: true,
+ }
+ }
+}
+
+/// Configure a window for optimal Hyprland wallpaper behavior
+pub fn configure_hyprland_window(
+ _window: &winit::window::Window,
+ _config: &HyprlandConfig,
+) -> Result<()> {
+ // On Wayland, we can set window properties for better integration
+ // For now, skip advanced Wayland protocol setup as it's not implemented
+
+ // For Hyprland, we can use hyprctl to configure the window
+ // This requires the window to be created first, so we'll do this after creation
+ if let Ok(output) = Command::new("which").arg("hyprctl").output() {
+ if output.status.success() {
+ info!("Hyprland detected, will configure window properties");
+ // We'll configure the window after it's mapped in the event loop
+ }
+ }
+
+ Ok(())
+}
+
+/// Apply Hyprland-specific window rules after window creation
+pub fn apply_hyprland_rules(window_id: u64, config: &HyprlandConfig) -> Result<()> {
+ #[cfg(target_os = "linux")]
+ {
+ use std::process::Command;
+ use std::thread;
+ use std::time::Duration;
+
+ // Wait a bit for the window to be mapped
+ thread::sleep(Duration::from_millis(100));
+
+ // Use hyprctl to configure the window
+ let mut rules = Vec::new();
+
+ if config.floating {
+ rules.push("float");
+ }
+
+ if config.pin {
+ rules.push("pin");
+ }
+
+ if config.no_focus {
+ rules.push("nofocus");
+ }
+
+ if !rules.is_empty() {
+ let rules_str = rules.join(",");
+ let window_selector = format!("address:0x{:x}", window_id);
+
+ let output = Command::new("hyprctl")
+ .args(&[
+ "keyword",
+ "windowrule",
+ &format!("{},{}", rules_str, window_selector),
+ ])
+ .output()
+ .map_err(|e| anyhow!("Failed to execute hyprctl: {}", e))?;
+
+ if output.status.success() {
+ info!(
+ "Applied Hyprland rules: {} to window {}",
+ rules_str, window_selector
+ );
+ } else {
+ let error_msg = String::from_utf8_lossy(&output.stderr);
+ warn!("Failed to apply Hyprland rules: {}", error_msg);
+ }
+
+ // Also try to move it to the background layer
+ let workspace = format!("special:background,{}", window_selector);
+ let output = Command::new("hyprctl")
+ .args(&["dispatch", "movetoworkspace", &workspace])
+ .output()
+ .map_err(|e| anyhow!("Failed to move window to background: {}", e))?;
+
+ if output.status.success() {
+ info!("Moved wallpaper window to background workspace");
+ }
+ }
+ }
+
+ Ok(())
+}
+
+/// Get information about available outputs (monitors)
+pub fn get_output_info() -> Result<Vec<OutputInfo>> {
+ #[cfg(target_os = "linux")]
+ {
+ use std::process::Command;
+
+ let output = Command::new("hyprctl")
+ .args(&["monitors", "-j"])
+ .output()
+ .map_err(|e| anyhow!("Failed to execute hyprctl: {}", e))?;
+
+ if output.status.success() {
+ let output_str = String::from_utf8_lossy(&output.stdout);
+ let monitors: Vec<HyprlandMonitor> = serde_json::from_str(&output_str)
+ .map_err(|e| anyhow!("Failed to parse hyprctl output: {}", e))?;
+
+ let output_info = monitors
+ .into_iter()
+ .map(|monitor| OutputInfo {
+ name: monitor.name,
+ width: monitor.width,
+ height: monitor.height,
+ x: monitor.x,
+ y: monitor.y,
+ })
+ .collect();
+
+ Ok(output_info)
+ } else {
+ // Fallback to basic monitor detection
+ Ok(vec![OutputInfo::default()])
+ }
+ }
+
+ #[cfg(not(target_os = "linux"))]
+ {
+ Ok(vec![OutputInfo::default()])
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct OutputInfo {
+ pub name: String,
+ pub width: i32,
+ pub height: i32,
+ pub x: i32,
+ pub y: i32,
+}
+
+impl Default for OutputInfo {
+ fn default() -> Self {
+ Self {
+ name: "eDP-1".to_string(),
+ width: 1920,
+ height: 1080,
+ x: 0,
+ y: 0,
+ }
+ }
+}
+
+#[cfg(target_os = "linux")]
+#[derive(serde::Deserialize)]
+struct HyprlandMonitor {
+ name: String,
+ width: i32,
+ height: i32,
+ x: i32,
+ y: i32,
+}