mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-18 18:09:30 +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
|
||||
|
||||
### Fixed
|
||||
- Module issues
|
||||
### Fixed
|
||||
- Module issues
|
||||
|
||||
## 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)
|
||||
- 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)
|
||||
- [windows] add `SetIgnoreMouseEvents` for already created window by [@bruxaodev](https://github.com/bruxaodev) in [#3667](https://github.com/wailsapp/wails/pull/3667)
|
||||
|
||||
### 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()
|
||||
windowCounter++
|
||||
})
|
||||
myMenu.Add("New Frameless WebviewWindow").
|
||||
myMenu.Add("New WebviewWindow (Frameless)").
|
||||
SetAccelerator("CmdOrCtrl+F").
|
||||
OnClick(func(ctx *application.Context) {
|
||||
app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{
|
||||
@ -231,23 +231,21 @@ func main() {
|
||||
}).Show()
|
||||
windowCounter++
|
||||
})
|
||||
if runtime.GOOS != "linux" {
|
||||
myMenu.Add("New WebviewWindow (ignores mouse events)").
|
||||
SetAccelerator("CmdOrCtrl+F").
|
||||
OnClick(func(ctx *application.Context) {
|
||||
app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{
|
||||
HTML: "<div style='width: 100%; height: 95%; border: 3px solid red; background-color: \"0000\";'></div>",
|
||||
X: rand.Intn(1000),
|
||||
Y: rand.Intn(800),
|
||||
IgnoreMouseEvents: true,
|
||||
BackgroundType: application.BackgroundTypeTransparent,
|
||||
Mac: application.MacWindow{
|
||||
InvisibleTitleBarHeight: 50,
|
||||
},
|
||||
}).Show()
|
||||
windowCounter++
|
||||
})
|
||||
}
|
||||
myMenu.Add("New WebviewWindow (Ignores mouse events)").
|
||||
SetAccelerator("CmdOrCtrl+F").
|
||||
OnClick(func(ctx *application.Context) {
|
||||
app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{
|
||||
HTML: "<div style='width: 100%; height: 95%; border: 3px solid red; background-color: \"0000\";'></div>",
|
||||
X: rand.Intn(1000),
|
||||
Y: rand.Intn(800),
|
||||
IgnoreMouseEvents: true,
|
||||
BackgroundType: application.BackgroundTypeTransparent,
|
||||
Mac: application.MacWindow{
|
||||
InvisibleTitleBarHeight: 50,
|
||||
},
|
||||
}).Show()
|
||||
windowCounter++
|
||||
})
|
||||
if runtime.GOOS == "darwin" {
|
||||
myMenu.Add("New WebviewWindow (MacTitleBarHiddenInset)").
|
||||
OnClick(func(ctx *application.Context) {
|
||||
|
@ -90,6 +90,8 @@ type (
|
||||
setMinimiseButtonState(state ButtonState)
|
||||
setMaximiseButtonState(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()
|
||||
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];
|
||||
}
|
||||
|
||||
// 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
|
||||
static void windowSetFrameless(void *window, bool frameless) {
|
||||
WebviewWindow* nsWindow = (WebviewWindow*)window;
|
||||
@ -772,6 +766,16 @@ void windowFocus(void *window) {
|
||||
[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 (
|
||||
@ -1159,9 +1163,8 @@ func (w *macosWebviewWindow) run() {
|
||||
w.setMaximiseButtonState(options.MaximiseButtonState)
|
||||
w.setCloseButtonState(options.CloseButtonState)
|
||||
|
||||
if options.IgnoreMouseEvents {
|
||||
C.windowIgnoreMouseEvents(w.nsWindow, C.bool(true))
|
||||
}
|
||||
// Ignore mouse events if requested
|
||||
w.setIgnoreMouseEvents(options.IgnoreMouseEvents)
|
||||
|
||||
titleBarOptions := macOptions.TitleBar
|
||||
if !w.parent.options.Frameless {
|
||||
@ -1302,3 +1305,11 @@ func (w *macosWebviewWindow) setMaximiseButtonState(state ButtonState) {
|
||||
func (w *macosWebviewWindow) setCloseButtonState(state ButtonState) {
|
||||
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
|
||||
ctxMenuOpened bool
|
||||
|
||||
moveDebouncer func(func())
|
||||
resizeDebouncer func(func())
|
||||
moveDebouncer func(func())
|
||||
resizeDebouncer func(func())
|
||||
ignoreMouseEvents bool
|
||||
}
|
||||
|
||||
var (
|
||||
@ -280,9 +281,8 @@ func (w *linuxWebviewWindow) run() {
|
||||
case WindowStateNormal:
|
||||
}
|
||||
|
||||
//if w.parent.options.IgnoreMouseEvents {
|
||||
// windowIgnoreMouseEvents(w.window, w.webview, true)
|
||||
//}
|
||||
// Ignore mouse events if requested
|
||||
w.setIgnoreMouseEvents(options.IgnoreMouseEvents)
|
||||
|
||||
startURL, err := assetserver.GetStartURL(w.parent.options.URL)
|
||||
if err != nil {
|
||||
@ -369,3 +369,17 @@ func (w *linuxWebviewWindow) setMaximiseButtonState(state ButtonState) {}
|
||||
|
||||
// SetCloseButtonState is unsupported on Linux
|
||||
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.setIgnoreMouseEvents(options.IgnoreMouseEvents)
|
||||
|
||||
if options.Frameless {
|
||||
// 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
|
||||
@ -1761,3 +1763,18 @@ func (w *windowsWebviewWindow) setCloseButtonState(state ButtonState) {
|
||||
func (w *windowsWebviewWindow) setGWLStyle(style int) {
|
||||
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)
|
||||
IsFocused() bool
|
||||
IsFullscreen() bool
|
||||
IsIgnoreMouseEvents() bool
|
||||
IsMaximised() bool
|
||||
IsMinimised() bool
|
||||
HandleKeyEvent(acceleratorString string)
|
||||
@ -63,6 +64,7 @@ type Window interface {
|
||||
SetMinSize(minWidth, minHeight int) Window
|
||||
SetRelativePosition(x, y int) Window
|
||||
SetResizable(b bool) Window
|
||||
SetIgnoreMouseEvents(ignore bool) Window
|
||||
SetSize(width, height int) Window
|
||||
SetTitle(title string) Window
|
||||
SetURL(s string) Window
|
||||
|
Loading…
Reference in New Issue
Block a user