zerolaunch_plugin_api/services/window/window_positioner.rs
1use crate::host::error::HostApiError;
2
3/// Platform-independent monitor info.
4/// Collected from Tauri AppHandle and passed into the positioner,
5/// avoiding a direct Tauri dependency in the SDK trait.
6#[derive(Debug, Clone)]
7pub struct MonitorInfo {
8 /// Monitor top-left X in physical pixels.
9 pub x: i32,
10 /// Monitor top-left Y in physical pixels.
11 pub y: i32,
12 /// Monitor width in physical pixels.
13 pub width: u32,
14 /// Monitor height in physical pixels.
15 pub height: u32,
16 /// DPI scale factor (1.0 = 96 DPI, 1.5 = 144 DPI, etc.).
17 /// Used to convert logical window dimensions to physical pixels.
18 pub scale_factor: f64,
19}
20
21/// Window position in physical pixel coordinates.
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub struct WindowPosition {
24 pub x: i32,
25 pub y: i32,
26}
27
28/// Input parameters for the position calculation.
29pub struct PositionRequest {
30 /// Whether drag-window mode is enabled (highest priority).
31 pub enable_drag_window: bool,
32 /// Previously saved window position (only used if enable_drag_window is true).
33 pub saved_position: Option<WindowPosition>,
34 /// Whether follow-mouse mode is enabled (second priority).
35 pub follow_mouse: bool,
36 /// Vertical position ratio 0.0–1.0 for default centering.
37 pub vertical_position_ratio: f64,
38 /// Window width in physical pixels, for horizontal centering.
39 pub window_width: i32,
40 /// Available monitors collected from the system.
41 pub monitors: Vec<MonitorInfo>,
42}
43
44/// Calculates the optimal window position from configuration and platform state.
45///
46/// Three-tier priority (mutually exclusive, first match wins):
47/// 1. `enable_drag_window` + valid `saved_position` → use saved position
48/// 2. `follow_mouse` → center on the monitor containing the cursor
49/// 3. Neither → center on the primary monitor
50#[async_trait::async_trait]
51pub trait WindowPositioner: Send + Sync {
52 /// Compute the optimal window position.
53 /// Returns the position in physical pixels, or an error if unrecoverable.
54 async fn compute_position(
55 &self,
56 request: PositionRequest,
57 ) -> Result<WindowPosition, HostApiError>;
58}