mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-19 02:19:31 +08:00
[windows] Add support for click-through overlay window (#3667)
* [windows] Add support for click-through overlay window * update changelog * setIgnoreMouseEvents - exemple * fix - remove unused import * Add macOS+Linux support. Update example. * Fix SetIgnoreMouseEvents before window created. --------- Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
This commit is contained in:
parent
96b97b25bf
commit
fbcce0b20c
@ -22,8 +22,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## v3.0.0-alpha.6 - 2024-07-30
|
## v3.0.0-alpha.6 - 2024-07-30
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Module issues
|
- Module issues
|
||||||
|
|
||||||
## v3.0.0-alpha.5 - 2024-07-30
|
## v3.0.0-alpha.5 - 2024-07-30
|
||||||
|
|
||||||
@ -47,6 +47,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Implement `setIcon` on linux by [@abichinger](https://github.com/abichinger) in [#3354](https://github.com/wailsapp/wails/pull/3354)
|
- Implement `setIcon` on linux by [@abichinger](https://github.com/abichinger) in [#3354](https://github.com/wailsapp/wails/pull/3354)
|
||||||
- Add flag `-port` to dev command and support environment variable `WAILS_VITE_PORT` by [@abichinger](https://github.com/abichinger) in [#3429](https://github.com/wailsapp/wails/pull/3429)
|
- Add flag `-port` to dev command and support environment variable `WAILS_VITE_PORT` by [@abichinger](https://github.com/abichinger) in [#3429](https://github.com/wailsapp/wails/pull/3429)
|
||||||
- Add tests for bound method calls by [@abichinger](https://github.com/abichinger) in [#3431](https://github.com/wailsapp/wails/pull/3431)
|
- Add tests for bound method calls by [@abichinger](https://github.com/abichinger) in [#3431](https://github.com/wailsapp/wails/pull/3431)
|
||||||
|
- [windows] add `SetIgnoreMouseEvents` for already created window by [@bruxaodev](https://github.com/bruxaodev) in [#3667](https://github.com/wailsapp/wails/pull/3667)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
19
v3/examples/ignore-mouse/README.md
Normal file
19
v3/examples/ignore-mouse/README.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Window Example
|
||||||
|
|
||||||
|
This example is a demonstration of how to disable or enable mouse events.
|
||||||
|
|
||||||
|
## Running the example
|
||||||
|
|
||||||
|
To run the example, simply run the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go run .
|
||||||
|
```
|
||||||
|
|
||||||
|
# Status
|
||||||
|
|
||||||
|
| Platform | Status |
|
||||||
|
|----------|---------|
|
||||||
|
| Mac | |
|
||||||
|
| Windows | Working |
|
||||||
|
| Linux | |
|
36
v3/examples/ignore-mouse/main.go
Normal file
36
v3/examples/ignore-mouse/main.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v3/pkg/application"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := application.New(application.Options{
|
||||||
|
Name: "WebviewWindow Demo",
|
||||||
|
Description: "A demo of the WebviewWindow API",
|
||||||
|
Assets: application.AlphaAssets,
|
||||||
|
Mac: application.MacOptions{
|
||||||
|
ApplicationShouldTerminateAfterLastWindowClosed: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
window := app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{
|
||||||
|
Width: 800,
|
||||||
|
Height: 600,
|
||||||
|
Title: "Ignore Mouse Example",
|
||||||
|
URL: "https://wails.io",
|
||||||
|
IgnoreMouseEvents: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
window.SetIgnoreMouseEvents(true)
|
||||||
|
log.Println("IgnoreMouseEvents set", window.IsIgnoreMouseEvents())
|
||||||
|
|
||||||
|
err := app.Run()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -217,7 +217,7 @@ func main() {
|
|||||||
Show()
|
Show()
|
||||||
windowCounter++
|
windowCounter++
|
||||||
})
|
})
|
||||||
myMenu.Add("New Frameless WebviewWindow").
|
myMenu.Add("New WebviewWindow (Frameless)").
|
||||||
SetAccelerator("CmdOrCtrl+F").
|
SetAccelerator("CmdOrCtrl+F").
|
||||||
OnClick(func(ctx *application.Context) {
|
OnClick(func(ctx *application.Context) {
|
||||||
app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{
|
app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{
|
||||||
@ -231,23 +231,21 @@ func main() {
|
|||||||
}).Show()
|
}).Show()
|
||||||
windowCounter++
|
windowCounter++
|
||||||
})
|
})
|
||||||
if runtime.GOOS != "linux" {
|
myMenu.Add("New WebviewWindow (Ignores mouse events)").
|
||||||
myMenu.Add("New WebviewWindow (ignores mouse events)").
|
SetAccelerator("CmdOrCtrl+F").
|
||||||
SetAccelerator("CmdOrCtrl+F").
|
OnClick(func(ctx *application.Context) {
|
||||||
OnClick(func(ctx *application.Context) {
|
app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{
|
||||||
app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{
|
HTML: "<div style='width: 100%; height: 95%; border: 3px solid red; background-color: \"0000\";'></div>",
|
||||||
HTML: "<div style='width: 100%; height: 95%; border: 3px solid red; background-color: \"0000\";'></div>",
|
X: rand.Intn(1000),
|
||||||
X: rand.Intn(1000),
|
Y: rand.Intn(800),
|
||||||
Y: rand.Intn(800),
|
IgnoreMouseEvents: true,
|
||||||
IgnoreMouseEvents: true,
|
BackgroundType: application.BackgroundTypeTransparent,
|
||||||
BackgroundType: application.BackgroundTypeTransparent,
|
Mac: application.MacWindow{
|
||||||
Mac: application.MacWindow{
|
InvisibleTitleBarHeight: 50,
|
||||||
InvisibleTitleBarHeight: 50,
|
},
|
||||||
},
|
}).Show()
|
||||||
}).Show()
|
windowCounter++
|
||||||
windowCounter++
|
})
|
||||||
})
|
|
||||||
}
|
|
||||||
if runtime.GOOS == "darwin" {
|
if runtime.GOOS == "darwin" {
|
||||||
myMenu.Add("New WebviewWindow (MacTitleBarHiddenInset)").
|
myMenu.Add("New WebviewWindow (MacTitleBarHiddenInset)").
|
||||||
OnClick(func(ctx *application.Context) {
|
OnClick(func(ctx *application.Context) {
|
||||||
|
@ -90,6 +90,8 @@ type (
|
|||||||
setMinimiseButtonState(state ButtonState)
|
setMinimiseButtonState(state ButtonState)
|
||||||
setMaximiseButtonState(state ButtonState)
|
setMaximiseButtonState(state ButtonState)
|
||||||
setCloseButtonState(state ButtonState)
|
setCloseButtonState(state ButtonState)
|
||||||
|
isIgnoreMouseEvents() bool
|
||||||
|
setIgnoreMouseEvents(ignore bool)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1232,3 +1234,21 @@ func (w *WebviewWindow) addMenuBinding(a *accelerator, menuItem *MenuItem) {
|
|||||||
defer w.menuBindingsLock.Unlock()
|
defer w.menuBindingsLock.Unlock()
|
||||||
w.menuBindings[a.String()] = menuItem
|
w.menuBindings[a.String()] = menuItem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *WebviewWindow) IsIgnoreMouseEvents() bool {
|
||||||
|
if w.impl == nil && !w.isDestroyed() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return InvokeSyncWithResult(w.impl.isIgnoreMouseEvents)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WebviewWindow) SetIgnoreMouseEvents(ignore bool) Window {
|
||||||
|
w.options.IgnoreMouseEvents = ignore
|
||||||
|
if w.impl == nil && !w.isDestroyed() {
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
InvokeSync(func() {
|
||||||
|
w.impl.setIgnoreMouseEvents(ignore)
|
||||||
|
})
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
@ -689,12 +689,6 @@ static void windowShowMenu(void *window, void *menu, int x, int y) {
|
|||||||
[nsMenu popUpMenuPositioningItem:nil atLocation:point inView:webView];
|
[nsMenu popUpMenuPositioningItem:nil atLocation:point inView:webView];
|
||||||
}
|
}
|
||||||
|
|
||||||
// windowIgnoreMouseEvents makes the window ignore mouse events
|
|
||||||
static void windowIgnoreMouseEvents(void *window, bool ignore) {
|
|
||||||
WebviewWindow* nsWindow = (WebviewWindow*)window;
|
|
||||||
[nsWindow setIgnoresMouseEvents:ignore];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make the given window frameless
|
// Make the given window frameless
|
||||||
static void windowSetFrameless(void *window, bool frameless) {
|
static void windowSetFrameless(void *window, bool frameless) {
|
||||||
WebviewWindow* nsWindow = (WebviewWindow*)window;
|
WebviewWindow* nsWindow = (WebviewWindow*)window;
|
||||||
@ -772,6 +766,16 @@ void windowFocus(void *window) {
|
|||||||
[nsWindow makeKeyWindow];
|
[nsWindow makeKeyWindow];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isIgnoreMouseEvents(void *nsWindow) {
|
||||||
|
NSWindow *window = (__bridge NSWindow *)nsWindow;
|
||||||
|
return [window ignoresMouseEvents];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setIgnoreMouseEvents(void *nsWindow, bool ignore) {
|
||||||
|
NSWindow *window = (__bridge NSWindow *)nsWindow;
|
||||||
|
[window setIgnoresMouseEvents:ignore];
|
||||||
|
}
|
||||||
|
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
@ -1159,9 +1163,8 @@ func (w *macosWebviewWindow) run() {
|
|||||||
w.setMaximiseButtonState(options.MaximiseButtonState)
|
w.setMaximiseButtonState(options.MaximiseButtonState)
|
||||||
w.setCloseButtonState(options.CloseButtonState)
|
w.setCloseButtonState(options.CloseButtonState)
|
||||||
|
|
||||||
if options.IgnoreMouseEvents {
|
// Ignore mouse events if requested
|
||||||
C.windowIgnoreMouseEvents(w.nsWindow, C.bool(true))
|
w.setIgnoreMouseEvents(options.IgnoreMouseEvents)
|
||||||
}
|
|
||||||
|
|
||||||
titleBarOptions := macOptions.TitleBar
|
titleBarOptions := macOptions.TitleBar
|
||||||
if !w.parent.options.Frameless {
|
if !w.parent.options.Frameless {
|
||||||
@ -1302,3 +1305,11 @@ func (w *macosWebviewWindow) setMaximiseButtonState(state ButtonState) {
|
|||||||
func (w *macosWebviewWindow) setCloseButtonState(state ButtonState) {
|
func (w *macosWebviewWindow) setCloseButtonState(state ButtonState) {
|
||||||
C.setCloseButtonState(w.nsWindow, C.int(state))
|
C.setCloseButtonState(w.nsWindow, C.int(state))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *macosWebviewWindow) isIgnoreMouseEvents() bool {
|
||||||
|
return bool(C.isIgnoreMouseEvents(w.nsWindow))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *macosWebviewWindow) setIgnoreMouseEvents(ignore bool) {
|
||||||
|
C.setIgnoreMouseEvents(w.nsWindow, C.bool(ignore))
|
||||||
|
}
|
||||||
|
@ -42,8 +42,9 @@ type linuxWebviewWindow struct {
|
|||||||
gtkmenu pointer
|
gtkmenu pointer
|
||||||
ctxMenuOpened bool
|
ctxMenuOpened bool
|
||||||
|
|
||||||
moveDebouncer func(func())
|
moveDebouncer func(func())
|
||||||
resizeDebouncer func(func())
|
resizeDebouncer func(func())
|
||||||
|
ignoreMouseEvents bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -280,9 +281,8 @@ func (w *linuxWebviewWindow) run() {
|
|||||||
case WindowStateNormal:
|
case WindowStateNormal:
|
||||||
}
|
}
|
||||||
|
|
||||||
//if w.parent.options.IgnoreMouseEvents {
|
// Ignore mouse events if requested
|
||||||
// windowIgnoreMouseEvents(w.window, w.webview, true)
|
w.setIgnoreMouseEvents(options.IgnoreMouseEvents)
|
||||||
//}
|
|
||||||
|
|
||||||
startURL, err := assetserver.GetStartURL(w.parent.options.URL)
|
startURL, err := assetserver.GetStartURL(w.parent.options.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -369,3 +369,17 @@ func (w *linuxWebviewWindow) setMaximiseButtonState(state ButtonState) {}
|
|||||||
|
|
||||||
// SetCloseButtonState is unsupported on Linux
|
// SetCloseButtonState is unsupported on Linux
|
||||||
func (w *linuxWebviewWindow) setCloseButtonState(state ButtonState) {}
|
func (w *linuxWebviewWindow) setCloseButtonState(state ButtonState) {}
|
||||||
|
|
||||||
|
func (w *linuxWebviewWindow) isIgnoreMouseEvents() bool {
|
||||||
|
return w.ignoreMouseEvents
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *linuxWebviewWindow) setIgnoreMouseEvents(ignore bool) {
|
||||||
|
w.ignoreMouseEvents = ignore
|
||||||
|
|
||||||
|
if ignore {
|
||||||
|
C.gtk_widget_set_events((*C.GtkWidget)(unsafe.Pointer(w.window)), C.GDK_ENTER_NOTIFY_MASK|C.GDK_LEAVE_NOTIFY_MASK)
|
||||||
|
} else {
|
||||||
|
C.gtk_widget_set_events((*C.GtkWidget)(unsafe.Pointer(w.window)), C.GDK_ALL_EVENTS_MASK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -279,6 +279,8 @@ func (w *windowsWebviewWindow) run() {
|
|||||||
|
|
||||||
w.setResizable(!options.DisableResize)
|
w.setResizable(!options.DisableResize)
|
||||||
|
|
||||||
|
w.setIgnoreMouseEvents(options.IgnoreMouseEvents)
|
||||||
|
|
||||||
if options.Frameless {
|
if options.Frameless {
|
||||||
// Inform the application of the frame change this is needed to trigger the WM_NCCALCSIZE event.
|
// Inform the application of the frame change this is needed to trigger the WM_NCCALCSIZE event.
|
||||||
// => https://learn.microsoft.com/en-us/windows/win32/dwm/customframe#removing-the-standard-frame
|
// => https://learn.microsoft.com/en-us/windows/win32/dwm/customframe#removing-the-standard-frame
|
||||||
@ -1761,3 +1763,18 @@ func (w *windowsWebviewWindow) setCloseButtonState(state ButtonState) {
|
|||||||
func (w *windowsWebviewWindow) setGWLStyle(style int) {
|
func (w *windowsWebviewWindow) setGWLStyle(style int) {
|
||||||
w32.SetWindowLong(w.hwnd, w32.GWL_STYLE, uint32(style))
|
w32.SetWindowLong(w.hwnd, w32.GWL_STYLE, uint32(style))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *windowsWebviewWindow) isIgnoreMouseEvents() bool {
|
||||||
|
exStyle := w32.GetWindowLong(w.hwnd, w32.GWL_EXSTYLE)
|
||||||
|
return exStyle&w32.WS_EX_TRANSPARENT != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *windowsWebviewWindow) setIgnoreMouseEvents(ignore bool) {
|
||||||
|
exStyle := w32.GetWindowLong(w.hwnd, w32.GWL_EXSTYLE)
|
||||||
|
if ignore {
|
||||||
|
exStyle |= w32.WS_EX_LAYERED | w32.WS_EX_TRANSPARENT
|
||||||
|
} else {
|
||||||
|
exStyle &^= w32.WS_EX_TRANSPARENT
|
||||||
|
}
|
||||||
|
w32.SetWindowLong(w.hwnd, w32.GWL_EXSTYLE, uint32(exStyle))
|
||||||
|
}
|
||||||
|
@ -36,6 +36,7 @@ type Window interface {
|
|||||||
Info(message string, args ...any)
|
Info(message string, args ...any)
|
||||||
IsFocused() bool
|
IsFocused() bool
|
||||||
IsFullscreen() bool
|
IsFullscreen() bool
|
||||||
|
IsIgnoreMouseEvents() bool
|
||||||
IsMaximised() bool
|
IsMaximised() bool
|
||||||
IsMinimised() bool
|
IsMinimised() bool
|
||||||
HandleKeyEvent(acceleratorString string)
|
HandleKeyEvent(acceleratorString string)
|
||||||
@ -63,6 +64,7 @@ type Window interface {
|
|||||||
SetMinSize(minWidth, minHeight int) Window
|
SetMinSize(minWidth, minHeight int) Window
|
||||||
SetRelativePosition(x, y int) Window
|
SetRelativePosition(x, y int) Window
|
||||||
SetResizable(b bool) Window
|
SetResizable(b bool) Window
|
||||||
|
SetIgnoreMouseEvents(ignore bool) Window
|
||||||
SetSize(width, height int) Window
|
SetSize(width, height int) Window
|
||||||
SetTitle(title string) Window
|
SetTitle(title string) Window
|
||||||
SetURL(s string) Window
|
SetURL(s string) Window
|
||||||
|
Loading…
Reference in New Issue
Block a user