Added menu cloning.

Introduced the ability to clone a menu, along with its submenus, in Linux-based web applications to create a full deep copy. This fixes reusing the application menu for window menus.
This commit is contained in:
Lea Anthony
2024-03-06 11:42:19 -06:00
committed by Travis McLane
parent 809863d61a
commit 3d93c83920
9 changed files with 111 additions and 39 deletions
+17 -15
View File
@@ -154,21 +154,23 @@ func main() {
}).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 != "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++
})
}
if runtime.GOOS == "darwin" {
myMenu.Add("New WebviewWindow (MacTitleBarHiddenInset)").
OnClick(func(ctx *application.Context) {
+4 -20
View File
@@ -22,9 +22,8 @@ func init() {
}
type linuxApp struct {
application pointer
applicationMenu pointer
parent *App
application pointer
parent *App
startupActions []func()
@@ -55,8 +54,8 @@ func (l *linuxApp) show() {
}
func (l *linuxApp) on(eventID uint) {
// TODO: What do we need to do here?
log.Println("linuxApp.on()", eventID)
// TODO: Test register/unregister events
//C.registerApplicationEvent(l.application, C.uint(eventID))
}
func (l *linuxApp) setIcon(icon []byte) {
@@ -80,21 +79,6 @@ func (r rnr) run() {
r.f()
}
func (l *linuxApp) getApplicationMenu() pointer {
if l.applicationMenu != nilPointer {
return l.applicationMenu
}
menu := globalApplication.ApplicationMenu
if menu != nil {
InvokeSync(func() {
menu.Update()
})
l.applicationMenu = (menu.impl).(*linuxMenu).native
}
return l.applicationMenu
}
func (l *linuxApp) setApplicationMenu(menu *Menu) {
// FIXME: How do we avoid putting a menu?
if menu == nil {
+5
View File
@@ -70,6 +70,11 @@ type accelerator struct {
Modifiers []modifier
}
func (a *accelerator) clone() *accelerator {
result := *a
return &result
}
func (a *accelerator) String() string {
var result []string
// Sort modifiers
+15 -1
View File
@@ -13,7 +13,7 @@ import (
)
/*
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 javascriptcoregtk-4.1
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 javascriptcoregtk-4.1 gdk-3.0
#include <JavaScriptCore/JavaScript.h>
#include <gtk/gtk.h>
@@ -697,6 +697,10 @@ func windowDestroy(window pointer) {
//C.gtk_widget_destroy((*C.GtkWidget)(window))
}
func menuDestroy(gtkMenu pointer) {
C.gtk_widget_destroy((*C.GtkWidget)(gtkMenu))
}
func windowFullscreen(window pointer) {
C.gtk_window_fullscreen((*C.GtkWindow)(window))
}
@@ -867,6 +871,16 @@ func windowShow(window pointer) {
C.gtk_widget_show_all((*C.GtkWidget)(window))
}
func windowIgnoreMouseEvents(window pointer, webview pointer, ignore bool) {
var enable C.int
if ignore {
enable = 1
}
gdkWindow := (*C.GdkWindow)(window)
C.gdk_window_set_pass_through(gdkWindow, enable)
C.webkit_web_view_set_editable((*C.WebKitWebView)(webview), C.gboolean(enable))
}
func windowSetBackgroundColour(vbox, webview pointer, colour RGBA) {
rgba := C.GdkRGBA{C.double(colour.Red) / 255.0, C.double(colour.Green) / 255.0, C.double(colour.Blue) / 255.0, C.double(colour.Alpha) / 255.0}
C.webkit_web_view_set_background_color((*C.WebKitWebView)(webview), &rgba)
+11
View File
@@ -95,6 +95,17 @@ func (m *Menu) setContextData(data *ContextMenuData) {
}
}
// Clone recursively clones the menu and all its submenus.
func (m *Menu) clone() *Menu {
result := &Menu{
label: m.label,
}
for _, item := range m.items {
result.items = append(result.items, item.clone())
}
return result
}
func (a *App) NewMenu() *Menu {
return &Menu{}
}
+26
View File
@@ -332,3 +332,29 @@ func (m *MenuItem) setContextData(data *ContextMenuData) {
m.submenu.setContextData(data)
}
}
// clone returns a deep copy of the MenuItem
func (m *MenuItem) clone() *MenuItem {
result := &MenuItem{
id: m.id,
label: m.label,
tooltip: m.tooltip,
disabled: m.disabled,
checked: m.checked,
hidden: m.hidden,
bitmap: m.bitmap,
callback: m.callback,
itemType: m.itemType,
role: m.role,
}
if m.submenu != nil {
result.submenu = m.submenu.clone()
}
if m.accelerator != nil {
result.accelerator = m.accelerator.clone()
}
if m.contextMenuData != nil {
result.contextMenuData = m.contextMenuData.clone()
}
return result
}
@@ -11,6 +11,15 @@ type ContextMenuData struct {
Data any `json:"data"`
}
func (d ContextMenuData) clone() *ContextMenuData {
return &ContextMenuData{
Id: d.Id,
X: d.X,
Y: d.Y,
Data: d.Data,
}
}
const (
ContextMenuOpen = 0
)
+1 -1
View File
@@ -116,7 +116,7 @@ type WebviewWindowOptions struct {
// KeyBindings is a map of key bindings to functions
KeyBindings map[string]func(window *WebviewWindow)
// IgnoreMouseEvents will ignore mouse events in the window
// IgnoreMouseEvents will ignore mouse events in the window (Windows + Mac only)
IgnoreMouseEvents bool
}
+23 -2
View File
@@ -34,6 +34,7 @@ type linuxWebviewWindow struct {
lastHeight int
drag dragInfo
lastX, lastY int
gtkmenu pointer
}
var (
@@ -357,8 +358,19 @@ func (w *linuxWebviewWindow) run() {
app := getNativeApplication()
menu := app.getApplicationMenu()
w.window, w.webview, w.vbox = windowNew(app.application, menu, w.parent.id, w.parent.options.Linux.WebviewGpuPolicy)
var menu = w.menu
if menu == nil && globalApplication.ApplicationMenu != nil {
menu = globalApplication.ApplicationMenu.clone()
}
if menu != nil {
InvokeSync(func() {
menu.Update()
})
w.menu = menu
w.gtkmenu = (menu.impl).(*linuxMenu).native
}
w.window, w.webview, w.vbox = windowNew(app.application, w.gtkmenu, w.parent.id, w.parent.options.Linux.WebviewGpuPolicy)
app.registerWindow(w.window, w.parent.id) // record our mapping
w.connectSignals()
if w.parent.options.EnableDragAndDrop {
@@ -403,6 +415,10 @@ func (w *linuxWebviewWindow) run() {
case WindowStateNormal:
}
//if w.parent.options.IgnoreMouseEvents {
// windowIgnoreMouseEvents(w.window, w.webview, true)
//}
startURL, err := assetserver.GetStartURL(w.parent.options.URL)
if err != nil {
globalApplication.fatal(err.Error())
@@ -459,6 +475,11 @@ func (w *linuxWebviewWindow) relativePosition() (int, int) {
func (w *linuxWebviewWindow) destroy() {
w.parent.markAsDestroyed()
// Free menu
if w.gtkmenu != nil {
menuDestroy(w.gtkmenu)
w.gtkmenu = nil
}
windowDestroy(w.window)
}