feat(tray): add enter, move and leave events (#9777)

* feat(tray): add `enter`, `move` and `leave` events

closes #8584

* update api example

* check button state [skip ci]

* fix enum [skip ci]

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
Co-authored-by: Lucas Nogueira <lucas@tauri.app>
This commit is contained in:
Amr Bashir 2024-05-24 20:56:32 +03:00 committed by GitHub
parent 276c4b1438
commit c4410daa85
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 236 additions and 84 deletions

View File

@ -0,0 +1,10 @@
---
"tauri": "patch:breaking"
"@tauri-apps/api": "patch:breaking"
---
This release contains breaking changes to the tray event structure because of newly added events:
- Changed `TrayIconEvent` to be an enum instead of a struct.
- Added `MouseButtonState` and `MouseButton` enums.
- Removed `ClickType` enum and replaced it with `MouseButton` enum.
- Added `MouseButtonState` enum.

4
Cargo.lock generated
View File

@ -4077,9 +4077,9 @@ dependencies = [
[[package]]
name = "tray-icon"
version = "0.13.5"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39240037d755a1832e752d64f99078c3b0b21c09a71c12405070c75ef4e7cd3c"
checksum = "f79da804c7d1fd82da182b39d4fe5ac1044b08117358b23b41daf88840a3e70d"
dependencies = [
"cocoa",
"core-graphics",

View File

@ -79,7 +79,7 @@ specta = { version = "^2.0.0-rc.9", optional = true, default-features = false, f
[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"windows\", target_os = \"macos\"))".dependencies]
muda = { version = "0.13.4", default-features = false, features = [ "serde" ] }
tray-icon = { version = "0.13", default-features = false, features = [ "serde" ], optional = true }
tray-icon = { version = "0.14", default-features = false, features = [ "serde" ], optional = true }
[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
gtk = { version = "0.18", features = [ "v3_24" ] }

View File

@ -1947,7 +1947,7 @@ fn on_event_loop_event<R: Runtime>(
}
for (id, listener) in &*app_handle.manager.tray.event_listeners.lock().unwrap() {
if e.id == id {
if e.id() == id {
if let Some(tray) = app_handle.tray_by_id(id) {
listener(&tray, e.clone());
}

View File

@ -19,69 +19,165 @@ use serde::Serialize;
use std::path::Path;
pub use tray_icon::TrayIconId;
/// Describes the click type that triggered this tray icon event.
/// Describes the mouse button state.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize)]
pub enum ClickType {
/// Left mouse click.
Left,
/// Right mouse click.
Right,
/// Double left mouse click.
Double,
pub enum MouseButtonState {
/// Mouse button pressed.
Up,
/// Mouse button released.
Down,
}
impl Default for ClickType {
impl Default for MouseButtonState {
fn default() -> Self {
Self::Up
}
}
impl From<tray_icon::MouseButtonState> for MouseButtonState {
fn from(value: tray_icon::MouseButtonState) -> Self {
match value {
tray_icon::MouseButtonState::Up => MouseButtonState::Up,
tray_icon::MouseButtonState::Down => MouseButtonState::Down,
}
}
}
/// Describes which mouse button triggered the event..
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize)]
pub enum MouseButton {
/// Left mouse button.
Left,
/// Right mouse button.
Right,
/// Middle mouse button.
Middle,
}
impl Default for MouseButton {
fn default() -> Self {
Self::Left
}
}
/// Describes a tray event emitted when a tray icon is clicked
///
/// ## Platform-specific:
///
/// - **Linux**: Unsupported. The event is not emitted even though the icon is shown,
/// the icon will still show a context menu on right click.
#[derive(Debug, Clone, Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TrayIconEvent {
/// Id of the tray icon which triggered this event.
pub id: TrayIconId,
/// Physical Position of the click the triggered this event.
pub position: PhysicalPosition<f64>,
/// Position and size of the tray icon
pub icon_rect: Rect,
/// The click type that triggered this event.
pub click_type: ClickType,
}
impl TrayIconEvent {
/// Returns the id of the tray icon which triggered this event.
pub fn id(&self) -> &TrayIconId {
&self.id
impl From<tray_icon::MouseButton> for MouseButton {
fn from(value: tray_icon::MouseButton) -> Self {
match value {
tray_icon::MouseButton::Left => MouseButton::Left,
tray_icon::MouseButton::Right => MouseButton::Right,
tray_icon::MouseButton::Middle => MouseButton::Middle,
}
}
}
impl From<tray_icon::ClickType> for ClickType {
fn from(value: tray_icon::ClickType) -> Self {
match value {
tray_icon::ClickType::Left => Self::Left,
tray_icon::ClickType::Right => Self::Right,
tray_icon::ClickType::Double => Self::Double,
/// Describes a tray icon event.
///
/// ## Platform-specific:
///
/// - **Linux**: Unsupported. The event is not emmited even though the icon is shown
/// and will still show a context menu on right click.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub enum TrayIconEvent {
/// A click happened on the tray icon.
Click {
/// Id of the tray icon which triggered this event.
id: TrayIconId,
/// Physical Position of this event.
position: PhysicalPosition<f64>,
/// Position and size of the tray icon.
rect: Rect,
/// Mouse button that triggered this event.
button: MouseButton,
/// Mouse button state when this event was triggered.
button_state: MouseButtonState,
},
/// The mouse entered the tray icon region.
Enter {
/// Id of the tray icon which triggered this event.
id: TrayIconId,
/// Physical Position of this event.
position: PhysicalPosition<f64>,
/// Position and size of the tray icon.
rect: Rect,
},
/// The mouse moved over the tray icon region.
Move {
/// Id of the tray icon which triggered this event.
id: TrayIconId,
/// Physical Position of this event.
position: PhysicalPosition<f64>,
/// Position and size of the tray icon.
rect: Rect,
},
/// The mouse left the tray icon region.
Leave {
/// Id of the tray icon which triggered this event.
id: TrayIconId,
/// Physical Position of this event.
position: PhysicalPosition<f64>,
/// Position and size of the tray icon.
rect: Rect,
},
}
impl TrayIconEvent {
/// Get the id of the tray icon that triggered this event.
pub fn id(&self) -> &TrayIconId {
match self {
TrayIconEvent::Click { id, .. } => id,
TrayIconEvent::Enter { id, .. } => id,
TrayIconEvent::Move { id, .. } => id,
TrayIconEvent::Leave { id, .. } => id,
}
}
}
impl From<tray_icon::TrayIconEvent> for TrayIconEvent {
fn from(value: tray_icon::TrayIconEvent) -> Self {
Self {
id: value.id,
position: value.position,
icon_rect: Rect {
position: value.icon_rect.position.into(),
size: value.icon_rect.size.into(),
match value {
tray_icon::TrayIconEvent::Click {
id,
position,
rect,
button,
button_state,
} => TrayIconEvent::Click {
id,
position,
rect: Rect {
position: rect.position.into(),
size: rect.size.into(),
},
button: button.into(),
button_state: button_state.into(),
},
click_type: value.click_type.into(),
tray_icon::TrayIconEvent::Enter { id, position, rect } => TrayIconEvent::Enter {
id,
position,
rect: Rect {
position: rect.position.into(),
size: rect.size.into(),
},
},
tray_icon::TrayIconEvent::Move { id, position, rect } => TrayIconEvent::Move {
id,
position,
rect: Rect {
position: rect.position.into(),
size: rect.size.into(),
},
},
tray_icon::TrayIconEvent::Leave { id, position, rect } => TrayIconEvent::Leave {
id,
position,
rect: Rect {
position: rect.position.into(),
size: rect.size.into(),
},
},
_ => todo!(),
}
}
}

View File

@ -107,7 +107,6 @@ dependencies = [
"tauri",
"tauri-build",
"tauri-plugin-sample",
"tauri-plugin-xcode",
"tiny_http",
]
@ -3140,16 +3139,6 @@ dependencies = [
"thiserror",
]
[[package]]
name = "tauri-plugin-xcode"
version = "0.0.0"
dependencies = [
"serde",
"tauri",
"tauri-plugin",
"thiserror",
]
[[package]]
name = "tauri-runtime"
version = "2.0.0-beta.17"
@ -3521,9 +3510,9 @@ dependencies = [
[[package]]
name = "tray-icon"
version = "0.13.5"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39240037d755a1832e752d64f99078c3b0b21c09a71c12405070c75ef4e7cd3c"
checksum = "f79da804c7d1fd82da182b39d4fe5ac1044b08117358b23b41daf88840a3e70d"
dependencies = [
"cocoa",
"core-graphics",

View File

@ -5,7 +5,7 @@
use std::sync::atomic::{AtomicBool, Ordering};
use tauri::{
menu::{Menu, MenuItem},
tray::{ClickType, TrayIconBuilder},
tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent},
Manager, Runtime, WebviewUrl,
};
@ -108,7 +108,12 @@ pub fn create_tray<R: Runtime>(app: &tauri::AppHandle<R>) -> tauri::Result<()> {
_ => {}
})
.on_tray_icon_event(|tray, event| {
if event.click_type == ClickType::Left {
if let TrayIconEvent::Click {
button: MouseButton::Left,
button_state: MouseButtonState::Up,
..
} = event
{
let app = tray.app_handle();
if let Some(window) = app.get_webview_window("main") {
let _ = window.show();

View File

@ -5,16 +5,13 @@
import type { Menu, Submenu } from './menu'
import { Channel, invoke, Resource } from './core'
import { Image, transformImage } from './image'
import { PhysicalPosition, PhysicalSize } from './dpi'
/**
* Describes a tray event emitted when a tray icon is clicked
*
* #### Platform-specific:
*
* - **Linux**: Unsupported. The event is not emitted even though the icon is shown,
* the icon will still show a context menu on right click.
*/
export interface TrayIconEvent {
export type MouseButtonState = 'Up' | 'Down'
export type MouseButton = 'Left' | 'Right' | 'Middle'
/** A click happened on the tray icon. */
export interface TrayIconClickEvent {
/** Id of the tray icon which triggered this event. */
id: string
/** Physical X Position of the click the triggered this event. */
@ -22,20 +19,75 @@ export interface TrayIconEvent {
/** Physical Y Position of the click the triggered this event. */
y: number
/** Position and size of the tray icon. */
iconRect: {
/** The x-coordinate of the upper-left corner of the rectangle. */
left: number
/** The y-coordinate of the upper-left corner of the rectangle. */
top: number
/** The x-coordinate of the lower-right corner of the rectangle. */
right: number
/** The y-coordinate of the lower-right corner of the rectangle. */
bottom: number
rect: {
position: PhysicalPosition
size: PhysicalSize
}
/** The click type that triggered this event. */
clickType: 'Left' | 'Right' | 'Double'
/** Mouse button that triggered this event. */
button: MouseButton
/** Mouse button state when this event was triggered. */
button_state: MouseButtonState
}
/** The mouse entered the tray icon region. */
export interface TrayIconEnterEvent {
/** Id of the tray icon which triggered this event. */
id: string
/** Physical X Position of the click the triggered this event. */
x: number
/** Physical Y Position of the click the triggered this event. */
y: number
/** Position and size of the tray icon. */
rect: {
position: PhysicalPosition
size: PhysicalSize
}
}
/** The mouse moved over the tray icon region. */
export interface TrayIconMoveEvent {
/** Id of the tray icon which triggered this event. */
id: string
/** Physical X Position of the click the triggered this event. */
x: number
/** Physical Y Position of the click the triggered this event. */
y: number
/** Position and size of the tray icon. */
rect: {
position: PhysicalPosition
size: PhysicalSize
}
}
/** The mouse left the tray icon region. */
export interface TrayIconLeaveEvent {
/** Id of the tray icon which triggered this event. */
id: string
/** Physical X Position of the click the triggered this event. */
x: number
/** Physical Y Position of the click the triggered this event. */
y: number
/** Position and size of the tray icon. */
rect: {
position: PhysicalPosition
size: PhysicalSize
}
}
/**
* Describes a tray icon event.
*
* #### Platform-specific:
*
* - **Linux**: Unsupported. The event is not emitted even though the icon is shown,
* the icon will still show a context menu on right click.
*/
export type TrayIconEvent =
| { click: TrayIconClickEvent }
| { enter: TrayIconEnterEvent }
| { move: TrayIconMoveEvent }
| { leave: TrayIconLeaveEvent }
/**
* Tray icon types and utilities.
*