feat(core): add hotkey to toggle devtools, closes #3776 (#3791)

This commit is contained in:
Lucas Fernandes Nogueira 2022-03-28 07:17:28 -07:00 committed by GitHub
parent 9ddf8d84a2
commit e05d718a7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 239 additions and 64 deletions

View File

@ -0,0 +1,6 @@
---
"tauri-runtime": minor
"tauri-runtime-wry": minor
---
Added `close_devtools` and `is_devtools_open` APIs to the `Dispatch` trait.

View File

@ -0,0 +1,5 @@
---
"tauri": patch
---
Toggle devtools when `Ctrl + Shift + I` or `Command + Option + I` is pressed.

View File

@ -0,0 +1,5 @@
---
"tauri": patch
---
Added `close_devtools` and `is_devtools_open` APIs to the `Window` struct.

View File

@ -984,8 +984,13 @@ unsafe impl Send for GtkWindow {}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum WindowMessage { pub enum WindowMessage {
// Devtools
#[cfg(any(debug_assertions, feature = "devtools"))] #[cfg(any(debug_assertions, feature = "devtools"))]
OpenDevTools, OpenDevTools,
#[cfg(any(debug_assertions, feature = "devtools"))]
CloseDevTools,
#[cfg(any(debug_assertions, feature = "devtools"))]
IsDevToolsOpen(Sender<bool>),
// Getters // Getters
ScaleFactor(Sender<f64>), ScaleFactor(Sender<f64>),
InnerPosition(Sender<Result<PhysicalPosition<i32>>>), InnerPosition(Sender<Result<PhysicalPosition<i32>>>),
@ -1174,6 +1179,20 @@ impl<T: UserEvent> Dispatch<T> for WryDispatcher<T> {
); );
} }
#[cfg(any(debug_assertions, feature = "devtools"))]
fn close_devtools(&self) {
let _ = send_user_message(
&self.context,
Message::Window(self.window_id, WindowMessage::CloseDevTools),
);
}
/// Gets the devtools window's current open state.
#[cfg(any(debug_assertions, feature = "devtools"))]
fn is_devtools_open(&self) -> Result<bool> {
window_getter!(self, WindowMessage::IsDevToolsOpen)
}
// Getters // Getters
fn scale_factor(&self) -> Result<f64> { fn scale_factor(&self) -> Result<f64> {
@ -2002,6 +2021,20 @@ fn handle_user_message<T: UserEvent>(
w.open_devtools(); w.open_devtools();
} }
} }
#[cfg(any(debug_assertions, feature = "devtools"))]
WindowMessage::CloseDevTools => {
if let WindowHandle::Webview(w) = &webview.inner {
w.close_devtools();
}
}
#[cfg(any(debug_assertions, feature = "devtools"))]
WindowMessage::IsDevToolsOpen(tx) => {
if let WindowHandle::Webview(w) = &webview.inner {
tx.send(w.is_devtools_open()).unwrap();
} else {
tx.send(false).unwrap();
}
}
// Getters // Getters
WindowMessage::ScaleFactor(tx) => tx.send(window.scale_factor()).unwrap(), WindowMessage::ScaleFactor(tx) => tx.send(window.scale_factor()).unwrap(),
WindowMessage::InnerPosition(tx) => tx WindowMessage::InnerPosition(tx) => tx

View File

