pub struct WindowHandle(/* private fields */);
Expand description
A handle to a platform window object.
Implementations§
Source§impl WindowHandle
impl WindowHandle
Sourcepub fn show(&self)
pub fn show(&self)
Make this window visible.
Examples found in repository?
More examples
138fn main() {
139 tracing_subscriber::fmt().init();
140 let app = Application::new().unwrap();
141 let mut builder = WindowBuilder::new(app.clone());
142 let perf_test = PerfTest {
143 size: Size::ZERO,
144 handle: Default::default(),
145 start_time: time::Instant::now(),
146 last_time: time::Instant::now(),
147 red: true,
148 };
149 builder.set_handler(Box::new(perf_test));
150 builder.set_title("Performance tester");
151
152 let window = builder.build().unwrap();
153 window.show();
154
155 app.run(None);
156}
104fn main() {
105 tracing_subscriber::fmt().init();
106 let app = Application::new().unwrap();
107 let mut builder = WindowBuilder::new(app.clone());
108 let inv_test = InvalidateTest {
109 size: Size::ZERO,
110 handle: Default::default(),
111 start_time: Instant::now(),
112 rect: Rect::from_origin_size(Point::ZERO, (10.0, 20.0)),
113 cursor: Rect::from_origin_size(Point::ZERO, (2.0, 100.0)),
114 color: Color::WHITE,
115 };
116 builder.set_handler(Box::new(inv_test));
117 builder.set_title("Invalidate tester");
118
119 let window = builder.build().unwrap();
120 window.show();
121 app.run(None);
122}
69fn main() {
70 tracing_subscriber::fmt().init();
71 let app = Application::new().unwrap();
72
73 let mut file_menu = Menu::new();
74 file_menu.add_item(
75 0x100,
76 "E&xit",
77 Some(&HotKey::new(SysMods::Cmd, "q")),
78 None,
79 true,
80 );
81
82 let mut menubar = Menu::new();
83 menubar.add_dropdown(file_menu, "Application", true);
84
85 let mut builder = WindowBuilder::new(app.clone());
86 builder.set_handler(Box::<QuitState>::default());
87 builder.set_title("Quit example");
88 builder.set_menu(menubar);
89
90 let window = builder.build().unwrap();
91 window.show();
92
93 app.run(None);
94}
136fn main() {
137 tracing_subscriber::fmt().init();
138 let mut file_menu = Menu::new();
139 file_menu.add_item(
140 0x100,
141 "E&xit",
142 Some(&HotKey::new(SysMods::Cmd, "q")),
143 None,
144 true,
145 );
146 file_menu.add_item(
147 0x101,
148 "O&pen",
149 Some(&HotKey::new(SysMods::Cmd, "o")),
150 None,
151 true,
152 );
153 file_menu.add_item(
154 0x102,
155 "S&ave",
156 Some(&HotKey::new(SysMods::Cmd, "s")),
157 None,
158 true,
159 );
160 let mut menubar = Menu::new();
161 menubar.add_dropdown(Menu::new(), "Application", true);
162 menubar.add_dropdown(file_menu, "&File", true);
163
164 let app = Application::new().unwrap();
165 let mut builder = WindowBuilder::new(app.clone());
166 builder.set_handler(Box::<HelloState>::default());
167 builder.set_title("Hello example");
168 builder.set_menu(menubar);
169
170 let window = builder.build().unwrap();
171 window.show();
172
173 app.run(None);
174}
Sourcepub fn close(&self)
pub fn close(&self)
Close the window.
Examples found in repository?
More examples
109 fn command(&mut self, id: u32) {
110 match id {
111 0x100 => self.handle.close(),
112 _ => println!("unexpected id {id}"),
113 }
114 }
115
116 fn key_down(&mut self, event: KeyEvent) -> bool {
117 println!("keydown: {event:?}");
118 false
119 }
120
121 fn size(&mut self, size: Size) {
122 self.size = size;
123 }
124
125 fn request_close(&mut self) {
126 self.handle.close();
127 }
119 fn command(&mut self, id: u32) {
120 match id {
121 0x100 => {
122 self.handle.close();
123 Application::global().quit()
124 }
125 _ => println!("unexpected id {id}"),
126 }
127 }
128
129 fn key_down(&mut self, event: KeyEvent) -> bool {
130 if event.key == Key::Character("c".to_string()) {
131 // custom hotkey for pressing "c"
132 println!("user pressed c! wow! setting selection to 0");
133
134 // update internal selection state
135 self.document.borrow_mut().selection = Selection::caret(0);
136
137 // notify the OS that we've updated the selection
138 self.handle
139 .update_text_field(self.text_input_token.unwrap(), Event::SelectionChanged);
140
141 // repaint window
142 self.handle.request_anim_frame();
143
144 // return true prevents the keypress event from being handled as text input
145 return true;
146 }
147 false
148 }
149
150 fn acquire_input_lock(
151 &mut self,
152 _token: TextFieldToken,
153 _mutable: bool,
154 ) -> Box<dyn InputHandler> {
155 Box::new(AppInputHandler {
156 state: self.document.clone(),
157 window_size: self.size,
158 window_handle: self.handle.clone(),
159 })
160 }
161
162 fn release_input_lock(&mut self, _token: TextFieldToken) {
163 // no action required; this example is simple enough that this
164 // state is not actually shared.
165 }
166
167 fn size(&mut self, size: Size) {
168 self.size = size;
169 }
170
171 fn request_close(&mut self) {
172 self.handle.close();
173 }
47 fn command(&mut self, id: u32) {
48 match id {
49 0x100 => {
50 self.handle.close();
51 Application::global().quit()
52 }
53 0x101 => {
54 let options = FileDialogOptions::new().show_hidden().allowed_types(vec![
55 FileSpec::new("Rust Files", &["rs", "toml"]),
56 FileSpec::TEXT,
57 FileSpec::JPG,
58 ]);
59 self.handle.open_file(options);
60 }
61 0x102 => {
62 let options = FileDialogOptions::new().show_hidden().allowed_types(vec![
63 FileSpec::new("Rust Files", &["rs", "toml"]),
64 FileSpec::TEXT,
65 FileSpec::JPG,
66 ]);
67 self.handle.save_as(options);
68 }
69 _ => println!("unexpected id {id}"),
70 }
71 }
72
73 fn open_file(&mut self, _token: FileDialogToken, file_info: Option<FileInfo>) {
74 println!("open file result: {file_info:?}");
75 }
76
77 fn save_as(&mut self, _token: FileDialogToken, file: Option<FileInfo>) {
78 println!("save file result: {file:?}");
79 }
80
81 fn key_down(&mut self, event: KeyEvent) -> bool {
82 println!("keydown: {event:?}");
83 false
84 }
85
86 fn key_up(&mut self, event: KeyEvent) {
87 println!("keyup: {event:?}");
88 }
89
90 fn wheel(&mut self, event: &MouseEvent) {
91 println!("mouse_wheel {event:?}");
92 }
93
94 fn mouse_move(&mut self, event: &MouseEvent) {
95 self.handle.set_cursor(&Cursor::Arrow);
96 println!("mouse_move {event:?}");
97 }
98
99 fn mouse_down(&mut self, event: &MouseEvent) {
100 println!("mouse_down {event:?}");
101 }
102
103 fn mouse_up(&mut self, event: &MouseEvent) {
104 println!("mouse_up {event:?}");
105 }
106
107 fn timer(&mut self, id: TimerToken) {
108 println!("timer fired: {id:?}");
109 }
110
111 fn size(&mut self, size: Size) {
112 self.size = size;
113 }
114
115 fn got_focus(&mut self) {
116 println!("Got focus");
117 }
118
119 fn lost_focus(&mut self) {
120 println!("Lost focus");
121 }
122
123 fn request_close(&mut self) {
124 self.handle.close();
125 }
Sourcepub fn set_window_state(&mut self, state: WindowState)
pub fn set_window_state(&mut self, state: WindowState)
Sets the state of the window.
Sourcepub fn get_window_state(&self) -> WindowState
pub fn get_window_state(&self) -> WindowState
Gets the state of the window.
Sourcepub fn handle_titlebar(&self, val: bool)
pub fn handle_titlebar(&self, val: bool)
Informs the system that the current location of the mouse should be treated as part of the
window’s titlebar. This can be used to implement a custom titlebar widget. Note that
because this refers to the current location of the mouse, you should probably call this
function in response to every relevant WinHandler::mouse_move
.
This is currently only implemented on Windows and GTK.
Sourcepub fn show_titlebar(&self, show_titlebar: bool)
pub fn show_titlebar(&self, show_titlebar: bool)
Set whether the window should show titlebar.
Sourcepub fn set_position(&self, position: impl Into<Point>)
pub fn set_position(&self, position: impl Into<Point>)
Sets the position of the window.
The position is given in display points, measured relative to the parent window if there is one, or the origin of the virtual screen if there is no parent.
Sourcepub fn set_always_on_top(&self, always_on_top: bool)
pub fn set_always_on_top(&self, always_on_top: bool)
Sets whether the window is always on top of other windows.
How and if this works is system dependent, by either setting a flag, or setting the level. On Wayland systems, the user needs to manually set this in the titlebar.
Sourcepub fn set_input_region(&self, region: Option<Region>)
pub fn set_input_region(&self, region: Option<Region>)
Sets where in the window the user can interact with the program.
This enables irregularly shaped windows. For example, you can make it simply not rectangular or you can make a sub-window which can be moved even on Wayland.
The contents of region
are added together, and are specified in display points, so
you do not need to deal with scale yourself.
On GTK and Wayland, this is specified as where the user can interact with the program. On Windows, this is specified as both where you can interact, and where the window is visible. So on Windows it will hide all regions not specified. On macOS, this does nothing, but you can make the window transparent for the same effect. On Web, this does nothing.
Sourcepub fn get_position(&self) -> Point
pub fn get_position(&self) -> Point
Returns the position of the top left corner of the window.
The position is returned in display points, measured relative to the parent window if there is one, of the origin of the virtual screen if there is no parent.
Sourcepub fn content_insets(&self) -> Insets
pub fn content_insets(&self) -> Insets
Returns the insets of the window content from its position and size in display points.
This is to account for any window system provided chrome, e.g. title bars. For example, if
you want your window to have room for contents of size contents
, then you should call
WindowHandle::get_size
with an argument of (contents.to_rect() + insets).size()
,
where insets
is the return value of this function.
The details of this function are somewhat platform-dependent. For example, on Windows both the insets and the window size include the space taken up by the title bar and window decorations; on GTK neither the insets nor the window size include the title bar or window decorations.
Sourcepub fn set_size(&self, size: impl Into<Size>)
pub fn set_size(&self, size: impl Into<Size>)
Set the window’s size in display points.
The actual window size in pixels will depend on the platform DPI settings.
This should be considered a request to the platform to set the size of the window. The
platform might choose a different size depending on its DPI or other platform-dependent
configuration. To know the actual size of the window you should handle the
WinHandler::size
method.
Sourcepub fn get_size(&self) -> Size
pub fn get_size(&self) -> Size
Gets the window size, in display points.
Sourcepub fn bring_to_front_and_focus(&self)
pub fn bring_to_front_and_focus(&self)
Bring this window to the front of the window stack and give it focus.
Sourcepub fn request_anim_frame(&self)
pub fn request_anim_frame(&self)
Request that prepare_paint
and paint
be called next time there’s the opportunity to
render another frame. This differs from invalidate
and invalidate_rect
in that it
doesn’t invalidate any part of the window.
Examples found in repository?
More examples
129 fn key_down(&mut self, event: KeyEvent) -> bool {
130 if event.key == Key::Character("c".to_string()) {
131 // custom hotkey for pressing "c"
132 println!("user pressed c! wow! setting selection to 0");
133
134 // update internal selection state
135 self.document.borrow_mut().selection = Selection::caret(0);
136
137 // notify the OS that we've updated the selection
138 self.handle
139 .update_text_field(self.text_input_token.unwrap(), Event::SelectionChanged);
140
141 // repaint window
142 self.handle.request_anim_frame();
143
144 // return true prevents the keypress event from being handled as text input
145 return true;
146 }
147 false
148 }
149
150 fn acquire_input_lock(
151 &mut self,
152 _token: TextFieldToken,
153 _mutable: bool,
154 ) -> Box<dyn InputHandler> {
155 Box::new(AppInputHandler {
156 state: self.document.clone(),
157 window_size: self.size,
158 window_handle: self.handle.clone(),
159 })
160 }
161
162 fn release_input_lock(&mut self, _token: TextFieldToken) {
163 // no action required; this example is simple enough that this
164 // state is not actually shared.
165 }
166
167 fn size(&mut self, size: Size) {
168 self.size = size;
169 }
170
171 fn request_close(&mut self) {
172 self.handle.close();
173 }
174
175 fn destroy(&mut self) {
176 Application::global().quit()
177 }
178
179 fn as_any(&mut self) -> &mut dyn Any {
180 self
181 }
182}
183
184struct AppInputHandler {
185 state: Rc<RefCell<DocumentState>>,
186 window_size: Size,
187 window_handle: WindowHandle,
188}
189
190impl InputHandler for AppInputHandler {
191 fn selection(&self) -> Selection {
192 self.state.borrow().selection
193 }
194 fn composition_range(&self) -> Option<Range<usize>> {
195 self.state.borrow().composition.clone()
196 }
197 fn set_selection(&mut self, range: Selection) {
198 self.state.borrow_mut().selection = range;
199 self.window_handle.request_anim_frame();
200 }
201 fn set_composition_range(&mut self, range: Option<Range<usize>>) {
202 self.state.borrow_mut().composition = range;
203 self.window_handle.request_anim_frame();
204 }
205 fn replace_range(&mut self, range: Range<usize>, text: &str) {
206 let mut doc = self.state.borrow_mut();
207 doc.text.replace_range(range.clone(), text);
208 if doc.selection.anchor < range.start && doc.selection.active < range.start {
209 // no need to update selection
210 } else if doc.selection.anchor > range.end && doc.selection.active > range.end {
211 doc.selection.anchor -= range.len();
212 doc.selection.active -= range.len();
213 doc.selection.anchor += text.len();
214 doc.selection.active += text.len();
215 } else {
216 doc.selection.anchor = range.start + text.len();
217 doc.selection.active = range.start + text.len();
218 }
219 doc.refresh_layout();
220 doc.composition = None;
221 self.window_handle.request_anim_frame();
222 }
46 fn paint(&mut self, piet: &mut Piet, _: &Region) {
47 let rect = self.size.to_rect();
48 piet.fill(rect, &BG_COLOR);
49
50 piet.stroke(
51 Line::new((0.0, self.size.height), (self.size.width, 0.0)),
52 &FG_COLOR,
53 1.0,
54 );
55
56 let current_ns = (Instant::now() - self.start_time).whole_nanoseconds();
57 let th = ::std::f64::consts::PI * (current_ns as f64) * 2e-9;
58 let dx = 100.0 * th.sin();
59 let dy = 100.0 * th.cos();
60 piet.stroke(
61 Line::new((100.0, 100.0), (100.0 + dx, 100.0 - dy)),
62 &FG_COLOR,
63 1.0,
64 );
65
66 let now = Instant::now();
67 let msg = format!("{}ms", (now - self.last_time).whole_milliseconds());
68 self.last_time = now;
69 let layout = piet
70 .text()
71 .new_text_layout(msg)
72 .font(FontFamily::MONOSPACE, 15.0)
73 .text_color(FG_COLOR)
74 .build()
75 .unwrap();
76 piet.draw_text(&layout, (10.0, 210.0));
77
78 let msg = "VSYNC";
79 let color = if self.red { RED } else { CYAN };
80
81 let layout = piet
82 .text()
83 .new_text_layout(msg)
84 .text_color(color)
85 .font(FontFamily::MONOSPACE, 48.0)
86 .build()
87 .unwrap();
88 piet.draw_text(&layout, (10.0, 280.0));
89 self.red = !self.red;
90
91 let msg = "Hello DWrite! This is a somewhat longer string of text intended to provoke slightly longer draw times.";
92 let layout = piet
93 .text()
94 .new_text_layout(msg)
95 .font(FontFamily::MONOSPACE, 15.0)
96 .text_color(FG_COLOR)
97 .build()
98 .unwrap();
99 let dy = 15.0;
100 let x0 = 210.0;
101 let y0 = 10.0;
102 for i in 0..60 {
103 let y = y0 + (i as f64) * dy;
104 piet.draw_text(&layout, (x0, y));
105 }
106 self.handle.request_anim_frame();
107 }
Sourcepub fn invalidate(&self)
pub fn invalidate(&self)
Request invalidation of the entire window contents.
Examples found in repository?
More examples
Sourcepub fn invalidate_rect(&self, rect: Rect)
pub fn invalidate_rect(&self, rect: Rect)
Request invalidation of a region of the window.
Examples found in repository?
34 fn update_color_and_rect(&mut self) {
35 let time_since_start = (Instant::now() - self.start_time).as_millis();
36 let (r, g, b, _) = self.color.as_rgba8();
37 self.color = match (time_since_start % 2, time_since_start % 3) {
38 (0, _) => Color::rgb8(r.wrapping_add(10), g, b),
39 (_, 0) => Color::rgb8(r, g.wrapping_add(10), b),
40 (_, _) => Color::rgb8(r, g, b.wrapping_add(10)),
41 };
42
43 self.rect.x0 = (self.rect.x0 + 5.0) % self.size.width;
44 self.rect.x1 = (self.rect.x1 + 5.5) % self.size.width;
45 self.rect.y0 = (self.rect.y0 + 3.0) % self.size.height;
46 self.rect.y1 = (self.rect.y1 + 3.5) % self.size.height;
47
48 // Invalidate the old and new cursor positions.
49 self.handle.invalidate_rect(self.cursor);
50 self.cursor.x0 += 4.0;
51 self.cursor.x1 += 4.0;
52 if self.cursor.x0 > self.size.width {
53 self.cursor.x1 = self.cursor.width();
54 self.cursor.x0 = 0.0;
55 }
56 self.handle.invalidate_rect(self.cursor);
57 }
58}
59
60impl WinHandler for InvalidateTest {
61 fn connect(&mut self, handle: &WindowHandle) {
62 self.handle = handle.clone();
63 }
64
65 fn prepare_paint(&mut self) {
66 self.update_color_and_rect();
67 self.handle.invalidate_rect(self.rect);
68 }
Set the top-level menu for this window.
Sourcepub fn add_text_field(&self) -> TextFieldToken
pub fn add_text_field(&self) -> TextFieldToken
Register a new text input receiver for this window.
This method should be called any time a new editable text field is
created inside a window. Any text field with a TextFieldToken
that
has not yet been destroyed with remove_text_field
must be ready to
accept input from the platform via WinHandler::text_input
at any time,
even if it is not currently focused.
Returns the TextFieldToken
associated with this new text input.
Sourcepub fn remove_text_field(&self, token: TextFieldToken)
pub fn remove_text_field(&self, token: TextFieldToken)
Unregister a previously registered text input receiver.
If token
is the text field currently focused, the platform automatically
sets the focused field to None
.
Sourcepub fn set_focused_text_field(&self, active_field: Option<TextFieldToken>)
pub fn set_focused_text_field(&self, active_field: Option<TextFieldToken>)
Notify the platform that the focused text input receiver has changed.
This must be called any time focus changes to a different text input, or when focus switches away from a text input.
Sourcepub fn update_text_field(&self, token: TextFieldToken, update: Event)
pub fn update_text_field(&self, token: TextFieldToken, update: Event)
Notify the platform that some text input state has changed, such as the selection, contents, etc.
This method should never be called in response to edits from a
InputHandler
; only in response to changes from the application:
scrolling, remote edits, etc.
Examples found in repository?
129 fn key_down(&mut self, event: KeyEvent) -> bool {
130 if event.key == Key::Character("c".to_string()) {
131 // custom hotkey for pressing "c"
132 println!("user pressed c! wow! setting selection to 0");
133
134 // update internal selection state
135 self.document.borrow_mut().selection = Selection::caret(0);
136
137 // notify the OS that we've updated the selection
138 self.handle
139 .update_text_field(self.text_input_token.unwrap(), Event::SelectionChanged);
140
141 // repaint window
142 self.handle.request_anim_frame();
143
144 // return true prevents the keypress event from being handled as text input
145 return true;
146 }
147 false
148 }
Sourcepub fn request_timer(&self, deadline: Duration) -> TimerToken
pub fn request_timer(&self, deadline: Duration) -> TimerToken
Schedule a timer.
This causes a WinHandler::timer
call at the deadline. The
return value is a token that can be used to associate the request
with the handler call.
Note that this is not a precise timer. On Windows, the typical resolution is around 10ms. Therefore, it’s best used for things like blinking a cursor or triggering tooltips, not for anything requiring precision.
Sourcepub fn set_cursor(&mut self, cursor: &Cursor)
pub fn set_cursor(&mut self, cursor: &Cursor)
Set the cursor icon.
pub fn make_cursor(&self, desc: &CursorDesc) -> Option<Cursor>
Sourcepub fn open_file(
&mut self,
options: FileDialogOptions,
) -> Option<FileDialogToken>
pub fn open_file( &mut self, options: FileDialogOptions, ) -> Option<FileDialogToken>
Prompt the user to choose a file to open.
This won’t block immediately; the file dialog will be shown whenever control returns to
druid-shell
, and the WinHandler::open_file
method will be called when the dialog is
closed.
Examples found in repository?
47 fn command(&mut self, id: u32) {
48 match id {
49 0x100 => {
50 self.handle.close();
51 Application::global().quit()
52 }
53 0x101 => {
54 let options = FileDialogOptions::new().show_hidden().allowed_types(vec![
55 FileSpec::new("Rust Files", &["rs", "toml"]),
56 FileSpec::TEXT,
57 FileSpec::JPG,
58 ]);
59 self.handle.open_file(options);
60 }
61 0x102 => {
62 let options = FileDialogOptions::new().show_hidden().allowed_types(vec![
63 FileSpec::new("Rust Files", &["rs", "toml"]),
64 FileSpec::TEXT,
65 FileSpec::JPG,
66 ]);
67 self.handle.save_as(options);
68 }
69 _ => println!("unexpected id {id}"),
70 }
71 }
Sourcepub fn save_as(&mut self, options: FileDialogOptions) -> Option<FileDialogToken>
pub fn save_as(&mut self, options: FileDialogOptions) -> Option<FileDialogToken>
Prompt the user to choose a path for saving.
This won’t block immediately; the file dialog will be shown whenever control returns to
druid-shell
, and the WinHandler::save_as
method will be called when the dialog is
closed.
Examples found in repository?
47 fn command(&mut self, id: u32) {
48 match id {
49 0x100 => {
50 self.handle.close();
51 Application::global().quit()
52 }
53 0x101 => {
54 let options = FileDialogOptions::new().show_hidden().allowed_types(vec![
55 FileSpec::new("Rust Files", &["rs", "toml"]),
56 FileSpec::TEXT,
57 FileSpec::JPG,
58 ]);
59 self.handle.open_file(options);
60 }
61 0x102 => {
62 let options = FileDialogOptions::new().show_hidden().allowed_types(vec![
63 FileSpec::new("Rust Files", &["rs", "toml"]),
64 FileSpec::TEXT,
65 FileSpec::JPG,
66 ]);
67 self.handle.save_as(options);
68 }
69 _ => println!("unexpected id {id}"),
70 }
71 }
Display a pop-up menu at the given position.
pos
is in the coordinate space of the window.
Sourcepub fn get_idle_handle(&self) -> Option<IdleHandle>
pub fn get_idle_handle(&self) -> Option<IdleHandle>
Get a handle that can be used to schedule an idle task.
Sourcepub fn get_scale(&self) -> Result<Scale, Error>
pub fn get_scale(&self) -> Result<Scale, Error>
Get the DPI scale of the window.
The returned Scale
is a copy and thus its information will be stale after
the platform DPI changes. This means you should not stash it and rely on it later; it is
only guaranteed to be valid for the current pass of the runloop.
Trait Implementations§
Source§impl Clone for WindowHandle
impl Clone for WindowHandle
Source§fn clone(&self) -> WindowHandle
fn clone(&self) -> WindowHandle
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read more