Skip to content

Commit e05d718

Browse files
authored
feat(core): add hotkey to toggle devtools, closes #3776 (#3791)
1 parent 9ddf8d8 commit e05d718

File tree

11 files changed

+239
-64
lines changed

11 files changed

+239
-64
lines changed

.changes/devtools-apis.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"tauri-runtime": minor
3+
"tauri-runtime-wry": minor
4+
---
5+
6+
Added `close_devtools` and `is_devtools_open` APIs to the `Dispatch` trait.

.changes/devtools-hotkey.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": patch
3+
---
4+
5+
Toggle devtools when `Ctrl + Shift + I` or `Command + Option + I` is pressed.

.changes/window-devtools-apis.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": patch
3+
---
4+
5+
Added `close_devtools` and `is_devtools_open` APIs to the `Window` struct.

core/tauri-runtime-wry/src/lib.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,8 +984,13 @@ unsafe impl Send for GtkWindow {}
984984

985985
#[derive(Debug, Clone)]
986986
pub enum WindowMessage {
987+
// Devtools
987988
#[cfg(any(debug_assertions, feature = "devtools"))]
988989
OpenDevTools,
990+
#[cfg(any(debug_assertions, feature = "devtools"))]
991+
CloseDevTools,
992+
#[cfg(any(debug_assertions, feature = "devtools"))]
993+
IsDevToolsOpen(Sender<bool>),
989994
// Getters
990995
ScaleFactor(Sender<f64>),
991996
InnerPosition(Sender<Result<PhysicalPosition<i32>>>),
@@ -1174,6 +1179,20 @@ impl<T: UserEvent> Dispatch<T> for WryDispatcher<T> {
11741179
);
11751180
}
11761181

1182+
#[cfg(any(debug_assertions, feature = "devtools"))]
1183+
fn close_devtools(&self) {
1184+
let _ = send_user_message(
1185+
&self.context,
1186+
Message::Window(self.window_id, WindowMessage::CloseDevTools),
1187+
);
1188+
}
1189+
1190+
/// Gets the devtools window's current open state.
1191+
#[cfg(any(debug_assertions, feature = "devtools"))]
1192+
fn is_devtools_open(&self) -> Result<bool> {
1193+
window_getter!(self, WindowMessage::IsDevToolsOpen)
1194+
}
1195+
11771196
// Getters
11781197

11791198
fn scale_factor(&self) -> Result<f64> {
@@ -2002,6 +2021,20 @@ fn handle_user_message<T: UserEvent>(
20022021
w.open_devtools();
20032022
}
20042023
}
2024+
#[cfg(any(debug_assertions, feature = "devtools"))]
2025+
WindowMessage::CloseDevTools => {
2026+
if let WindowHandle::Webview(w) = &webview.inner {
2027+
w.close_devtools();
2028+
}
2029+
}
2030+
#[cfg(any(debug_assertions, feature = "devtools"))]
2031+
WindowMessage::IsDevToolsOpen(tx) => {
2032+
if let WindowHandle::Webview(w) = &webview.inner {
2033+
tx.send(w.is_devtools_open()).unwrap();
2034+
} else {
2035+
tx.send(false).unwrap();
2036+
}
2037+
}
20052038
// Getters
20062039
WindowMessage::ScaleFactor(tx) => tx.send(window.scale_factor()).unwrap(),
20072040
WindowMessage::InnerPosition(tx) => tx

core/tauri-runtime/src/lib.rs

Lines changed: 66 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -284,33 +284,29 @@ pub trait RuntimeHandle<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'st
284284
fn create_window(
285285
&self,
286286
pending: PendingWindow<T, Self::Runtime>,
287-
) -> crate::Result<DetachedWindow<T, Self::Runtime>>;
287+
) -> Result<DetachedWindow<T, Self::Runtime>>;
288288

289289
/// Run a task on the main thread.
290-
fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> crate::Result<()>;
290+
fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> Result<()>;
291291

292292
#[cfg(all(windows, feature = "system-tray"))]
293293
#[cfg_attr(doc_cfg, doc(cfg(all(windows, feature = "system-tray"))))]
294-
fn remove_system_tray(&self) -> crate::Result<()>;
294+
fn remove_system_tray(&self) -> Result<()>;
295295
}
296296

297297
/// A global shortcut manager.
298298
pub trait GlobalShortcutManager: Debug + Clone + Send + Sync {
299299
/// Whether the application has registered the given `accelerator`.
300-
fn is_registered(&self, accelerator: &str) -> crate::Result<bool>;
300+
fn is_registered(&self, accelerator: &str) -> Result<bool>;
301301

302302
/// Register a global shortcut of `accelerator`.
303-
fn register<F: Fn() + Send + 'static>(
304-
&mut self,
305-
accelerator: &str,
306-
handler: F,
307-
) -> crate::Result<()>;
303+
fn register<F: Fn() + Send + 'static>(&mut self, accelerator: &str, handler: F) -> Result<()>;
308304

