Skip to content

Commit

Permalink
feat: adds monitor_from_point method (#9770)
Browse files Browse the repository at this point in the history
  • Loading branch information
clearlysid committed May 14, 2024
1 parent 31aa90f commit ec0e092
Show file tree
Hide file tree
Showing 13 changed files with 122 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changes/monitor-from-point-js.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tauri-apps/api': 'patch:feat'
---

Add `monitorFromPoint` function in `window` module to get the monitor from a given point.
5 changes: 5 additions & 0 deletions .changes/monitor-from-point.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'tauri': 'patch:feat'
---

Add `App/AppHandle/Window/Webview/WebviewWindow::monitor_from_point(x, y)` getter to get the monitor from a given point.
37 changes: 37 additions & 0 deletions core/tauri-runtime-wry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,7 @@ pub enum WindowMessage {
Title(Sender<String>),
CurrentMonitor(Sender<Option<MonitorHandle>>),
PrimaryMonitor(Sender<Option<MonitorHandle>>),
MonitorFromPoint(Sender<Option<MonitorHandle>>, (f64, f64)),
AvailableMonitors(Sender<Vec<MonitorHandle>>),
#[cfg(any(
target_os = "linux",
Expand Down Expand Up @@ -1578,6 +1579,21 @@ impl<T: UserEvent> WindowDispatch<T> for WryWindowDispatcher<T> {
Ok(window_getter!(self, WindowMessage::PrimaryMonitor)?.map(|m| MonitorHandleWrapper(m).into()))
}

fn monitor_from_point(&self, x: f64, y: f64) -> Result<Option<Monitor>> {
let (tx, rx) = channel();

let _ = send_user_message(
&self.context,
Message::Window(self.window_id, WindowMessage::MonitorFromPoint(tx, (x, y))),
);

Ok(
rx.recv()
.map_err(|_| crate::Error::FailedToReceiveMessage)?
.map(|m| MonitorHandleWrapper(m).into()),
)
}

fn available_monitors(&self) -> Result<Vec<Monitor>> {
Ok(
window_getter!(self, WindowMessage::AvailableMonitors)?
Expand Down Expand Up @@ -2149,6 +2165,15 @@ impl<T: UserEvent> RuntimeHandle<T> for WryHandle<T> {
.map(|m| MonitorHandleWrapper(m).into())
}

fn monitor_from_point(&self, x: f64, y: f64) -> Option<Monitor> {
self
.context
.main_thread
.window_target
.monitor_from_point(x, y)
.map(|m| MonitorHandleWrapper(m).into())
}

fn available_monitors(&self) -> Vec<Monitor> {
self
.context
Expand Down Expand Up @@ -2407,6 +2432,15 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
.map(|m| MonitorHandleWrapper(m).into())
}

fn monitor_from_point(&self, x: f64, y: f64) -> Option<Monitor> {
self
.context
.main_thread
.window_target
.monitor_from_point(x, y)
.map(|m| MonitorHandleWrapper(m).into())
}

fn available_monitors(&self) -> Vec<Monitor> {
self
.context
Expand Down Expand Up @@ -2643,6 +2677,9 @@ fn handle_user_message<T: UserEvent>(
WindowMessage::Title(tx) => tx.send(window.title()).unwrap(),
WindowMessage::CurrentMonitor(tx) => tx.send(window.current_monitor()).unwrap(),
WindowMessage::PrimaryMonitor(tx) => tx.send(window.primary_monitor()).unwrap(),
WindowMessage::MonitorFromPoint(tx, (x, y)) => {
tx.send(window.monitor_from_point(x, y)).unwrap()
}
WindowMessage::AvailableMonitors(tx) => {
tx.send(window.available_monitors().collect()).unwrap()
}
Expand Down
5 changes: 5 additions & 0 deletions core/tauri-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ pub trait RuntimeHandle<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'st
fn display_handle(&self) -> std::result::Result<DisplayHandle, raw_window_handle::HandleError>;

fn primary_monitor(&self) -> Option<Monitor>;
fn monitor_from_point(&self, x: f64, y: f64) -> Option<Monitor>;
fn available_monitors(&self) -> Vec<Monitor>;

fn cursor_position(&self) -> Result<PhysicalPosition<f64>>;
Expand Down Expand Up @@ -382,6 +383,7 @@ pub trait Runtime<T: UserEvent>: Debug + Sized + 'static {
) -> Result<DetachedWebview<T, Self>>;

fn primary_monitor(&self) -> Option<Monitor>;
fn monitor_from_point(&self, x: f64, y: f64) -> Option<Monitor>;
fn available_monitors(&self) -> Vec<Monitor>;

fn cursor_position(&self) -> Result<PhysicalPosition<f64>>;
Expand Down Expand Up @@ -587,6 +589,9 @@ pub trait WindowDispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 's
/// Returns None if it can't identify any monitor as a primary one.
fn primary_monitor(&self) -> Result<Option<Monitor>>;

/// Returns the monitor that contains the given point.
fn monitor_from_point(&self, x: f64, y: f64) -> Result<Option<Monitor>>;

/// Returns the list of all the monitors available on the system.
fn available_monitors(&self) -> Result<Vec<Monitor>>;

Expand Down
1 change: 1 addition & 0 deletions core/tauri/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const PLUGINS: &[(&str, &[(&str, bool)])] = &[
("title", true),
("current_monitor", true),
("primary_monitor", true),
("monitor_from_point", true),
("available_monitors", true),
("cursor_position", true),
("theme", true),
Expand Down
2 changes: 2 additions & 0 deletions core/tauri/permissions/window/autogenerated/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
|`deny-maximize`|Denies the maximize command without any pre-configured scope.|
|`allow-minimize`|Enables the minimize command without any pre-configured scope.|
|`deny-minimize`|Denies the minimize command without any pre-configured scope.|
|`allow-monitor-from-point`|Enables the monitor_from_point command without any pre-configured scope.|
|`deny-monitor-from-point`|Denies the monitor_from_point command without any pre-configured scope.|
|`allow-outer-position`|Enables the outer_position command without any pre-configured scope.|
|`deny-outer-position`|Denies the outer_position command without any pre-configured scope.|
|`allow-outer-size`|Enables the outer_size command without any pre-configured scope.|
Expand Down
2 changes: 1 addition & 1 deletion core/tauri/scripts/bundle.global.js

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions core/tauri/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,15 @@ macro_rules! shared_app_impl {
})
}

/// Returns the monitor that contains the given point.
pub fn monitor_from_point(&self, x: f64, y: f64) -> crate::Result<Option<Monitor>> {
Ok(match self.runtime() {
RuntimeOrDispatch::Runtime(h) => h.monitor_from_point(x, y).map(Into::into),
RuntimeOrDispatch::RuntimeHandle(h) => h.monitor_from_point(x, y).map(Into::into),
_ => unreachable!(),
})
}

/// Returns the list of all the monitors available on the system.
pub fn available_monitors(&self) -> crate::Result<Vec<Monitor>> {
Ok(match self.runtime() {
Expand Down
12 changes: 12 additions & 0 deletions core/tauri/src/test/mock_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,10 @@ impl<T: UserEvent> RuntimeHandle<T> for MockRuntimeHandle {
unimplemented!()
}

fn monitor_from_point(&self, x: f64, y: f64) -> Option<Monitor> {
unimplemented!()
}

fn available_monitors(&self) -> Vec<Monitor> {
unimplemented!()
}
Expand Down Expand Up @@ -650,6 +654,10 @@ impl<T: UserEvent> WindowDispatch<T> for MockWindowDispatcher {
Ok(None)
}

fn monitor_from_point(&self, x: f64, y: f64) -> Result<Option<Monitor>> {
Ok(None)
}

fn available_monitors(&self) -> Result<Vec<Monitor>> {
Ok(Vec::new())
}
Expand Down Expand Up @@ -1054,6 +1062,10 @@ impl<T: UserEvent> Runtime<T> for MockRuntime {
unimplemented!()
}

fn monitor_from_point(&self, x: f64, y: f64) -> Option<Monitor> {
unimplemented!()
}

fn available_monitors(&self) -> Vec<Monitor> {
unimplemented!()
}
Expand Down
5 changes: 5 additions & 0 deletions core/tauri/src/webview/webview_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,11 @@ impl<R: Runtime> WebviewWindow<R> {
self.webview.window().primary_monitor()
}

/// Returns the monitor that contains the given point.
pub fn monitor_from_point(&self, x: f64, y: f64) -> crate::Result<Option<Monitor>> {
self.webview.window().monitor_from_point(x, y)
}

/// Returns the list of all the monitors available on the system.
pub fn available_monitors(&self) -> crate::Result<Vec<Monitor>> {
self.webview.window().available_monitors()
Expand Down
10 changes: 10 additions & 0 deletions core/tauri/src/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1437,6 +1437,16 @@ impl<R: Runtime> Window<R> {
.map_err(Into::into)
}

/// Returns the monitor that contains the given point.
pub fn monitor_from_point(&self, x: f64, y: f64) -> crate::Result<Option<Monitor>> {
self
.window
.dispatcher
.monitor_from_point(x, y)
.map(|m| m.map(Into::into))
.map_err(Into::into)
}

/// Returns the primary monitor of the system.
///
/// Returns None if it can't identify any monitor as a primary one.
Expand Down
12 changes: 12 additions & 0 deletions core/tauri/src/window/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,17 @@ mod desktop_commands {
}
Ok(())
}

#[command(root = "crate")]
pub async fn monitor_from_point<R: Runtime>(
window: Window<R>,
label: Option<String>,
x: f64,
y: f64,
) -> crate::Result<Option<Monitor>> {
let window = get_window(window, label)?;
window.monitor_from_point(x, y)
}
}

/// Initializes the plugin.
Expand Down Expand Up @@ -222,6 +233,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
desktop_commands::title,
desktop_commands::current_monitor,
desktop_commands::primary_monitor,
desktop_commands::monitor_from_point,
desktop_commands::available_monitors,
desktop_commands::cursor_position,
desktop_commands::theme,
Expand Down
18 changes: 18 additions & 0 deletions tooling/api/src/window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2240,6 +2240,23 @@ async function primaryMonitor(): Promise<Monitor | null> {
)
}

/**
* Returns the monitor that contains the given point. Returns `null` if can't find any.
* @example
* ```typescript
* import { monitorFromPoint } from '@tauri-apps/api/window';
* const monitor = monitorFromPoint();
* ```
*
* @since 1.0.0
*/
async function monitorFromPoint(x: number, y: number): Promise<Monitor | null> {
return invoke<Monitor | null>('plugin:window|monitor_from_point', {
x,
y
}).then(mapMonitor)
}

/**
* Returns the list of all the monitors available on the system.
* @example
Expand Down Expand Up @@ -2285,6 +2302,7 @@ export {
Effect,
EffectState,
currentMonitor,
monitorFromPoint,
primaryMonitor,
availableMonitors,
cursorPosition
Expand Down

0 comments on commit ec0e092

Please sign in to comment.