@ -284,33 +284,29 @@ pub trait RuntimeHandle<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'st
fn create_window( fn create_window(
&self, &self,
pending: PendingWindow<T, Self::Runtime>, pending: PendingWindow<T, Self::Runtime>,
) -> crate::Result<DetachedWindow<T, Self::Runtime>>; ) -> Result<DetachedWindow<T, Self::Runtime>>;
/// Run a task on the main thread. /// Run a task on the main thread.
fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> crate::Result<()>; fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> Result<()>;
#[cfg(all(windows, feature = "system-tray"))] #[cfg(all(windows, feature = "system-tray"))]
#[cfg_attr(doc_cfg, doc(cfg(all(windows, feature = "system-tray"))))] #[cfg_attr(doc_cfg, doc(cfg(all(windows, feature = "system-tray"))))]
fn remove_system_tray(&self) -> crate::Result<()>; fn remove_system_tray(&self) -> Result<()>;
} }
/// A global shortcut manager. /// A global shortcut manager.
pub trait GlobalShortcutManager: Debug + Clone + Send + Sync { pub trait GlobalShortcutManager: Debug + Clone + Send + Sync {
/// Whether the application has registered the given `accelerator`. /// Whether the application has registered the given `accelerator`.
fn is_registered(&self, accelerator: &str) -> crate::Result<bool>; fn is_registered(&self, accelerator: &str) -> Result<bool>;
/// Register a global shortcut of `accelerator`. /// Register a global shortcut of `accelerator`.
fn register<F: Fn() + Send + 'static>( fn register<F: Fn() + Send + 'static>(&mut self, accelerator: &str, handler: F) -> Result<()>;
&mut self,
accelerator: &str,
handler: F,
) -> crate::Result<()>;
/// Unregister all accelerators registered by the manager instance. /// Unregister all accelerators registered by the manager instance.
fn unregister_all(&mut self) -> crate::Result<()>; fn unregister_all(&mut self) -> Result<()>;
/// Unregister the provided `accelerator`. /// Unregister the provided `accelerator`.
fn unregister(&mut self, accelerator: &str) -> crate::Result<()>; fn unregister(&mut self, accelerator: &str) -> Result<()>;
} }
/// Clipboard manager. /// Clipboard manager.
@ -342,12 +338,12 @@ pub trait Runtime<T: UserEvent>: Debug + Sized + 'static {
type EventLoopProxy: EventLoopProxy<T>; type EventLoopProxy: EventLoopProxy<T>;
/// Creates a new webview runtime. Must be used on the main thread. /// Creates a new webview runtime. Must be used on the main thread.
fn new() -> crate::Result<Self>; fn new() -> Result<Self>;
/// Creates a new webview runtime on any thread. /// Creates a new webview runtime on any thread.
#[cfg(any(windows, target_os = "linux"))] #[cfg(any(windows, target_os = "linux"))]
#[cfg_attr(doc_cfg, doc(cfg(any(windows, target_os = "linux"))))] #[cfg_attr(doc_cfg, doc(cfg(any(windows, target_os = "linux"))))]
fn new_any_thread() -> crate::Result<Self>; fn new_any_thread() -> Result<Self>;
/// Creates an `EventLoopProxy` that can be used to dispatch user events to the main event loop. /// Creates an `EventLoopProxy` that can be used to dispatch user events to the main event loop.
fn create_proxy(&self) -> Self::EventLoopProxy; fn create_proxy(&self) -> Self::EventLoopProxy;
@ -362,15 +358,12 @@ pub trait Runtime<T: UserEvent>: Debug + Sized + 'static {
fn clipboard_manager(&self) -> Self::ClipboardManager; fn clipboard_manager(&self) -> Self::ClipboardManager;
/// Create a new webview window. /// Create a new webview window.
fn create_window( fn create_window(&self, pending: PendingWindow<T, Self>) -> Result<DetachedWindow<T, Self>>;
&self,
pending: PendingWindow<T, Self>,
) -> crate::Result<DetachedWindow<T, Self>>;
/// Adds the icon to the system tray with the specified menu items. /// Adds the icon to the system tray with the specified menu items.
#[cfg(feature = "system-tray")] #[cfg(feature = "system-tray")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "system-tray")))] #[cfg_attr(doc_cfg, doc(cfg(feature = "system-tray")))]
fn system_tray(&self, system_tray: SystemTray) -> crate::Result<Self::TrayHandler>; fn system_tray(&self, system_tray: SystemTray) -> Result<Self::TrayHandler>;
/// Registers a system tray event handler. /// Registers a system tray event handler.
#[cfg(feature = "system-tray")] #[cfg(feature = "system-tray")]
@ -398,7 +391,7 @@ pub trait Dispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'static
type WindowBuilder: WindowBuilder; type WindowBuilder: WindowBuilder;
/// Run a task on the main thread. /// Run a task on the main thread.
fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> crate::Result<()>; fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> Result<()>;
/// Registers a window event handler. /// Registers a window event handler.
fn on_window_event<F: Fn(&WindowEvent) + Send + 'static>(&self, f: F) -> Uuid; fn on_window_event<F: Fn(&WindowEvent) + Send + 'static>(&self, f: F) -> Uuid;
@ -406,68 +399,77 @@ pub trait Dispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'static
/// Registers a window event handler. /// Registers a window event handler.
fn on_menu_event<F: Fn(&window::MenuEvent) + Send + 'static>(&self, f: F) -> Uuid; fn on_menu_event<F: Fn(&window::MenuEvent) + Send + 'static>(&self, f: F) -> Uuid;
/// Open the web inspector which is usually called devtools.
#[cfg(any(debug_assertions, feature = "devtools"))] #[cfg(any(debug_assertions, feature = "devtools"))]
fn open_devtools(&self); fn open_devtools(&self);
/// Close the web inspector which is usually called devtools.
#[cfg(any(debug_assertions, feature = "devtools"))]
fn close_devtools(&self);
/// Gets the devtools window's current open state.
#[cfg(any(debug_assertions, feature = "devtools"))]
fn is_devtools_open(&self) -> Result<bool>;
// GETTERS // GETTERS
/// Returns the scale factor that can be used to map logical pixels to physical pixels, and vice versa. /// Returns the scale factor that can be used to map logical pixels to physical pixels, and vice versa.
fn scale_factor(&self) -> crate::Result<f64>; fn scale_factor(&self) -> Result<f64>;
/// Returns the position of the top-left hand corner of the window's client area relative to the top-left hand corner of the desktop. /// Returns the position of the top-left hand corner of the window's client area relative to the top-left hand corner of the desktop.
fn inner_position(&self) -> crate::Result<PhysicalPosition<i32>>; fn inner_position(&self) -> Result<PhysicalPosition<i32>>;
/// Returns the position of the top-left hand corner of the window relative to the top-left hand corner of the desktop. /// Returns the position of the top-left hand corner of the window relative to the top-left hand corner of the desktop.
fn outer_position(&self) -> crate::Result<PhysicalPosition<i32>>; fn outer_position(&self) -> Result<PhysicalPosition<i32>>;
/// Returns the physical size of the window's client area. /// Returns the physical size of the window's client area.
/// ///
/// The client area is the content of the window, excluding the title bar and borders. /// The client area is the content of the window, excluding the title bar and borders.
fn inner_size(&self) -> crate::Result<PhysicalSize<u32>>; fn inner_size(&self) -> Result<PhysicalSize<u32>>;
/// Returns the physical size of the entire window. /// Returns 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. /// These dimensions include the title bar and borders. If you don't want that (and you usually don't), use inner_size instead.
fn outer_size(&self) -> crate::Result<PhysicalSize<u32>>; fn outer_size(&self) -> Result<PhysicalSize<u32>>;
/// Gets the window's current fullscreen state. /// Gets the window's current fullscreen state.
fn is_fullscreen(&self) -> crate::Result<bool>; fn is_fullscreen(&self) -> Result<bool>;
/// Gets the window's current maximized state. /// Gets the window's current maximized state.
fn is_maximized(&self) -> crate::Result<bool>; fn is_maximized(&self) -> Result<bool>;
/// Gets the windows current decoration state. /// Gets the windows current decoration state.
fn is_decorated(&self) -> crate::Result<bool>; fn is_decorated(&self) -> Result<bool>;
/// Gets the windows current resizable state. /// Gets the windows current resizable state.
fn is_resizable(&self) -> crate::Result<bool>; fn is_resizable(&self) -> Result<bool>;
/// Gets the window's current vibility state. /// Gets the window's current vibility state.
fn is_visible(&self) -> crate::Result<bool>; fn is_visible(&self) -> Result<bool>;
/// Gets the window menu current visibility state. /// Gets the window menu current visibility state.
fn is_menu_visible(&self) -> crate::Result<bool>; fn is_menu_visible(&self) -> Result<bool>;
/// Returns the monitor on which the window currently resides. /// Returns the monitor on which the window currently resides.
/// ///
/// Returns None if current monitor can't be detected. /// Returns None if current monitor can't be detected.
fn current_monitor(&self) -> crate::Result<Option<Monitor>>; fn current_monitor(&self) -> Result<Option<Monitor>>;
/// Returns the primary monitor of the system. /// Returns the primary monitor of the system.
/// ///
/// Returns None if it can't identify any monitor as a primary one. /// Returns None if it can't identify any monitor as a primary one.
fn primary_monitor(&self) -> crate::Result<Option<Monitor>>; fn primary_monitor(&self) -> Result<Option<Monitor>>;
/// Returns the list of all the monitors available on the system. /// Returns the list of all the monitors available on the system.
fn available_monitors(&self) -> crate::Result<Vec<Monitor>>; fn available_monitors(&self) -> Result<Vec<Monitor>>;
/// Returns the native handle that is used by this window. /// Returns the native handle that is used by this window.
#[cfg(windows)] #[cfg(windows)]
fn hwnd(&self) -> crate::Result<HWND>; fn hwnd(&self) -> Result<HWND>;
/// Returns the native handle that is used by this window. /// Returns the native handle that is used by this window.
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
fn ns_window(&self) -> crate::Result<*mut std::ffi::c_void>; fn ns_window(&self) -> Result<*mut std::ffi::c_void>;
/// Returns the `ApplicatonWindow` from gtk crate that is used by this window. /// Returns the `ApplicatonWindow` from gtk crate that is used by this window.
#[cfg(any( #[cfg(any(
@ -477,96 +479,96 @@ pub trait Dispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'static
target_os = "netbsd", target_os = "netbsd",
target_os = "openbsd" target_os = "openbsd"
))] ))]
fn gtk_window(&self) -> crate::Result<gtk::ApplicationWindow>; fn gtk_window(&self) -> Result<gtk::ApplicationWindow>;
// SETTERS // SETTERS
/// Centers the window. /// Centers the window.
fn center(&self) -> crate::Result<()>; fn center(&self) -> Result<()>;
/// Opens the dialog to prints the contents of the webview. /// Opens the dialog to prints the contents of the webview.
fn print(&self) -> crate::Result<()>; fn print(&self) -> Result<()>;
/// Requests user attention to the window. /// Requests user attention to the window.
/// ///
/// Providing `None` will unset the request for user attention. /// Providing `None` will unset the request for user attention.
fn request_user_attention(&self, request_type: Option<UserAttentionType>) -> crate::Result<()>; fn request_user_attention(&self, request_type: Option<UserAttentionType>) -> Result<()>;
/// Create a new webview window. /// Create a new webview window.
fn create_window( fn create_window(
&mut self, &mut self,
pending: PendingWindow<T, Self::Runtime>, pending: PendingWindow<T, Self::Runtime>,
) -> crate::Result<DetachedWindow<T, Self::Runtime>>; ) -> Result<DetachedWindow<T, Self::Runtime>>;
/// Updates the window resizable flag. /// Updates the window resizable flag.
fn set_resizable(&self, resizable: bool) -> crate::Result<()>; fn set_resizable(&self, resizable: bool) -> Result<()>;
/// Updates the window title. /// Updates the window title.
fn set_title<S: Into<String>>(&self, title: S) -> crate::Result<()>; fn set_title<S: Into<String>>(&self, title: S) -> Result<()>;
/// Maximizes the window. /// Maximizes the window.
fn maximize(&self) -> crate::Result<()>; fn maximize(&self) -> Result<()>;
/// Unmaximizes the window. /// Unmaximizes the window.
fn unmaximize(&self) -> crate::Result<()>; fn unmaximize(&self) -> Result<()>;
/// Minimizes the window. /// Minimizes the window.
fn minimize(&self) -> crate::Result<()>; fn minimize(&self) -> Result<()>;
/// Unminimizes the window. /// Unminimizes the window.
fn unminimize(&self) -> crate::Result<()>; fn unminimize(&self) -> Result<()>;
/// Shows the window menu. /// Shows the window menu.
fn show_menu(&self) -> crate::Result<()>; fn show_menu(&self) -> Result<()>;
/// Hides the window menu. /// Hides the window menu.
fn hide_menu(&self) -> crate::Result<()>; fn hide_menu(&self) -> Result<()>;
/// Shows the window. /// Shows the window.
fn show(&self) -> crate::Result<()>; fn show(&self) -> Result<()>;
/// Hides the window. /// Hides the window.
fn hide(&self) -> crate::Result<()>; fn hide(&self) -> Result<()>;
/// Closes the window. /// Closes the window.
fn close(&self) -> crate::Result<()>; fn close(&self) -> Result<()>;
/// Updates the hasDecorations flag. /// Updates the hasDecorations flag.
fn set_decorations(&self, decorations: bool) -> crate::Result<()>; fn set_decorations(&self, decorations: bool) -> Result<()>;
/// Updates the window alwaysOnTop flag. /// Updates the window alwaysOnTop flag.
fn set_always_on_top(&self, always_on_top: bool) -> crate::Result<()>; fn set_always_on_top(&self, always_on_top: bool) -> Result<()>;
/// Resizes the window. /// Resizes the window.
fn set_size(&self, size: Size) -> crate::Result<()>; fn set_size(&self, size: Size) -> Result<()>;
/// Updates the window min size. /// Updates the window min size.
fn set_min_size(&self, size: Option<Size>) -> crate::Result<()>; fn set_min_size(&self, size: Option<Size>) -> Result<()>;
/// Updates the window max size. /// Updates the window max size.
fn set_max_size(&self, size: Option<Size>) -> crate::Result<()>; fn set_max_size(&self, size: Option<Size>) -> Result<()>;
/// Updates the window position. /// Updates the window position.
fn set_position(&self, position: Position) -> crate::Result<()>; fn set_position(&self, position: Position) -> Result<()>;
/// Updates the window fullscreen state. /// Updates the window fullscreen state.
fn set_fullscreen(&self, fullscreen: bool) -> crate::Result<()>; fn set_fullscreen(&self, fullscreen: bool) -> Result<()>;
/// Bring the window to front and focus. /// Bring the window to front and focus.
fn set_focus(&self) -> crate::Result<()>; fn set_focus(&self) -> Result<()>;
/// Updates the window icon. /// Updates the window icon.
fn set_icon(&self, icon: WindowIcon) -> crate::Result<()>; fn set_icon(&self, icon: WindowIcon) -> Result<()>;
/// Whether to show the window icon in the task bar or not. /// Whether to show the window icon in the task bar or not.
fn set_skip_taskbar(&self, skip: bool) -> crate::Result<()>; fn set_skip_taskbar(&self, skip: bool) -> Result<()>;
/// Starts dragging the window. /// Starts dragging the window.
fn start_dragging(&self) -> crate::Result<()>; fn start_dragging(&self) -> Result<()>;
/// Executes javascript on the window this [`Dispatch`] represents. /// Executes javascript on the window this [`Dispatch`] represents.
fn eval_script<S: Into<String>>(&self, script: S) -> crate::Result<()>; fn eval_script<S: Into<String>>(&self, script: S) -> Result<()>;
/// Applies the specified `update` to the menu item associated with the given `id`. /// Applies the specified `update` to the menu item associated with the given `id`.
fn update_menu_item(&self, id: u16, update: menu::MenuUpdate) -> crate::Result<()>; fn update_menu_item(&self, id: u16, update: menu::MenuUpdate) -> Result<()>;
} }

