5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-02 10:51:35 +08:00

Devtools hotkey (#2915)

* Add Ctrl/Cmd+Shift+F12 Hotkey to open devtools when `-devtools` flag used.
This commit is contained in:
Lea Anthony 2023-09-19 05:56:14 +10:00 committed by GitHub
parent 64e44b1b51
commit 6aa6762f12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 138 additions and 61 deletions

Binary file not shown.

View File

@ -323,6 +323,11 @@ func (f *Frontend) processMessage(message string) {
return
}
if message == "wails:openInspector" {
showInspector(f.mainWindow.context)
return
}
//if strings.HasPrefix(message, "systemevent:") {
// f.processSystemEvent(message)
// return
@ -390,6 +395,6 @@ func processCallback(callbackID uint) {
}
//export processURLRequest
func processURLRequest(ctx unsafe.Pointer, wkURLSchemeTask unsafe.Pointer) {
func processURLRequest(_ unsafe.Pointer, wkURLSchemeTask unsafe.Pointer) {
requestBuffer <- webview.NewRequest(wkURLSchemeTask)
}

View File

@ -1,4 +1,4 @@
//go:build darwin && !(dev || debug)
//go:build darwin && !(dev || debug || devtools)
package darwin
@ -6,6 +6,6 @@ import (
"unsafe"
)
func showInspector(context unsafe.Pointer) {
func showInspector(_ unsafe.Pointer) {
}

View File

@ -1,4 +1,4 @@
//go:build darwin && (dev || debug)
//go:build darwin && (dev || debug || devtools)
package darwin
@ -11,6 +11,8 @@ package darwin
#import <Foundation/Foundation.h>
#import "WailsContext.h"
extern void processMessage(const char *message);
@interface _WKInspector : NSObject
- (void)show;
- (void)detach;
@ -21,28 +23,44 @@ package darwin
@end
void showInspector(void *inctx) {
if (@available(macOS 12.0, *)) {
WailsContext *ctx = (__bridge WailsContext*) inctx;
ON_MAIN_THREAD(
if (@available(macOS 12.0, *)) {
WailsContext *ctx = (__bridge WailsContext*) inctx;
@try {
[ctx.webview._inspector show];
} @catch (NSException *exception) {
NSLog(@"Opening the inspector failed: %@", exception.reason);
return;
}
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// Detach must be deferred a little bit and is ignored directly after a show.
@try {
[ctx.webview._inspector detach];
[ctx.webview._inspector show];
} @catch (NSException *exception) {
NSLog(@"Detaching the inspector failed: %@", exception.reason);
NSLog(@"Opening the inspector failed: %@", exception.reason);
return;
}
});
} else {
NSLog(@"Opening the inspector needs at least MacOS 12");
}
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// Detach must be deferred a little bit and is ignored directly after a show.
@try {
[ctx.webview._inspector detach];
} @catch (NSException *exception) {
NSLog(@"Detaching the inspector failed: %@", exception.reason);
}
});
} else {
NSLog(@"Opening the inspector needs at least MacOS 12");
}
);
}
void setupF12hotkey() {
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyDown handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) {
if (event.keyCode == 111 &&
event.modifierFlags & NSEventModifierFlagFunction &&
event.modifierFlags & NSEventModifierFlagCommand &&
event.modifierFlags & NSEventModifierFlagShift) {
processMessage("wails:openInspector");
return nil;
}
return event;
}];
}
*/
import "C"
@ -50,6 +68,10 @@ import (
"unsafe"
)
func init() {
C.setupF12hotkey()
}
func showInspector(context unsafe.Pointer) {
C.showInspector(context)
}

View File

