mirror of
https://github.com/tauri-apps/tauri.git
synced 2025-01-03 16:42:42 +03:00
feat: implement raw_window_handle
on Linux (#4469)
Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
This commit is contained in:
parent
82eb6e79e8
commit
3efbc67f74
7
.changes/linux-raw-window-handle.md
Normal file
7
.changes/linux-raw-window-handle.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
"tauri": "patch"
|
||||
"tauri-runtime": "patch"
|
||||
"tauri-runtime-wry": "patch"
|
||||
---
|
||||
|
||||
Implement `raw_window_handle::HasRawWindowHandle` on Linux.
|
6
.changes/runtime-remove-hwnd-ns_window.md
Normal file
6
.changes/runtime-remove-hwnd-ns_window.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
"tauri-runtime": minor
|
||||
"tauri-runtime-wry": minor
|
||||
---
|
||||
|
||||
Removed the `hwnd` and `ns_window` functions from `Dispatch` in favor of `raw_window_handle`.
|
@ -18,6 +18,7 @@ tauri-runtime = { version = "0.9.0", path = "../tauri-runtime" }
|
||||
tauri-utils = { version = "1.0.0", path = "../tauri-utils" }
|
||||
uuid = { version = "1", features = [ "v4" ] }
|
||||
rand = "0.8"
|
||||
raw-window-handle = "0.4.3"
|
||||
|
||||
[target."cfg(windows)".dependencies]
|
||||
webview2-com = "0.16.0"
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
//! The [`wry`] Tauri [`Runtime`].
|
||||
|
||||
use raw_window_handle::HasRawWindowHandle;
|
||||
use tauri_runtime::{
|
||||
http::{
|
||||
Request as HttpRequest, RequestParts as HttpRequestParts, Response as HttpResponse,
|
||||
@ -976,18 +977,6 @@ impl From<FileDropEventWrapper> for FileDropEvent {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub struct NSWindow(*mut std::ffi::c_void);
|
||||
#[cfg(target_os = "macos")]
|
||||
#[allow(clippy::non_send_fields_in_send_ty)]
|
||||
unsafe impl Send for NSWindow {}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub struct Hwnd(HWND);
|
||||
#[cfg(windows)]
|
||||
#[allow(clippy::non_send_fields_in_send_ty)]
|
||||
unsafe impl Send for Hwnd {}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "dragonfly",
|
||||
@ -1006,6 +995,9 @@ pub struct GtkWindow(gtk::ApplicationWindow);
|
||||
#[allow(clippy::non_send_fields_in_send_ty)]
|
||||
unsafe impl Send for GtkWindow {}
|
||||
|
||||
pub struct RawWindowHandle(raw_window_handle::RawWindowHandle);
|
||||
unsafe impl Send for RawWindowHandle {}
|
||||
|
||||
pub enum WindowMessage {
|
||||
WithWebview(Box<dyn FnOnce(Webview) + Send>),
|
||||
// Devtools
|
||||
@ -1030,10 +1022,6 @@ pub enum WindowMessage {
|
||||
CurrentMonitor(Sender<Option<MonitorHandle>>),
|
||||
PrimaryMonitor(Sender<Option<MonitorHandle>>),
|
||||
AvailableMonitors(Sender<Vec<MonitorHandle>>),
|
||||
#[cfg(target_os = "macos")]
|
||||
NSWindow(Sender<NSWindow>),
|
||||
#[cfg(windows)]
|
||||
Hwnd(Sender<Hwnd>),
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "dragonfly",
|
||||
@ -1042,6 +1030,7 @@ pub enum WindowMessage {
|
||||
target_os = "openbsd"
|
||||
))]
|
||||
GtkWindow(Sender<GtkWindow>),
|
||||
RawWindowHandle(Sender<RawWindowHandle>),
|
||||
Theme(Sender<Theme>),
|
||||
// Setters
|
||||
Center(Sender<Result<()>>),
|
||||
@ -1285,16 +1274,6 @@ impl<T: UserEvent> Dispatch<T> for WryDispatcher<T> {
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn ns_window(&self) -> Result<*mut std::ffi::c_void> {
|
||||
window_getter!(self, WindowMessage::NSWindow).map(|w| w.0)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn hwnd(&self) -> Result<HWND> {
|
||||
window_getter!(self, WindowMessage::Hwnd).map(|w| w.0)
|
||||
}
|
||||
|
||||
fn theme(&self) -> Result<Theme> {
|
||||
window_getter!(self, WindowMessage::Theme)
|
||||
}
|
||||
@ -1311,6 +1290,10 @@ impl<T: UserEvent> Dispatch<T> for WryDispatcher<T> {
|
||||
window_getter!(self, WindowMessage::GtkWindow).map(|w| w.0)
|
||||
}
|
||||
|
||||
fn raw_window_handle(&self) -> Result<raw_window_handle::RawWindowHandle> {
|
||||
window_getter!(self, WindowMessage::RawWindowHandle).map(|w| w.0)
|
||||
}
|
||||
|
||||
// Setters
|
||||
|
||||
fn center(&self) -> Result<()> {
|
||||
@ -2330,10 +2313,6 @@ fn handle_user_message<T: UserEvent>(
|
||||
WindowMessage::AvailableMonitors(tx) => {
|
||||
tx.send(window.available_monitors().collect()).unwrap()
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
WindowMessage::NSWindow(tx) => tx.send(NSWindow(window.ns_window())).unwrap(),
|
||||
#[cfg(windows)]
|
||||
WindowMessage::Hwnd(tx) => tx.send(Hwnd(HWND(window.hwnd() as _))).unwrap(),
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "dragonfly",
|
||||
@ -2344,6 +2323,9 @@ fn handle_user_message<T: UserEvent>(
|
||||
WindowMessage::GtkWindow(tx) => {
|
||||
tx.send(GtkWindow(window.gtk_window().clone())).unwrap()
|
||||
}
|
||||
WindowMessage::RawWindowHandle(tx) => tx
|
||||
.send(RawWindowHandle(window.raw_window_handle()))
|
||||
.unwrap(),
|
||||
WindowMessage::Theme(tx) => {
|
||||
#[cfg(any(windows, target_os = "macos"))]
|
||||
tx.send(map_theme(&window.theme())).unwrap();
|
||||
|
@ -31,6 +31,7 @@ uuid = { version = "1", features = [ "v4" ] }
|
||||
http = "0.2.4"
|
||||
http-range = "0.1.4"
|
||||
infer = "0.7"
|
||||
raw-window-handle = "0.4.3"
|
||||
|
||||
[target."cfg(windows)".dependencies]
|
||||
webview2-com = "0.16.0"
|
||||
|
@ -11,9 +11,6 @@ use std::{fmt::Debug, sync::mpsc::Sender};
|
||||
use tauri_utils::Theme;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[cfg(windows)]
|
||||
use windows::Win32::Foundation::HWND;
|
||||
|
||||
pub mod http;
|
||||
/// Create window and system tray menus.
|
||||
pub mod menu;
|
||||
@ -433,14 +430,6 @@ pub trait Dispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'static
|
||||
/// Returns the list of all the monitors available on the system.
|
||||
fn available_monitors(&self) -> Result<Vec<Monitor>>;
|
||||
|
||||
/// Returns the native handle that is used by this window.
|
||||
#[cfg(windows)]
|
||||
fn hwnd(&self) -> Result<HWND>;
|
||||
|
||||
/// Returns the native handle that is used by this window.
|
||||
#[cfg(target_os = "macos")]
|
||||
fn ns_window(&self) -> Result<*mut std::ffi::c_void>;
|
||||
|
||||
/// Returns the `ApplicationWindow` from gtk crate that is used by this window.
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
@ -451,6 +440,8 @@ pub trait Dispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'static
|
||||
))]
|
||||
fn gtk_window(&self) -> Result<gtk::ApplicationWindow>;
|
||||
|
||||
fn raw_window_handle(&self) -> Result<raw_window_handle::RawWindowHandle>;
|
||||
|
||||
/// Returns the current window theme.
|
||||
fn theme(&self) -> Result<Theme>;
|
||||
|
||||
|
@ -128,6 +128,9 @@ pub enum Error {
|
||||
#[cfg(feature = "icon-png")]
|
||||
#[error("failed to decode PNG: {0}")]
|
||||
PngDecode(#[from] png::DecodingError),
|
||||
/// The Window's raw handle is invalid for the platform.
|
||||
#[error("Unexpected `raw_window_handle` for the current platform")]
|
||||
InvalidWindowHandle,
|
||||
}
|
||||
|
||||
pub(crate) fn into_anyhow<T: std::fmt::Display>(err: T) -> anyhow::Error {
|
||||
|
@ -355,20 +355,10 @@ impl<T: UserEvent> Dispatch<T> for MockDispatcher {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn hwnd(&self) -> Result<HWND> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn theme(&self) -> Result<Theme> {
|
||||
Ok(Theme::Light)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn ns_window(&self) -> Result<*mut std::ffi::c_void> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "dragonfly",
|
||||
@ -380,6 +370,10 @@ impl<T: UserEvent> Dispatch<T> for MockDispatcher {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn raw_window_handle(&self) -> Result<raw_window_handle::RawWindowHandle> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn center(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -489,23 +489,9 @@ pub struct Window<R: Runtime> {
|
||||
pub(crate) app_handle: AppHandle<R>,
|
||||
}
|
||||
|
||||
#[cfg(any(windows, target_os = "macos"))]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(any(windows, target_os = "macos"))))]
|
||||
unsafe impl<R: Runtime> raw_window_handle::HasRawWindowHandle for Window<R> {
|
||||
#[cfg(windows)]
|
||||
fn raw_window_handle(&self) -> raw_window_handle::RawWindowHandle {
|
||||
let mut handle = raw_window_handle::Win32Handle::empty();
|
||||
handle.hwnd = self.hwnd().expect("failed to get window `hwnd`").0 as *mut _;
|
||||
raw_window_handle::RawWindowHandle::Win32(handle)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn raw_window_handle(&self) -> raw_window_handle::RawWindowHandle {
|
||||
let mut handle = raw_window_handle::AppKitHandle::empty();
|
||||
handle.ns_window = self
|
||||
.ns_window()
|
||||
.expect("failed to get window's `ns_window`");
|
||||
raw_window_handle::RawWindowHandle::AppKit(handle)
|
||||
self.window.dispatcher.raw_window_handle().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@ -855,13 +841,35 @@ impl<R: Runtime> Window<R> {
|
||||
/// Returns the native handle that is used by this window.
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn ns_window(&self) -> crate::Result<*mut std::ffi::c_void> {
|
||||
self.window.dispatcher.ns_window().map_err(Into::into)
|
||||
self
|
||||
.window
|
||||
.dispatcher
|
||||
.raw_window_handle()
|
||||
.map_err(Into::into)
|
||||
.and_then(|handle| {
|
||||
if let raw_window_handle::RawWindowHandle::AppKit(h) = handle {
|
||||
Ok(h.ns_window)
|
||||
} else {
|
||||
Err(crate::Error::InvalidWindowHandle)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the native handle that is used by this window.
|
||||
#[cfg(windows)]
|
||||
pub fn hwnd(&self) -> crate::Result<HWND> {
|
||||
self.window.dispatcher.hwnd().map_err(Into::into)
|
||||
self
|
||||
.window
|
||||
.dispatcher
|
||||
.raw_window_handle()
|
||||
.map_err(Into::into)
|
||||
.and_then(|handle| {
|
||||
if let raw_window_handle::RawWindowHandle::Win32(h) = handle {
|
||||
Ok(HWND(h.hwnd as _))
|
||||
} else {
|
||||
Err(crate::Error::InvalidWindowHandle)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the `ApplicatonWindow` from gtk crate that is used by this window.
|
||||
|
Loading…
Reference in New Issue
Block a user