309305
/// Unregister all accelerators registered by the manager instance.
310-
fn unregister_all(&mut self) -> crate::Result<()>;
306+
fn unregister_all(&mut self) -> Result<()>;
311307

312308
/// Unregister the provided `accelerator`.
313-
fn unregister(&mut self, accelerator: &str) -> crate::Result<()>;
309+
fn unregister(&mut self, accelerator: &str) -> Result<()>;
314310
}
315311

316312
/// Clipboard manager.
@@ -342,12 +338,12 @@ pub trait Runtime<T: UserEvent>: Debug + Sized + 'static {
342338
type EventLoopProxy: EventLoopProxy<T>;
343339

344340
/// Creates a new webview runtime. Must be used on the main thread.
345-
fn new() -> crate::Result<Self>;
341+
fn new() -> Result<Self>;
346342

347343
/// Creates a new webview runtime on any thread.
348344
#[cfg(any(windows, target_os = "linux"))]
349345
#[cfg_attr(doc_cfg, doc(cfg(any(windows, target_os = "linux"))))]
350-
fn new_any_thread() -> crate::Result<Self>;
346+
fn new_any_thread() -> Result<Self>;
351347

352348
/// Creates an `EventLoopProxy` that can be used to dispatch user events to the main event loop.
353349
fn create_proxy(&self) -> Self::EventLoopProxy;
@@ -362,15 +358,12 @@ pub trait Runtime<T: UserEvent>: Debug + Sized + 'static {
362358
fn clipboard_manager(&self) -> Self::ClipboardManager;
363359

364360
/// Create a new webview window.
365-
fn create_window(
366-
&self,
367-
pending: PendingWindow<T, Self>,
368-
) -> crate::Result<DetachedWindow<T, Self>>;
361+
fn create_window(&self, pending: PendingWindow<T, Self>) -> Result<DetachedWindow<T, Self>>;
369362

370363
/// Adds the icon to the system tray with the specified menu items.
371364
#[cfg(feature = "system-tray")]
372365
#[cfg_attr(doc_cfg, doc(cfg(feature = "system-tray")))]
373-
fn system_tray(&self, system_tray: SystemTray) -> crate::Result<Self::TrayHandler>;
366+
fn system_tray(&self, system_tray: SystemTray) -> Result<Self::TrayHandler>;
374367

375368
/// Registers a system tray event handler.
376369
#[cfg(feature = "system-tray")]
@@ -398,76 +391,85 @@ pub trait Dispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'static
398391
type WindowBuilder: WindowBuilder;
399392

400393
/// Run a task on the main thread.
401-
fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> crate::Result<()>;
394+
fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> Result<()>;
402395

403396
/// Registers a window event handler.
404397
fn on_window_event<F: Fn(&WindowEvent) + Send + 'static>(&self, f: F) -> Uuid;
405398

406399
/// Registers a window event handler.
407400
fn on_menu_event<F: Fn(&window::MenuEvent) + Send + 'static>(&self, f: F) -> Uuid;
408401

402+
/// Open the web inspector which is usually called devtools.
409403
#[cfg(any(debug_assertions, feature = "devtools"))]
410404
fn open_devtools(&self);
411405

406+
/// Close the web inspector which is usually called devtools.
407+
#[cfg(any(debug_assertions, feature = "devtools"))]
408+
fn close_devtools(&self);
409+
410+
/// Gets the devtools window's current open state.
411+
#[cfg(any(debug_assertions, feature = "devtools"))]
412+
fn is_devtools_open(&self) -> Result<bool>;
413+
412414
// GETTERS
413415

414416
/// Returns the scale factor that can be used to map logical pixels to physical pixels, and vice versa.
415-
fn scale_factor(&self) -> crate::Result<f64>;
417+
fn scale_factor(&self) -> Result<f64>;
416418

417419
/// 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.
418-
fn inner_position(&self) -> crate::Result<PhysicalPosition<i32>>;
420+
fn inner_position(&self) -> Result<PhysicalPosition<i32>>;
419421

420422
/// Returns the position of the top-left hand corner of the window relative to the top-left hand corner of the desktop.
421-
fn outer_position(&self) -> crate::Result<PhysicalPosition<i32>>;
423+
fn outer_position(&self) -> Result<PhysicalPosition<i32>>;
422424