@ -410,6 +410,11 @@ func (f *Frontend) processMessage(message string) {
return
}
if message == "wails:showInspector" {
f.mainWindow.ShowInspector()
return
}
if strings.HasPrefix(message, "resize:") {
if !f.mainWindow.IsFullScreen() {
sl := strings.Split(message, ":")

View File

@ -732,3 +732,21 @@ GtkFileFilter *newFileFilter()
g_object_ref(result);
return result;
}
void ShowInspector(void *webview) {
WebKitWebInspector *inspector = webkit_web_view_get_inspector(WEBKIT_WEB_VIEW(webview));
webkit_web_inspector_show(WEBKIT_WEB_INSPECTOR(inspector));
}
void sendShowInspectorMessage() {
processMessage("wails:showInspector");
}
void InstallF12Hotkey(void *window)
{
// When the user presses Ctrl+Shift+F12, call ShowInspector
GtkAccelGroup *accel_group = gtk_accel_group_new();
gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
GClosure *closure = g_cclosure_new(G_CALLBACK(sendShowInspectorMessage), window, NULL);
gtk_accel_group_connect(accel_group, GDK_KEY_F12, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE, closure);
}

View File

@ -105,6 +105,8 @@ func NewWindow(appoptions *options.App, debug bool, devtools bool) *Window {
if devtools {
C.DevtoolsEnabled(unsafe.Pointer(webview), C.int(1), C.bool(debug && appoptions.Debug.OpenInspectorOnStartup))
// Install Ctrl-Shift-F12 hotkey to call ShowInspector
C.InstallF12Hotkey(unsafe.Pointer(gtkWindow))
} else if !appoptions.EnableDefaultContextMenu {
C.DisableContextMenu(unsafe.Pointer(webview))
}
@ -446,6 +448,10 @@ func (w *Window) ToggleMaximise() {
}
}
func (w *Window) ShowInspector() {
invokeOnMainThread(func() { C.ShowInspector(w.webview) })
}
// showModalDialogAndExit shows a modal dialog and exits the app.
func showModalDialogAndExit(title, message string) {
go func() {

View File

@ -120,4 +120,9 @@ void MessageDialog(void *data);
GtkFileFilter **AllocFileFilterArray(size_t ln);
void Opendialog(void *data);
// Inspector
void sendShowInspectorMessage();
void ShowInspector(void *webview);
void InstallF12Hotkey(void *window);
#endif /* window_h */

View File

@ -458,6 +458,18 @@ func (f *Frontend) setupChromium() {
chromium.WebResourceRequestedCallback = f.processRequest
chromium.NavigationCompletedCallback = f.navigationCompleted
chromium.AcceleratorKeyCallback = func(vkey uint) bool {
if vkey == w32.VK_F12 && f.devtools {
var keyState [256]byte
if w32.GetKeyboardState(keyState[:]) {
// Check if CTRL is pressed
if keyState[w32.VK_CONTROL]&0x80 != 0 && keyState[w32.VK_SHIFT]&0x80 != 0 {
chromium.OpenDevToolsWindow()
return true
}
} else {
f.logger.Error("Call to GetKeyboardState failed")
}
}
w32.PostMessage(f.mainWindow.Handle(), w32.WM_KEYDOWN, uintptr(vkey), 0)
return false
}

View File

@ -1023,9 +1023,11 @@ func EndPaint(hwnd HWND, paint *PAINTSTRUCT) {
uintptr(unsafe.Pointer(paint)))
}
func GetKeyboardState(lpKeyState *[]byte) bool {
ret, _, _ := procGetKeyboardState.Call(
uintptr(unsafe.Pointer(&(*lpKeyState)[0])))
func GetKeyboardState(keyState []byte) bool {
if len(keyState) != 256 {
panic("keyState slice must have a size of 256 bytes")
}
ret, _, _ := procGetKeyboardState.Call(uintptr(unsafe.Pointer(&keyState[0])))
return ret != 0
}

View File

@ -348,8 +348,8 @@ func execBuildApplication(builder Builder, options *Options) (string, error) {
}
}
if options.Platform == "darwin" && options.Mode == Debug {
pterm.Warning.Println("A darwin debug build contains private APIs, please don't distribute this build. Please use it only as a test build for testing and debug purposes.")
if options.Platform == "darwin" && (options.Mode == Debug || options.Devtools) {
pterm.Warning.Println("This darwin build contains the use of private APIs. This will not pass Apple's AppStore approval process. Please use it only as a test build for testing and debug purposes.")
}
return options.CompiledBinary, nil

View File

@ -52,35 +52,35 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for
`wails build` is used for compiling your project to a production-ready binary.
| Flag | Description | Default |
|:---------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------|
| -clean | Cleans the `build/bin` directory | |
| -compiler "compiler" | Use a different go compiler to build, eg go1.15beta1 | go |
| -debug | Retains debug information in the application and shows the debug console. Allows the use of the devtools in the application window | |
| -devtools | Allows the use of the devtools in the application window in production (when -debug is not used) | |
| -dryrun | Prints the build command without executing it | |
| -f | Force build application | |
| -garbleargs | Arguments to pass to garble | `-literals -tiny -seed=random` |
| -ldflags "flags" | Additional ldflags to pass to the compiler | |
| -m | Skip mod tidy before compile | |
| -nopackage | Do not package application | |
| -nocolour | Disable colour in output | |
| -nosyncgomod | Do not sync go.mod with the Wails version | |
| -nsis | Generate NSIS installer for Windows | |
| -o filename | Output filename | |
| -obfuscated | Obfuscate the application using [garble](https://github.com/burrowers/garble) | |
| -platform | Build for the given (comma delimited) [platforms](../reference/cli.mdx#platforms) eg. `windows/arm64`. Note, if you do not give the architecture, `runtime.GOARCH` is used. | platform = `GOOS` environment variable if given else `runtime.GOOS`.<br/>arch = `GOARCH` envrionment variable if given else `runtime.GOARCH`. |
| -race | Build with Go's race detector | |
| -s | Skip building the frontend | |
| -skipbindings | Skip bindings generation | |
| -tags "extra tags" | Build tags to pass to Go compiler. Must be quoted. Space or comma (but not both) separated | |
| -trimpath | Remove all file system paths from the resulting executable. | |
| -u | Updates your project's `go.mod` to use the same version of Wails as the CLI | |
| -upx | Compress final binary using "upx" | |
| -upxflags | Flags to pass to upx | |
| -v int | Verbosity level (0 - silent, 1 - default, 2 - verbose) | 1 |
| -webview2 | WebView2 installer strategy: download,embed,browser,error | download |
| -windowsconsole | Keep the console window for Windows builds | |
| Flag | Description | Default |
|:---------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------|
| -clean | Cleans the `build/bin` directory | |
| -compiler "compiler" | Use a different go compiler to build, eg go1.15beta1 | go |
| -debug | Retains debug information in the application and shows the debug console. Allows the use of the devtools in the application window | |
| -devtools | Allows the use of the devtools in the application window in production (when -debug is not used). Ctrl/Cmd+Shift+F12 may be used to open the devtools window. *NOTE*: This option will make your application FAIL Mac appstore guidelines. Use for debugging only. | |
| -dryrun | Prints the build command without executing it | |
| -f | Force build application | |
| -garbleargs | Arguments to pass to garble | `-literals -tiny -seed=random` |
| -ldflags "flags" | Additional ldflags to pass to the compiler | |
| -m | Skip mod tidy before compile | |
| -nopackage | Do not package application | |
| -nocolour | Disable colour in output | |
| -nosyncgomod | Do not sync go.mod with the Wails version | |
| -nsis | Generate NSIS installer for Windows | |
| -o filename | Output filename | |
| -obfuscated | Obfuscate the application using [garble](https://github.com/burrowers/garble) | |
| -platform | Build for the given (comma delimited) [platforms](../reference/cli.mdx#platforms) eg. `windows/arm64`. Note, if you do not give the architecture, `runtime.GOARCH` is used. | platform = `GOOS` environment variable if given else `runtime.GOOS`.<br/>arch = `GOARCH` envrionment variable if given else `runtime.GOARCH`. |
| -race | Build with Go's race detector | |
| -s | Skip building the frontend | |
| -skipbindings | Skip bindings generation | |
| -tags "extra tags" | Build tags to pass to Go compiler. Must be quoted. Space or comma (but not both) separated | |
| -trimpath | Remove all file system paths from the resulting executable. | |
| -u | Updates your project's `go.mod` to use the same version of Wails as the CLI | |
| -upx | Compress final binary using "upx" | |
| -upxflags | Flags to pass to upx | |
| -v int | Verbosity level (0 - silent, 1 - default, 2 - verbose) | 1 |
| -webview2 | WebView2 installer strategy: download,embed,browser,error | download |
| -windowsconsole | Keep the console window for Windows builds | |
For a detailed description of the `webview2` flag, please refer to the [Windows](../guides/windows.mdx) Guide.
@ -170,8 +170,8 @@ Your system is ready for Wails development!
- A webserver is started on `http://localhost:34115` which serves your application (not just frontend) over http. This allows you to use your favourite browser development extensions
- All application assets are loaded from disk. If they are changed, the application will automatically reload (not rebuild). All connected browsers will also reload
- A JS module is generated that provides the following:
- JavaScript wrappers of your Go methods with autogenerated JSDoc, providing code hinting
- TypeScript versions of your Go structs, that can be constructed and passed to your go methods
- JavaScript wrappers of your Go methods with autogenerated JSDoc, providing code hinting
- TypeScript versions of your Go structs, that can be constructed and passed to your go methods
- A second JS module is generated that provides a wrapper + TS declaration for the runtime
- On macOS, it will bundle the application into a `.app` file and run it. It will use a `build/darwin/Info.dev.plist` for development.

View File

@ -14,6 +14,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- When building with `-devtools` flag, CMD/CTRL+SHIFT+F12 can be used to open the devtools. Added by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/2915)
#### Fixed
- Fixed typo on docs/reference/options page. Added by [@pylotlight](https://github.com/pylotlight) in [PR](https://github.com/wailsapp/wails/pull/2887)
@ -716,9 +721,6 @@ Experimental: &options.Experimental{
- [v2, nsis] Seems like / as path separator works only for some directives in a cross platform way
by [@stffabi](https://github.com/stffabi) in #1227
- import models on binding definition by [@adalessa](https://github.com/adalessa) in #123
1
- Use local search on website by [@leaanthony](https://github.com/leaanthony) in #1234
- Ensure binary resources can be served by [@napalu](https://github.com/napalu) in #1240
- Only retry loading assets when loading from disk by [@leaanthony](https://github.com/leaanthony) in #1241