|
1 | | -use base64::Engine; |
2 | | -use seelen_core::state::{FancyToolbarSide, HideMode, SeelenWegSide}; |
3 | | -use tauri::{WebviewWindow, Wry}; |
4 | | -use windows::Win32::{ |
5 | | - Foundation::{HWND, RECT}, |
6 | | - UI::WindowsAndMessaging::{SWP_ASYNCWINDOWPOS, SWP_NOSIZE}, |
7 | | -}; |
| 1 | +use crate::{error::Result, state::application::FULL_STATE, windows_api::monitor::Monitor}; |
8 | 2 |
|
9 | | -use crate::{ |
10 | | - app::get_app_handle, |
11 | | - error::Result, |
12 | | - log_error, |
13 | | - state::application::FULL_STATE, |
14 | | - widgets::{toolbar::FancyToolbar, webview::WebviewArgs}, |
15 | | - windows_api::{monitor::Monitor, AppBarData, WindowsApi}, |
16 | | -}; |
17 | | - |
18 | | -pub struct SeelenWeg { |
19 | | - pub window: WebviewWindow<Wry>, |
20 | | - /// This is the GUI rect of the dock, not used as webview window rect |
21 | | - pub theoretical_rect: RECT, |
22 | | - /// This is the webview/window rect |
23 | | - pub webview_rect: RECT, |
24 | | -} |
25 | | - |
26 | | -impl Drop for SeelenWeg { |
27 | | - fn drop(&mut self) { |
28 | | - log::info!("Dropping {}", self.window.label()); |
29 | | - if let Ok(hwnd) = self.hwnd() { |
30 | | - AppBarData::from_handle(hwnd).unregister_bar(); |
31 | | - } |
32 | | - log_error!(self.window.destroy()); |
33 | | - } |
34 | | -} |
| 3 | +pub struct SeelenWeg {} |
35 | 4 |
|
36 | 5 | impl SeelenWeg { |
37 | | - pub const TITLE: &'static str = "SeelenWeg"; |
38 | | - pub const TARGET: &'static str = "@seelen/weg"; |
39 | | - |
40 | | - pub fn hwnd(&self) -> Result<HWND> { |
41 | | - Ok(HWND(self.window.hwnd()?.0)) |
42 | | - } |
43 | | - |
44 | | - fn create_window(monitor_id: &str) -> Result<WebviewWindow> { |
45 | | - let manager = get_app_handle(); |
46 | | - let label = format!("{}?monitorId={}", Self::TARGET, monitor_id); |
47 | | - let args = WebviewArgs::default(); |
48 | | - |
49 | | - log::info!("Creating {label}"); |
50 | | - let label = base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(&label); |
51 | | - |
52 | | - let window = tauri::WebviewWindowBuilder::new( |
53 | | - manager, |
54 | | - label, |
55 | | - tauri::WebviewUrl::App("react/weg/index.html".into()), |
56 | | - ) |
57 | | - .title(Self::TITLE) |
58 | | - .minimizable(false) |
59 | | - .maximizable(false) |
60 | | - .closable(false) |
61 | | - .resizable(false) |
62 | | - .visible(false) |
63 | | - .decorations(false) |
64 | | - .transparent(true) |
65 | | - .shadow(false) |
66 | | - .skip_taskbar(true) |
67 | | - .always_on_top(true) |
68 | | - .data_directory(args.data_directory()) |
69 | | - .additional_browser_args(&args.to_string()) |
70 | | - .build()?; |
71 | | - |
72 | | - window.set_ignore_cursor_events(true)?; |
73 | | - Ok(window) |
74 | | - } |
75 | | - |
76 | | - pub fn new(monitor_id: &str) -> Result<Self> { |
77 | | - let weg = Self { |
78 | | - window: Self::create_window(monitor_id)?, |
79 | | - theoretical_rect: RECT::default(), |
80 | | - webview_rect: RECT::default(), |
81 | | - }; |
82 | | - SeelenWeg::hide_native_taskbar(); |
83 | | - Ok(weg) |
84 | | - } |
85 | | - |
86 | 6 | pub fn get_weg_size_on_monitor(monitor: &Monitor) -> Result<i32> { |
87 | 7 | let state = FULL_STATE.load(); |
88 | 8 | let settings: &seelen_core::state::SeelenWegSettings = &state.settings.by_widget.weg; |
89 | 9 | let total_size = (settings.total_size() as f64 * monitor.scale_factor()?) as i32; |
90 | 10 | Ok(total_size) |
91 | 11 | } |
92 | | - |
93 | | - pub fn set_position(&mut self, monitor: &Monitor) -> Result<()> { |
94 | | - let state = FULL_STATE.load(); |
95 | | - let toolbar_config = &state.settings.by_widget.fancy_toolbar; |
96 | | - let is_toolbar_enabled = state.is_bar_enabled_on_monitor(&monitor.stable_id()?); |
97 | | - |
98 | | - let settings = &state.settings.by_widget.weg; |
99 | | - |
100 | | - let hwnd = HWND(self.hwnd()?.0); |
101 | | - let monitor_info = WindowsApi::monitor_info(monitor.handle())?; |
102 | | - |
103 | | - let mut work_area = monitor_info.monitorInfo.rcMonitor; |
104 | | - if is_toolbar_enabled && toolbar_config.hide_mode != HideMode::Always { |
105 | | - let toolbar_size = FancyToolbar::get_toolbar_height_on_monitor(monitor)?; |
106 | | - match state.settings.by_widget.fancy_toolbar.position { |
107 | | - FancyToolbarSide::Top => { |
108 | | - work_area.top += toolbar_size; |
109 | | - } |
110 | | - FancyToolbarSide::Bottom => { |
111 | | - work_area.bottom -= toolbar_size; |
112 | | - } |
113 | | - } |
114 | | - } |
115 | | - |
116 | | - self.theoretical_rect = work_area; |
117 | | - self.webview_rect = work_area; |
118 | | - |
119 | | - // note: we reduce by 10px the webview size of the dock to avoid be matched as a fullscreen window |
120 | | - let dock_size = Self::get_weg_size_on_monitor(monitor)?; |
121 | | - match settings.position { |
122 | | - SeelenWegSide::Left => { |
123 | | - self.theoretical_rect.right = self.theoretical_rect.left + dock_size; |
124 | | - self.webview_rect.right = work_area.right - (work_area.right - work_area.left) / 2; |
125 | | - } |
126 | | - SeelenWegSide::Right => { |
127 | | - self.theoretical_rect.left = self.theoretical_rect.right - dock_size; |
128 | | - self.webview_rect.left = work_area.left + (work_area.right - work_area.left) / 2; |
129 | | - } |
130 | | - SeelenWegSide::Top => { |
131 | | - self.theoretical_rect.bottom = self.theoretical_rect.top + dock_size; |
132 | | - self.webview_rect.bottom = work_area.top + (work_area.bottom - work_area.top) / 2; |
133 | | - } |
134 | | - SeelenWegSide::Bottom => { |
135 | | - self.theoretical_rect.top = self.theoretical_rect.bottom - dock_size; |
136 | | - self.webview_rect.top = work_area.bottom - (work_area.bottom - work_area.top) / 2; |
137 | | - } |
138 | | - } |
139 | | - |
140 | | - let mut abd = AppBarData::from_handle(hwnd); |
141 | | - match settings.hide_mode { |
142 | | - HideMode::Never => { |
143 | | - // abd.set_edge(settings.position.into()); |
144 | | - abd.set_rect(self.theoretical_rect); |
145 | | - abd.register_as_new_bar(); |
146 | | - } |
147 | | - _ => abd.unregister_bar(), |
148 | | - }; |
149 | | - |
150 | | - // pre set position for resize in case of multiples dpi |
151 | | - WindowsApi::set_position(hwnd, None, &self.webview_rect, SWP_NOSIZE)?; |
152 | | - WindowsApi::set_position(hwnd, None, &self.webview_rect, SWP_ASYNCWINDOWPOS)?; |
153 | | - Ok(()) |
154 | | - } |
155 | | - |
156 | | - pub fn reposition_if_needed(&mut self) -> Result<()> { |
157 | | - let hwnd = self.hwnd()?; |
158 | | - if self.webview_rect == WindowsApi::get_outer_window_rect(hwnd)? { |
159 | | - return Ok(()); // position is ok no need to reposition |
160 | | - } |
161 | | - self.set_position(&Monitor::from(WindowsApi::monitor_from_window(hwnd)))?; |
162 | | - Ok(()) |
163 | | - } |
164 | 12 | } |
0 commit comments