iced_runtime/window.rs
1//! Build window-based GUI applications.
2use crate::core::time::Instant;
3use crate::core::window::{
4 AppCommands, Direction, Event, Icon, Id, Identity, Level, Mode, Screenshot, Settings,
5 UserAttention,
6};
7use crate::core::{Point, Size};
8use crate::futures::Subscription;
9use crate::futures::event;
10use crate::futures::futures::channel::oneshot;
11use crate::task::{self, Task};
12
13pub use raw_window_handle;
14
15use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
16
17/// An operation to be performed on some window.
18pub enum Action {
19 /// Open a new window with some [`Settings`].
20 Open(Id, Settings, oneshot::Sender<Id>),
21
22 /// Close the window and exits the application.
23 Close(Id),
24
25 /// Gets the [`Id`] of the oldest window.
26 GetOldest(oneshot::Sender<Option<Id>>),
27
28 /// Gets the [`Id`] of the latest window.
29 GetLatest(oneshot::Sender<Option<Id>>),
30
31 /// Move the window with the left mouse button until the button is
32 /// released.
33 ///
34 /// There's no guarantee that this will work unless the left mouse
35 /// button was pressed immediately before this function is called.
36 Drag(Id),
37
38 /// Resize the window with the left mouse button until the button is
39 /// released.
40 ///
41 /// There's no guarantee that this will work unless the left mouse
42 /// button was pressed immediately before this function is called.
43 DragResize(Id, Direction),
44
45 /// Resize the window to the given logical dimensions.
46 Resize(Id, Size),
47
48 /// Resize the window with animation (COSMIC compositor protocol).
49 /// Parameters are (id, width, height, duration_ms).
50 AnimatedResize(Id, u32, u32, u32),
51
52 /// Resize the window with animation and explicit position (COSMIC compositor protocol).
53 /// Parameters are (id, x, y, width, height, duration_ms).
54 /// If the window is maximized, the position and size will be stored and used when restored.
55 AnimatedResizeWithPosition(Id, i32, i32, u32, u32, u32),
56
57 /// Embed a toplevel by process ID into the window's surface (COSMIC compositor protocol).
58 /// Parameters are (window_id, pid, app_id, x, y, width, height, interactive, result_sender).
59 /// Returns the embed ID via the sender, or None if the protocol is not available.
60 EmbedToplevelByPid(
61 Id,
62 u32,
63 String,
64 i32,
65 i32,
66 i32,
67 i32,
68 bool,
69 oneshot::Sender<Option<u64>>,
70 ),
71
72 /// Update the geometry of an embedded surface (COSMIC compositor protocol).
73 /// Parameters are (window_id, embed_id, x, y, width, height).
74 SetEmbedGeometry(Id, u64, i32, i32, i32, i32),
75
76 /// Set anchor-based positioning for an embedded surface (COSMIC compositor protocol).
77 /// Parameters are (window_id, embed_id, anchor, margin_top, margin_right, margin_bottom, margin_left, width, height).
78 /// Anchor is a bitfield: 0=none, 1=top, 2=bottom, 4=left, 8=right.
79 SetEmbedAnchor(Id, u64, u32, i32, i32, i32, i32, i32, i32),
80
81 /// Set corner radius for an embedded surface (COSMIC compositor protocol).
82 /// Parameters are (window_id, embed_id, top_left, top_right, bottom_right, bottom_left).
83 SetEmbedCornerRadius(Id, u64, u32, u32, u32, u32),
84
85 /// Set interactivity for an embedded surface (COSMIC compositor protocol).
86 /// Parameters are (window_id, embed_id, interactive).
87 SetEmbedInteractive(Id, u64, bool),
88
89 /// Remove an embedded surface (COSMIC compositor protocol).
90 /// Parameters are (window_id, embed_id).
91 RemoveEmbed(Id, u64),
92
93 /// Get the current logical dimensions of the window.
94 GetSize(Id, oneshot::Sender<Size>),
95
96 /// Gets the complete compositor-authenticated identity, if available.
97 GetIdentity(Id, oneshot::Sender<Option<Identity>>),
98
99 /// Get if the current window is maximized or not.
100 GetMaximized(Id, oneshot::Sender<bool>),
101
102 /// Set the window to maximized or back
103 Maximize(Id, bool),
104
105 /// Get if the current window is minimized or not.
106 ///
107 /// ## Platform-specific
108 /// - **Wayland:** Always `None`.
109 GetMinimized(Id, oneshot::Sender<Option<bool>>),
110
111 /// Set the window to minimized or back
112 Minimize(Id, bool),
113
114 /// Get the current logical coordinates of the window.
115 GetPosition(Id, oneshot::Sender<Option<Point>>),
116
117 /// Get the current scale factor (DPI) of the window.
118 GetScaleFactor(Id, oneshot::Sender<f32>),
119
120 /// Move the window to the given logical coordinates.
121 ///
122 /// Unsupported on Wayland.
123 Move(Id, Point),
124
125 /// Change the [`Mode`] of the window.
126 SetMode(Id, Mode),
127
128 /// Get the current [`Mode`] of the window.
129 GetMode(Id, oneshot::Sender<Mode>),
130
131 /// Toggle the window to maximized or back
132 ToggleMaximize(Id),
133
134 /// Toggle whether window has decorations.
135 ///
136 /// ## Platform-specific
137 /// - **X11:** Not implemented.
138 /// - **Web:** Unsupported.
139 ToggleDecorations(Id),
140
141 /// Request user attention to the window, this has no effect if the application
142 /// is already focused. How requesting for user attention manifests is platform dependent,
143 /// see [`UserAttention`] for details.
144 ///
145 /// Providing `None` will unset the request for user attention. Unsetting the request for
146 /// user attention might not be done automatically by the WM when the window receives input.
147 ///
148 /// ## Platform-specific
149 ///
150 /// - **iOS / Android / Web:** Unsupported.
151 /// - **macOS:** `None` has no effect.
152 /// - **X11:** Requests for user attention must be manually cleared.
153 /// - **Wayland:** Requires `xdg_activation_v1` protocol, `None` has no effect.
154 RequestUserAttention(Id, Option<UserAttention>),
155
156 /// Bring the window to the front and sets input focus. Has no effect if the window is
157 /// already in focus, minimized, or not visible.
158 ///
159 /// This method steals input focus from other applications. Do not use this method unless
160 /// you are certain that's what the user wants. Focus stealing can cause an extremely disruptive
161 /// user experience.
162 ///
163 /// ## Platform-specific
164 ///
165 /// - **Web / Wayland:** Unsupported.
166 GainFocus(Id),
167
168 /// Inhibit (or release) the compositor's global keyboard shortcuts for the
169 /// window, so it receives reserved combos (e.g. Super) for key capture.
170 ///
171 /// - **Wayland:** uses `zwp_keyboard_shortcuts_inhibit`.
172 /// - **Other platforms:** no-op.
173 SetKeyboardShortcutsInhibit(Id, bool),
174
175 /// Change the window [`Level`].
176 SetLevel(Id, Level),
177
178 /// Show the system menu at cursor position.
179 ///
180 /// ## Platform-specific
181 /// Android / iOS / macOS / Orbital / Web / X11: Unsupported.
182 ShowSystemMenu(Id),
183
184 /// Get the raw identifier unique to the window.
185 GetRawId(Id, oneshot::Sender<u64>),
186
187 /// Change the window [`Icon`].
188 ///
189 /// On Windows and X11, this is typically the small icon in the top-left
190 /// corner of the titlebar.
191 ///
192 /// ## Platform-specific
193 ///
194 /// - **Web / Wayland / macOS:** Unsupported.
195 ///
196 /// - **Windows:** Sets `ICON_SMALL`. The base size for a window icon is 16x16, but it's
197 /// recommended to account for screen scaling and pick a multiple of that, i.e. 32x32.
198 ///
199 /// - **X11:** Has no universal guidelines for icon sizes, so you're at the whims of the WM. That
200 /// said, it's usually in the same ballpark as on Windows.
201 SetIcon(Id, Icon),
202
203 /// Runs the closure with a reference to the [`Window`] with the given [`Id`].
204 Run(Id, Box<dyn FnOnce(&dyn Window) + Send>),
205
206 /// Screenshot the viewport of the window.
207 Screenshot(Id, oneshot::Sender<Screenshot>),
208
209 /// Enable mouse passthrough for the given window.
210 ///
211 /// This disables mouse events for the window and passes mouse events
212 /// through to whatever window is underneath.
213 EnableMousePassthrough(Id),
214
215 /// Disable mouse passthrough for the given window.
216 ///
217 /// This enables mouse events for the window and stops mouse events
218 /// from being passed to whatever is underneath.
219 DisableMousePassthrough(Id),
220
221 /// Set the minimum inner window size.
222 SetMinSize(Id, Option<Size>),
223
224 /// Set the maximum inner window size.
225 SetMaxSize(Id, Option<Size>),
226
227 /// Set the window to be resizable or not.
228 SetResizable(Id, bool),
229
230 /// Set the window size increment.
231 SetResizeIncrements(Id, Option<Size>),
232
233 /// Get the logical dimensions of the monitor containing the window with the given [`Id`].
234 GetMonitorSize(Id, oneshot::Sender<Option<Size>>),
235
236 /// Set whether the system can automatically organize windows into tabs.
237 ///
238 /// See <https://developer.apple.com/documentation/appkit/nswindow/1646657-allowsautomaticwindowtabbing>
239 SetAllowAutomaticTabbing(bool),
240
241 /// Redraw all the windows.
242 RedrawAll,
243
244 /// Recompute the layouts of all the windows.
245 RelayoutAll,
246
247 /// Set corner radius for the window (COSMIC compositor protocol).
248 /// Communicates corner radius hints to the compositor for blur outlines and rounded corners.
249 /// Parameters are (window_id, top_left, top_right, bottom_right, bottom_left).
250 SetCornerRadius(Id, u32, u32, u32, u32),
251
252 /// Set a compositor-rendered backdrop color for the window.
253 /// The compositor renders a colored rectangle behind the window content,
254 /// respecting the window's corner radius.
255 /// Parameters are (window_id, r, g, b, a) where each component is 0-255.
256 SetBackdropColor(Id, u32, u32, u32, u32),
257
258 /// Enable or disable blur behind the window at runtime.
259 SetBlur(Id, bool),
260
261 /// Register the window to receive the device's special key.
262 /// Parameters are (window_id, is_default_receiver).
263 RegisterSpecialAction(Id, bool),
264
265 /// Stop receiving the device's special key.
266 UnregisterSpecialAction(Id),
267
268 /// Get whether Kora's Halo has a drag strip over the window's top edge.
269 GetHaloHeaderOverlay(Id, oneshot::Sender<bool>),
270
271 /// Publish the window's commands to the shell, replacing what it published.
272 SetAppCommands(Id, AppCommands),
273
274 /// Ask the shell for the window's command palette.
275 RequestAppPalette(Id),
276}
277
278/// A window managed by iced.
279///
280/// It implements both [`HasWindowHandle`] and [`HasDisplayHandle`].
281pub trait Window: HasWindowHandle + HasDisplayHandle {}
282
283impl<T> Window for T where T: HasWindowHandle + HasDisplayHandle {}
284
285/// Subscribes to the frames of the window of the running application.
286///
287/// The resulting [`Subscription`] will produce items at a rate equal to the
288/// refresh rate of the first application window. Note that this rate may be variable, as it is
289/// normally managed by the graphics driver and/or the OS.
290///
291/// In any case, this [`Subscription`] is useful to smoothly draw application-driven
292/// animations without missing any frames.
293pub fn frames() -> Subscription<Instant> {
294 event::listen_raw(|event, _status, _window| match event {
295 crate::core::Event::Window(Event::RedrawRequested(at)) => Some(at),
296 _ => None,
297 })
298}
299
300/// Subscribes to all window events of the running application.
301pub fn events() -> Subscription<(Id, Event)> {
302 event::listen_with(|event, _status, id| {
303 if let crate::core::Event::Window(event) = event {
304 Some((id, event))
305 } else {
306 None
307 }
308 })
309}
310
311/// Subscribes to all [`Event::Opened`] occurrences in the running application.
312pub fn open_events() -> Subscription<Id> {
313 event::listen_with(|event, _status, id| {
314 if let crate::core::Event::Window(Event::Opened { .. }) = event {
315 Some(id)
316 } else {
317 None
318 }
319 })
320}
321
322/// Subscribes to all [`Event::Closed`] occurrences in the running application.
323pub fn close_events() -> Subscription<Id> {
324 event::listen_with(|event, _status, id| {
325 if let crate::core::Event::Window(Event::Closed) = event {
326 Some(id)
327 } else {
328 None
329 }
330 })
331}
332
333/// Subscribes to all [`Event::Resized`] occurrences in the running application.
334pub fn resize_events() -> Subscription<(Id, Size)> {
335 event::listen_with(|event, _status, id| {
336 if let crate::core::Event::Window(Event::Resized(size)) = event {
337 Some((id, size))
338 } else {
339 None
340 }
341 })
342}
343
344/// Subscribes to all [`Event::CloseRequested`] occurrences in the running application.
345pub fn close_requests() -> Subscription<Id> {
346 event::listen_with(|event, _status, id| {
347 if let crate::core::Event::Window(Event::CloseRequested) = event {
348 Some(id)
349 } else {
350 None
351 }
352 })
353}
354
355/// Registers the window to receive the device's special key.
356///
357/// The compositor resolves the gesture and delivers it as
358/// [`Event::SpecialAction`](crate::core::Event::SpecialAction): a tap asks the
359/// window to focus its input, a hold brackets push-to-talk.
360///
361/// When `is_default_receiver` the window also becomes the fallback, used
362/// whenever no registered surface is focused. Only one fallback exists at a
363/// time; registering a second replaces the first.
364///
365/// ## Platform-specific
366/// - **COSMIC/Wayland:** Uses the `zcosmic_special_action_v1` protocol.
367/// - **Other platforms:** No effect.
368pub fn register_special_action<T>(id: Id, is_default_receiver: bool) -> Task<T> {
369 task::effect(crate::Action::Window(Action::RegisterSpecialAction(
370 id,
371 is_default_receiver,
372 )))
373}
374
375/// Stops the window receiving the device's special key.
376///
377/// ## Platform-specific
378/// - **COSMIC/Wayland:** Uses the `zcosmic_special_action_v1` protocol.
379/// - **Other platforms:** No effect.
380pub fn unregister_special_action<T>(id: Id) -> Task<T> {
381 task::effect(crate::Action::Window(Action::UnregisterSpecialAction(id)))
382}
383
384/// Gets whether Kora's Halo has a drag strip over the window's top edge, so the
385/// window must keep its own controls clear of it.
386///
387/// `true` only for a window opened with `PlatformSpecific::halo_header_overlay`
388/// on a compositor that offers `kora_halo_header_manager_v1`; otherwise nothing
389/// of the Halo reaches into the window, which it floats above, outside the
390/// window's geometry. Fixed once the window is open.
391///
392/// ## Platform-specific
393/// - **Kora/Wayland:** Uses the `kora_halo_header_manager_v1` protocol.
394/// - **Other platforms:** Always `false`.
395pub fn is_halo_header_overlay(id: Id) -> Task<bool> {
396 task::oneshot(move |channel| crate::Action::Window(Action::GetHaloHeaderOverlay(id, channel)))
397}
398
399/// Gets the complete compositor-authenticated identity for this window.
400///
401/// Returns `None` before it arrives, after revocation, for a closed window, or
402/// on an unsupported platform. An empty workspace in an existing identity
403/// explicitly means the machine plane. Subscribe to [`Event::IdentityChanged`]
404/// and [`Event::Closed`] to invalidate cached attribution.
405pub fn get_identity(id: Id) -> Task<Option<Identity>> {
406 task::oneshot(move |channel| crate::Action::Window(Action::GetIdentity(id, channel)))
407}
408
409/// Publishes the window's commands and recent items to the shell, replacing
410/// what it published before.
411///
412/// The shell lists them in its own menus and palette, and sends
413/// [`Event::AppCommand`] back when one is picked. Publish again whenever the
414/// set, a command's availability or the recent items change.
415///
416/// ## Platform-specific
417/// - **Kora/Wayland:** Uses the `kora_app_commands_v1` protocol.
418/// - **Other platforms:** No effect.
419pub fn set_app_commands<T>(id: Id, commands: AppCommands) -> Task<T> {
420 task::effect(crate::Action::Window(Action::SetAppCommands(id, commands)))
421}
422
423/// Asks the shell to open its command palette for the window, as the window's
424/// own shortcut for it. Ignored unless the window has keyboard focus.
425///
426/// ## Platform-specific
427/// - **Kora/Wayland:** Uses the `kora_app_commands_v1` protocol.
428/// - **Other platforms:** No effect.
429pub fn request_app_palette<T>(id: Id) -> Task<T> {
430 task::effect(crate::Action::Window(Action::RequestAppPalette(id)))
431}
432
433/// Opens a new window with the given [`Settings`]; producing the [`Id`]
434/// of the new window on completion.
435pub fn open(settings: Settings) -> (Id, Task<Id>) {
436 let id = Id::unique();
437
438 (
439 id,
440 task::oneshot(|channel| crate::Action::Window(Action::Open(id, settings, channel))),
441 )
442}
443
444/// Closes the window with `id`.
445pub fn close<T>(id: Id) -> Task<T> {
446 task::effect(crate::Action::Window(Action::Close(id)))
447}
448
449/// Gets the window [`Id`] of the oldest window.
450pub fn oldest() -> Task<Option<Id>> {
451 task::oneshot(|channel| crate::Action::Window(Action::GetOldest(channel)))
452}
453
454/// Gets the window [`Id`] of the latest window.
455pub fn latest() -> Task<Option<Id>> {
456 task::oneshot(|channel| crate::Action::Window(Action::GetLatest(channel)))
457}
458
459/// Begins dragging the window while the left mouse button is held.
460pub fn drag<T>(id: Id) -> Task<T> {
461 task::effect(crate::Action::Window(Action::Drag(id)))
462}
463
464/// Begins resizing the window while the left mouse button is held.
465pub fn drag_resize<T>(id: Id, direction: Direction) -> Task<T> {
466 task::effect(crate::Action::Window(Action::DragResize(id, direction)))
467}
468
469/// Resizes the window to the given logical dimensions.
470pub fn resize<T>(id: Id, new_size: Size) -> Task<T> {
471 task::effect(crate::Action::Window(Action::Resize(id, new_size)))
472}
473
474/// Resizes the window with animation using the COSMIC animated resize protocol.
475///
476/// This requests the compositor to smoothly animate the window from its current
477/// size to the target size over the specified duration.
478///
479/// ## Platform-specific
480/// - **COSMIC/Wayland:** Uses `zcosmic_animated_resize_v1` protocol.
481/// - **Other platforms:** Falls back to instant resize.
482pub fn animated_resize<T>(id: Id, width: u32, height: u32, duration_ms: u32) -> Task<T> {
483 task::effect(crate::Action::Window(Action::AnimatedResize(
484 id,
485 width,
486 height,
487 duration_ms,
488 )))
489}
490
491/// Resizes the window with animation and explicit position using the COSMIC animated resize protocol.
492///
493/// This requests the compositor to smoothly animate the window from its current
494/// geometry to the target position and size over the specified duration.
495///
496/// If the window is maximized, the position and size will be stored and used
497/// when the window is restored to normal state.
498///
499/// ## Platform-specific
500/// - **COSMIC/Wayland:** Uses `zcosmic_animated_resize_v1` protocol.
501/// - **Other platforms:** Falls back to instant resize (position ignored).
502pub fn animated_resize_with_position<T>(
503 id: Id,
504 x: i32,
505 y: i32,
506 width: u32,
507 height: u32,
508 duration_ms: u32,
509) -> Task<T> {
510 task::effect(crate::Action::Window(Action::AnimatedResizeWithPosition(
511 id,
512 x,
513 y,
514 width,
515 height,
516 duration_ms,
517 )))
518}
519
520/// Embed a toplevel by process ID into this window's surface.
521///
522/// This uses the `zcosmic_surface_embed_manager_v1` protocol to embed a
523/// foreign toplevel window within this window's surface. The compositor
524/// will monitor for new toplevels from the specified PID and embed the
525/// first matching one.
526///
527/// Returns a [`Task`] that resolves to the embed ID (which can be used to
528/// update geometry or remove the embed), or `None` if the protocol is not
529/// available.
530///
531/// ## Platform-specific
532/// - **COSMIC/Wayland:** Uses `zcosmic_surface_embed_manager_v1` protocol.
533/// - **Other platforms:** Always returns `None`.
534///
535/// # Arguments
536/// * `id` - Window ID to embed into
537/// * `pid` - Process ID of the application to embed
538/// * `app_id` - Optional app_id hint for verification (can be empty)
539/// * `x` - X position within this window's surface
540/// * `y` - Y position within this window's surface
541/// * `width` - Width of the embed region
542/// * `height` - Height of the embed region
543/// * `interactive` - Whether input should be routed to the embedded surface
544#[allow(clippy::too_many_arguments)]
545pub fn embed_toplevel_by_pid(
546 id: Id,
547 pid: u32,
548 app_id: impl Into<String>,
549 x: i32,
550 y: i32,
551 width: i32,
552 height: i32,
553 interactive: bool,
554) -> Task<Option<u64>> {
555 task::oneshot(move |channel| {
556 crate::Action::Window(Action::EmbedToplevelByPid(
557 id,
558 pid,
559 app_id.into(),
560 x,
561 y,
562 width,
563 height,
564 interactive,
565 channel,
566 ))
567 })
568}
569
570/// Update the geometry of an embedded surface.
571///
572/// ## Platform-specific
573/// - **COSMIC/Wayland:** Uses `zcosmic_surface_embed_manager_v1` protocol.
574/// - **Other platforms:** No-op.
575pub fn set_embed_geometry<T>(
576 id: Id,
577 embed_id: u64,
578 x: i32,
579 y: i32,
580 width: i32,
581 height: i32,
582) -> Task<T> {
583 task::effect(crate::Action::Window(Action::SetEmbedGeometry(
584 id, embed_id, x, y, width, height,
585 )))
586}
587
588/// Set anchor-based positioning for an embedded surface.
589///
590/// Instead of specifying absolute (x, y) coordinates, this allows
591/// positioning relative to the parent window edges. The geometry is
592/// automatically recalculated by the compositor when the parent window resizes.
593///
594/// # Arguments
595/// * `id` - The parent window ID
596/// * `embed_id` - The embedded surface ID
597/// * `anchor` - Bitflags indicating which edges to anchor to:
598/// - 0: none (use absolute positioning)
599/// - 1: top
600/// - 2: bottom
601/// - 4: left
602/// - 8: right
603/// - Combinations like 9 (top | right) are valid
604/// * `margin_top` - Margin from top edge (when anchored to top)
605/// * `margin_right` - Margin from right edge (when anchored to right)
606/// * `margin_bottom` - Margin from bottom edge (when anchored to bottom)
607/// * `margin_left` - Margin from left edge (when anchored to left)
608/// * `width` - Width of embed region (0 to stretch between left/right anchors)
609/// * `height` - Height of embed region (0 to stretch between top/bottom anchors)
610///
611/// ## Platform-specific
612/// - **COSMIC/Wayland:** Uses `zcosmic_surface_embed_manager_v1` protocol.
613/// - **Other platforms:** No-op.
614pub fn set_embed_anchor<T>(
615 id: Id,
616 embed_id: u64,
617 anchor: u32,
618 margin_top: i32,
619 margin_right: i32,
620 margin_bottom: i32,
621 margin_left: i32,
622 width: i32,
623 height: i32,
624) -> Task<T> {
625 task::effect(crate::Action::Window(Action::SetEmbedAnchor(
626 id,
627 embed_id,
628 anchor,
629 margin_top,
630 margin_right,
631 margin_bottom,
632 margin_left,
633 width,
634 height,
635 )))
636}
637
638/// Set corner radius for an embedded surface.
639///
640/// This allows the parent to specify rounded corners that match its own UI.
641/// Each corner can have a different radius. Values are in logical pixels.
642/// A value of 0 means no rounding for that corner.
643///
644/// ## Platform-specific
645/// - **COSMIC/Wayland:** Uses `zcosmic_surface_embed_manager_v1` protocol.
646/// - **Other platforms:** No-op.
647pub fn set_embed_corner_radius<T>(
648 id: Id,
649 embed_id: u64,
650 top_left: u32,
651 top_right: u32,
652 bottom_right: u32,
653 bottom_left: u32,
654) -> Task<T> {
655 task::effect(crate::Action::Window(Action::SetEmbedCornerRadius(
656 id,
657 embed_id,
658 top_left,
659 top_right,
660 bottom_right,
661 bottom_left,
662 )))
663}
664
665/// Set interactivity for an embedded surface.
666///
667/// When interactive, pointer/keyboard/touch events within the embed
668/// region will be routed to the embedded toplevel.
669///
670/// ## Platform-specific
671/// - **COSMIC/Wayland:** Uses `zcosmic_surface_embed_manager_v1` protocol.
672/// - **Other platforms:** No-op.
673pub fn set_embed_interactive<T>(id: Id, embed_id: u64, interactive: bool) -> Task<T> {
674 task::effect(crate::Action::Window(Action::SetEmbedInteractive(
675 id,
676 embed_id,
677 interactive,
678 )))
679}
680
681/// Remove an embedded surface.
682///
683/// ## Platform-specific
684/// - **COSMIC/Wayland:** Uses `zcosmic_surface_embed_manager_v1` protocol.
685/// - **Other platforms:** No-op.
686pub fn remove_embed<T>(id: Id, embed_id: u64) -> Task<T> {
687 task::effect(crate::Action::Window(Action::RemoveEmbed(id, embed_id)))
688}
689
690/// Set the window to be resizable or not.
691pub fn set_resizable<T>(id: Id, resizable: bool) -> Task<T> {
692 task::effect(crate::Action::Window(Action::SetResizable(id, resizable)))
693}
694
695/// Set the inner maximum size of the window.
696pub fn set_max_size<T>(id: Id, size: Option<Size>) -> Task<T> {
697 task::effect(crate::Action::Window(Action::SetMaxSize(id, size)))
698}
699
700/// Set the inner minimum size of the window.
701pub fn set_min_size<T>(id: Id, size: Option<Size>) -> Task<T> {
702 task::effect(crate::Action::Window(Action::SetMinSize(id, size)))
703}
704
705/// Set the window size increment.
706///
707/// This is usually used by apps such as terminal emulators that need "blocky" resizing.
708pub fn set_resize_increments<T>(id: Id, increments: Option<Size>) -> Task<T> {
709 task::effect(crate::Action::Window(Action::SetResizeIncrements(
710 id, increments,
711 )))
712}
713
714/// Gets the window size in logical dimensions.
715pub fn size(id: Id) -> Task<Size> {
716 task::oneshot(move |channel| crate::Action::Window(Action::GetSize(id, channel)))
717}
718
719/// Gets the maximized state of the window with the given [`Id`].
720pub fn is_maximized(id: Id) -> Task<bool> {
721 task::oneshot(move |channel| crate::Action::Window(Action::GetMaximized(id, channel)))
722}
723
724/// Maximizes the window.
725pub fn maximize<T>(id: Id, maximized: bool) -> Task<T> {
726 task::effect(crate::Action::Window(Action::Maximize(id, maximized)))
727}
728
729/// Gets the minimized state of the window with the given [`Id`].
730pub fn is_minimized(id: Id) -> Task<Option<bool>> {
731 task::oneshot(move |channel| crate::Action::Window(Action::GetMinimized(id, channel)))
732}
733
734/// Minimizes the window.
735pub fn minimize<T>(id: Id, minimized: bool) -> Task<T> {
736 task::effect(crate::Action::Window(Action::Minimize(id, minimized)))
737}
738
739/// Gets the position in logical coordinates of the window with the given [`Id`].
740pub fn position(id: Id) -> Task<Option<Point>> {
741 task::oneshot(move |channel| crate::Action::Window(Action::GetPosition(id, channel)))
742}
743
744/// Gets the scale factor of the window with the given [`Id`].
745pub fn scale_factor(id: Id) -> Task<f32> {
746 task::oneshot(move |channel| crate::Action::Window(Action::GetScaleFactor(id, channel)))
747}
748
749/// Moves the window to the given logical coordinates.
750pub fn move_to<T>(id: Id, position: Point) -> Task<T> {
751 task::effect(crate::Action::Window(Action::Move(id, position)))
752}
753
754/// Gets the current [`Mode`] of the window.
755pub fn mode(id: Id) -> Task<Mode> {
756 task::oneshot(move |channel| crate::Action::Window(Action::GetMode(id, channel)))
757}
758
759/// Changes the [`Mode`] of the window.
760pub fn set_mode<T>(id: Id, mode: Mode) -> Task<T> {
761 task::effect(crate::Action::Window(Action::SetMode(id, mode)))
762}
763
764/// Toggles the window to maximized or back.
765pub fn toggle_maximize<T>(id: Id) -> Task<T> {
766 task::effect(crate::Action::Window(Action::ToggleMaximize(id)))
767}
768
769/// Toggles the window decorations.
770pub fn toggle_decorations<T>(id: Id) -> Task<T> {
771 task::effect(crate::Action::Window(Action::ToggleDecorations(id)))
772}
773
774/// Requests user attention to the window. This has no effect if the application
775/// is already focused. How requesting for user attention manifests is platform dependent,
776/// see [`UserAttention`] for details.
777///
778/// Providing `None` will unset the request for user attention. Unsetting the request for
779/// user attention might not be done automatically by the WM when the window receives input.
780pub fn request_user_attention<T>(id: Id, user_attention: Option<UserAttention>) -> Task<T> {
781 task::effect(crate::Action::Window(Action::RequestUserAttention(
782 id,
783 user_attention,
784 )))
785}
786
787/// Brings the window to the front and sets input focus. Has no effect if the window is
788/// already in focus, minimized, or not visible.
789///
790/// This [`Task`] steals input focus from other applications. Do not use this method unless
791/// you are certain that's what the user wants. Focus stealing can cause an extremely disruptive
792/// user experience.
793pub fn gain_focus<T>(id: Id) -> Task<T> {
794 task::effect(crate::Action::Window(Action::GainFocus(id)))
795}
796
797/// Inhibit (or release) the compositor's global keyboard shortcuts for a window.
798///
799/// While inhibited, the compositor delivers **all** key events — including its own
800/// reserved combos such as `Super` — to the window. Use this around a key-capture /
801/// shortcut-recording session and release it as soon as capture ends.
802///
803/// **Wayland-only** (`zwp_keyboard_shortcuts_inhibit`); a no-op on other platforms.
804pub fn set_keyboard_shortcuts_inhibit<T>(id: Id, inhibit: bool) -> Task<T> {
805 task::effect(crate::Action::Window(Action::SetKeyboardShortcutsInhibit(
806 id, inhibit,
807 )))
808}
809
810/// Changes the window [`Level`].
811pub fn set_level<T>(id: Id, level: Level) -> Task<T> {
812 task::effect(crate::Action::Window(Action::SetLevel(id, level)))
813}
814
815/// Shows the [system menu] at cursor position.
816///
817/// [system menu]: https://en.wikipedia.org/wiki/Common_menus_in_Microsoft_Windows#System_menu
818pub fn show_system_menu<T>(id: Id) -> Task<T> {
819 task::effect(crate::Action::Window(Action::ShowSystemMenu(id)))
820}
821
822/// Gets an identifier unique to the window, provided by the underlying windowing system. This is
823/// not to be confused with [`Id`].
824pub fn raw_id<Message>(id: Id) -> Task<u64> {
825 task::oneshot(|channel| crate::Action::Window(Action::GetRawId(id, channel)))
826}
827
828/// Changes the [`Icon`] of the window.
829pub fn set_icon<T>(id: Id, icon: Icon) -> Task<T> {
830 task::effect(crate::Action::Window(Action::SetIcon(id, icon)))
831}
832
833/// Runs the given callback with a reference to the [`Window`] with the given [`Id`].
834///
835/// Note that if the window closes before this call is processed the callback will not be run.
836pub fn run<T>(id: Id, f: impl FnOnce(&dyn Window) -> T + Send + 'static) -> Task<T>
837where
838 T: Send + 'static,
839{
840 task::oneshot(move |channel| {
841 crate::Action::Window(Action::Run(
842 id,
843 Box::new(move |handle| {
844 let _ = channel.send(f(handle));
845 }),
846 ))
847 })
848}
849
850/// Captures a [`Screenshot`] from the window.
851pub fn screenshot(id: Id) -> Task<Screenshot> {
852 task::oneshot(move |channel| crate::Action::Window(Action::Screenshot(id, channel)))
853}
854
855/// Enables mouse passthrough for the given window.
856///
857/// This disables mouse events for the window and passes mouse events
858/// through to whatever window is underneath.
859pub fn enable_mouse_passthrough<Message>(id: Id) -> Task<Message> {
860 task::effect(crate::Action::Window(Action::EnableMousePassthrough(id)))
861}
862
863/// Disables mouse passthrough for the given window.
864///
865/// This enables mouse events for the window and stops mouse events
866/// from being passed to whatever is underneath.
867pub fn disable_mouse_passthrough<Message>(id: Id) -> Task<Message> {
868 task::effect(crate::Action::Window(Action::DisableMousePassthrough(id)))
869}
870
871/// Gets the logical dimensions of the monitor containing the window with the given [`Id`].
872pub fn monitor_size(id: Id) -> Task<Option<Size>> {
873 task::oneshot(move |channel| crate::Action::Window(Action::GetMonitorSize(id, channel)))
874}
875
876/// Sets whether the system can automatically organize windows into tabs.
877///
878/// See <https://developer.apple.com/documentation/appkit/nswindow/1646657-allowsautomaticwindowtabbing>
879pub fn allow_automatic_tabbing<T>(enabled: bool) -> Task<T> {
880 task::effect(crate::Action::Window(Action::SetAllowAutomaticTabbing(
881 enabled,
882 )))
883}
884
885/// Sets the corner radius for the window using the COSMIC corner radius protocol.
886///
887/// Communicates corner radius hints to the compositor so it can draw proper
888/// blur outlines and apply rounded corners.
889///
890/// ## Platform-specific
891/// - **COSMIC/Wayland:** Uses `layer_corner_radius_manager_v1` protocol.
892/// - **Other platforms:** No effect.
893pub fn set_corner_radius<T>(
894 id: Id,
895 top_left: u32,
896 top_right: u32,
897 bottom_right: u32,
898 bottom_left: u32,
899) -> Task<T> {
900 task::effect(crate::Action::Window(Action::SetCornerRadius(
901 id,
902 top_left,
903 top_right,
904 bottom_right,
905 bottom_left,
906 )))
907}
908
909/// Sets a compositor-rendered backdrop color for the window.
910///
911/// The compositor will render a colored rectangle behind the window content,
912/// using the window's corner radius. RGBA components are in the range 0-255.
913///
914/// ## Platform-specific
915/// - **COSMIC/Wayland:** Uses `backdrop_color_manager_v1` protocol.
916/// - **Other platforms:** No effect.
917pub fn set_backdrop_color<T>(id: Id, r: u32, g: u32, b: u32, a: u32) -> Task<T> {
918 task::effect(crate::Action::Window(Action::SetBackdropColor(
919 id, r, g, b, a,
920 )))
921}
922
923/// Enable or disable blur behind the window at runtime.
924///
925/// The window must have been created with `transparent: true` for blur to
926/// have a visible effect.
927///
928/// ## Platform-specific
929/// - **Wayland/macOS:** Supported.
930/// - **Other platforms:** No effect.
931pub fn set_blur<T>(id: Id, blur: bool) -> Task<T> {
932 task::effect(crate::Action::Window(Action::SetBlur(id, blur)))
933}