Added initial window module functionality. (#57)

This commit is contained in:
bicarlsen 2024-07-23 09:35:07 +02:00 committed by GitHub
parent 125136ae79
commit 9c3cd94275
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 931 additions and 29 deletions

View file

@ -24,9 +24,11 @@ wasm-bindgen-test = "0.3.42"
all-features = true
[features]
all = ["core", "event"]
all = ["core", "dpi", "event", "window"]
core = []
dpi = []
event = ["dep:futures"]
window = ["dpi", "event"]
[workspace]
members = ["examples/test", "examples/test/src-tauri"]

View file

@ -53,6 +53,7 @@ All modules are gated by accordingly named Cargo features. It is recommended you
- **all**: Enables all modules.
- **core**: Enables the `core` module. (Only `invoke` and `convertFileSrc` currently implemented.)
- **event**: Enables the `event` module.
- **window**: Enables the `windows` module. (~20% implemented)
## Are we Tauri yet?
@ -60,7 +61,7 @@ These API bindings are not completely on-par with `@tauri-apps/api` yet, but her
- [ ] `app`
- [x] `core` (partial implementation)
- [ ] `dpi`
- [x] `dpi`
- [x] `event`
- [ ] `image`
- [ ] `menu`
@ -69,7 +70,7 @@ These API bindings are not completely on-par with `@tauri-apps/api` yet, but her
- [ ] `tray`
- [ ] `webview`
- [ ] `webviewWindow`
- [ ] `window`
- [x] `window` (partial implementation)
The current API also very closely mirrors the JS API even though that might not be the most ergonomic choice, ideas for improving the API with quality-of-life features beyond the regular JS API interface are very welcome.

View file

@ -43,7 +43,6 @@ mod inner {
#[wasm_bindgen(module = "/src/core.js")]
extern "C" {
#[wasm_bindgen]
pub async fn invoke(cmd: &str, args: JsValue) -> JsValue;
#[wasm_bindgen(js_name = "invoke", catch)]
pub async fn invoke_result(cmd: &str, args: JsValue) -> Result<JsValue, JsValue>;

110
src/dpi.rs Normal file
View file

@ -0,0 +1,110 @@
use serde::Deserialize;
pub type ScaleFactor = f64;
pub type PixelCount = isize;
#[derive(Debug)]
pub enum Kind {
Logical,
Physical,
}
/// A size represented in logical pixels.
#[derive(Deserialize, Clone, Debug)]
pub struct LogicalSize {
width: PixelCount,
height: PixelCount,
}
impl LogicalSize {
pub fn kind() -> Kind {
Kind::Logical
}
pub fn width(&self) -> PixelCount {
self.width
}
pub fn height(&self) -> PixelCount {
self.height
}
}
/// A size represented in physical pixels.
#[derive(Deserialize, Clone, Debug)]
pub struct PhysicalSize {
width: PixelCount,
height: PixelCount,
}
impl PhysicalSize {
pub fn kind() -> Kind {
Kind::Physical
}
pub fn width(&self) -> PixelCount {
self.width
}
pub fn height(&self) -> PixelCount {
self.height
}
/// Converts the physical size to a logical one.
pub fn as_logical(&self, scale_factor: ScaleFactor) -> LogicalSize {
LogicalSize {
width: (self.width as f64 / scale_factor) as PixelCount,
height: (self.height as f64 / scale_factor) as PixelCount,
}
}
}
/// A position represented in logical pixels.
#[derive(Deserialize, Clone, Debug)]
pub struct LogicalPosition {
x: PixelCount,
y: PixelCount,
}
impl LogicalPosition {
pub fn kind() -> Kind {
Kind::Logical
}
pub fn x(&self) -> PixelCount {
self.x
}
pub fn y(&self) -> PixelCount {
self.y
}
}
/// A position represented in physical pixels.
#[derive(Deserialize, Clone, Debug)]
pub struct PhysicalPosition {
x: PixelCount,
y: PixelCount,
}
impl PhysicalPosition {
pub fn kind() -> Kind {
Kind::Physical
}
pub fn x(&self) -> PixelCount {
self.x
}
pub fn y(&self) -> PixelCount {
self.y
}
/// Converts the physical position to a logical one.
pub fn as_logical(&self, scale_factor: ScaleFactor) -> LogicalPosition {
LogicalPosition {
x: (self.x as f64 / scale_factor) as PixelCount,
y: (self.y as f64 / scale_factor) as PixelCount,
}
}
}

View file

@ -55,28 +55,9 @@ async function once(event, handler, options) {
)
}
// tauri/tooling/api/src/event.ts
var TauriEvent = /* @__PURE__ */ ((TauriEvent2) => {
TauriEvent2["WINDOW_RESIZED"] = 'tauri://resize';
TauriEvent2["WINDOW_MOVED"] = 'tauri://move';
TauriEvent2["WINDOW_CLOSE_REQUESTED"] = 'tauri://close-requested';
TauriEvent2["WINDOW_DESTROYED"] = 'tauri://destroyed';
TauriEvent2["WINDOW_FOCUS"] = 'tauri://focus';
TauriEvent2["WINDOW_BLUR"] = 'tauri://blur';
TauriEvent2["WINDOW_SCALE_FACTOR_CHANGED"] = 'tauri://scale-change';
TauriEvent2["WINDOW_THEME_CHANGED"] = 'tauri://theme-changed';
TauriEvent2["WINDOW_CREATED"] = 'tauri://window-created';
TauriEvent2["WEBVIEW_CREATED"] = 'tauri://webview-created';
TauriEvent2["DRAG"] = 'tauri://drag';
TauriEvent2["DROP"] = 'tauri://drop';
TauriEvent2["DROP_OVER"] = 'tauri://drop-over';
TauriEvent2["DROP_CANCELLED"] = 'tauri://drag-cancelled';
return TauriEvent2;
})(TauriEvent || {});
export {
TauriEvent,
emit,
emitTo,
listen,
once
once,
};

View file

@ -1,5 +1,4 @@
//! The event system allows you to emit events to the backend and listen to events from it.
use futures::{
channel::{mpsc, oneshot},
Future, FutureExt, Stream, StreamExt,
@ -8,13 +7,28 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::fmt::Debug;
use wasm_bindgen::{prelude::Closure, JsValue};
pub const WINDOW_RESIZED: &str = "tauri://resize";
pub const WINDOW_MOVED: &str = "tauri://move";
pub const WINDOW_CLOSE_REQUESTED: &str = "tauri://close-requested";
pub const WINDOW_DESTROYED: &str = "tauri://destroyed";
pub const WINDOW_FOCUS: &str = "tauri://focus";
pub const WINDOW_BLUR: &str = "tauri://blur";
pub const WINDOW_SCALE_FACTOR_CHANGED: &str = "tauri://scale-change";
pub const WINDOW_THEME_CHANGED: &str = "tauri://theme-changed";
pub const WINDOW_CREATED: &str = "tauri://window-created";
pub const WEBVIEW_CREATED: &str = "tauri://webview-created";
pub const DRAG: &str = "tauri://drag";
pub const DROP: &str = "tauri://drop";
pub const DROP_OVER: &str = "tauri://drop-over";
pub const DROP_CANCELLED: &str = "tauri://drag-cancelled";
#[derive(Debug, Clone, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Event<T> {
/// Event name
pub event: String,
/// Event identifier used to unlisten
pub id: f32,
pub id: isize,
/// Event payload
pub payload: T,
}
@ -31,8 +45,8 @@ pub enum EventTarget {
}
#[derive(Debug, Clone, PartialEq, Serialize)]
struct Options {
target: EventTarget,
pub(crate) struct Options {
pub target: EventTarget,
}
/// Emits an event to the backend.
@ -334,7 +348,7 @@ impl<T> Future for Once<T> {
}
}
mod inner {
pub(crate) mod inner {
use wasm_bindgen::{
prelude::{wasm_bindgen, Closure},
JsValue,

View file

@ -92,6 +92,12 @@ pub mod event;
#[cfg(feature = "core")]
pub mod core;
#[cfg(feature = "dpi")]
pub mod dpi;
#[cfg(feature = "window")]
pub mod window;
pub use error::Error;
pub(crate) type Result<T> = std::result::Result<T, Error>;

38
src/window.js Normal file
View file

@ -0,0 +1,38 @@
// tauri/tooling/api/src/core.ts
async function invoke(cmd, args = {}) {
// NB: `options` ignored as not used here.
return window.__TAURI_INTERNALS__.invoke(cmd, args)
}
// tauri/tooling/api/src/window.ts
function getCurrent() {
return window.__TAURI_INTERNALS__.metadata.currentWindow
}
function getAll() {
return window.__TAURI_INTERNALS__.metadata.windows
}
async function currentMonitor() {
return invoke('plugin:window|current_monitor')
}
async function primaryMonitor() {
return invoke('plugin:window|primary_monitor')
}
async function monitorFromPoint(x, y) {
return invoke('plugin:window|monitor_from_point', { x, y })
}
async function availableMonitors() {
return invoke('plugin:window|available_monitors')
}
async function cursorPosition() {
return invoke('plugin:window|cursor_position')
}
export {
getCurrent,
getAll,
currentMonitor,
primaryMonitor,
monitorFromPoint,
availableMonitors,
cursorPosition,
}

751
src/window.rs Normal file
View file

@ -0,0 +1,751 @@
//! Provides APIs to create windows, communicate with other windows and manipulate the current window.
//!
//! ## Window events
//! Events can be listened to using [`Window::listen`].
use crate::{
dpi,
event::{self, Event},
};
use futures::{
channel::{
mpsc::{self, UnboundedSender},
oneshot,
},
Future, FutureExt, Stream, StreamExt,
};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::{any::Any, collections::HashMap};
use wasm_bindgen::{prelude::Closure, JsValue};
/// Events that are emitted right here instead of by the created window.
const LOCAL_TAURI_EVENTS: &'static [&'static str; 2] = &["tauri://created", "tauri://error"];
trait SenderVec: Any {
fn as_any(&self) -> &dyn std::any::Any;
fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
}
impl<T> SenderVec for Vec<mpsc::UnboundedSender<T>>
where
T: DeserializeOwned + 'static,
{
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self as &mut dyn Any
}
}
pub(crate) struct Listen<T> {
pub rx: mpsc::UnboundedReceiver<T>,
}
impl<T> Stream for Listen<T> {
type Item = T;
fn poll_next(
mut self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Option<Self::Item>> {
self.rx.poll_next_unpin(cx)
}
}
pub(crate) struct DragDropListen {
pub rx: mpsc::UnboundedReceiver<Event<DragDropEvent>>,
pub unlisten_drag: js_sys::Function,
pub unlisten_drop: js_sys::Function,
pub unlisten_drag_over: js_sys::Function,
pub unlisten_cancel: js_sys::Function,
}
impl Drop for DragDropListen {
fn drop(&mut self) {
log::debug!("Calling unlisten for listen callback");
self.unlisten_drag
.call0(&wasm_bindgen::JsValue::NULL)
.unwrap();
self.unlisten_drop
.call0(&wasm_bindgen::JsValue::NULL)
.unwrap();
self.unlisten_drag_over
.call0(&wasm_bindgen::JsValue::NULL)
.unwrap();
self.unlisten_cancel
.call0(&wasm_bindgen::JsValue::NULL)
.unwrap();
}
}
impl Stream for DragDropListen {
type Item = Event<DragDropEvent>;
fn poll_next(
mut self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Option<Self::Item>> {
self.rx.poll_next_unpin(cx)
}
}
#[derive(Deserialize)]
struct WindowLabel {
label: String,
}
#[derive(Deserialize)]
pub enum DragDropEvent {
Dragged(DragDropPayload),
DragOver(DragOverPayload),
Dropped(DragDropPayload),
Cancelled,
}
#[derive(Deserialize)]
pub struct DragDropPayload {
paths: Vec<String>,
position: dpi::PhysicalPosition,
}
impl DragDropPayload {
pub fn paths(&self) -> &Vec<String> {
&self.paths
}
pub fn position(&self) -> &dpi::PhysicalPosition {
&self.position
}
}
#[derive(Deserialize)]
pub struct DragOverPayload {
position: dpi::PhysicalPosition,
}
impl DragOverPayload {
pub fn position(&self) -> &dpi::PhysicalPosition {
&self.position
}
}
pub struct Window {
label: String,
listeners: HashMap<String, Box<dyn SenderVec>>,
}
impl Window {
/// Create a new Window.
///
/// # Arguments
/// + `label`: Unique window label. Must be alphanumberic: `a-zA-Z-/:_`.
pub fn new(label: impl Into<String>) -> Self {
Self {
label: label.into(),
listeners: HashMap::new(),
}
}
/// Gets the Window associated with the given label.
pub fn get_by_label(label: impl AsRef<str>) -> Option<Self> {
js_sys::try_iter(&inner::get_all())
.unwrap()
.unwrap()
.into_iter()
.find_map(|value| {
let window_label = value.unwrap().as_string().unwrap();
if window_label == label.as_ref() {
Some(Window::new(window_label))
} else {
None
}
})
}
/// Get an instance of `Window` for the current window.
pub fn get_current() -> Self {
get_current()
}
/// Gets a list of instances of `Window` for all available windows.
pub fn get_all() -> Vec<Self> {
get_all()
}
}
impl Window {
pub fn label(&self) -> &String {
&self.label
}
fn handle_tauri_event<T>(&mut self, event: String) -> Option<impl Stream<Item = Event<T>>>
where
T: DeserializeOwned + 'static,
{
if LOCAL_TAURI_EVENTS.contains(&event.as_str()) {
let (tx, rx) = mpsc::unbounded::<Event<T>>();
let entry = self
.listeners
.entry(event)
.or_insert(Box::new(Vec::<mpsc::UnboundedSender<Event<T>>>::new()));
let senders = entry
.as_any_mut()
.downcast_mut::<Vec<mpsc::UnboundedSender<Event<T>>>>()
.unwrap();
senders.push(tx);
Some(Listen { rx })
} else {
None
}
}
}
impl Window {
/// Listen to an emitted event on this window.
///
/// # Arguments
/// + `event`: Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`.
/// + `handler`: Event handler.
///
/// # Returns
/// A function to unlisten to the event.
/// Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
pub async fn listen<T>(
&mut self,
event: impl Into<String>,
) -> crate::Result<impl Stream<Item = Event<T>>>
where
T: DeserializeOwned + 'static,
{
use futures::future::Either;
let event = event.into();
if let Some(listener) = self.handle_tauri_event(event.clone()) {
Ok(Either::Left(listener))
} else {
let listener =
event::listen_to(&event, event::EventTarget::Window(self.label.clone())).await?;
Ok(Either::Right(listener))
}
}
/// Listen to an emitted event on this window only once.
///
/// # Arguments
/// + `event`: Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`.
/// + `handler`: Event handler.
///
/// # Returns
/// A promise resolving to a function to unlisten to the event.
/// Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
pub async fn once(&self, event: impl Into<String>, handler: Closure<dyn FnMut(JsValue)>) {
todo!();
}
/// Emits an event to all {@link EventTarget|targets}.
///
/// # Arguments
/// + `event`: Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`.
/// + `payload`: Event payload.
pub async fn emit<T: Serialize + Clone + 'static>(
&self,
event: impl Into<String>,
payload: T,
) -> crate::Result<()> {
let event: String = event.into();
if LOCAL_TAURI_EVENTS.contains(&event.as_str()) {
if let Some(listeners) = self.listeners.get(&event) {
let listeners = listeners
.as_any()
.downcast_ref::<Vec<UnboundedSender<Event<T>>>>()
.unwrap();
for listener in listeners {
listener
.unbounded_send(event::Event {
event: event.clone(),
id: -1,
payload: payload.clone(),
})
.unwrap();
}
}
Ok(())
} else {
event::emit(event.as_str(), &payload).await
}
}
/// Emits an event to all {@link EventTarget|targets} matching the given target.
///
/// # Arguments
/// + `target`: Label of the target Window/Webview/WebviewWindow or raw {@link EventTarget} object.
/// + `event`: Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`.
/// + `payload`: Event payload.
pub async fn emit_to<T: Serialize + Clone + 'static>(
&self,
target: &event::EventTarget,
event: impl Into<String>,
payload: T,
) -> crate::Result<()> {
let event: String = event.into();
if LOCAL_TAURI_EVENTS.contains(&event.as_str()) {
if let Some(listeners) = self.listeners.get(&event) {
let listeners = listeners
.as_any()
.downcast_ref::<Vec<UnboundedSender<Event<T>>>>()
.unwrap();
for listener in listeners {
listener
.unbounded_send(event::Event {
event: event.clone(),
id: -1,
payload: payload.clone(),
})
.unwrap();
}
}
Ok(())
} else {
event::emit_to(target, event.as_str(), &payload).await
}
}
}
impl Window {
/// Listen to a file drop event.
/// The listener is triggered when the user hovers the selected files on the webview,
/// drops the files or cancels the operation.
///
/// You need to call unlisten if your handler goes out of scope e.g. the component is unmounted
/// unlisten();
///
/// # Returns
/// Function to unlisten to the event.
/// Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
pub async fn on_drag_drop_event(
&mut self,
) -> crate::Result<impl Stream<Item = Event<DragDropEvent>>> {
let (tx, rx) = mpsc::unbounded::<Event<DragDropEvent>>();
let closure = {
let tx = tx.clone();
Closure::<dyn FnMut(JsValue)>::new(move |raw| {
let Event { event, id, payload } =
serde_wasm_bindgen::from_value::<Event<DragDropPayload>>(raw).unwrap();
let _ = tx.unbounded_send(Event {
event,
id,
payload: DragDropEvent::Dragged(payload),
});
})
};
let unlisten = event::inner::listen(
event::DRAG,
&closure,
serde_wasm_bindgen::to_value(&event::Options {
target: event::EventTarget::Window(self.label.clone()),
})?,
)
.await?;
closure.forget();
let unlisten_drag = js_sys::Function::from(unlisten);
let closure = {
let tx = tx.clone();
Closure::<dyn FnMut(JsValue)>::new(move |raw| {
let Event { event, id, payload } =
serde_wasm_bindgen::from_value::<Event<DragDropPayload>>(raw).unwrap();
let _ = tx.unbounded_send(Event {
event,
id,
payload: DragDropEvent::Dropped(payload),
});
})
};
let unlisten = event::inner::listen(
event::DROP,
&closure,
serde_wasm_bindgen::to_value(&event::Options {
target: event::EventTarget::Window(self.label.clone()),
})?,
)
.await?;
closure.forget();
let unlisten_drop = js_sys::Function::from(unlisten);
let closure = {
let tx = tx.clone();
Closure::<dyn FnMut(JsValue)>::new(move |raw| {
let Event { event, id, payload } =
serde_wasm_bindgen::from_value::<Event<DragOverPayload>>(raw).unwrap();
let _ = tx.unbounded_send(Event {
event,
id,
payload: DragDropEvent::DragOver(payload),
});
})
};
let unlisten = event::inner::listen(
event::DROP_OVER,
&closure,
serde_wasm_bindgen::to_value(&event::Options {
target: event::EventTarget::Window(self.label.clone()),
})?,
)
.await?;
closure.forget();
let unlisten_drag_over = js_sys::Function::from(unlisten);
let closure = {
let tx = tx.clone();
Closure::<dyn FnMut(JsValue)>::new(move |raw| {
let Event { event, id, .. } =
serde_wasm_bindgen::from_value::<Event<()>>(raw).unwrap();
let _ = tx.unbounded_send(Event {
event,
id,
payload: DragDropEvent::Cancelled,
});
})
};
let unlisten = event::inner::listen(
event::DROP_CANCELLED,
&closure,
serde_wasm_bindgen::to_value(&event::Options {
target: event::EventTarget::Window(self.label.clone()),
})?,
)
.await?;
closure.forget();
let unlisten_cancel = js_sys::Function::from(unlisten);
Ok(DragDropListen {
rx,
unlisten_drag,
unlisten_drop,
unlisten_drag_over,
unlisten_cancel,
})
}
}
#[derive(Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Monitor {
/// Human-readable name of the monitor.
name: Option<String>,
/// The monitor's resolution.
size: dpi::PhysicalSize,
/// the Top-left corner position of the monitor relative to the larger full screen area.
position: dpi::PhysicalPosition,
/// The scale factor that can be used to map physical pixels to logical pixels.
scale_factor: f64,
}
impl Monitor {
pub fn name(&self) -> &Option<String> {
&self.name
}
pub fn size(&self) -> &dpi::PhysicalSize {
&self.size
}
pub fn position(&self) -> &dpi::PhysicalPosition {
&self.position
}
pub fn scale_factor(&self) -> f64 {
self.scale_factor
}
}
pub fn get_current() -> Window {
let WindowLabel { label } = serde_wasm_bindgen::from_value(inner::get_current()).unwrap();
Window::new(label)
}
pub fn get_all() -> Vec<Window> {
js_sys::try_iter(&inner::get_all())
.unwrap()
.unwrap()
.into_iter()
.map(|value| {
let WindowLabel { label } = serde_wasm_bindgen::from_value(value.unwrap()).unwrap();
Window::new(label)
})
.collect()
}
/// # Returns
/// Monitor on which the window currently resides.
pub async fn current_monitor() -> Option<Monitor> {
let value = inner::current_monitor().await;
if value.is_null() {
None
} else {
Some(serde_wasm_bindgen::from_value(value).unwrap())
}
}
/// # Returns
/// Primary monitor of the system.
pub async fn primary_monitor() -> Option<Monitor> {
let value = inner::primary_monitor().await;
if value.is_null() {
None
} else {
Some(serde_wasm_bindgen::from_value(value).unwrap())
}
}
/// # Returns
/// Monitor that contains the given point.
pub async fn monitor_from_point(x: isize, y: isize) -> Option<Monitor> {
let value = inner::monitor_from_point(x, y).await;
if value.is_null() {
None
} else {
Some(serde_wasm_bindgen::from_value(value).unwrap())
}
}
/// # Returns
/// All the monitors available on the system.
pub async fn available_monitors() -> Vec<Monitor> {
let value = inner::available_monitors().await;
js_sys::try_iter(&value)
.unwrap()
.unwrap()
.into_iter()
.map(|value| serde_wasm_bindgen::from_value(value.unwrap()).unwrap())
.collect()
}
// TODO: Issue with cursorPosition in Tauri.
// See: https://github.com/tauri-apps/tauri/issues/10340
///// Get the cursor position relative to the top-left hand corner of the desktop.
/////
///// Note that the top-left hand corner of the desktop is not necessarily the same as the screen.
///// If the user uses a desktop with multiple monitors,
///// the top-left hand corner of the desktop is the top-left hand corner of the main monitor on Windows and macOS
///// or the top-left of the leftmost monitor on X11.
/////
///// The coordinates can be negative if the top-left hand corner of the window is outside of the visible screen region.
//pub async fn cursor_position() -> PhysicalPosition {
// serde_wasm_bindgen::from_value(inner::cursor_position().await).unwrap()
//}
mod inner {
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
#[wasm_bindgen(module = "/src/window.js")]
extern "C" {
#[wasm_bindgen(js_name = "getCurrent")]
pub fn get_current() -> JsValue;
#[wasm_bindgen(js_name = "getAll")]
pub fn get_all() -> JsValue;
#[wasm_bindgen(js_name = "currentMonitor")]
pub async fn current_monitor() -> JsValue;
#[wasm_bindgen(js_name = "primaryMonitor")]
pub async fn primary_monitor() -> JsValue;
#[wasm_bindgen(js_name = "monitorFromPoint")]
pub async fn monitor_from_point(x: isize, y: isize) -> JsValue;
#[wasm_bindgen(js_name = "availableMonitors")]
pub async fn available_monitors() -> JsValue;
#[wasm_bindgen(js_name = "cursorPosition")]
pub async fn cursor_position() -> JsValue;
}
}
// partial mocks
/*
pub enum Theme {
Light,
Dark,
}
/// Attention type to request on a window.
pub enum UserAttentionType {
/// # Platform-specific
/// - **macOS:** Bounces the dock icon until the application is in focus.
/// - **Windows:** Flashes both the window and the taskbar button until the application is in focus.
Critical = 1,
/// # Platform-specific
/// - **macOS:** Bounces the dock icon once.
/// - **Windows:** Flashes the taskbar button until the application is in focus.
Informational,
}
impl Window {
/// The scale factor that can be used to map physical pixels to logical pixels.
pub async fn scale_factor(&self) -> dpi::ScaleFactor {
todo!();
}
/// The position of the top-left hand corner of the window's client area relative to the top-left hand corner of the desktop.
pub async fn inner_position(&self) -> dpi::PhysicalPosition {
todo!();
}
/// The position of the top-left hand corner of the window relative to the top-left hand corner of the desktop.
pub async fn outer_position(&self) -> dpi::PhysicalPosition {
todo!();
}
/// The physical size of the window's client area.
/// The client area is the content of the window, excluding the title bar and borders.
pub async fn inner_size(&self) -> dpi::PhysicalSize {
todo!();
}
/// The physical size of the entire window.
/// These dimensions include the title bar and borders. If you don't want that (and you usually don't), use inner_size instead.
pub async fn outer_size(&self) -> dpi::PhysicalSize {
todo!();
}
/// Gets the window's current fullscreen state.
pub async fn is_fullscreen(&self) -> bool {
todo!();
}
/// Gets the window's current minimized state.
pub async fn is_minimized(&self) -> bool {
todo!();
}
/// Gets the window's current maximized state.
pub async fn is_maximized(&self) -> bool {
todo!();
}
/// Gets the window's current focused state.
pub async fn is_focused(&self) -> bool {
todo!();
}
/// Gets the window's current decorated state.
pub async fn is_decorated(&self) -> bool {
todo!();
}
/// Gets the window's current resizable state.
pub async fn is_resizable(&self) -> bool {
todo!();
}
/// Gets the window's current visible state.
pub async fn is_visible(&self) -> bool {
todo!();
}
/// Gets the window's current title.
pub async fn title(&self) -> String {
todo!();
}
/// Gets the window's current theme.
pub async fn theme(&self) -> Option<Theme> {
todo!();
}
}
/// # Platform-specific
/// - **Linux / iOS / Android:** Unsupported.
impl Window {
/// Gets the window's native maximize button state.
///
/// # Platform-specific
/// - **Linux / iOS / Android:** Unsupported.
pub async fn is_maximizable(&self) -> bool {
todo!();
}
/// Gets the window's native minimize button state.
///
/// # Platform-specific
/// - **Linux / iOS / Android:** Unsupported.
pub async fn is_minimizable(&self) -> bool {
todo!();
}
/// Gets the window's native close button state.
///
/// # Platform-specific
/// - **Linux / iOS / Android:** Unsupported.
pub async fn is_closable(&self) -> bool {
todo!();
}
}
impl Window {
/// Centers the window.
///
/// # Returns
/// The success or failure of the operation.
pub async fn center(&self) -> Result<(), ()> {
todo!();
}
/// Requests user attention to the window, this has no effect if the application
/// is already focused. How requesting for user attention manifests is platform dependent,
/// see `UserAttentionType` for details.
///
/// Providing `null` will unset the request for user attention. Unsetting the request for
/// user attention might not be done automatically by the WM when the window receives input.
///
/// # Platform-specific
/// - **macOS:** `null` has no effect.
/// - **Linux:** Urgency levels have the same effect.
///
/// # Returns
/// The success or failure of the operation.
pub async fn request_user_attention() -> Result<(), ()> {
todo!();
}
/// Requests user attention to the window, this has no effect if the application
/// is already focused. How requesting for user attention manifests is platform dependent,
/// see `UserAttentionType` for details.
///
/// Providing `null` will unset the request for user attention. Unsetting the request for
/// user attention might not be done automatically by the WM when the window receives input.
///
/// # Platform-specific
/// - **macOS:** `null` has no effect.
/// - **Linux:** Urgency levels have the same effect.
///
/// # Returns
/// The success or failure of the operation.
pub async fn request_user_attention_with_type(
request_type: UserAttentionType,
) -> Result<(), ()> {
todo!();
}
/// Updates the window resizable flag.
///
/// # Returns
/// The success or failure of the operation.
pub async fn set_resizable(&self, resizable: bool) -> Result<(), ()> {
todo!();
}
}
*/