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