mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-06-18 14:40:07 +02:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 57f6e45b27 | |||
| b65a193e6d |
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
"single-instance": minor:fix
|
||||||
|
---
|
||||||
|
|
||||||
|
**Breaking Change:** On Linux, the DBus ID/name will now be `<bundle-id>.SingleInstance` instead of `org.<bundle_id_underscores>.SingleInstance` to follow DBus specifications.
|
||||||
|
|
||||||
|
This will break the single-instance mechanism across different app versions if the app was installed multiple times.
|
||||||
|
|
||||||
|
Added `dbus_id` builder method, which can be used to restore previous behavior. For a bundle identifier of `com.tauri.my-example` this would be `dbus_id("org.com_tauri_my_example")`.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"single-instance": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Add `setup` function to run the single instance initialization manually, without waiting for the tauri setup hook to run.
|
||||||
Generated
+2
-2
@@ -6683,7 +6683,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-plugin-deep-link"
|
name = "tauri-plugin-deep-link"
|
||||||
version = "2.4.7"
|
version = "2.4.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dunce",
|
"dunce",
|
||||||
"plist",
|
"plist",
|
||||||
@@ -6961,7 +6961,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-plugin-single-instance"
|
name = "tauri-plugin-single-instance"
|
||||||
version = "2.4.0"
|
version = "2.3.7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"semver",
|
"semver",
|
||||||
"serde",
|
"serde",
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## \[2.4.7]
|
|
||||||
|
|
||||||
- [`8374e997`](https://github.com/tauri-apps/plugins-workspace/commit/8374e997b82c95516fc0c1f6d665d9fc3b52edf8) ([#3258](https://github.com/tauri-apps/plugins-workspace/pull/3258) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Fix runtime deep link registration failing on Linux when the app path has spaces.
|
|
||||||
|
|
||||||
## \[2.4.6]
|
## \[2.4.6]
|
||||||
|
|
||||||
- [`28048039`](https://github.com/tauri-apps/plugins-workspace/commit/28048039496e84b46847c008416d341f1349e30e) ([#3143](https://github.com/tauri-apps/plugins-workspace/pull/3143) by [@Tunglies](https://github.com/tauri-apps/plugins-workspace/../../Tunglies)) Fix clippy warnings. No user facing changes.
|
- [`28048039`](https://github.com/tauri-apps/plugins-workspace/commit/28048039496e84b46847c008416d341f1349e30e) ([#3143](https://github.com/tauri-apps/plugins-workspace/pull/3143) by [@Tunglies](https://github.com/tauri-apps/plugins-workspace/../../Tunglies)) Fix clippy warnings. No user facing changes.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "tauri-plugin-deep-link"
|
name = "tauri-plugin-deep-link"
|
||||||
version = "2.4.7"
|
version = "2.4.6"
|
||||||
description = "Set your Tauri application as the default handler for an URL"
|
description = "Set your Tauri application as the default handler for an URL"
|
||||||
authors = { workspace = true }
|
authors = { workspace = true }
|
||||||
license = { workspace = true }
|
license = { workspace = true }
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## \[2.2.10]
|
|
||||||
|
|
||||||
### Dependencies
|
|
||||||
|
|
||||||
- Upgraded to `deep-link-js@2.4.7`
|
|
||||||
|
|
||||||
## \[2.2.9]
|
## \[2.2.9]
|
||||||
|
|
||||||
### Dependencies
|
### Dependencies
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "deep-link-example",
|
"name": "deep-link-example",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2.2.10",
|
"version": "2.2.9",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tauri-apps/api": "^2.10.1",
|
"@tauri-apps/api": "^2.10.1",
|
||||||
"@tauri-apps/plugin-deep-link": "2.4.7"
|
"@tauri-apps/plugin-deep-link": "2.4.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tauri-apps/cli": "2.10.0",
|
"@tauri-apps/cli": "2.10.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@tauri-apps/plugin-deep-link",
|
"name": "@tauri-apps/plugin-deep-link",
|
||||||
"version": "2.4.7",
|
"version": "2.4.6",
|
||||||
"description": "Set your Tauri application as the default handler for an URL",
|
"description": "Set your Tauri application as the default handler for an URL",
|
||||||
"license": "MIT OR Apache-2.0",
|
"license": "MIT OR Apache-2.0",
|
||||||
"authors": [
|
"authors": [
|
||||||
|
|||||||
@@ -293,7 +293,7 @@ mod imp {
|
|||||||
.unwrap_or_else(|| bin.into_os_string())
|
.unwrap_or_else(|| bin.into_os_string())
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
.to_string();
|
.to_string();
|
||||||
let qualified_exec = format!("\"{}\" %u", exec);
|
let qualified_exec = format!("{} %u", exec);
|
||||||
|
|
||||||
let target = self.app.path().data_dir()?.join("applications");
|
let target = self.app.path().data_dir()?.join("applications");
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,5 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## \[2.4.0]
|
|
||||||
|
|
||||||
### Dependencies
|
|
||||||
|
|
||||||
- Upgraded to `deep-link@2.4.7`
|
|
||||||
|
|
||||||
### fix
|
|
||||||
|
|
||||||
- [`98e2c11e`](https://github.com/tauri-apps/plugins-workspace/commit/98e2c11eefc3ee562f1ed280efe7e8ea6ff0f3b0) ([#3194](https://github.com/tauri-apps/plugins-workspace/pull/3194) by [@mrquantumoff](https://github.com/tauri-apps/plugins-workspace/../../mrquantumoff)) **Breaking Change:** On Linux, the DBus ID/name will now be `<bundle-id>.SingleInstance` instead of `org.<bundle_id_underscores>.SingleInstance` to follow DBus specifications.
|
|
||||||
|
|
||||||
This will break the single-instance mechanism across different app versions if the app was installed multiple times.
|
|
||||||
|
|
||||||
Added `dbus_id` builder method, which can be used to restore previous behavior. For a bundle identifier of `com.tauri.my-example` this would be `dbus_id("org.com_tauri_my_example")`.
|
|
||||||
|
|
||||||
## \[2.3.7]
|
## \[2.3.7]
|
||||||
|
|
||||||
### Dependencies
|
### Dependencies
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "tauri-plugin-single-instance"
|
name = "tauri-plugin-single-instance"
|
||||||
version = "2.4.0"
|
version = "2.3.7"
|
||||||
description = "Ensure a single instance of your tauri app is running."
|
description = "Ensure a single instance of your tauri app is running."
|
||||||
authors = { workspace = true }
|
authors = { workspace = true }
|
||||||
license = { workspace = true }
|
license = { workspace = true }
|
||||||
@@ -22,7 +22,7 @@ serde_json = { workspace = true }
|
|||||||
tauri = { workspace = true }
|
tauri = { workspace = true }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
tauri-plugin-deep-link = { path = "../deep-link", version = "2.4.7", optional = true }
|
tauri-plugin-deep-link = { path = "../deep-link", version = "2.4.6", optional = true }
|
||||||
semver = { version = "1", optional = true }
|
semver = { version = "1", optional = true }
|
||||||
|
|
||||||
[target."cfg(target_os = \"windows\")".dependencies.windows-sys]
|
[target."cfg(target_os = \"windows\")".dependencies.windows-sys]
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
)]
|
)]
|
||||||
#![cfg(not(any(target_os = "android", target_os = "ios")))]
|
#![cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
|
||||||
use tauri::{plugin::TauriPlugin, AppHandle, Manager, Runtime};
|
use tauri::{plugin, plugin::TauriPlugin, AppHandle, Manager, RunEvent, Runtime};
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
#[path = "platform_impl/windows.rs"]
|
#[path = "platform_impl/windows.rs"]
|
||||||
@@ -34,6 +34,17 @@ pub fn init<R: Runtime, F: FnMut(&AppHandle<R>, Vec<String>, String) + Send + Sy
|
|||||||
Builder::new().callback(f).build()
|
Builder::new().callback(f).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Runs the single-instance setup flow with the given app and callback.
|
||||||
|
/// Use this when you need to run single-instance from your own plugin or app setup.
|
||||||
|
/// On Linux, pass `dbus_id` (e.g. `Some("com.mycompany.myapp".into())`); on other platforms it is ignored.
|
||||||
|
pub fn setup<R: Runtime, F: FnMut(&AppHandle<R>, Vec<String>, String) + Send + Sync + 'static>(
|
||||||
|
app: &AppHandle<R>,
|
||||||
|
callback: F,
|
||||||
|
dbus_id: Option<String>,
|
||||||
|
) -> Result<(), ()> {
|
||||||
|
platform_impl::setup_single_instance(app, Box::new(callback), dbus_id)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn destroy<R: Runtime, M: Manager<R>>(manager: &M) {
|
pub fn destroy<R: Runtime, M: Manager<R>>(manager: &M) {
|
||||||
platform_impl::destroy(manager)
|
platform_impl::destroy(manager)
|
||||||
}
|
}
|
||||||
@@ -89,10 +100,18 @@ impl<R: Runtime> Builder<R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(self) -> TauriPlugin<R> {
|
pub fn build(self) -> TauriPlugin<R> {
|
||||||
platform_impl::init(
|
let callback = self.callback;
|
||||||
self.callback,
|
let dbus_id = self.dbus_id;
|
||||||
#[cfg(target_os = "linux")]
|
plugin::Builder::new("single-instance")
|
||||||
self.dbus_id,
|
.setup(move |app, _api| {
|
||||||
)
|
let _ = platform_impl::setup_single_instance(app, callback, dbus_id);
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.on_event(|app, event| {
|
||||||
|
if let RunEvent::Exit = event {
|
||||||
|
destroy(app);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
use crate::semver_compat::semver_compat_string;
|
use crate::semver_compat::semver_compat_string;
|
||||||
|
|
||||||
use crate::SingleInstanceCallback;
|
use crate::SingleInstanceCallback;
|
||||||
use tauri::{
|
use tauri::{AppHandle, Manager, Runtime};
|
||||||
plugin::{self, TauriPlugin},
|
|
||||||
AppHandle, Manager, RunEvent, Runtime,
|
|
||||||
};
|
|
||||||
use zbus::{blocking::Connection, interface, names::WellKnownName};
|
use zbus::{blocking::Connection, interface, names::WellKnownName};
|
||||||
|
|
||||||
struct ConnectionHandle(Connection);
|
struct ConnectionHandle(Connection);
|
||||||
@@ -28,76 +25,69 @@ impl<R: Runtime> SingleInstanceDBus<R> {
|
|||||||
|
|
||||||
struct DBusName(String);
|
struct DBusName(String);
|
||||||
|
|
||||||
pub fn init<R: Runtime>(
|
pub fn setup_single_instance<R: Runtime>(
|
||||||
|
app: &AppHandle<R>,
|
||||||
callback: Box<SingleInstanceCallback<R>>,
|
callback: Box<SingleInstanceCallback<R>>,
|
||||||
dbus_id: Option<String>,
|
dbus_id: Option<String>,
|
||||||
) -> TauriPlugin<R> {
|
) -> Result<(), ()> {
|
||||||
plugin::Builder::new("single-instance")
|
let mut dbus_name = dbus_id.unwrap_or_else(|| app.config().identifier.clone());
|
||||||
.setup(move |app, _api| {
|
|
||||||
let mut dbus_name = dbus_id.unwrap_or_else(|| app.config().identifier.clone());
|
|
||||||
dbus_name.push_str(".SingleInstance");
|
|
||||||
|
|
||||||
#[cfg(feature = "semver")]
|
#[cfg(feature = "semver")]
|
||||||
{
|
{
|
||||||
dbus_name.push('_');
|
dbus_name.push('_');
|
||||||
dbus_name.push_str(semver_compat_string(&app.package_info().version).as_str());
|
dbus_name.push_str(semver_compat_string(&app.package_info().version).as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut dbus_path = dbus_name.replace('.', "/").replace('-', "_");
|
dbus_name.push_str(".SingleInstance");
|
||||||
if !dbus_path.starts_with('/') {
|
|
||||||
dbus_path = format!("/{dbus_path}");
|
|
||||||
}
|
|
||||||
|
|
||||||
let single_instance_dbus = SingleInstanceDBus {
|
let mut dbus_path = dbus_name.replace('.', "/").replace('-', "_");
|
||||||
callback,
|
if !dbus_path.starts_with('/') {
|
||||||
app_handle: app.clone(),
|
dbus_path = format!("/{dbus_path}");
|
||||||
};
|
}
|
||||||
|
|
||||||
match zbus::blocking::connection::Builder::session()
|
let single_instance_dbus = SingleInstanceDBus {
|
||||||
.unwrap()
|
callback,
|
||||||
.name(dbus_name.as_str())
|
app_handle: app.clone(),
|
||||||
.unwrap()
|
};
|
||||||
.replace_existing_names(false)
|
|
||||||
.allow_name_replacements(false)
|
|
||||||
.serve_at(dbus_path.as_str(), single_instance_dbus)
|
|
||||||
.unwrap()
|
|
||||||
.build()
|
|
||||||
{
|
|
||||||
Ok(connection) => {
|
|
||||||
app.manage(ConnectionHandle(connection));
|
|
||||||
}
|
|
||||||
Err(zbus::Error::NameTaken) => {
|
|
||||||
if let Ok(connection) = Connection::session() {
|
|
||||||
let _ = connection.call_method(
|
|
||||||
Some(dbus_name.as_str()),
|
|
||||||
dbus_path.as_str(),
|
|
||||||
Some("org.SingleInstance.DBus"),
|
|
||||||
"ExecuteCallback",
|
|
||||||
&(
|
|
||||||
std::env::args().collect::<Vec<String>>(),
|
|
||||||
std::env::current_dir()
|
|
||||||
.unwrap_or_default()
|
|
||||||
.to_str()
|
|
||||||
.unwrap_or_default(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
app.cleanup_before_exit();
|
|
||||||
std::process::exit(0);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
app.manage(DBusName(dbus_name));
|
match zbus::blocking::connection::Builder::session()
|
||||||
|
.unwrap()
|
||||||
Ok(())
|
.name(dbus_name.as_str())
|
||||||
})
|
.unwrap()
|
||||||
.on_event(move |app, event| {
|
.replace_existing_names(false)
|
||||||
if let RunEvent::Exit = event {
|
.allow_name_replacements(false)
|
||||||
destroy(app);
|
.serve_at(dbus_path.as_str(), single_instance_dbus)
|
||||||
}
|
.unwrap()
|
||||||
})
|
|
||||||
.build()
|
.build()
|
||||||
|
{
|
||||||
|
Ok(connection) => {
|
||||||
|
app.manage(ConnectionHandle(connection));
|
||||||
|
}
|
||||||
|
Err(zbus::Error::NameTaken) => {
|
||||||
|
if let Ok(connection) = Connection::session() {
|
||||||
|
let _ = connection.call_method(
|
||||||
|
Some(dbus_name.as_str()),
|
||||||
|
dbus_path.as_str(),
|
||||||
|
Some("org.SingleInstance.DBus"),
|
||||||
|
"ExecuteCallback",
|
||||||
|
&(
|
||||||
|
std::env::args().collect::<Vec<String>>(),
|
||||||
|
std::env::current_dir()
|
||||||
|
.unwrap_or_default()
|
||||||
|
.to_str()
|
||||||
|
.unwrap_or_default(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
app.cleanup_before_exit();
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
app.manage(DBusName(dbus_name));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy<R: Runtime, M: Manager<R>>(manager: &M) {
|
pub fn destroy<R: Runtime, M: Manager<R>>(manager: &M) {
|
||||||
|
|||||||
@@ -11,45 +11,37 @@ use std::{
|
|||||||
#[cfg(feature = "semver")]
|
#[cfg(feature = "semver")]
|
||||||
use crate::semver_compat::semver_compat_string;
|
use crate::semver_compat::semver_compat_string;
|
||||||
use crate::SingleInstanceCallback;
|
use crate::SingleInstanceCallback;
|
||||||
use tauri::{
|
use tauri::{AppHandle, Config, Manager, Runtime};
|
||||||
plugin::{self, TauriPlugin},
|
|
||||||
AppHandle, Config, Manager, RunEvent, Runtime,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn init<R: Runtime>(cb: Box<SingleInstanceCallback<R>>) -> TauriPlugin<R> {
|
pub fn setup_single_instance<R: Runtime>(
|
||||||
plugin::Builder::new("single-instance")
|
app: &AppHandle<R>,
|
||||||
.setup(|app, _api| {
|
cb: Box<SingleInstanceCallback<R>>,
|
||||||
let socket = socket_path(app.config(), app.package_info());
|
_dbus_id: Option<String>,
|
||||||
|
) -> Result<(), ()> {
|
||||||
|
let socket = socket_path(app.config(), app.package_info());
|
||||||
|
|
||||||
// Notify the singleton which may or may not exist.
|
// Notify the singleton which may or may not exist.
|
||||||
match notify_singleton(&socket) {
|
match notify_singleton(&socket) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
match e.kind() {
|
||||||
|
ErrorKind::NotFound | ErrorKind::ConnectionRefused => {
|
||||||
|
// This process claims itself as singleton as likely none exists
|
||||||
|
socket_cleanup(&socket);
|
||||||
|
listen_for_other_instances(&socket, app.clone(), cb);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
_ => {
|
||||||
match e.kind() {
|
tracing::debug!(
|
||||||
ErrorKind::NotFound | ErrorKind::ConnectionRefused => {
|
"single_instance failed to notify - launching normally: {}",
|
||||||
// This process claims itself as singleton as likely none exists
|
e
|
||||||
socket_cleanup(&socket);
|
);
|
||||||
listen_for_other_instances(&socket, app.clone(), cb);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
tracing::debug!(
|
|
||||||
"single_instance failed to notify - launching normally: {}",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
}
|
||||||
})
|
}
|
||||||
.on_event(|app, event| {
|
Ok(())
|
||||||
if let RunEvent::Exit = event {
|
|
||||||
destroy(app);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.build()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy<R: Runtime, M: Manager<R>>(manager: &M) {
|
pub fn destroy<R: Runtime, M: Manager<R>>(manager: &M) {
|
||||||
|
|||||||
@@ -7,10 +7,7 @@ use crate::semver_compat::semver_compat_string;
|
|||||||
|
|
||||||
use crate::SingleInstanceCallback;
|
use crate::SingleInstanceCallback;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use tauri::{
|
use tauri::{AppHandle, Manager, Runtime};
|
||||||
plugin::{self, TauriPlugin},
|
|
||||||
AppHandle, Manager, RunEvent, Runtime,
|
|
||||||
};
|
|
||||||
use windows_sys::Win32::{
|
use windows_sys::Win32::{
|
||||||
Foundation::{CloseHandle, GetLastError, ERROR_ALREADY_EXISTS, HWND, LPARAM, LRESULT, WPARAM},
|
Foundation::{CloseHandle, GetLastError, ERROR_ALREADY_EXISTS, HWND, LPARAM, LRESULT, WPARAM},
|
||||||
System::{
|
System::{
|
||||||
@@ -51,69 +48,63 @@ impl<R: Runtime> UserData<R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init<R: Runtime>(callback: Box<SingleInstanceCallback<R>>) -> TauriPlugin<R> {
|
pub fn setup_single_instance<R: Runtime>(
|
||||||
plugin::Builder::new("single-instance")
|
app: &AppHandle<R>,
|
||||||
.setup(|app, _api| {
|
callback: Box<SingleInstanceCallback<R>>,
|
||||||
#[allow(unused_mut)]
|
_dbus_id: Option<String>,
|
||||||
let mut id = app.config().identifier.clone();
|
) -> Result<(), ()> {
|
||||||
#[cfg(feature = "semver")]
|
#[allow(unused_mut)]
|
||||||
{
|
let mut id = app.config().identifier.clone();
|
||||||
id.push('_');
|
#[cfg(feature = "semver")]
|
||||||
id.push_str(semver_compat_string(&app.package_info().version).as_str());
|
{
|
||||||
}
|
id.push('_');
|
||||||
|
id.push_str(semver_compat_string(&app.package_info().version).as_str());
|
||||||
|
}
|
||||||
|
|
||||||
let class_name = encode_wide(format!("{id}-sic"));
|
let class_name = encode_wide(format!("{id}-sic"));
|
||||||
let window_name = encode_wide(format!("{id}-siw"));
|
let window_name = encode_wide(format!("{id}-siw"));
|
||||||
let mutex_name = encode_wide(format!("{id}-sim"));
|
let mutex_name = encode_wide(format!("{id}-sim"));
|
||||||
|
|
||||||
let hmutex =
|
let hmutex = unsafe { CreateMutexW(std::ptr::null(), true.into(), mutex_name.as_ptr()) };
|
||||||
unsafe { CreateMutexW(std::ptr::null(), true.into(), mutex_name.as_ptr()) };
|
|
||||||
|
|
||||||
if unsafe { GetLastError() } == ERROR_ALREADY_EXISTS {
|
if unsafe { GetLastError() } == ERROR_ALREADY_EXISTS {
|
||||||
unsafe {
|
unsafe {
|
||||||
let hwnd = FindWindowW(class_name.as_ptr(), window_name.as_ptr());
|
let hwnd = FindWindowW(class_name.as_ptr(), window_name.as_ptr());
|
||||||
|
|
||||||
if !hwnd.is_null() {
|
if !hwnd.is_null() {
|
||||||
let cwd = std::env::current_dir().unwrap_or_default();
|
let cwd = std::env::current_dir().unwrap_or_default();
|
||||||
let cwd = cwd.to_str().unwrap_or_default();
|
let cwd = cwd.to_str().unwrap_or_default();
|
||||||
|
|
||||||
let args = std::env::args().collect::<Vec<String>>().join("|");
|
let args = std::env::args().collect::<Vec<String>>().join("|");
|
||||||
|
|
||||||
let data = format!("{cwd}|{args}\0",);
|
let data = format!("{cwd}|{args}\0",);
|
||||||
|
|
||||||
let bytes = data.as_bytes();
|
let bytes = data.as_bytes();
|
||||||
let cds = COPYDATASTRUCT {
|
let cds = COPYDATASTRUCT {
|
||||||
dwData: WMCOPYDATA_SINGLE_INSTANCE_DATA,
|
dwData: WMCOPYDATA_SINGLE_INSTANCE_DATA,
|
||||||
cbData: bytes.len() as _,
|
cbData: bytes.len() as _,
|
||||||
lpData: bytes.as_ptr() as _,
|
lpData: bytes.as_ptr() as _,
|
||||||
};
|
|
||||||
|
|
||||||
SendMessageW(hwnd, WM_COPYDATA, 0, &cds as *const _ as _);
|
|
||||||
|
|
||||||
app.cleanup_before_exit();
|
|
||||||
std::process::exit(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
app.manage(MutexHandle(hmutex as _));
|
|
||||||
|
|
||||||
let userdata = UserData {
|
|
||||||
app: app.clone(),
|
|
||||||
callback,
|
|
||||||
};
|
};
|
||||||
let userdata = Box::into_raw(Box::new(userdata));
|
|
||||||
let hwnd = create_event_target_window::<R>(&class_name, &window_name, userdata);
|
|
||||||
app.manage(TargetWindowHandle(hwnd as _));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
SendMessageW(hwnd, WM_COPYDATA, 0, &cds as *const _ as _);
|
||||||
})
|
|
||||||
.on_event(|app, event| {
|
app.cleanup_before_exit();
|
||||||
if let RunEvent::Exit = event {
|
std::process::exit(0);
|
||||||
destroy(app);
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.build()
|
} else {
|
||||||
|
app.manage(MutexHandle(hmutex as _));
|
||||||
|
|
||||||
|
let userdata = UserData {
|
||||||
|
app: app.clone(),
|
||||||
|
callback,
|
||||||
|
};
|
||||||
|
let userdata = Box::into_raw(Box::new(userdata));
|
||||||
|
let hwnd = create_event_target_window::<R>(&class_name, &window_name, userdata);
|
||||||
|
app.manage(TargetWindowHandle(hwnd as _));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy<R: Runtime, M: Manager<R>>(manager: &M) {
|
pub fn destroy<R: Runtime, M: Manager<R>>(manager: &M) {
|
||||||
|
|||||||
Generated
+1
-1
@@ -189,7 +189,7 @@ importers:
|
|||||||
specifier: ^2.10.1
|
specifier: ^2.10.1
|
||||||
version: 2.10.1
|
version: 2.10.1
|
||||||
'@tauri-apps/plugin-deep-link':
|
'@tauri-apps/plugin-deep-link':
|
||||||
specifier: 2.4.7
|
specifier: 2.4.6
|
||||||
version: link:../..
|
version: link:../..
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@tauri-apps/cli':
|
'@tauri-apps/cli':
|
||||||
|
|||||||
Reference in New Issue
Block a user