Skip to main content

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}