File diff suppressed because one or more lines are too long

View File

@ -2,6 +2,10 @@
if (window.location.origin.startsWith(__TEMPLATE_origin__)) { if (window.location.origin.startsWith(__TEMPLATE_origin__)) {
__RAW_freeze_prototype__ __RAW_freeze_prototype__
;(function () {
__RAW_hotkeys__
})()
__RAW_pattern_script__ __RAW_pattern_script__
__RAW_ipc_script__ __RAW_ipc_script__

View File

@ -99,6 +99,9 @@ pub enum WindowManagerCmd {
// internals // internals
#[serde(rename = "__toggleMaximize")] #[serde(rename = "__toggleMaximize")]
InternalToggleMaximize, InternalToggleMaximize,
#[cfg(any(debug_assertions, feature = "devtools"))]
#[serde(rename = "__toggleDevtools")]
InternalToggleDevtools,
} }
impl WindowManagerCmd { impl WindowManagerCmd {
@ -279,6 +282,14 @@ impl Cmd {
} }
} }
} }
#[cfg(any(debug_assertions, feature = "devtools"))]
WindowManagerCmd::InternalToggleDevtools => {
if window.is_devtools_open() {
window.close_devtools();
} else {
window.open_devtools();
}
}
#[allow(unreachable_patterns)] #[allow(unreachable_patterns)]
_ => return Err(cmd.into_allowlist_error()), _ => return Err(cmd.into_allowlist_error()),
} }