423425
/// Returns the physical size of the window's client area.
424426
///
425427
/// The client area is the content of the window, excluding the title bar and borders.
426-
fn inner_size(&self) -> crate::Result<PhysicalSize<u32>>;
428+
fn inner_size(&self) -> Result<PhysicalSize<u32>>;
427429

428430
/// Returns the physical size of the entire window.
429431
///
430432
/// These dimensions include the title bar and borders. If you don't want that (and you usually don't), use inner_size instead.
431-
fn outer_size(&self) -> crate::Result<PhysicalSize<u32>>;
433+
fn outer_size(&self) -> Result<PhysicalSize<u32>>;
432434

433435
/// Gets the window's current fullscreen state.
434-
fn is_fullscreen(&self) -> crate::Result<bool>;
436+
fn is_fullscreen(&self) -> Result<bool>;
435437

436438
/// Gets the window's current maximized state.
437-
fn is_maximized(&self) -> crate::Result<bool>;
439+
fn is_maximized(&self) -> Result<bool>;
438440

439441
/// Gets the window’s current decoration state.
440-
fn is_decorated(&self) -> crate::Result<bool>;
442+
fn is_decorated(&self) -> Result<bool>;
441443

442444
/// Gets the window’s current resizable state.
443-
fn is_resizable(&self) -> crate::Result<bool>;
445+
fn is_resizable(&self) -> Result<bool>;
444446

445447
/// Gets the window's current vibility state.
446-
fn is_visible(&self) -> crate::Result<bool>;
448+
fn is_visible(&self) -> Result<bool>;
447449

448450
/// Gets the window menu current visibility state.
449-
fn is_menu_visible(&self) -> crate::Result<bool>;
451+
fn is_menu_visible(&self) -> Result<bool>;
450452

451453
/// Returns the monitor on which the window currently resides.
452454
///
453455
/// Returns None if current monitor can't be detected.
454-
fn current_monitor(&self) -> crate::Result<Option<Monitor>>;
456+
fn current_monitor(&self) -> Result<Option<Monitor>>;
455457

456458
/// Returns the primary monitor of the system.
457459
///
458460
/// Returns None if it can't identify any monitor as a primary one.
459-
fn primary_monitor(&self) -> crate::Result<Option<Monitor>>;
461+
fn primary_monitor(&self) -> Result<Option<Monitor>>;
460462

461463
/// Returns the list of all the monitors available on the system.
462-
fn available_monitors(&self) -> crate::Result<Vec<Monitor>>;
464+
fn available_monitors(&self) -> Result<Vec<Monitor>>;
463465

464466
/// Returns the native handle that is used by this window.
465467
#[cfg(windows)]
466-
fn hwnd(&self) -> crate::Result<HWND>;
468+
fn hwnd(&self) -> Result<HWND>;
467469

468470
/// Returns the native handle that is used by this window.
469471
#[cfg(target_os = "macos")]
470-
fn ns_window(&self) -> crate::Result<*mut std::ffi::c_void>;
472+
fn ns_window(&self) -> Result<*mut std::ffi::c_void>;
471473

472474
/// Returns the `ApplicatonWindow` from gtk crate that is used by this window.
473475
#[cfg(any(
@@ -477,96 +479,96 @@ pub trait Dispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'static
477479
target_os = "netbsd",
478480
target_os = "openbsd"
479481
))]
480-
fn gtk_window(&self) -> crate::Result<gtk::ApplicationWindow>;
482+
fn gtk_window(&self) -> Result<gtk::ApplicationWindow>;
481483

482484
// SETTERS
483485

484486
/// Centers the window.
485-
fn center(&self) -> crate::Result<()>;
487+
fn center(&self) -> Result<()>;
486488

487489
/// Opens the dialog to prints the contents of the webview.
488-
fn print(&self) -> crate::Result<()>;
490+
fn print(&self) -> Result<()>;
489491

490492
/// Requests user attention to the window.
491493
///
492494
/// Providing `None` will unset the request for user attention.
493-
fn request_user_attention(&self, request_type: Option<UserAttentionType>) -> crate::Result<()>;
495+
fn request_user_attention(&self, request_type: Option<UserAttentionType>) -> Result<()>;
494496

495497
/// Create a new webview window.
496498
fn create_window(
497499
&mut self,
498500
pending: PendingWindow<T, Self::Runtime>,
499-
) -> crate::Result<DetachedWindow<T, Self::Runtime>>;
501+
) -> Result<DetachedWindow<T, Self::Runtime>>;
500502

