mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-04 17:42:24 +08:00
765 lines
23 KiB
Go
765 lines
23 KiB
Go
//go:build linux && purego
|
|
|
|
package application
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"sync"
|
|
"unsafe"
|
|
|
|
"github.com/ebitengine/purego"
|
|
"github.com/wailsapp/wails/v2/pkg/menu"
|
|
"github.com/wailsapp/wails/v3/pkg/events"
|
|
)
|
|
|
|
var (
|
|
registered bool = false // avoid 'already registered message'
|
|
)
|
|
|
|
const (
|
|
// https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gdk/gdkwindow.h#L121
|
|
GDK_HINT_MIN_SIZE = 1 << 1
|
|
GDK_HINT_MAX_SIZE = 1 << 2
|
|
// https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gdk/gdkevents.h#L512
|
|
GDK_WINDOW_STATE_ICONIFIED = 1 << 1
|
|
GDK_WINDOW_STATE_MAXIMIZED = 1 << 2
|
|
GDK_WINDOW_STATE_FULLSCREEN = 1 << 4
|
|
)
|
|
|
|
type GdkGeometry struct {
|
|
minWidth int32
|
|
minHeight int32
|
|
maxWidth int32
|
|
maxHeight int32
|
|
baseWidth int32
|
|
baseHeight int32
|
|
widthInc int32
|
|
heightInc int32
|
|
padding int32
|
|
minAspect float64
|
|
maxAspect float64
|
|
GdkGravity int32
|
|
}
|
|
|
|
type linuxWebviewWindow struct {
|
|
application uintptr
|
|
window uintptr
|
|
webview uintptr
|
|
parent *WebviewWindow
|
|
menubar uintptr
|
|
vbox uintptr
|
|
menu *menu.Menu
|
|
accels uintptr
|
|
minWidth, minHeight, maxWidth, maxHeight int
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) newWebview(gpuPolicy int) uintptr {
|
|
var newContentMgr func() uintptr
|
|
purego.RegisterLibFunc(
|
|
&newContentMgr,
|
|
webkit,
|
|
"webkit_user_content_manager_new")
|
|
var registerScriptMessageHandler func(uintptr, string)
|
|
purego.RegisterLibFunc(®isterScriptMessageHandler, webkit, "webkit_user_content_manager_register_script_message_handler")
|
|
var newWebview func(uintptr) uintptr
|
|
purego.RegisterLibFunc(&newWebview, webkit, "webkit_web_view_new_with_user_content_manager")
|
|
|
|
manager := newContentMgr()
|
|
registerScriptMessageHandler(manager, "external")
|
|
webview := newWebview(manager)
|
|
if !registered {
|
|
var registerUriScheme func(uintptr, string, uintptr, uintptr, uintptr)
|
|
purego.RegisterLibFunc(®isterUriScheme, webkit, "webkit_web_context_register_uri_scheme")
|
|
cb := purego.NewCallback(func(request uintptr) {
|
|
processURLRequest(w.parent.id, request)
|
|
})
|
|
var defaultContext func() uintptr
|
|
purego.RegisterLibFunc(&defaultContext, webkit, "webkit_web_context_get_default")
|
|
registerUriScheme(defaultContext(), "wails", cb, 0, 0)
|
|
}
|
|
|
|
var g_signal_connect func(uintptr, string, uintptr, uintptr, bool, int) int
|
|
purego.RegisterLibFunc(&g_signal_connect, gtk, "g_signal_connect_data")
|
|
|
|
loadChanged := purego.NewCallback(func(window uintptr) {
|
|
//fmt.Println("loadChanged", window)
|
|
})
|
|
if g_signal_connect(webview, "load-changed", loadChanged, 0, false, 0) == 0 {
|
|
fmt.Println("failed to connect 'load-changed' event")
|
|
}
|
|
|
|
if g_signal_connect(webview, "button-press-event", purego.NewCallback(w.buttonPress), 0, false, 0) == 0 {
|
|
fmt.Println("failed to connect 'button-press-event")
|
|
}
|
|
if g_signal_connect(webview, "button-release-event", purego.NewCallback(w.buttonRelease), 0, false, 0) == 0 {
|
|
fmt.Println("failed to connect 'button-release-event")
|
|
}
|
|
|
|
handleDelete := purego.NewCallback(func(uintptr) {
|
|
w.close()
|
|
if !w.parent.options.HideOnClose {
|
|
fmt.Println("Need to do more!")
|
|
}
|
|
})
|
|
g_signal_connect(w.window, "delete-event", handleDelete, 0, false, 0)
|
|
|
|
var getSettings func(uintptr) uintptr
|
|
purego.RegisterLibFunc(&getSettings, webkit, "webkit_web_view_get_settings")
|
|
var setSettings func(uintptr, uintptr)
|
|
purego.RegisterLibFunc(&setSettings, webkit, "webkit_web_view_set_settings")
|
|
var setUserAgent func(uintptr, string, string)
|
|
purego.RegisterLibFunc(&setUserAgent, webkit, "webkit_settings_set_user_agent_with_application_details")
|
|
settings := getSettings(webview)
|
|
setUserAgent(settings, "wails.io", "")
|
|
|
|
var setHWAccel func(uintptr, int)
|
|
purego.RegisterLibFunc(&setHWAccel, webkit, "webkit_settings_set_hardware_acceleration_policy")
|
|
|
|
setHWAccel(settings, gpuPolicy)
|
|
setSettings(webview, settings)
|
|
|
|
return webview
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) openContextMenu(menu *Menu, data *ContextMenuData) {
|
|
// Create the menu
|
|
thisMenu := newMenuImpl(menu)
|
|
thisMenu.update()
|
|
fmt.Println("linux.openContextMenu()")
|
|
//C.windowShowMenu(w.nsWindow, thisMenu.nsMenu, C.int(data.X), C.int(data.Y))
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) getZoom() float64 {
|
|
var getZoom func(uintptr) float32
|
|
purego.RegisterLibFunc(&getZoom, webkit, "webkit_web_view_get_zoom_level")
|
|
return float64(getZoom(w.webview))
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) setZoom(zoom float64) {
|
|
var setZoom func(uintptr, float64)
|
|
purego.RegisterLibFunc(&setZoom, webkit, "webkit_web_view_set_zoom_level")
|
|
setZoom(w.webview, zoom)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) setFrameless(frameless bool) {
|
|
var setDecorated func(uintptr, int)
|
|
purego.RegisterLibFunc(&setDecorated, gtk, "gtk_window_set_decorated")
|
|
decorated := 1
|
|
if frameless {
|
|
decorated = 0
|
|
}
|
|
setDecorated(w.window, decorated)
|
|
if !frameless {
|
|
// TODO: Deal with transparency for the titlebar if possible
|
|
// Perhaps we just make it undecorated and add a menu bar inside?
|
|
}
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) getScreen() (*Screen, error) {
|
|
return getScreenForWindow(w)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) show() {
|
|
var widgetShow func(uintptr)
|
|
purego.RegisterLibFunc(&widgetShow, gtk, "gtk_widget_show_all")
|
|
globalApplication.dispatchOnMainThread(func() {
|
|
widgetShow(w.window)
|
|
})
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) hide() {
|
|
var widgetHide func(uintptr)
|
|
purego.RegisterLibFunc(&widgetHide, gtk, "gtk_widget_hide")
|
|
widgetHide(w.window)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) setFullscreenButtonEnabled(enabled bool) {
|
|
// C.setFullscreenButtonEnabled(w.nsWindow, C.bool(enabled))
|
|
fmt.Println("setFullscreenButtonEnabled - not implemented")
|
|
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) disableSizeConstraints() {
|
|
x, y, width, height, scale := w.getCurrentMonitorGeometry()
|
|
w.setMinMaxSize(x, y, width*scale, height*scale)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) unfullscreen() {
|
|
var unfullScreen func(uintptr)
|
|
purego.RegisterLibFunc(&unfullScreen, gtk, "gtk_window_unfullscreen")
|
|
|
|
globalApplication.dispatchOnMainThread(func() {
|
|
unfullScreen(w.window)
|
|
w.unmaximise()
|
|
})
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) setEnabled(enabled bool) {
|
|
var gtkWidgetSensitive func(uintptr, int)
|
|
purego.RegisterLibFunc(>kWidgetSensitive, gtk, "gtk_widget_set_sensitive")
|
|
globalApplication.dispatchOnMainThread(func() {
|
|
gtkWidgetSensitive(w.window, boolToInt(enabled))
|
|
})
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) fullscreen() {
|
|
var fullScreen func(uintptr)
|
|
purego.RegisterLibFunc(&fullScreen, gtk, "gtk_window_fullscreen")
|
|
|
|
globalApplication.dispatchOnMainThread(func() {
|
|
w.maximise()
|
|
// w.lastWidth, w.lastHeight = w.size() // do we need this?
|
|
|
|
x, y, width, height, scale := w.getCurrentMonitorGeometry()
|
|
if x == -1 && y == -1 && width == -1 && height == -1 {
|
|
return
|
|
}
|
|
w.setMinMaxSize(0, 0, width*scale, height*scale)
|
|
w.setSize(width*scale, height*scale)
|
|
w.setRelativePosition(0, 0)
|
|
fullScreen(w.window)
|
|
})
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) unminimise() {
|
|
var present func(uintptr)
|
|
purego.RegisterLibFunc(&present, gtk, "gtk_window_present")
|
|
present(w.window)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) unmaximise() {
|
|
var unmaximize func(uintptr)
|
|
purego.RegisterLibFunc(&unmaximize, gtk, "gtk_window_unmaximize")
|
|
unmaximize(w.window)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) maximise() {
|
|
var maximize func(uintptr)
|
|
purego.RegisterLibFunc(&maximize, gtk, "gtk_window_maximize")
|
|
maximize(w.window)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) minimise() {
|
|
var iconify func(uintptr)
|
|
purego.RegisterLibFunc(&iconify, gtk, "gtk_window_iconify")
|
|
iconify(w.window)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) on(eventID uint) {
|
|
// Don't think this is correct!
|
|
// GTK Events are strings
|
|
fmt.Println("on()", eventID)
|
|
//C.registerListener(C.uint(eventID))
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) zoom() {
|
|
w.zoomIn()
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) windowZoom() {
|
|
w.zoom()
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) close() {
|
|
var close func(uintptr)
|
|
purego.RegisterLibFunc(&close, gtk, "gtk_window_close")
|
|
close(w.window)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) zoomIn() {
|
|
var getZoom func(uintptr) float32
|
|
purego.RegisterLibFunc(&getZoom, webkit, "webkit_web_view_get_zoom_level")
|
|
var setZoom func(uintptr, float32)
|
|
purego.RegisterLibFunc(&setZoom, webkit, "webkit_web_view_set_zoom_level")
|
|
lvl := getZoom(w.webview)
|
|
setZoom(w.webview, lvl+0.5)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) zoomOut() {
|
|
var getZoom func(uintptr) float32
|
|
purego.RegisterLibFunc(&getZoom, webkit, "webkit_web_view_get_zoom_level")
|
|
var setZoom func(uintptr, float32)
|
|
purego.RegisterLibFunc(&setZoom, webkit, "webkit_web_view_set_zoom_level")
|
|
lvl := getZoom(w.webview)
|
|
setZoom(w.webview, lvl-0.5)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) zoomReset() {
|
|
var setZoom func(uintptr, float32)
|
|
purego.RegisterLibFunc(&setZoom, webkit, "webkit_web_view_set_zoom_level")
|
|
setZoom(w.webview, 0.0)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) toggleDevTools() {
|
|
var getSettings func(uintptr) uintptr
|
|
purego.RegisterLibFunc(&getSettings, webkit, "webkit_web_view_get_settings")
|
|
var isEnabled func(uintptr) bool
|
|
purego.RegisterLibFunc(&isEnabled, webkit, "webkit_settings_get_enable_developer_extras")
|
|
var enableDev func(uintptr, bool)
|
|
purego.RegisterLibFunc(&enableDev, webkit, "webkit_settings_set_enable_developer_extras")
|
|
settings := getSettings(w.webview)
|
|
enabled := isEnabled(settings)
|
|
enableDev(settings, !enabled)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) reload() {
|
|
var reload func(uintptr)
|
|
purego.RegisterLibFunc(&reload, webkit, "webkit_web_view_reload")
|
|
reload(w.webview)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) forceReload() {
|
|
var reload func(uintptr)
|
|
purego.RegisterLibFunc(&reload, webkit, "webkit_web_view_reload_bypass_cache")
|
|
reload(w.webview)
|
|
}
|
|
|
|
func (w linuxWebviewWindow) getCurrentMonitor() uintptr {
|
|
var getDisplay func(uintptr) uintptr
|
|
purego.RegisterLibFunc(&getDisplay, gtk, "gtk_widget_get_display")
|
|
var getWindow func(uintptr) uintptr
|
|
purego.RegisterLibFunc(&getWindow, gtk, "gtk_widget_get_window")
|
|
var getMonitor func(uintptr, uintptr) uintptr
|
|
purego.RegisterLibFunc(&getMonitor, gtk, "gdk_display_get_monitor_at_window")
|
|
|
|
display := getDisplay(w.window)
|
|
window := getWindow(w.window)
|
|
if window == 0 {
|
|
return 0
|
|
}
|
|
return getMonitor(display, window)
|
|
}
|
|
|
|
func (w linuxWebviewWindow) getCurrentMonitorGeometry() (x int, y int, width int, height int, scale int) {
|
|
var getGeometry func(uintptr, uintptr)
|
|
purego.RegisterLibFunc(&getGeometry, gtk, "gdk_monitor_get_geometry")
|
|
var getScaleFactor func(uintptr) int
|
|
purego.RegisterLibFunc(&getScaleFactor, gtk, "gdk_monitor_get_scale_factor")
|
|
|
|
monitor := w.getCurrentMonitor()
|
|
if monitor == 0 {
|
|
return -1, -1, -1, -1, 1
|
|
}
|
|
result := struct {
|
|
x int32
|
|
y int32
|
|
width int32
|
|
height int32
|
|
}{}
|
|
getGeometry(monitor, uintptr(unsafe.Pointer(&result)))
|
|
scale = getScaleFactor(monitor)
|
|
return int(result.x), int(result.y), int(result.width), int(result.height), scale
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) center() {
|
|
fmt.Println("attempting to set in the center")
|
|
|
|
x, y, width, height, _ := w.getCurrentMonitorGeometry()
|
|
if x == -1 && y == -1 && width == -1 && height == -1 {
|
|
return
|
|
}
|
|
|
|
windowWidth, windowHeight := w.size()
|
|
|
|
newX := ((width - int(windowWidth)) / 2) + x
|
|
newY := ((height - int(windowHeight)) / 2) + y
|
|
|
|
w.setRelativePosition(newX, newY)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) isMinimised() bool {
|
|
var getWindow func(uintptr) uintptr
|
|
purego.RegisterLibFunc(&getWindow, gtk, "gtk_widget_get_window")
|
|
var getWindowState func(uintptr) int
|
|
purego.RegisterLibFunc(&getWindowState, gtk, "gdk_window_get_state")
|
|
|
|
return w.syncMainThreadReturningBool(func() bool {
|
|
state := getWindowState(getWindow(w.window))
|
|
return state&GDK_WINDOW_STATE_ICONIFIED > 0
|
|
})
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) isMaximised() bool {
|
|
var getWindow func(uintptr) uintptr
|
|
purego.RegisterLibFunc(&getWindow, gtk, "gtk_widget_get_window")
|
|
var getWindowState func(uintptr) int
|
|
purego.RegisterLibFunc(&getWindowState, gtk, "gdk_window_get_state")
|
|
|
|
return w.syncMainThreadReturningBool(func() bool {
|
|
state := getWindowState(getWindow(w.window))
|
|
return state&GDK_WINDOW_STATE_MAXIMIZED > 0 && state&GDK_WINDOW_STATE_FULLSCREEN == 0
|
|
})
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) isFullscreen() bool {
|
|
var getWindow func(uintptr) uintptr
|
|
purego.RegisterLibFunc(&getWindow, gtk, "gtk_widget_get_window")
|
|
var getWindowState func(uintptr) int
|
|
purego.RegisterLibFunc(&getWindowState, gtk, "gdk_window_get_state")
|
|
|
|
return w.syncMainThreadReturningBool(func() bool {
|
|
state := getWindowState(getWindow(w.window))
|
|
return state&GDK_WINDOW_STATE_FULLSCREEN > 0
|
|
})
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) syncMainThreadReturningBool(fn func() bool) bool {
|
|
var wg sync.WaitGroup
|
|
wg.Add(1)
|
|
var result bool
|
|
globalApplication.dispatchOnMainThread(func() {
|
|
result = fn()
|
|
wg.Done()
|
|
})
|
|
wg.Wait()
|
|
return result
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) restore() {
|
|
// restore window to normal size
|
|
fmt.Println("restore")
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) execJS(js string) {
|
|
var evalJS func(uintptr, string, int, uintptr, string, uintptr, uintptr, uintptr)
|
|
purego.RegisterLibFunc(&evalJS, webkit, "webkit_web_view_evaluate_javascript")
|
|
evalJS(w.webview, js, len(js), 0, "", 0, 0, 0)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) setURL(uri string) {
|
|
fmt.Println("setURL", uri)
|
|
var loadUri func(uintptr, string)
|
|
purego.RegisterLibFunc(&loadUri, webkit, "webkit_web_view_load_uri")
|
|
|
|
url, err := url.Parse(uri)
|
|
if url != nil && err == nil && url.Scheme == "" && url.Host == "" {
|
|
// TODO handle this in a central location, the scheme and host might be platform dependant
|
|
url.Scheme = "wails"
|
|
url.Host = "wails"
|
|
uri = url.String()
|
|
loadUri(w.webview, uri)
|
|
}
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) {
|
|
var keepAbove func(uintptr, bool)
|
|
purego.RegisterLibFunc(&keepAbove, gtk, "gtk_window_set_keep_above")
|
|
keepAbove(w.window, alwaysOnTop)
|
|
}
|
|
|
|
func newWindowImpl(parent *WebviewWindow) *linuxWebviewWindow {
|
|
return &linuxWebviewWindow{
|
|
application: getNativeApplication().application,
|
|
parent: parent,
|
|
}
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) setTitle(title string) {
|
|
if !w.parent.options.Frameless {
|
|
var setTitle func(uintptr, string)
|
|
purego.RegisterLibFunc(&setTitle, gtk, "gtk_window_set_title")
|
|
setTitle(w.window, title)
|
|
}
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) setSize(width, height int) {
|
|
var setSize func(uintptr, int, int)
|
|
purego.RegisterLibFunc(&setSize, gtk, "gtk_window_set_default_size")
|
|
setSize(w.window, width, height)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) setMinMaxSize(minWidth, minHeight, maxWidth, maxHeight int) {
|
|
fmt.Println("setMinMaxSize", minWidth, minHeight, maxWidth, maxHeight)
|
|
if minWidth == 0 {
|
|
minWidth = -1
|
|
}
|
|
if minHeight == 0 {
|
|
minHeight = -1
|
|
}
|
|
if maxWidth == 0 {
|
|
maxWidth = -1
|
|
}
|
|
if maxHeight == 0 {
|
|
maxHeight = -1
|
|
}
|
|
size := GdkGeometry{
|
|
minWidth: int32(minWidth),
|
|
minHeight: int32(minHeight),
|
|
maxWidth: int32(maxWidth),
|
|
maxHeight: int32(maxHeight),
|
|
}
|
|
|
|
var setHints func(uintptr, uintptr, uintptr, int)
|
|
purego.RegisterLibFunc(&setHints, gtk, "gtk_window_set_geometry_hints")
|
|
setHints(w.window, 0, uintptr(unsafe.Pointer(&size)), GDK_HINT_MIN_SIZE|GDK_HINT_MAX_SIZE)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) setMinSize(width, height int) {
|
|
w.setMinMaxSize(width, height, w.parent.options.MaxWidth, w.parent.options.MaxHeight)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) setMaxSize(width, height int) {
|
|
w.setMinMaxSize(w.parent.options.MinWidth, w.parent.options.MinHeight, width, height)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) setResizable(resizable bool) {
|
|
var setResizable func(uintptr, int)
|
|
purego.RegisterLibFunc(&setResizable, gtk, "gtk_window_set_resizable")
|
|
globalApplication.dispatchOnMainThread(func() {
|
|
if resizable {
|
|
setResizable(w.window, 1)
|
|
} else {
|
|
setResizable(w.window, 0)
|
|
}
|
|
})
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) size() (int, int) {
|
|
var width, height int
|
|
var windowGetSize func(uintptr, *int, *int)
|
|
purego.RegisterLibFunc(&windowGetSize, gtk, "gtk_window_get_size")
|
|
|
|
var wg sync.WaitGroup
|
|
wg.Add(1)
|
|
globalApplication.dispatchOnMainThread(func() {
|
|
windowGetSize(w.window, &width, &height)
|
|
wg.Done()
|
|
})
|
|
wg.Wait()
|
|
return width, height
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) setRelativePosition(x, y int) {
|
|
var windowMove func(uintptr, int, int)
|
|
purego.RegisterLibFunc(&windowMove, gtk, "gtk_window_move")
|
|
mx, my, _, _, _ := w.getCurrentMonitorGeometry()
|
|
fmt.Println("setRelativePosition", mx, my)
|
|
globalApplication.dispatchOnMainThread(func() {
|
|
windowMove(w.window, x+mx, y+my)
|
|
})
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) width() int {
|
|
width, _ := w.size()
|
|
return width
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) height() int {
|
|
_, height := w.size()
|
|
return height
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) buttonPress(widget uintptr, event uintptr, user_data uintptr) {
|
|
GdkEventButton := (*byte)(unsafe.Pointer(event))
|
|
fmt.Println("buttonpress", w.parent.id, widget, GdkEventButton, user_data)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) buttonRelease(widget uintptr, event uintptr, user_data uintptr) {
|
|
GdkEventButton := (*byte)(unsafe.Pointer(event))
|
|
fmt.Println("buttonrelease", w.parent.id, widget, GdkEventButton, user_data)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) run() {
|
|
for eventId := range w.parent.eventListeners {
|
|
w.on(eventId)
|
|
}
|
|
|
|
globalApplication.dispatchOnMainThread(func() {
|
|
app := getNativeApplication()
|
|
menu := app.applicationMenu
|
|
var newWindow func(uintptr) uintptr
|
|
purego.RegisterLibFunc(&newWindow, gtk, "gtk_application_window_new")
|
|
var refSink func(uintptr)
|
|
purego.RegisterLibFunc(&refSink, gtk, "g_object_ref_sink")
|
|
var boxNew func(int, int) uintptr
|
|
purego.RegisterLibFunc(&boxNew, gtk, "gtk_box_new")
|
|
var containerAdd func(uintptr, uintptr)
|
|
purego.RegisterLibFunc(&containerAdd, gtk, "gtk_container_add")
|
|
var boxPackStart func(uintptr, uintptr, int, int, int)
|
|
purego.RegisterLibFunc(&boxPackStart, gtk, "gtk_box_pack_start")
|
|
|
|
var g_signal_connect func(uintptr, string, uintptr, uintptr, bool, int) int
|
|
purego.RegisterLibFunc(&g_signal_connect, gtk, "g_signal_connect_data")
|
|
|
|
w.window = newWindow(w.application)
|
|
|
|
refSink(w.window)
|
|
w.webview = w.newWebview(1)
|
|
w.vbox = boxNew(1, 0)
|
|
containerAdd(w.window, w.vbox)
|
|
if menu != 0 {
|
|
w.menubar = menu
|
|
boxPackStart(w.vbox, menu, 0, 0, 0)
|
|
}
|
|
boxPackStart(w.vbox, w.webview, 1, 1, 0)
|
|
|
|
w.setSize(w.parent.options.Width, w.parent.options.Height)
|
|
w.setTitle(w.parent.options.Title)
|
|
w.setAlwaysOnTop(w.parent.options.AlwaysOnTop)
|
|
w.setResizable(!w.parent.options.DisableResize)
|
|
if w.parent.options.MinWidth != 0 &&
|
|
w.parent.options.MinHeight != 0 &&
|
|
w.parent.options.MaxWidth != 0 &&
|
|
w.parent.options.MaxHeight != 0 {
|
|
w.setMinMaxSize(
|
|
w.parent.options.MinWidth,
|
|
w.parent.options.MinHeight,
|
|
w.parent.options.MaxWidth,
|
|
w.parent.options.MaxHeight,
|
|
)
|
|
}
|
|
w.setZoom(w.parent.options.Zoom)
|
|
w.setBackgroundColour(w.parent.options.BackgroundColour)
|
|
w.setFrameless(w.parent.options.Frameless)
|
|
|
|
switch w.parent.options.StartState {
|
|
case WindowStateMaximised:
|
|
w.maximise()
|
|
case WindowStateMinimised:
|
|
w.minimise()
|
|
case WindowStateFullscreen:
|
|
w.fullscreen()
|
|
|
|
}
|
|
if w.parent.options.URL != "" {
|
|
w.setURL(w.parent.options.URL)
|
|
}
|
|
// We need to wait for the HTML to load before we can execute the javascript
|
|
w.parent.On(events.Mac.WebViewDidFinishNavigation, func(_ *WindowEventContext) {
|
|
if w.parent.options.JS != "" {
|
|
w.execJS(w.parent.options.JS)
|
|
}
|
|
if w.parent.options.CSS != "" {
|
|
js := fmt.Sprintf("(function() { var style = document.createElement('style'); style.appendChild(document.createTextNode('%s')); document.head.appendChild(style); })();", w.parent.options.CSS)
|
|
w.execJS(js)
|
|
}
|
|
})
|
|
if w.parent.options.HTML != "" {
|
|
w.setHTML(w.parent.options.HTML)
|
|
}
|
|
if w.parent.options.Hidden == false {
|
|
w.show()
|
|
if w.parent.options.X != 0 || w.parent.options.Y != 0 {
|
|
w.setRelativePosition(w.parent.options.X, w.parent.options.Y)
|
|
} else {
|
|
w.center()
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) setTransparent() {
|
|
var getScreen func(uintptr) uintptr
|
|
purego.RegisterLibFunc(&getScreen, gtk, "gtk_widget_get_screen")
|
|
var getVisual func(uintptr) uintptr
|
|
purego.RegisterLibFunc(&getVisual, gtk, "gdk_screen_get_rgba_visual")
|
|
var isComposited func(uintptr) int
|
|
purego.RegisterLibFunc(&isComposited, gtk, "gdk_screen_is_composited")
|
|
var setPaintable func(uintptr, int)
|
|
purego.RegisterLibFunc(&setPaintable, gtk, "gtk_widget_set_app_paintable")
|
|
var setVisual func(uintptr, uintptr)
|
|
purego.RegisterLibFunc(&setVisual, gtk, "gtk_widget_set_visual")
|
|
|
|
screen := getScreen(w.window)
|
|
visual := getVisual(screen)
|
|
if visual == 0 {
|
|
return
|
|
}
|
|
if isComposited(screen) == 1 {
|
|
setPaintable(w.window, 1)
|
|
setVisual(w.window, visual)
|
|
}
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) setBackgroundColour(colour RGBA) {
|
|
if colour.Alpha != 0 {
|
|
w.setTransparent()
|
|
}
|
|
|
|
var rgbaParse func(uintptr, string) bool
|
|
purego.RegisterLibFunc(&rgbaParse, gtk, "gdk_rgba_parse")
|
|
var setBackgroundColor func(uintptr, uintptr)
|
|
purego.RegisterLibFunc(&setBackgroundColor, webkit, "webkit_web_view_set_background_color")
|
|
|
|
rgba := make([]byte, 4*8) // C.sizeof_GdkRGBA == 32
|
|
pointer := uintptr(unsafe.Pointer(&rgba[0]))
|
|
if !rgbaParse(
|
|
pointer,
|
|
fmt.Sprintf("rgba(%v,%v,%v,%v)",
|
|
colour.Red,
|
|
colour.Green,
|
|
colour.Blue,
|
|
float32(colour.Alpha)/255.0,
|
|
)) {
|
|
return
|
|
}
|
|
setBackgroundColor(w.webview, pointer)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) relativePosition() (int, int) {
|
|
var getPosition func(uintptr, *int, *int) bool
|
|
purego.RegisterLibFunc(&getPosition, gtk, "gtk_window_get_position")
|
|
|
|
var x, y int
|
|
var wg sync.WaitGroup
|
|
wg.Add(1)
|
|
go globalApplication.dispatchOnMainThread(func() {
|
|
getPosition(w.window, &x, &y)
|
|
|
|
// Get the position of the window relative to the screen
|
|
var getOrigin func(uintptr, *int, *int)
|
|
purego.RegisterLibFunc(&getOrigin, gtk, "gtk_widget_translate_coordinates")
|
|
getOrigin(w.window, &x, &y)
|
|
|
|
wg.Done()
|
|
})
|
|
wg.Wait()
|
|
return x, y
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) absolutePosition() (int, int) {
|
|
var getOrigin func(uintptr, *int, *int)
|
|
purego.RegisterLibFunc(&getOrigin, gtk, "gtk_widget_translate_coordinates")
|
|
|
|
var x, y int
|
|
var wg sync.WaitGroup
|
|
wg.Add(1)
|
|
go globalApplication.dispatchOnMainThread(func() {
|
|
getOrigin(w.window, nil, nil)
|
|
wg.Done()
|
|
})
|
|
wg.Wait()
|
|
return x, y
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) destroy() {
|
|
var close func(uintptr)
|
|
purego.RegisterLibFunc(&close, gtk, "gtk_window_close")
|
|
go globalApplication.dispatchOnMainThread(func() {
|
|
close(w.window)
|
|
})
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) setHTML(html string) {
|
|
var loadHTML func(uintptr, string, string, *string)
|
|
purego.RegisterLibFunc(&loadHTML, webkit, "webkit_web_view_load_alternate_html")
|
|
go globalApplication.dispatchOnMainThread(func() {
|
|
loadHTML(w.webview, html, "wails://", nil)
|
|
})
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) isNormal() bool {
|
|
return !w.isMinimised() && !w.isMaximised() && !w.isFullscreen()
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) isVisible() bool {
|
|
var isVisible func(uintptr) bool
|
|
purego.RegisterLibFunc(&isVisible, gtk, "gtk_widget_is_visible")
|
|
return isVisible(w.window)
|
|
}
|
|
|
|
func (w *linuxWebviewWindow) nativeWindowHandle() uintptr {
|
|
return w.window
|
|
}
|