diff options
Diffstat (limited to 'src/wayland.rs')
| -rw-r--r-- | src/wayland.rs | 176 |
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, +} |
