Skip to main content

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}