Skip to main content

zng_view_api/
lib.rs

1#![doc(html_favicon_url = "https://zng-ui.github.io/res/zng-logo-icon.png")]
2#![doc(html_logo_url = "https://zng-ui.github.io/res/zng-logo.png")]
3//!
4//! The View Process API.
5//!
6//! Zng isolates all render and windowing related code to a different process (the view-process), this crate
7//! provides the API that must be implemented to create a view-process backend, plus the [`Controller`] that
8//! can be used from an app-process to spawn and communicate with a view-process.
9//!
10//! # VERSION
11//!
12//! The [`VERSION`] of this crate must match exactly in both *App-Process* and *View-Process*, otherwise a runtime
13//! panic error is generated.
14//!
15//! # Same Process Patch
16//!
17//! Dynamically loaded same process implementers must propagate a [`StaticPatch`], otherwise the view will not connect.
18//!
19//! # Crate
20//!
21#![doc = include_str!(concat!("../", std::env!("CARGO_PKG_README")))]
22#![warn(missing_docs)]
23#![warn(unused_extern_crates)]
24
25use drag_drop::{DragDropData, DragDropEffect, DragDropError};
26use serde::{Deserialize, Serialize};
27
28/// The *App Process* and *View Process* must be build using the same exact version and this is
29/// validated during run-time, causing a panic if the versions don't match.
30pub const VERSION: &str = env!("CARGO_PKG_VERSION");
31
32pub mod access;
33pub mod api_extension;
34pub mod audio;
35pub mod clipboard;
36pub mod config;
37pub mod dialog;
38pub mod display_list;
39pub mod drag_drop;
40pub mod font;
41pub mod image;
42pub mod ipc;
43pub mod keyboard;
44pub mod menu;
45pub mod mouse;
46pub mod raw_input;
47pub mod touch;
48pub mod video;
49pub mod window;
50
51mod types;
52pub use types::*;
53
54mod app_process;
55pub use app_process::*;
56
57mod view_process;
58pub use view_process::*;
59use zng_txt::Txt;
60
61use std::fmt;
62
63use api_extension::{ApiExtensionId, ApiExtensionPayload};
64use clipboard::{ClipboardData, ClipboardError};
65use dialog::DialogId;
66use font::{FontFaceId, FontId, FontOptions, FontVariationName};
67use image::{ImageId, ImageMaskMode, ImageRequest, ImageTextureId};
68use window::WindowId;
69use zng_task::channel::{IpcBytes, IpcReadHandle, IpcReceiver};
70use zng_unit::{DipPoint, DipRect, DipSize, Factor, Px, PxRect};
71
72/// Packaged API request.
73#[derive(Debug)]
74#[cfg_attr(ipc, derive(Serialize, Deserialize))]
75pub struct Request(RequestData);
76impl Request {
77    /// Returns `true` if the request can only be made after the *init* event.
78    pub fn must_be_connected(&self) -> bool {
79        !matches!(&self.0, RequestData::init { .. })
80    }
81
82    /// Returns `true` if the request represents a new frame or frame update for the window with the same wait ID.
83    pub fn is_frame(&self, window_id: WindowId, wait_id: Option<window::FrameWaitId>) -> bool {
84        match &self.0 {
85            RequestData::render { id, frame } if *id == window_id && frame.wait_id == wait_id => true,
86            RequestData::render_update { id, frame } if *id == window_id && frame.wait_id == wait_id => true,
87            _ => false,
88        }
89    }
90
91    /// Returns `true` if the request affects position or size of the window.
92    pub fn affects_window_rect(&self, window_id: WindowId) -> bool {
93        matches!(
94            &self.0,
95            RequestData::set_state { id, .. }
96            if *id == window_id
97        )
98    }
99
100    /// Returns `true` if this request will receive a response. Only [`Api`] methods
101    /// that have a return value send back a response.
102    pub fn expect_response(&self) -> bool {
103        self.0.expect_response()
104    }
105}
106
107/// Packaged API response.
108#[derive(Debug, Serialize, Deserialize)]
109pub struct Response(ResponseData);
110impl Response {
111    /// If this response must be send back to the app process. Only [`Api`] methods
112    /// that have a return value send back a response.
113    pub fn must_be_send(&self) -> bool {
114        self.0.must_be_send()
115    }
116}
117
118macro_rules! TypeOrNil {
119    ($T:ty) => {
120        $T
121    };
122    () => {
123        ()
124    };
125}
126
127macro_rules! type_is_some {
128    (if $T:ty { $($t_true:tt)* } else { $($t_false:tt)* }) => {
129        $($t_true)*
130    };
131    (if { $($t_true:tt)* } else { $($t_false:tt)* }) => {
132        $($t_false)*
133    };
134}
135
136/// Declares the internal `Request` and `Response` enums, public methods in `Controller` and the public trait `ViewApp`, in the
137/// controller it packs and sends the request and receives and unpacks the response. In the view it implements
138/// the method.
139macro_rules! declare_api {
140    (
141        $(
142            $(#[$meta:meta])*
143            $vis:vis fn $method:ident(
144                &mut $self:ident
145                $(, $input:ident : $RequestType:ty)* $(,)?
146            ) $(-> $ResponseType:ty)?;
147        )*
148    ) => {
149        #[cfg_attr(ipc, derive(Serialize, Deserialize))]
150        #[allow(non_camel_case_types)]
151        #[allow(clippy::large_enum_variant)]
152        #[repr(u32)]
153        enum RequestData {
154            $(
155                $(#[$meta])*
156                $method { $($input: $RequestType),* },
157            )*
158        }
159        impl RequestData {
160            #[allow(unused_doc_comments)]
161            pub fn expect_response(&self) -> bool {
162                match self {
163                    $(
164                        $(#[$meta])*
165                        Self::$method { .. } => type_is_some! {
166                            if $($ResponseType)? {
167                                true
168                            } else {
169                                false
170                            }
171                        },
172                    )*
173                }
174            }
175        }
176        impl fmt::Debug for RequestData {
177            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
178                #[allow(unused_doc_comments)]
179                if f.alternate() {
180                    match self {
181                        $(
182                            $(#[$meta])*
183                            RequestData::$method { $($input),* } => write!(f, "{}{:#?}", stringify!($method), ($($input),*)),
184                        )+
185                    }
186                } else {
187                    match self {
188                        $(
189                            $(#[$meta])*
190                            RequestData::$method { .. } => write!(f, "{}(..)", stringify!($method)),
191                        )+
192                    }
193                }
194            }
195        }
196
197        #[derive(Debug)]
198        #[derive(Serialize, Deserialize)]
199        #[allow(non_camel_case_types)]
200        #[repr(u32)]
201        enum ResponseData {
202            $(
203                $(#[$meta])*
204                $method(TypeOrNil![$($ResponseType)?]),
205            )*
206        }
207        impl ResponseData {
208            #[allow(unused_doc_comments)]
209            pub fn must_be_send(&self) -> bool {
210                match self {
211                    $(
212                        $(#[$meta])*
213                        Self::$method(_) => type_is_some! {
214                            if $($ResponseType)? {
215                                true
216                            } else {
217                                false
218                            }
219                        },
220                    )*
221                }
222            }
223        }
224
225        #[allow(unused_parens)]
226        impl Controller {
227            $(
228                $(#[$meta])*
229                #[allow(clippy::too_many_arguments)]
230                $vis fn $method(&mut self $(, $input: $RequestType)*) -> VpResult<TypeOrNil![$($ResponseType)?]> {
231                    let req = Request(RequestData::$method { $($input),* });
232                    type_is_some! {
233                        if $($ResponseType)? {
234                            match self.talk(req)?.0 {
235                                ResponseData::$method(r) => Ok(r),
236                                r => panic!("view-process did not respond correctly for `{}`, {r:?}", stringify!($method))
237                            }
238                        } else {
239                            self.command(req)
240                        }
241                    }
242                }
243            )*
244        }
245
246        /// The view-process API.
247        pub trait Api {
248            /// Already implemented, matches a request, calls the corresponding method and packages the response.
249            fn respond(&mut self, request: Request) -> Response {
250                match request.0 {
251                    $(
252                        #[allow(unused_doc_comments)]
253                        $(#[$meta])* // for the cfg
254                        RequestData::$method { $($input),* } => {
255                            let r = self.$method($($input),*);
256                            Response(ResponseData::$method(r))
257                        }
258                    )*
259                }
260            }
261
262            $(
263                $(#[$meta])*
264                #[allow(clippy::too_many_arguments)]
265                fn $method(&mut self, $($input: $RequestType),*) $(-> $ResponseType)?;
266            )*
267        }
268    };
269}
270declare_api! {
271    /// Called once on init.
272    ///
273    /// Sends an [`Event::Inited`] once the view is completely connected, the event details what API features
274    /// are implemented by the view-process.
275    ///
276    /// Other methods may only be called after this event.
277    fn init(&mut self, vp_gen: ViewProcessGen, is_respawn: bool, headless: bool);
278
279    /// Called once after exit, if running in a managed external process it will be killed after this call.
280    fn exit(&mut self);
281
282    /// Enable/disable global device events.
283    ///
284    /// This filter affects device events not targeted at windows, such as mouse move outside windows or
285    /// key presses when the app has no focused window.
286    pub fn set_device_events_filter(&mut self, filter: DeviceEventsFilter);
287
288    /// Open a window.
289    ///
290    /// Sends an [`Event::WindowOpened`] once the window, context and renderer have finished initializing or a
291    /// [`Event::WindowOrHeadlessOpenError`] if it failed.
292    pub fn open_window(&mut self, request: window::WindowRequest);
293
294    /// Open a headless surface.
295    ///
296    /// This is a real renderer but not connected to any window, you can requests pixels to get the
297    /// rendered frames.
298    ///
299    /// Sends an [`Event::HeadlessOpened`] once the context and renderer have finished initializing or a
300    /// [`Event::WindowOrHeadlessOpenError`] if it failed.
301    pub fn open_headless(&mut self, request: window::HeadlessRequest);
302
303    /// Close the window or headless surface.
304    ///
305    /// All documents associated with the window or surface are also closed.
306    pub fn close(&mut self, id: WindowId);
307
308    /// Set window title.
309    pub fn set_title(&mut self, id: WindowId, title: Txt);
310
311    /// Set window visible.
312    pub fn set_visible(&mut self, id: WindowId, visible: bool);
313
314    /// Set if the window is "top-most".
315    pub fn set_always_on_top(&mut self, id: WindowId, always_on_top: bool);
316
317    /// Set if the user can drag-move the window when it is in `Normal` mode.
318    pub fn set_movable(&mut self, id: WindowId, movable: bool);
319
320    /// Set if the user can resize the window when it is in `Normal` mode.
321    pub fn set_resizable(&mut self, id: WindowId, resizable: bool);
322
323    /// Set if the user can minimize the window.
324    pub fn set_can_minimize(&mut self, id: WindowId, can: bool);
325    /// Set if the user can maximize/restore the window.
326    pub fn set_can_maximize(&mut self, id: WindowId, can: bool);
327    /// Set if the user can toggle fullscreen the window.
328    pub fn set_can_fullscreen(&mut self, id: WindowId, can: bool);
329    /// Set if the user can make window close requests.
330    pub fn set_can_close(&mut self, id: WindowId, can: bool);
331
332    /// Set the window taskbar icon visibility.
333    pub fn set_taskbar_visible(&mut self, id: WindowId, visible: bool);
334
335    /// Bring the window to the Z top, without focusing it.
336    pub fn bring_to_top(&mut self, id: WindowId);
337
338    /// Set the window state, position, size.
339    pub fn set_state(&mut self, id: WindowId, state: window::WindowStateAll);
340
341    /// Set the headless surface or document area size (viewport size).
342    pub fn set_headless_size(&mut self, id: WindowId, size: DipSize, scale_factor: Factor);
343
344    /// Set the window icon, the icon image must be loaded.
345    pub fn set_icon(&mut self, id: WindowId, icon: Option<ImageId>);
346
347    /// Set the window cursor icon and visibility.
348    pub fn set_cursor(&mut self, id: WindowId, cursor: Option<window::CursorIcon>);
349
350    /// Set the window cursor to a custom image.
351    ///
352    /// Falls back to cursor icon if not supported or if set to `None`.
353    pub fn set_cursor_image(&mut self, id: WindowId, cursor: Option<window::CursorImage>);
354
355    /// Sets the user attention request indicator, the indicator is cleared when the window is focused or
356    /// if canceled by setting to `None`.
357    pub fn set_focus_indicator(&mut self, id: WindowId, indicator: Option<window::FocusIndicator>);
358
359    /// Brings the window to the front and sets input focus.
360    ///
361    /// Sends an [`Event::FocusChanged`] if the window is focused, the request can be ignored by the window manager, or if the
362    /// window is not visible, minimized or already focused.
363    ///
364    /// This request can steal focus from other apps disrupting the user, be careful with it.
365    pub fn focus(&mut self, id: WindowId) -> FocusResult;
366
367    /// Moves the window with the left mouse button until the button is released.
368    ///
369    /// There's no guarantee that this will work unless the left mouse button was pressed immediately before this function is called.
370    pub fn drag_move(&mut self, id: WindowId);
371
372    /// Resizes the window with the left mouse button until the button is released.
373    ///
374    /// There's no guarantee that this will work unless the left mouse button was pressed immediately before this function is called.
375    pub fn drag_resize(&mut self, id: WindowId, direction: window::ResizeDirection);
376
377    /// Open the system title bar context menu.
378    pub fn open_title_bar_context_menu(&mut self, id: WindowId, position: DipPoint);
379
380    /// Cache an image resource.
381    ///
382    /// The image is decoded asynchronously, the events [`Event::ImageMetadataDecoded`], [`Event::ImageDecoded`]
383    /// or [`Event::ImageDecodeError`] will be send when the image is ready for use or failed.
384    ///
385    /// The [`ImageRequest::data`] handle must contain the full image data already, it will be dropped after the image finishes decoding.
386    ///
387    /// Images are shared between renderers, to use an image in a window you must first call [`use_image`]
388    /// this will register the image data with the renderer.
389    ///
390    /// [`use_image`]: Api::use_image
391    pub fn add_image(&mut self, request: ImageRequest<IpcReadHandle>) -> ImageId;
392
393    /// Cache an image from data that has not fully loaded.
394    ///
395    /// If the view-process implementation supports **progressive decoding** it will start decoding the image
396    /// as more data is received, otherwise it will collect all data first and then [`add_image`]. Each
397    /// [`ImageRequest::`data`] package is the continuation of the previous call, send an empty package to indicate finish.
398    ///
399    /// The events [`Event::ImageMetadataDecoded`], [`Event::ImageDecoded`] or [`Event::ImageDecodeError`] will
400    /// be send while decoding.
401    ///
402    /// [`add_image`]: Api::add_image
403    pub fn add_image_pro(&mut self, request: ImageRequest<IpcReceiver<IpcBytes>>) -> ImageId;
404
405    /// Remove an image from cache.
406    ///
407    /// Note that if the image is in use in a renderer it will remain in memory until [`delete_image_use`] is
408    /// called or the renderer is deinited by closing the window.
409    ///
410    /// [`delete_image_use`]: Api::delete_image_use
411    pub fn forget_image(&mut self, id: ImageId);
412
413    /// Add an image resource to the window renderer.
414    ///
415    /// Returns the new image texture ID. If the `image_id` is not loaded returns the [`INVALID`] texture ID.
416    ///
417    /// [`INVALID`]: ImageTextureId::INVALID
418    pub fn use_image(&mut self, id: WindowId, image_id: ImageId) -> ImageTextureId;
419
420    /// Replace the image resource in the window renderer.
421    ///
422    /// The new `image_id` must represent an image with same dimensions and format as the previous. If the
423    /// image cannot be updated an error is logged and `false` is returned.
424    ///
425    /// The `dirty_rect` can be set to optimize texture upload to the GPU, if not set the entire image region updates.
426    ///
427    /// The [`ImageTextureId`] will be associated with the new [`ImageId`].
428    pub fn update_image_use(&mut self, id: WindowId, texture_id: ImageTextureId, image_id: ImageId, dirty_rect: Option<PxRect>)
429    -> bool;
430
431    /// Delete the image resource in the window renderer.
432    pub fn delete_image_use(&mut self, id: WindowId, texture_id: ImageTextureId);
433
434    /// Encode the image.
435    ///
436    /// Returns immediately. The encoded data will be send as the event
437    /// [`Event::ImageEncoded`] or [`Event::ImageEncodeError`]. The returned ID identifies this request.
438    pub fn encode_image(&mut self, request: image::ImageEncodeRequest) -> image::ImageEncodeId;
439
440    /// Under development, see [`video`].
441    pub fn add_video(&mut self, request: video::VideoRequest<IpcReadHandle>) -> video::VideoId;
442
443    /// Under development, see [`video`].
444    pub fn add_video_pro(&mut self, request: video::VideoRequest<IpcReceiver<IpcBytes>>) -> video::VideoId;
445
446    /// Under development, see [`video`].
447    pub fn forget_video(&mut self, id: video::VideoId);
448
449    /// Under development, see [`video`].
450    pub fn use_video(&mut self, id: WindowId, video_id: video::VideoId) -> video::VideoTextureId;
451
452    /// Under development, see [`video`].
453    pub fn delete_video_use(&mut self, id: WindowId, texture_id: video::VideoTextureId);
454
455    /// Cache an audio resource.
456    ///
457    /// The entire audio source is already loaded in the request, it may be decoded fully or on demand depending on the request,
458    /// the returned ID can be played as soon as it starts decoding.
459    ///
460    /// The events [`Event::AudioMetadataDecoded`], [`Event::AudioDecoded`] and [`Event::AudioDecodeError`] will be send while decoding.
461    pub fn add_audio(&mut self, request: audio::AudioRequest<IpcReadHandle>) -> audio::AudioId;
462
463    /// Cache an streaming audio resource.
464    ///
465    /// The audio is decoded as bytes are buffered in. The returned ID can be played as soon as it starts decoding.
466    ///
467    /// The events [`Event::AudioMetadataDecoded`], [`Event::AudioDecoded`] and [`Event::AudioDecodeError`] will be send while decoding.
468    pub fn add_audio_pro(&mut self, request: audio::AudioRequest<IpcReceiver<IpcBytes>>) -> audio::AudioId;
469
470    /// Remove an audio from cache.
471    ///
472    /// Note that if the audio playing it will continue until the end or it is stopped.
473    pub fn forget_audio(&mut self, id: audio::AudioId);
474
475    /// Create a playback stream.
476    ///
477    /// Opens a connection with the audio device if there are no other streams connected to it.
478    pub fn open_audio_output(&mut self, request: audio::AudioOutputRequest);
479
480    /// Update configuration of an existing playback stream.
481    pub fn update_audio_output(&mut self, request: audio::AudioOutputUpdateRequest);
482
483    /// Stop and drop a playback stream.
484    ///
485    /// Note that even if this is the last connection to the device the underlying system connection may remain open as some systems expect this
486    /// resource to exist for the lifetime of the process.
487    pub fn close_audio_output(&mut self, id: audio::AudioOutputId);
488
489    /// Play or enqueue audio.
490    pub fn cue_audio(&mut self, request: audio::AudioPlayRequest) -> audio::AudioPlayId;
491
492    /// Encode the audio.
493    pub fn encode_audio(&mut self, request: audio::AudioEncodeRequest) -> audio::AudioEncodeId;
494
495    /// Add a raw font resource to the window renderer.
496    ///
497    /// Returns the new font key.
498    pub fn add_font_face(&mut self, id: WindowId, bytes: font::IpcFontBytes, index: u32) -> FontFaceId;
499
500    /// Delete the font resource in the window renderer.
501    pub fn delete_font_face(&mut self, id: WindowId, font_face_id: FontFaceId);
502
503    /// Add a sized font to the window renderer.
504    ///
505    /// Returns the new fond ID.
506    pub fn add_font(
507        &mut self,
508        id: WindowId,
509        font_face_id: FontFaceId,
510        glyph_size: Px,
511        options: FontOptions,
512        variations: Vec<(FontVariationName, f32)>,
513    ) -> FontId;
514
515    /// Delete a font instance.
516    pub fn delete_font(&mut self, id: WindowId, font_id: FontId);
517
518    /// Sets if the headed window is in *capture-mode*. If `true` the resources used to capture
519    /// a screenshot may be kept in memory to be reused in the next screenshot capture.
520    ///
521    /// Note that capture must still be requested in each frame request.
522    pub fn set_capture_mode(&mut self, id: WindowId, enable: bool);
523
524    /// Create a new image resource from the current rendered frame.
525    ///
526    /// If `mask` is set captures an A8 mask, otherwise captures a full BGRA8 image.
527    ///
528    /// Returns immediately, an [`Event::ImageDecoded`] will be send when the image is ready.
529    ///
530    /// Returns [`ImageId::INVALID`] if the window is not found.
531    pub fn frame_image(&mut self, id: WindowId, mask: Option<ImageMaskMode>) -> ImageId;
532
533    /// Create a new image from a selection of the current rendered frame.
534    ///
535    /// If `mask` is set captures an A8 mask, otherwise captures a full BGRA8 image.
536    ///
537    /// Returns immediately, an [`Event::ImageDecoded`] will be send when the image is ready.
538    ///
539    /// Returns [`ImageId::INVALID`] if the window is not found.
540    pub fn frame_image_rect(&mut self, id: WindowId, rect: PxRect, mask: Option<ImageMaskMode>) -> ImageId;
541
542    /// Set the video mode used when the window is in exclusive fullscreen.
543    pub fn set_video_mode(&mut self, id: WindowId, mode: window::VideoMode);
544
545    /// Render a new frame.
546    pub fn render(&mut self, id: WindowId, frame: window::FrameRequest);
547
548    /// Update the current frame and re-render it.
549    pub fn render_update(&mut self, id: WindowId, frame: window::FrameUpdateRequest);
550
551    /// Update the window's accessibility info tree.
552    pub fn access_update(&mut self, id: WindowId, update: access::AccessTreeUpdate);
553
554    /// Shows a native message dialog for the window.
555    ///
556    /// Returns an ID that identifies the response event.
557    pub fn message_dialog(&mut self, id: WindowId, dialog: dialog::MsgDialog) -> DialogId;
558
559    /// Shows a native file/folder picker for the window.
560    ///
561    /// Returns the ID that identifies the response event.
562    pub fn file_dialog(&mut self, id: WindowId, dialog: dialog::FileDialog) -> DialogId;
563
564    /// Register a native notification, either a popup or an entry in the system notifications list.
565    ///
566    /// Returns an ID that identifies the response event.
567    pub fn notification_dialog(&mut self, notification: dialog::Notification) -> DialogId;
568
569    /// Update the notification content.
570    pub fn update_notification(&mut self, id: DialogId, notification: dialog::Notification);
571
572    /// Get the clipboard content that matches the `data_types`.
573    ///
574    /// If `first` is true tries to read all data types requested and returns the first ok. If is false returns all requested data types ok.
575    pub fn read_clipboard(
576        &mut self,
577        data_types: Vec<clipboard::ClipboardType>,
578        first: bool,
579    ) -> Result<Vec<ClipboardData>, ClipboardError>;
580
581    /// Set the clipboard content.
582    ///
583    /// Returns the count of data types that where set, if at least one `data` is supported by the implementation
584    /// the operation is considered a success. If the implementation only support a single data entry the first
585    /// compatible entry is written.
586    pub fn write_clipboard(&mut self, data: Vec<ClipboardData>) -> Result<usize, ClipboardError>;
587
588    /// Start a drag and drop operation, if the window is pressed.
589    pub fn start_drag_drop(
590        &mut self,
591        id: WindowId,
592        data: Vec<DragDropData>,
593        allowed_effects: DragDropEffect,
594    ) -> Result<DragDropId, DragDropError>;
595
596    /// Cancel a drag and drop operation.
597    pub fn cancel_drag_drop(&mut self, id: WindowId, drag_id: DragDropId);
598
599    /// Notify the drag source of what effect was applied for a received drag&drop.
600    pub fn drag_dropped(&mut self, id: WindowId, drop_id: DragDropId, applied: DragDropEffect);
601
602    /// Enable or disable IME by setting a cursor area.
603    ///
604    /// In mobile platforms also shows the software keyboard for `Some(_)` and hides it for `None`.
605    pub fn set_ime_area(&mut self, id: WindowId, area: Option<DipRect>);
606
607    /// Attempt to set a system wide shutdown warning associated with the window.
608    ///
609    /// Operating systems that support this show the `reason` in a warning for the user, it must be a short text
610    /// that identifies the critical operation that cannot be cancelled.
611    ///
612    /// Note that there is no guarantee that the view-process or operating system will actually set a block, there
613    /// is no error result because operating systems can silently ignore block requests at any moment, even after
614    /// an initial successful block.
615    ///
616    /// Set to an empty text to remove the warning.
617    pub fn set_system_shutdown_warn(&mut self, id: WindowId, reason: Txt);
618
619    /// Set the custom menu items for the system application menu.
620    ///
621    /// The application menu is shown outside the app windows, usually at the top of the main screen in macOS and Gnome desktops.
622    ///
623    /// Set to empty to remove the menu.
624    pub fn set_app_menu(&mut self, menu: menu::AppMenu);
625
626    /// Set the tray icon indicator for the app.
627    ///
628    /// This is a small status indicator icon displayed near the notifications area.
629    pub fn set_tray_icon(&mut self, indicator: menu::TrayIcon);
630
631    /// Licenses that may be required to be displayed in the app about screen.
632    ///
633    /// This is specially important for prebuilt view users, as the tools that scrap licenses
634    /// may not find the prebuilt dependencies.
635    pub fn third_party_licenses(&mut self) -> Vec<zng_tp_licenses::LicenseUsed>;
636
637    /// Call the API extension.
638    ///
639    /// The `extension_id` is the index of an extension in the extensions list provided by the view-process on init.
640    /// The `extension_request` is any data required by the extension.
641    ///
642    /// Returns the extension response or [`ApiExtensionPayload::unknown_extension`] if the `extension_id` is
643    /// not on the list, or [`ApiExtensionPayload::invalid_request`] if the `extension_request` is not in a
644    /// format expected by the extension.
645    pub fn app_extension(&mut self, extension_id: ApiExtensionId, extension_request: ApiExtensionPayload) -> ApiExtensionPayload;
646
647    /// Call the API extension.
648    ///
649    /// This is similar to [`Api::app_extension`], but is targeting the instance of an extension associated
650    /// with the `id` window or headless surface.
651    pub fn window_extension(
652        &mut self,
653        id: WindowId,
654        extension_id: ApiExtensionId,
655        extension_request: ApiExtensionPayload,
656    ) -> ApiExtensionPayload;
657
658    /// Call the API extension.
659    ///
660    /// This is similar to [`Api::app_extension`], but is targeting the instance of an extension associated
661    /// with the `id` renderer.
662    pub fn render_extension(
663        &mut self,
664        id: WindowId,
665        extension_id: ApiExtensionId,
666        extension_request: ApiExtensionPayload,
667    ) -> ApiExtensionPayload;
668
669    /// Returns the `count` and notifies [`Event::Pong`] after ensuring the view-process is responsive.
670    ///
671    /// The app-process and view-process automatically monitor message frequency to detect when the paired process
672    /// is stuck. View-process implementers must only ensure the response event goes through its *main loop* to get an
673    /// accurate read of if it is stuck.
674    pub fn ping(&mut self, count: u16) -> u16;
675}
676
677pub(crate) type AnyResult<T> = std::result::Result<T, Box<dyn std::error::Error>>;