View File

@ -880,6 +880,8 @@ impl<R: Runtime> WindowManager<R> {
plugin_initialization_script: &'a str, plugin_initialization_script: &'a str,
#[raw] #[raw]
freeze_prototype: &'a str, freeze_prototype: &'a str,
#[raw]
hotkeys: &'a str,
} }
let bundle_script = if with_global_tauri { let bundle_script = if with_global_tauri {
@ -894,6 +896,34 @@ impl<R: Runtime> WindowManager<R> {
"" ""
}; };
#[cfg(any(debug_assertions, feature = "devtools"))]
let hotkeys = &format!(
"
{};
window.hotkeys('{}', () => {{
window.__TAURI_INVOKE__('tauri', {{
__tauriModule: 'Window',
message: {{
cmd: 'manage',
data: {{
cmd: {{
type: '__toggleDevtools'
}}
}}
}}
}});
}});
",
include_str!("../scripts/hotkey.js"),
if cfg!(target_os = "macos") {
"command+option+i"
} else {
"ctrl+shift+i"
}
);
#[cfg(not(any(debug_assertions, feature = "devtools")))]
let hotkeys = "";
InitJavascript { InitJavascript {
origin: self.get_browser_origin(), origin: self.get_browser_origin(),
pattern_script, pattern_script,
@ -913,6 +943,7 @@ impl<R: Runtime> WindowManager<R> {
event_initialization_script: &self.event_initialization_script(), event_initialization_script: &self.event_initialization_script(),
plugin_initialization_script, plugin_initialization_script,
freeze_prototype, freeze_prototype,
hotkeys,
} }
.render_default(&Default::default()) .render_default(&Default::default())
.map(|s| s.into_string()) .map(|s| s.into_string())

View File

@ -277,6 +277,14 @@ impl<T: UserEvent> Dispatch<T> for MockDispatcher {
#[cfg(any(debug_assertions, feature = "devtools"))] #[cfg(any(debug_assertions, feature = "devtools"))]
fn open_devtools(&self) {} fn open_devtools(&self) {}
#[cfg(any(debug_assertions, feature = "devtools"))]
fn close_devtools(&self) {}
#[cfg(any(debug_assertions, feature = "devtools"))]
fn is_devtools_open(&self) -> Result<bool> {
Ok(false)
}
fn scale_factor(&self) -> Result<f64> { fn scale_factor(&self) -> Result<f64> {
Ok(1.0) Ok(1.0)
} }

View File

@ -812,6 +812,74 @@ impl<R: Runtime> Window<R> {
self.window.dispatcher.open_devtools(); self.window.dispatcher.open_devtools();
} }
/// Closes the developer tools window (Web Inspector).
/// The devtools is only enabled on debug builds or with the `devtools` feature flag.
///
/// ## Platform-specific
///
/// - **macOS:** This is a private API on macOS,
/// so you cannot use this if your application will be published on the App Store.
/// - **Windows:** Unsupported.
///
/// # Examples
///
/// ```rust,no_run
/// use tauri::Manager;
/// tauri::Builder::default()
/// .setup(|app| {
/// #[cfg(debug_assertions)]
/// {
/// let window = app.get_window("main").unwrap();
/// window.open_devtools();
/// std::thread::spawn(move || {
/// std::thread::sleep(std::time::Duration::from_secs(10));
/// window.close_devtools();
/// });
/// }
/// Ok(())
/// });
/// ```
#[cfg(any(debug_assertions, feature = "devtools"))]
#[cfg_attr(doc_cfg, doc(cfg(any(debug_assertions, feature = "devtools"))))]
pub fn close_devtools(&self) {
self.window.dispatcher.close_devtools();
}
/// Checks if the developer tools window (Web Inspector) is opened.
/// The devtools is only enabled on debug builds or with the `devtools` feature flag.
///
/// ## Platform-specific
///
/// - **macOS:** This is a private API on macOS,
/// so you cannot use this if your application will be published on the App Store.
/// - **Windows:** Unsupported.
///
/// # Examples
///
/// ```rust,no_run
/// use tauri::Manager;
/// tauri::Builder::default()
/// .setup(|app| {
/// #[cfg(debug_assertions)]
/// {
/// let window = app.get_window("main").unwrap();
/// if !window.is_devtools_open() {
/// window.open_devtools();
/// }
/// }
/// Ok(())
/// });
/// ```
#[cfg(any(debug_assertions, feature = "devtools"))]
#[cfg_attr(doc_cfg, doc(cfg(any(debug_assertions, feature = "devtools"))))]
pub fn is_devtools_open(&self) -> bool {
self
.window
.dispatcher
.is_devtools_open()
.unwrap_or_default()
}
// Getters // Getters
/// Gets a handle to the window menu. /// Gets a handle to the window menu.