1mod events;
2mod keystroke;
3#[cfg(target_os = "macos")]
4mod mac;
5#[cfg(any(test, feature = "test"))]
6mod test;
7
8use crate::{
9 AnyWindowHandle, Bounds, FontFeatures, FontId, FontMetrics, FontStyle, FontWeight, GlyphId,
10 LineLayout, Pixels, Point, RunStyle, SharedString, Size,
11};
12use async_task::Runnable;
13use futures::channel::oneshot;
14use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
15use std::{any::Any, fmt::Debug, ops::Range, rc::Rc, sync::Arc};
16use uuid::Uuid;
17
18pub use events::*;
19pub use keystroke::*;
20#[cfg(target_os = "macos")]
21pub use mac::*;
22#[cfg(any(test, feature = "test"))]
23pub use test::*;
24
25pub trait Platform {
26 fn dispatcher(&self) -> Arc<dyn PlatformDispatcher>;
27 fn font_system(&self) -> Arc<dyn PlatformTextSystem>;
28
29 fn open_window(
30 &self,
31 handle: AnyWindowHandle,
32 options: WindowOptions,
33 ) -> Box<dyn PlatformWindow>;
34}
35
36pub trait PlatformScreen: Debug {
37 fn as_any(&self) -> &dyn Any;
38 fn bounds(&self) -> Bounds<Pixels>;
39 fn content_bounds(&self) -> Bounds<Pixels>;
40 fn display_uuid(&self) -> Option<Uuid>;
41}
42
43pub trait PlatformWindow: HasRawWindowHandle + HasRawDisplayHandle {
44 fn bounds(&self) -> WindowBounds;
45 fn content_size(&self) -> Size<Pixels>;
46 fn scale_factor(&self) -> f32;
47 fn titlebar_height(&self) -> Pixels;
48 fn appearance(&self) -> WindowAppearance;
49 fn screen(&self) -> Rc<dyn PlatformScreen>;
50 fn mouse_position(&self) -> Point<Pixels>;
51 fn as_any_mut(&mut self) -> &mut dyn Any;
52 fn set_input_handler(&mut self, input_handler: Box<dyn InputHandler>);
53 fn prompt(
54 &self,
55 level: WindowPromptLevel,
56 msg: &str,
57 answers: &[&str],
58 ) -> oneshot::Receiver<usize>;
59 fn activate(&self);
60 fn set_title(&mut self, title: &str);
61 fn set_edited(&mut self, edited: bool);
62 fn show_character_palette(&self);
63 fn minimize(&self);
64 fn zoom(&self);
65 fn toggle_full_screen(&self);
66 fn on_event(&mut self, callback: Box<dyn FnMut(Event) -> bool>);
67 fn on_active_status_change(&mut self, callback: Box<dyn FnMut(bool)>);
68 fn on_resize(&mut self, callback: Box<dyn FnMut()>);
69 fn on_fullscreen(&mut self, callback: Box<dyn FnMut(bool)>);
70 fn on_moved(&mut self, callback: Box<dyn FnMut()>);
71 fn on_should_close(&mut self, callback: Box<dyn FnMut() -> bool>);
72 fn on_close(&mut self, callback: Box<dyn FnOnce()>);
73 fn on_appearance_changed(&mut self, callback: Box<dyn FnMut()>);
74 fn is_topmost_for_position(&self, position: Point<Pixels>) -> bool;
75}
76
77pub trait PlatformDispatcher: Send + Sync {
78 fn is_main_thread(&self) -> bool;
79 fn run_on_main_thread(&self, task: Runnable);
80}
81
82pub trait PlatformTextSystem: Send + Sync {
83 fn add_fonts(&self, fonts: &[Arc<Vec<u8>>]) -> anyhow::Result<()>;
84 fn all_families(&self) -> Vec<String>;
85 fn load_family(&self, name: &str, features: &FontFeatures) -> anyhow::Result<Vec<FontId>>;
86 fn select_font(
87 &self,
88 font_ids: &[FontId],
89 weight: FontWeight,
90 style: FontStyle,
91 ) -> anyhow::Result<FontId>;
92 fn font_metrics(&self, font_id: FontId) -> FontMetrics;
93 fn typographic_bounds(
94 &self,
95 font_id: FontId,
96 glyph_id: GlyphId,
97 ) -> anyhow::Result<Bounds<Pixels>>;
98 fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> anyhow::Result<Point<Pixels>>;
99 fn glyph_for_char(&self, font_id: FontId, ch: char) -> Option<GlyphId>;
100 fn rasterize_glyph(
101 &self,
102 font_id: FontId,
103 font_size: f32,
104 glyph_id: GlyphId,
105 subpixel_shift: Point<Pixels>,
106 scale_factor: f32,
107 options: RasterizationOptions,
108 ) -> Option<(Bounds<u32>, Vec<u8>)>;
109 fn layout_line(&self, text: &str, font_size: Pixels, runs: &[(usize, RunStyle)]) -> LineLayout;
110 fn wrap_line(
111 &self,
112 text: &str,
113 font_id: FontId,
114 font_size: Pixels,
115 width: Pixels,
116 ) -> Vec<usize>;
117}
118
119pub trait InputHandler {
120 fn selected_text_range(&self) -> Option<Range<usize>>;
121 fn marked_text_range(&self) -> Option<Range<usize>>;
122 fn text_for_range(&self, range_utf16: Range<usize>) -> Option<String>;
123 fn replace_text_in_range(&mut self, replacement_range: Option<Range<usize>>, text: &str);
124 fn replace_and_mark_text_in_range(
125 &mut self,
126 range_utf16: Option<Range<usize>>,
127 new_text: &str,
128 new_selected_range: Option<Range<usize>>,
129 );
130 fn unmark_text(&mut self);
131 fn bounds_for_range(&self, range_utf16: Range<usize>) -> Option<Bounds<f32>>;
132}
133
134#[derive(Copy, Clone, Debug)]
135pub enum RasterizationOptions {
136 Alpha,
137 Bgra,
138}
139
140#[derive(Debug)]
141pub struct WindowOptions {
142 pub bounds: WindowBounds,
143 pub titlebar: Option<TitlebarOptions>,
144 pub center: bool,
145 pub focus: bool,
146 pub show: bool,
147 pub kind: WindowKind,
148 pub is_movable: bool,
149 pub screen: Option<Rc<dyn PlatformScreen>>,
150}
151
152impl Default for WindowOptions {
153 fn default() -> Self {
154 Self {
155 bounds: WindowBounds::default(),
156 titlebar: Some(TitlebarOptions {
157 title: Default::default(),
158 appears_transparent: Default::default(),
159 traffic_light_position: Default::default(),
160 }),
161 center: false,
162 focus: true,
163 show: true,
164 kind: WindowKind::Normal,
165 is_movable: true,
166 screen: None,
167 }
168 }
169}
170
171#[derive(Debug, Default)]
172pub struct TitlebarOptions {
173 pub title: Option<SharedString>,
174 pub appears_transparent: bool,
175 pub traffic_light_position: Option<Point<Pixels>>,
176}
177
178#[derive(Copy, Clone, Debug)]
179pub enum Appearance {
180 Light,
181 VibrantLight,
182 Dark,
183 VibrantDark,
184}
185
186impl Default for Appearance {
187 fn default() -> Self {
188 Self::Light
189 }
190}
191
192#[derive(Copy, Clone, Debug, PartialEq, Eq)]
193pub enum WindowKind {
194 Normal,
195 PopUp,
196}
197
198#[derive(Copy, Clone, Debug, PartialEq, Default)]
199pub enum WindowBounds {
200 Fullscreen,
201 #[default]
202 Maximized,
203 Fixed(Bounds<Pixels>),
204}
205
206#[derive(Copy, Clone, Debug)]
207pub enum WindowAppearance {
208 Light,
209 VibrantLight,
210 Dark,
211 VibrantDark,
212}
213
214impl Default for WindowAppearance {
215 fn default() -> Self {
216 Self::Light
217 }
218}
219
220#[derive(Copy, Clone, Debug, PartialEq, Default)]
221pub enum WindowPromptLevel {
222 #[default]
223 Info,
224 Warning,
225 Critical,
226}