501503
/// Updates the window resizable flag.
502-
fn set_resizable(&self, resizable: bool) -> crate::Result<()>;
504+
fn set_resizable(&self, resizable: bool) -> Result<()>;
503505

504506
/// Updates the window title.
505-
fn set_title<S: Into<String>>(&self, title: S) -> crate::Result<()>;
507+
fn set_title<S: Into<String>>(&self, title: S) -> Result<()>;
506508

507509
/// Maximizes the window.
508-
fn maximize(&self) -> crate::Result<()>;
510+
fn maximize(&self) -> Result<()>;
509511

510512
/// Unmaximizes the window.
511-
fn unmaximize(&self) -> crate::Result<()>;
513+
fn unmaximize(&self) -> Result<()>;
512514

513515
/// Minimizes the window.
514-
fn minimize(&self) -> crate::Result<()>;
516+
fn minimize(&self) -> Result<()>;
515517

516518
/// Unminimizes the window.
517-
fn unminimize(&self) -> crate::Result<()>;
519+
fn unminimize(&self) -> Result<()>;
518520

519521
/// Shows the window menu.
520-
fn show_menu(&self) -> crate::Result<()>;
522+
fn show_menu(&self) -> Result<()>;
521523

522524
/// Hides the window menu.
523-
fn hide_menu(&self) -> crate::Result<()>;
525+
fn hide_menu(&self) -> Result<()>;
524526

525527
/// Shows the window.
526-
fn show(&self) -> crate::Result<()>;
528+
fn show(&self) -> Result<()>;
527529

528530
/// Hides the window.
529-
fn hide(&self) -> crate::Result<()>;
531+
fn hide(&self) -> Result<()>;
530532

531533
/// Closes the window.
532-
fn close(&self) -> crate::Result<()>;
534+
fn close(&self) -> Result<()>;
533535

534536
/// Updates the hasDecorations flag.
535-
fn set_decorations(&self, decorations: bool) -> crate::Result<()>;
537+
fn set_decorations(&self, decorations: bool) -> Result<()>;
536538

537539
/// Updates the window alwaysOnTop flag.
538-
fn set_always_on_top(&self, always_on_top: bool) -> crate::Result<()>;
540+
fn set_always_on_top(&self, always_on_top: bool) -> Result<()>;
539541

540542
/// Resizes the window.
541-
fn set_size(&self, size: Size) -> crate::Result<()>;
543+
fn set_size(&self, size: Size) -> Result<()>;
542544

543545
/// Updates the window min size.
544-
fn set_min_size(&self, size: Option<Size>) -> crate::Result<()>;
546+
fn set_min_size(&self, size: Option<Size>) -> Result<()>;
545547

546548
/// Updates the window max size.
547-
fn set_max_size(&self, size: Option<Size>) -> crate::Result<()>;
549+
fn set_max_size(&self, size: Option<Size>) -> Result<()>;
548550

549551
/// Updates the window position.
550-
fn set_position(&self, position: Position) -> crate::Result<()>;
552+
fn set_position(&self, position: Position) -> Result<()>;
551553

552554
/// Updates the window fullscreen state.
553-
fn set_fullscreen(&self, fullscreen: bool) -> crate::Result<()>;
555+
fn set_fullscreen(&self, fullscreen: bool) -> Result<()>;
554556

555557
/// Bring the window to front and focus.
556-
fn set_focus(&self) -> crate::Result<()>;
558+
fn set_focus(&self) -> Result<()>;
557559

558560
/// Updates the window icon.
559-
fn set_icon(&self, icon: WindowIcon) -> crate::Result<()>;
561+
fn set_icon(&self, icon: WindowIcon) -> Result<()>;
560562

561563
/// Whether to show the window icon in the task bar or not.
562-
fn set_skip_taskbar(&self, skip: bool) -> crate::Result<()>;
564+
fn set_skip_taskbar(&self, skip: bool) -> Result<()>;
563565

564566
/// Starts dragging the window.
565-
fn start_dragging(&self) -> crate::Result<()>;
567+
fn start_dragging(&self) -> Result<()>;
566568

567569
/// Executes javascript on the window this [`Dispatch`] represents.
568-
fn eval_script<S: Into<String>>(&self, script: S) -> crate::Result<()>;
570+
fn eval_script<S: Into<String>>(&self, script: S) -> Result<()>;
569571

570572
/// Applies the specified `update` to the menu item associated with the given `id`.
571-
fn update_menu_item(&self, id: u16, update: menu::MenuUpdate) -> crate::Result<()>;
573+
fn update_menu_item(&self, id: u16, update: menu::MenuUpdate) -> Result<()>;
572574
}

core/tauri/scripts/hotkey.js

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)