diff --git a/v2/cmd/wails/wails b/v2/cmd/wails/wails deleted file mode 100755 index 75251b41d..000000000 Binary files a/v2/cmd/wails/wails and /dev/null differ diff --git a/v2/internal/frontend/desktop/darwin/frontend.go b/v2/internal/frontend/desktop/darwin/frontend.go index bfe470b40..e25099b7a 100644 --- a/v2/internal/frontend/desktop/darwin/frontend.go +++ b/v2/internal/frontend/desktop/darwin/frontend.go @@ -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) } diff --git a/v2/internal/frontend/desktop/darwin/inspector.go b/v2/internal/frontend/desktop/darwin/inspector.go index 3021c5c16..8499745d0 100644 --- a/v2/internal/frontend/desktop/darwin/inspector.go +++ b/v2/internal/frontend/desktop/darwin/inspector.go @@ -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) { } diff --git a/v2/internal/frontend/desktop/darwin/inspector_dev.go b/v2/internal/frontend/desktop/darwin/inspector_dev.go index e948435cb..f3520cb3e 100644 --- a/v2/internal/frontend/desktop/darwin/inspector_dev.go +++ b/v2/internal/frontend/desktop/darwin/inspector_dev.go @@ -1,4 +1,4 @@ -//go:build darwin && (dev || debug) +//go:build darwin && (dev || debug || devtools) package darwin @@ -11,6 +11,8 @@ package darwin #import #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) } diff --git a/v2/internal/frontend/desktop/linux/frontend.go b/v2/internal/frontend/desktop/linux/frontend.go index 7a25df4ac..b32ec5789 100644 --- a/v2/internal/frontend/desktop/linux/frontend.go +++ b/v2/internal/frontend/desktop/linux/frontend.go @@ -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, ":") diff --git a/v2/internal/frontend/desktop/linux/window.c b/v2/internal/frontend/desktop/linux/window.c index a70a3be83..19a07339f 100644 --- a/v2/internal/frontend/desktop/linux/window.c +++ b/v2/internal/frontend/desktop/linux/window.c @@ -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); +} \ No newline at end of file diff --git a/v2/internal/frontend/desktop/linux/window.go b/v2/internal/frontend/desktop/linux/window.go index 6d9b256f6..48db30f3b 100644 --- a/v2/internal/frontend/desktop/linux/window.go +++ b/v2/internal/frontend/desktop/linux/window.go @@ -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() { diff --git a/v2/internal/frontend/desktop/linux/window.h b/v2/internal/frontend/desktop/linux/window.h index eabcdd1e6..aa9499d73 100644 --- a/v2/internal/frontend/desktop/linux/window.h +++ b/v2/internal/frontend/desktop/linux/window.h @@ -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 */ diff --git a/v2/internal/frontend/desktop/windows/frontend.go b/v2/internal/frontend/desktop/windows/frontend.go index dabd1e2cd..b82684a95 100644 --- a/v2/internal/frontend/desktop/windows/frontend.go +++ b/v2/internal/frontend/desktop/windows/frontend.go @@ -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 } diff --git a/v2/internal/frontend/desktop/windows/winc/w32/user32.go b/v2/internal/frontend/desktop/windows/winc/w32/user32.go index 17e0d9991..ec5e4a596 100644 --- a/v2/internal/frontend/desktop/windows/winc/w32/user32.go +++ b/v2/internal/frontend/desktop/windows/winc/w32/user32.go @@ -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 } diff --git a/v2/pkg/commands/build/build.go b/v2/pkg/commands/build/build.go index 65d55aa91..a29840b1b 100644 --- a/v2/pkg/commands/build/build.go +++ b/v2/pkg/commands/build/build.go @@ -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 diff --git a/website/docs/reference/cli.mdx b/website/docs/reference/cli.mdx index 9dcc25bc9..bbfe5bea4 100644 --- a/website/docs/reference/cli.mdx +++ b/website/docs/reference/cli.mdx @@ -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`.
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`.
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. diff --git a/website/src/pages/changelog.mdx b/website/src/pages/changelog.mdx index d1ed1b516..87c942bd4 100644 --- a/website/src/pages/changelog.mdx +++ b/website/src/pages/changelog.mdx @@ -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