Skip to main content

tauri_plugin_snap_layout/
lib_win_impl.rs

1use crate::desktop::Snap;
2use serde::{Deserialize, Serialize};
3use tauri::{
4    plugin::{Builder, TauriPlugin},
5    Manager, Runtime,
6};
7
8pub(crate) mod snap;
9
10#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
11pub enum SnapCursor {
12    Arrow,
13    Hand,
14}
15
16#[derive(Clone, Serialize, Deserialize)]
17pub struct SnapConfig {
18    pub button_id: String,
19    pub padding_left: i32,
20    pub padding_right: i32,
21    pub padding_top: i32,
22    pub padding_bottom: i32,
23    pub padding_all: i32,
24    pub display: bool,
25    pub debug_color: String,
26    pub cursor: SnapCursor,
27}
28
29pub struct AreaBuilder {
30    config: SnapConfig,
31}
32
33#[tauri::command(rename_all = "snake_case", name = "update_snap_bounds")]
34fn fallback_update_snap_bounds(_x: i32, _y: i32, _width: i32, _height: i32) {}
35
36#[tauri::command(rename_all = "snake_case", name = "detach_snap_bounds")]
37fn fallback_detach_snap_bounds() {}
38
39impl AreaBuilder {
40    pub fn new() -> Self {
41        Self {
42            config: SnapConfig {
43                button_id: "".into(),
44                padding_left: 0,
45                padding_right: 0,
46                padding_top: 0,
47                padding_bottom: 0,
48                padding_all: 0,
49                display: false,
50                debug_color: "rgba(196, 42, 28, 0.42)".into(),
51                cursor: SnapCursor::Arrow,
52            },
53        }
54    }
55
56    pub fn button_id(mut self, id: impl Into<String>) -> Self {
57        self.config.button_id = id.into();
58        self
59    }
60
61    pub fn padding_left(mut self, padding_left: i32) -> Self {
62        self.config.padding_left = padding_left;
63        self
64    }
65
66    pub fn padding_right(mut self, padding_right: i32) -> Self {
67        self.config.padding_right = padding_right;
68        self
69    }
70
71    pub fn padding_top(mut self, padding_top: i32) -> Self {
72        self.config.padding_top = padding_top;
73        self
74    }
75
76    pub fn padding_bottom(mut self, padding_bottom: i32) -> Self {
77        self.config.padding_bottom = padding_bottom;
78        self
79    }
80
81    pub fn padding_all(mut self, padding_all: i32) -> Self {
82        self.config.padding_all = padding_all;
83        self
84    }
85
86    pub fn display(mut self, is_display: bool) -> Self {
87        self.config.display = is_display;
88        self
89    }
90
91    pub fn debug_color(mut self, color: impl Into<String>) -> Self {
92        self.config.debug_color = color.into();
93        self
94    }
95
96    pub fn cursor(mut self, cursor: SnapCursor) -> Self {
97        self.config.cursor = cursor;
98        self
99    }
100
101    pub fn build<R: Runtime>(self) -> TauriPlugin<R> {
102        let version = windows_version::OsVersion::current();
103        if version.build < 22000 {
104            return Builder::new("snap-layout")
105                .setup(|app, _| {
106                    app.manage(Snap::new(app.clone()));
107                    Ok(())
108                })
109                .invoke_handler(tauri::generate_handler![
110                    fallback_update_snap_bounds,
111                    fallback_detach_snap_bounds
112                ])
113                .build();
114        }
115
116        let base_script = include_str!("../dist-js/inline-injection.js");
117
118        let injection_script = base_script
119            .replace(
120                "__SNAP_BUTTON_ID__",
121                &serde_json::to_string(&self.config.button_id)
122                    .unwrap_or_else(|_| "\"\"".to_string()),
123            )
124            .replace("__SNAP_DISPLAY__", &self.config.display.to_string())
125            .replace(
126                "__SNAP_DEBUG_COLOR__",
127                &serde_json::to_string(&self.config.debug_color)
128                    .unwrap_or_else(|_| "\"\"".to_string()),
129            )
130            .replace(
131                "__SNAP_PADDING_LEFT__",
132                &format!("{}", self.config.padding_left),
133            )
134            .replace(
135                "__SNAP_PADDING_RIGHT__",
136                &format!("{}", self.config.padding_right),
137            )
138            .replace(
139                "__SNAP_PADDING_TOP__",
140                &format!("{}", self.config.padding_top),
141            )
142            .replace(
143                "__SNAP_PADDING_BOTTOM__",
144                &format!("{}", self.config.padding_bottom),
145            )
146            .replace(
147                "__SNAP_PADDING_ALL__",
148                &format!("{}", self.config.padding_all),
149            );
150
151        let plugin_config = self.config.clone();
152
153        Builder::new("snap-layout")
154            .setup(move |app, _| {
155                app.manage(Snap::new(app.clone()));
156                app.manage(plugin_config);
157                Ok(())
158            })
159            .invoke_handler(tauri::generate_handler![
160                snap::update_snap_bounds,
161                snap::detach_snap_bounds
162            ])
163            .js_init_script(injection_script)
164            .build()
165    }
166}