From 4cd4b46772f435ee29417f68e41f8177299bd83c Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 7 Feb 2024 22:19:33 +1100 Subject: [PATCH] [WIP] refactor CGO methods --- v3/pkg/application/application_linux.go | 72 +++--- v3/pkg/application/dialogs_linux.go | 4 +- v3/pkg/application/events_common_linux.go | 4 +- v3/pkg/application/linux_cgo.go | 271 ++++++++++++--------- v3/pkg/application/mainthread_linux.go | 2 +- v3/pkg/application/screen_linux.go | 6 +- v3/pkg/application/webview_window_linux.go | 173 ++----------- 7 files changed, 211 insertions(+), 321 deletions(-) diff --git a/v3/pkg/application/application_linux.go b/v3/pkg/application/application_linux.go index 2d50e9888..99981bd33 100644 --- a/v3/pkg/application/application_linux.go +++ b/v3/pkg/application/application_linux.go @@ -34,7 +34,7 @@ type linuxApp struct { theme string } -func (l *linuxApp) GetFlags(options Options) map[string]any { +func (a *linuxApp) GetFlags(options Options) map[string]any { if options.Flags == nil { options.Flags = make(map[string]any) } @@ -45,32 +45,28 @@ func getNativeApplication() *linuxApp { return globalApplication.impl.(*linuxApp) } -func (l *linuxApp) hide() { - hideAllWindows(l.application) +func (a *linuxApp) hide() { + a.hideAllWindows() } -func (l *linuxApp) show() { - showAllWindows(l.application) +func (a *linuxApp) show() { + a.showAllWindows() } -func (l *linuxApp) on(eventID uint) { +func (a *linuxApp) on(eventID uint) { // TODO: Test register/unregister events //C.registerApplicationEvent(l.application, C.uint(eventID)) } -func (l *linuxApp) setIcon(icon []byte) { +func (a *linuxApp) setIcon(icon []byte) { log.Println("linuxApp.setIcon", "not implemented") } -func (l *linuxApp) name() string { +func (a *linuxApp) name() string { return appName() } -func (l *linuxApp) getCurrentWindowID() uint { - return getCurrentWindowID(l.application, l.windowMap) -} - type rnr struct { f func() } @@ -79,7 +75,7 @@ func (r rnr) run() { r.f() } -func (l *linuxApp) setApplicationMenu(menu *Menu) { +func (a *linuxApp) setApplicationMenu(menu *Menu) { // FIXME: How do we avoid putting a menu? if menu == nil { // Create a default menu @@ -88,55 +84,55 @@ func (l *linuxApp) setApplicationMenu(menu *Menu) { } } -func (l *linuxApp) run() error { +func (a *linuxApp) run() error { - l.parent.On(events.Linux.ApplicationStartup, func(evt *Event) { + a.parent.On(events.Linux.ApplicationStartup, func(evt *Event) { fmt.Println("events.Linux.ApplicationStartup received!") }) - l.setupCommonEvents() - l.monitorThemeChanges() - return appRun(l.application) + a.setupCommonEvents() + a.monitorThemeChanges() + return appRun(a.application) } -func (l *linuxApp) unregisterWindow(w windowPointer) { - l.windowMapLock.Lock() - delete(l.windowMap, w) - l.windowMapLock.Unlock() +func (a *linuxApp) unregisterWindow(w windowPointer) { + a.windowMapLock.Lock() + delete(a.windowMap, w) + a.windowMapLock.Unlock() // If this was the last window... - if len(l.windowMap) == 0 && !l.parent.options.Linux.DisableQuitOnLastWindowClosed { - l.destroy() + if len(a.windowMap) == 0 && !a.parent.options.Linux.DisableQuitOnLastWindowClosed { + a.destroy() } } -func (l *linuxApp) destroy() { +func (a *linuxApp) destroy() { if !globalApplication.shouldQuit() { return } globalApplication.cleanup() - appDestroy(l.application) + appDestroy(a.application) } -func (l *linuxApp) isOnMainThread() bool { +func (a *linuxApp) isOnMainThread() bool { return isOnMainThread() } // register our window to our parent mapping -func (l *linuxApp) registerWindow(window pointer, id uint) { - l.windowMapLock.Lock() - l.windowMap[windowPointer(window)] = id - l.windowMapLock.Unlock() +func (a *linuxApp) registerWindow(window pointer, id uint) { + a.windowMapLock.Lock() + a.windowMap[windowPointer(window)] = id + a.windowMapLock.Unlock() } -func (l *linuxApp) isDarkMode() bool { - return strings.Contains(l.theme, "dark") +func (a *linuxApp) isDarkMode() bool { + return strings.Contains(a.theme, "dark") } -func (l *linuxApp) monitorThemeChanges() { +func (a *linuxApp) monitorThemeChanges() { go func() { conn, err := dbus.ConnectSessionBus() if err != nil { - l.parent.info("[WARNING] Failed to connect to session bus; monitoring for theme changes will not function:", err) + a.parent.info("[WARNING] Failed to connect to session bus; monitoring for theme changes will not function:", err) return } defer conn.Close() @@ -169,10 +165,10 @@ func (l *linuxApp) monitorThemeChanges() { continue } - if theme != l.theme { - l.theme = theme + if theme != a.theme { + a.theme = theme event := newApplicationEvent(events.Common.ThemeChanged) - event.Context().setIsDarkMode(l.isDarkMode()) + event.Context().setIsDarkMode(a.isDarkMode()) applicationEvents <- event } diff --git a/v3/pkg/application/dialogs_linux.go b/v3/pkg/application/dialogs_linux.go index 49499dda1..be480d176 100644 --- a/v3/pkg/application/dialogs_linux.go +++ b/v3/pkg/application/dialogs_linux.go @@ -1,7 +1,7 @@ package application -func (l *linuxApp) showAboutDialog(title string, message string, icon []byte) { - window := globalApplication.getWindowForID(l.getCurrentWindowID()) +func (a *linuxApp) showAboutDialog(title string, message string, icon []byte) { + window := globalApplication.getWindowForID(a.getCurrentWindowID()) var parent uintptr if window != nil { parent, _ = window.(*WebviewWindow).NativeWindowHandle() diff --git a/v3/pkg/application/events_common_linux.go b/v3/pkg/application/events_common_linux.go index 530ac1563..e06fb8cfe 100644 --- a/v3/pkg/application/events_common_linux.go +++ b/v3/pkg/application/events_common_linux.go @@ -9,11 +9,11 @@ var commonApplicationEventMap = map[events.ApplicationEventType]events.Applicati events.Linux.SystemThemeChanged: events.Common.ThemeChanged, } -func (l *linuxApp) setupCommonEvents() { +func (a *linuxApp) setupCommonEvents() { for sourceEvent, targetEvent := range commonApplicationEventMap { sourceEvent := sourceEvent targetEvent := targetEvent - l.parent.On(sourceEvent, func(event *Event) { + a.parent.On(sourceEvent, func(event *Event) { event.Id = uint(targetEvent) applicationEvents <- event }) diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index beba773fe..dc921df27 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -286,13 +286,13 @@ func appDestroy(application pointer) { C.g_application_quit((*C.GApplication)(application)) } -func contextMenuShow(window pointer, menu pointer, data *ContextMenuData) { +func (w *linuxWebviewWindow) contextMenuShow(menu pointer, data *ContextMenuData) { geometry := C.GdkRectangle{ x: C.int(data.X), y: C.int(data.Y), } event := C.GdkEvent{} - gdkWindow := C.gtk_widget_get_window((*C.GtkWidget)(window)) + gdkWindow := C.gtk_widget_get_window(w.gtkWidget()) C.gtk_menu_popup_at_rect( (*C.GtkMenu)(menu), gdkWindow, @@ -303,13 +303,13 @@ func contextMenuShow(window pointer, menu pointer, data *ContextMenuData) { ) } -func getCurrentWindowID(application pointer, windows map[windowPointer]uint) uint { +func (a *linuxApp) getCurrentWindowID() uint { // TODO: Add extra metadata to window and use it! - window := (*C.GtkWindow)(C.gtk_application_get_active_window((*C.GtkApplication)(application))) + window := (*C.GtkWindow)(C.gtk_application_get_active_window((*C.GtkApplication)(a.application))) if window == nil { return uint(1) } - identifier, ok := windows[window] + identifier, ok := a.windowMap[window] if ok { return identifier } @@ -317,9 +317,9 @@ func getCurrentWindowID(application pointer, windows map[windowPointer]uint) uin return uint(1) } -func getWindows(application pointer) []pointer { +func (a *linuxApp) getWindows() []pointer { result := []pointer{} - windows := C.gtk_application_get_windows((*C.GtkApplication)(application)) + windows := C.gtk_application_get_windows((*C.GtkApplication)(a.application)) for { result = append(result, pointer(windows.data)) windows = windows.next @@ -329,14 +329,14 @@ func getWindows(application pointer) []pointer { } } -func hideAllWindows(application pointer) { - for _, window := range getWindows(application) { +func (a *linuxApp) hideAllWindows() { + for _, window := range a.getWindows() { C.gtk_widget_hide((*C.GtkWidget)(window)) } } -func showAllWindows(application pointer) { - for _, window := range getWindows(application) { +func (a *linuxApp) showAllWindows() { + for _, window := range a.getWindows() { C.gtk_window_present((*C.GtkWindow)(window)) } } @@ -661,26 +661,27 @@ func widgetSetVisible(widget pointer, hidden bool) { } } -// window related functions -func windowClose(window pointer) { - C.gtk_window_close((*C.GtkWindow)(window)) +func (w *linuxWebviewWindow) close() { + C.gtk_window_close((*C.GtkWindow)(w.window)) + getNativeApplication().unregisterWindow(windowPointer(w.window)) } -func windowEnableDND(id uint, webview pointer) { +func (w *linuxWebviewWindow) enableDND() { + id := w.parent.id dnd := C.CString("text/uri-list") defer C.free(unsafe.Pointer(dnd)) targetentry := C.gtk_target_entry_new(dnd, 0, C.guint(id)) defer C.gtk_target_entry_free(targetentry) - C.gtk_drag_dest_set((*C.GtkWidget)(webview), C.GTK_DEST_DEFAULT_DROP, targetentry, 1, C.GDK_ACTION_COPY) + C.gtk_drag_dest_set((*C.GtkWidget)(w.webview), C.GTK_DEST_DEFAULT_DROP, targetentry, 1, C.GDK_ACTION_COPY) event := C.CString("drag-data-received") defer C.free(unsafe.Pointer(event)) windowId := C.uint(id) - C.signal_connect(unsafe.Pointer(webview), event, C.onDragNDrop, unsafe.Pointer(C.gpointer(&windowId))) + C.signal_connect(unsafe.Pointer(w.webview), event, C.onDragNDrop, unsafe.Pointer(C.gpointer(&windowId))) } -func windowExecJS(webview pointer, js string) { +func (w *linuxWebviewWindow) execJS(js string) { value := C.CString(js) - C.webkit_web_view_evaluate_javascript((*C.WebKitWebView)(webview), + C.webkit_web_view_evaluate_javascript((*C.WebKitWebView)(w.webview), value, C.long(len(js)), nil, @@ -715,8 +716,8 @@ func windowGetCurrentMonitor(window pointer) *C.GdkMonitor { return C.gdk_display_get_monitor_at_window(display, gdk_window) } -func windowGetCurrentMonitorGeometry(window pointer) (x int, y int, width int, height int, scale int) { - monitor := windowGetCurrentMonitor(window) +func (w *linuxWebviewWindow) getCurrentMonitorGeometry() (x int, y int, width int, height int, scale int) { + monitor := windowGetCurrentMonitor(w.window) if monitor == nil { return -1, -1, -1, -1, 1 } @@ -726,13 +727,6 @@ func windowGetCurrentMonitorGeometry(window pointer) (x int, y int, width int, h return int(result.x), int(result.y), int(result.width), int(result.height), scale } -func windowGetAbsolutePosition(window pointer) (int, int) { - var x C.int - var y C.int - C.gtk_window_get_position((*C.GtkWindow)(window), &x, &y) - return int(x), int(y) -} - func windowGetSize(window pointer) (int, int) { var windowWidth C.int var windowHeight C.int @@ -740,11 +734,11 @@ func windowGetSize(window pointer) (int, int) { return int(windowWidth), int(windowHeight) } -func windowGetRelativePosition(window pointer) (int, int) { - x, y := windowGetAbsolutePosition(window) +func (w *linuxWebviewWindow) relativePosition() (int, int) { + x, y := w.absolutePosition() // The position must be relative to the screen it is on // We need to get the screen it is on - monitor := windowGetCurrentMonitor(window) + monitor := windowGetCurrentMonitor(w.window) geometry := C.GdkRectangle{} C.gdk_monitor_get_geometry(monitor, &geometry) x = x - int(geometry.x) @@ -755,46 +749,52 @@ func windowGetRelativePosition(window pointer) (int, int) { return x, y } -func windowHide(window pointer) { - C.gtk_widget_hide((*C.GtkWidget)(window)) +func (w *linuxWebviewWindow) gtkWidget() *C.GtkWidget { + return (*C.GtkWidget)(w.window) } -func windowIsFullscreen(window pointer) bool { - gdkwindow := C.gtk_widget_get_window((*C.GtkWidget)(window)) - state := C.gdk_window_get_state(gdkwindow) +func (w *linuxWebviewWindow) hide() { + // save position + w.lastX, w.lastY = w.absolutePosition() + C.gtk_widget_hide(w.gtkWidget()) +} + +func (w *linuxWebviewWindow) isFullscreen() bool { + gdkWindow := C.gtk_widget_get_window((*C.GtkWidget)(w.window)) + state := C.gdk_window_get_state(gdkWindow) return state&C.GDK_WINDOW_STATE_FULLSCREEN > 0 } -func windowIsFocused(window pointer) bool { +func (w *linuxWebviewWindow) isFocused() bool { // returns true if window is focused - return C.gtk_window_has_toplevel_focus((*C.GtkWindow)(window)) == 1 + return C.gtk_window_has_toplevel_focus((*C.GtkWindow)(w.window)) == 1 } -func windowIsMaximized(window pointer) bool { - gdkwindow := C.gtk_widget_get_window((*C.GtkWidget)(window)) +func (w *linuxWebviewWindow) isMaximised() bool { + gdkwindow := C.gtk_widget_get_window((*C.GtkWidget)(w.window)) state := C.gdk_window_get_state(gdkwindow) return state&C.GDK_WINDOW_STATE_MAXIMIZED > 0 && state&C.GDK_WINDOW_STATE_FULLSCREEN == 0 } -func windowIsMinimized(window pointer) bool { - gdkwindow := C.gtk_widget_get_window((*C.GtkWidget)(window)) +func (w *linuxWebviewWindow) isMinimised() bool { + gdkwindow := C.gtk_widget_get_window((*C.GtkWidget)(w.window)) state := C.gdk_window_get_state(gdkwindow) return state&C.GDK_WINDOW_STATE_ICONIFIED > 0 } -func windowIsVisible(window pointer) bool { - if C.gtk_widget_is_visible((*C.GtkWidget)(window)) == 1 { +func (w *linuxWebviewWindow) isVisible() bool { + if C.gtk_widget_is_visible(w.gtkWidget()) == 1 { return true } return false } -func windowMaximize(window pointer) { - C.gtk_window_maximize((*C.GtkWindow)(window)) +func (w *linuxWebviewWindow) maximise() { + C.gtk_window_maximize((*C.GtkWindow)(w.window)) } -func windowMinimize(window pointer) { - C.gtk_window_iconify((*C.GtkWindow)(window)) +func (w *linuxWebviewWindow) minimise() { + C.gtk_window_iconify((*C.GtkWindow)(w.window)) } func windowNew(application pointer, menu pointer, windowId uint, gpuPolicy WebviewGpuPolicy) (window, webview, vbox pointer) { @@ -849,26 +849,24 @@ func windowNewWebview(parentId uint, gpuPolicy WebviewGpuPolicy) pointer { return pointer(webView) } -func windowPresent(window pointer) { - C.gtk_window_present((*C.GtkWindow)(window)) +func (w *linuxWebviewWindow) present() { + C.gtk_window_present((*C.GtkWindow)(w.window)) // gtk_window_unminimize ((*C.GtkWindow)(w.window)) /// gtk4 } -func windowReload(webview pointer, address string) { - uri := C.CString(address) - C.webkit_web_view_load_uri((*C.WebKitWebView)(webview), uri) - C.free(unsafe.Pointer(uri)) -} - -func windowResize(window pointer, width, height int) { +func (w *linuxWebviewWindow) setSize(width, height int) { C.gtk_window_resize( - (*C.GtkWindow)(window), + w.gtkWindow(), C.gint(width), C.gint(height)) } -func windowShow(window pointer) { - C.gtk_widget_show_all((*C.GtkWidget)(window)) +func (w *linuxWebviewWindow) show() { + if w.gtkWidget() == nil { + return + } + C.gtk_widget_show_all(w.gtkWidget()) + w.setAbsolutePosition(w.lastX, w.lastY) } func windowIgnoreMouseEvents(window pointer, webview pointer, ignore bool) { @@ -881,15 +879,27 @@ func windowIgnoreMouseEvents(window pointer, webview pointer, ignore bool) { C.webkit_web_view_set_editable((*C.WebKitWebView)(webview), C.gboolean(enable)) } -func windowSetBackgroundColour(vbox, webview pointer, colour RGBA) { +func (w *linuxWebviewWindow) webKitWebView() *C.WebKitWebView { + return (*C.WebKitWebView)(w.webview) +} + +func (w *linuxWebviewWindow) setBorderless(borderless bool) { + C.gtk_window_set_decorated(w.gtkWindow(), gtkBool(!borderless)) +} + +func (w *linuxWebviewWindow) setResizable(resizable bool) { + C.gtk_window_set_resizable(w.gtkWindow(), gtkBool(resizable)) +} + +func (w *linuxWebviewWindow) setBackgroundColour(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) + C.webkit_web_view_set_background_color((*C.WebKitWebView)(w.webview), &rgba) colour.Alpha = 255 cssStr := C.CString(fmt.Sprintf("#webview-box {background-color: rgba(%d, %d, %d, %1.1f);}", colour.Red, colour.Green, colour.Blue, float32(colour.Alpha)/255.0)) provider := C.gtk_css_provider_new() C.gtk_style_context_add_provider( - C.gtk_widget_get_style_context((*C.GtkWidget)(vbox)), + C.gtk_widget_get_style_context((*C.GtkWidget)(w.vbox)), (*C.GtkStyleProvider)(unsafe.Pointer(provider)), C.GTK_STYLE_PROVIDER_PRIORITY_USER) C.g_object_unref(C.gpointer(provider)) @@ -907,14 +917,14 @@ func windowSetGeometryHints(window pointer, minWidth, minHeight, maxWidth, maxHe C.gtk_window_set_geometry_hints((*C.GtkWindow)(window), nil, &size, C.GDK_HINT_MAX_SIZE|C.GDK_HINT_MIN_SIZE) } -func windowSetFrameless(window pointer, frameless bool) { - C.gtk_window_set_decorated((*C.GtkWindow)(window), gtkBool(!frameless)) +func (w *linuxWebviewWindow) setFrameless(frameless bool) { + C.gtk_window_set_decorated(w.gtkWindow(), gtkBool(!frameless)) // TODO: Deal with transparency for the titlebar if possible when !frameless // Perhaps we just make it undecorated and add a menu bar inside? } // TODO: confirm this is working properly -func windowSetHTML(webview pointer, html string) { +func (w *linuxWebviewWindow) setHTML(html string) { cHTML := C.CString(html) uri := C.CString("wails://") empty := C.CString("") @@ -922,39 +932,41 @@ func windowSetHTML(webview pointer, html string) { defer C.free(unsafe.Pointer(uri)) defer C.free(unsafe.Pointer(empty)) C.webkit_web_view_load_alternate_html( - (*C.WebKitWebView)(webview), + w.webKitWebView(), cHTML, uri, empty) } -func windowSetKeepAbove(window pointer, alwaysOnTop bool) { - C.gtk_window_set_keep_above((*C.GtkWindow)(window), gtkBool(alwaysOnTop)) +func (w *linuxWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) { + C.gtk_window_set_keep_above((*C.GtkWindow)(w.window), gtkBool(alwaysOnTop)) } -func windowSetResizable(window pointer, resizable bool) { - C.gtk_window_set_resizable((*C.GtkWindow)(window), gtkBool(resizable)) -} - -func windowSetTitle(window pointer, title string) { - cTitle := C.CString(title) - C.gtk_window_set_title((*C.GtkWindow)(window), cTitle) - C.free(unsafe.Pointer(cTitle)) -} - -func windowSetTransparent(window pointer) { - screen := C.gtk_widget_get_screen((*C.GtkWidget)(window)) - visual := C.gdk_screen_get_rgba_visual(screen) - - if visual != nil && C.gdk_screen_is_composited(screen) == C.int(1) { - C.gtk_widget_set_app_paintable((*C.GtkWidget)(window), C.gboolean(1)) - C.gtk_widget_set_visual((*C.GtkWidget)(window), visual) +func (w *linuxWebviewWindow) setTitle(title string) { + if !w.parent.options.Frameless { + cTitle := C.CString(title) + C.gtk_window_set_title(w.gtkWindow(), cTitle) + C.free(unsafe.Pointer(cTitle)) } } -func windowSetURL(webview pointer, uri string) { +func (w *linuxWebviewWindow) gtkWindow() *C.GtkWindow { + return (*C.GtkWindow)(w.window) +} + +func (w *linuxWebviewWindow) setTransparent() { + screen := C.gtk_widget_get_screen(w.gtkWidget()) + visual := C.gdk_screen_get_rgba_visual(screen) + + if visual != nil && C.gdk_screen_is_composited(screen) == C.int(1) { + C.gtk_widget_set_app_paintable(w.gtkWidget(), C.gboolean(1)) + C.gtk_widget_set_visual(w.gtkWidget(), visual) + } +} + +func (w *linuxWebviewWindow) setURL(uri string) { target := C.CString(uri) - C.webkit_web_view_load_uri((*C.WebKitWebView)(webview), target) + C.webkit_web_view_load_uri((*C.WebKitWebView)(w.webview), target) C.free(unsafe.Pointer(target)) } @@ -983,22 +995,23 @@ func handleLoadChanged(webview *C.WebKitWebView, event C.WebKitLoadEvent, data C } } -func windowSetupSignalHandlers(windowId uint, window, webview pointer, emit func(e events.WindowEventType)) { +func (w *linuxWebviewWindow) setupSignalHandlers(emit func(e events.WindowEventType)) { c := NewCalloc() defer c.Free() - winID := unsafe.Pointer(uintptr(C.uint(windowId))) + winID := unsafe.Pointer(uintptr(C.uint(w.parent.ID()))) // Set up the window close event - C.signal_connect(unsafe.Pointer(window), c.String("delete-event"), C.handleDeleteEvent, winID) - C.signal_connect(unsafe.Pointer(webview), c.String("load-changed"), C.handleLoadChanged, winID) + wv := unsafe.Pointer(w.webview) + C.signal_connect(unsafe.Pointer(w.window), c.String("delete-event"), C.handleDeleteEvent, winID) + C.signal_connect(wv, c.String("load-changed"), C.handleLoadChanged, winID) - contentManager := C.webkit_web_view_get_user_content_manager((*C.WebKitWebView)(webview)) + contentManager := C.webkit_web_view_get_user_content_manager(w.webKitWebView()) C.signal_connect(unsafe.Pointer(contentManager), c.String("script-message-received::external"), C.sendMessageToBackend, nil) - C.signal_connect(unsafe.Pointer(webview), c.String("button-press-event"), C.onButtonEvent, winID) - C.signal_connect(unsafe.Pointer(webview), c.String("button-release-event"), C.onButtonEvent, winID) - C.signal_connect(unsafe.Pointer(webview), c.String("key-press-event"), C.onKeyPressEvent, winID) + C.signal_connect(wv, c.String("button-press-event"), C.onButtonEvent, winID) + C.signal_connect(wv, c.String("button-release-event"), C.onButtonEvent, winID) + C.signal_connect(wv, c.String("key-press-event"), C.onKeyPressEvent, winID) } func windowShowDevTools(webview pointer) { @@ -1006,13 +1019,14 @@ func windowShowDevTools(webview pointer) { C.webkit_web_inspector_show(inspector) } -func windowStartDrag(window pointer, button uint, xroot int, yroot int, dragTime uint32) { +func (w *linuxWebviewWindow) startDrag() error { C.gtk_window_begin_move_drag( - (*C.GtkWindow)(window), - C.int(button), - C.int(xroot), - C.int(yroot), - C.uint32_t(dragTime)) + (*C.GtkWindow)(w.window), + C.int(w.drag.MouseButton), + C.int(w.drag.XRoot), + C.int(w.drag.YRoot), + C.uint32_t(w.drag.DragTime)) + return nil } func windowToggleDevTools(webview pointer) { @@ -1027,37 +1041,56 @@ func windowToggleDevTools(webview pointer) { C.webkit_settings_set_enable_developer_extras(settings, enabled) } -func windowUnfullscreen(window pointer) { - C.gtk_window_unfullscreen((*C.GtkWindow)(window)) +func (w *linuxWebviewWindow) unfullscreen() { + C.gtk_window_unfullscreen((*C.GtkWindow)(w.window)) + w.unmaximise() } -func windowUnmaximize(window pointer) { - C.gtk_window_unmaximize((*C.GtkWindow)(window)) +func (w *linuxWebviewWindow) unmaximise() { + C.gtk_window_unmaximize((*C.GtkWindow)(w.window)) } -func windowZoom(webview pointer) float64 { - return float64(C.webkit_web_view_get_zoom_level((*C.WebKitWebView)(webview))) +func (w *linuxWebviewWindow) getZoom() float64 { + return float64(C.webkit_web_view_get_zoom_level(w.webKitWebView())) } -// FIXME: ZoomIn/Out is assumed to be incorrect! -func windowZoomIn(webview pointer) { +func (w *linuxWebviewWindow) zoomIn() { + // FIXME: ZoomIn/Out is assumed to be incorrect! ZoomInFactor := 1.10 - windowZoomSet(webview, windowZoom(webview)*ZoomInFactor) -} -func windowZoomOut(webview pointer) { - ZoomOutFactor := -1.10 - windowZoomSet(webview, windowZoom(webview)*ZoomOutFactor) + w.setZoom(w.getZoom() * ZoomInFactor) } -func windowZoomSet(webview pointer, zoom float64) { +func (w *linuxWebviewWindow) zoomOut() { + ZoomInFactor := -1.10 + w.setZoom(w.getZoom() * ZoomInFactor) +} + +func (w *linuxWebviewWindow) zoomReset() { + w.setZoom(1.0) +} + +func (w *linuxWebviewWindow) reload() { + uri := C.CString("wails://") + C.webkit_web_view_load_uri((*C.WebKitWebView)(w.webview), uri) + C.free(unsafe.Pointer(uri)) +} + +func (w *linuxWebviewWindow) setZoom(zoom float64) { if zoom < 1 { // 1.0 is the smallest allowable zoom = 1 } - C.webkit_web_view_set_zoom_level((*C.WebKitWebView)(webview), C.double(zoom)) + C.webkit_web_view_set_zoom_level(w.webKitWebView(), C.double(zoom)) } -func windowMove(window pointer, x, y int) { - C.gtk_window_move((*C.GtkWindow)(window), C.int(x), C.int(y)) +func (w *linuxWebviewWindow) move(x, y int) { + C.gtk_window_move((*C.GtkWindow)(w.window), C.int(x), C.int(y)) +} + +func (w *linuxWebviewWindow) absolutePosition() (int, int) { + var x C.int + var y C.int + C.gtk_window_get_position((*C.GtkWindow)(w.window), &x, &y) + return int(x), int(y) } // FIXME Change this to reflect mouse button! diff --git a/v3/pkg/application/mainthread_linux.go b/v3/pkg/application/mainthread_linux.go index 2a5ff3e2c..a718688bc 100644 --- a/v3/pkg/application/mainthread_linux.go +++ b/v3/pkg/application/mainthread_linux.go @@ -2,7 +2,7 @@ package application -func (l *linuxApp) dispatchOnMainThread(id uint) { +func (a *linuxApp) dispatchOnMainThread(id uint) { dispatchOnMainThread(id) } diff --git a/v3/pkg/application/screen_linux.go b/v3/pkg/application/screen_linux.go index 526752ace..d93cfbd92 100644 --- a/v3/pkg/application/screen_linux.go +++ b/v3/pkg/application/screen_linux.go @@ -7,17 +7,17 @@ import ( "sync" ) -func (l *linuxApp) getPrimaryScreen() (*Screen, error) { +func (a *linuxApp) getPrimaryScreen() (*Screen, error) { return nil, fmt.Errorf("not implemented") } -func (l *linuxApp) getScreens() ([]*Screen, error) { +func (a *linuxApp) getScreens() ([]*Screen, error) { var wg sync.WaitGroup var screens []*Screen var err error wg.Add(1) InvokeSync(func() { - screens, err = getScreens(l.application) + screens, err = getScreens(a.application) wg.Done() }) wg.Wait() diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 80d5b9831..261287d13 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -9,6 +9,7 @@ import ( "github.com/wailsapp/wails/v3/internal/capabilities" "github.com/wailsapp/wails/v3/internal/runtime" "github.com/wailsapp/wails/v3/pkg/events" + "math" ) var showDevTools = func(window pointer) {} @@ -41,26 +42,17 @@ var ( registered bool = false // avoid 'already registered message' about 'wails://' ) -func (w *linuxWebviewWindow) startDrag() error { - windowStartDrag(w.window, w.drag.MouseButton, w.drag.XRoot, w.drag.YRoot, w.drag.DragTime) - return nil -} - func (w *linuxWebviewWindow) endDrag(button uint, x, y int) { w.drag.XRoot = 0.0 w.drag.YRoot = 0.0 w.drag.DragTime = 0 } -func (w *linuxWebviewWindow) enableDND() { - windowEnableDND(w.parent.id, w.webview) -} - func (w *linuxWebviewWindow) connectSignals() { cb := func(e events.WindowEventType) { w.parent.emit(e) } - windowSetupSignalHandlers(w.parent.id, w.window, w.webview, cb) + w.setupSignalHandlers(cb) } func (w *linuxWebviewWindow) openContextMenu(menu *Menu, data *ContextMenuData) { @@ -74,23 +66,11 @@ func (w *linuxWebviewWindow) openContextMenu(menu *Menu, data *ContextMenuData) } native := ctxMenu.menu.impl.(*linuxMenu).native - contextMenuShow(w.window, native, data) -} - -func (w *linuxWebviewWindow) getZoom() float64 { - return windowZoom(w.webview) -} - -func (w *linuxWebviewWindow) setZoom(zoom float64) { - windowZoomSet(w.webview, zoom) -} - -func (w *linuxWebviewWindow) setFrameless(frameless bool) { - windowSetFrameless(w.window, frameless) + w.contextMenuShow(native, data) } func (w *linuxWebviewWindow) getScreen() (*Screen, error) { - mx, my, width, height, scale := windowGetCurrentMonitorGeometry(w.window) + mx, my, width, height, scale := w.getCurrentMonitorGeometry() return &Screen{ ID: fmt.Sprintf("%d", w.id), // A unique identifier for the display Name: w.parent.Name(), // The name of the display @@ -106,47 +86,27 @@ func (w *linuxWebviewWindow) getScreen() (*Screen, error) { } func (w *linuxWebviewWindow) focus() { - windowPresent(w.window) -} - -func (w *linuxWebviewWindow) show() { - windowShow(w.window) - w.setAbsolutePosition(w.lastX, w.lastY) -} - -func (w *linuxWebviewWindow) hide() { - // save position - w.lastX, w.lastY = windowGetAbsolutePosition(w.window) - windowHide(w.window) + w.present() } func (w *linuxWebviewWindow) isNormal() bool { return !w.isMinimised() && !w.isMaximised() && !w.isFullscreen() } -func (w *linuxWebviewWindow) isVisible() bool { - return windowIsVisible(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 := windowGetCurrentMonitorGeometry(w.window) + x, y, width, height, scale := w.getCurrentMonitorGeometry() w.setMinMaxSize(x, y, width*scale, height*scale) } -func (w *linuxWebviewWindow) unfullscreen() { - windowUnfullscreen(w.window) - w.unmaximise() -} - func (w *linuxWebviewWindow) fullscreen() { w.maximise() //w.lastWidth, w.lastHeight = w.size() - x, y, width, height, scale := windowGetCurrentMonitorGeometry(w.window) + x, y, width, height, scale := w.getCurrentMonitorGeometry() if x == -1 && y == -1 && width == -1 && height == -1 { return } @@ -157,19 +117,7 @@ func (w *linuxWebviewWindow) fullscreen() { } func (w *linuxWebviewWindow) unminimise() { - windowPresent(w.window) -} - -func (w *linuxWebviewWindow) unmaximise() { - windowUnmaximize(w.window) -} - -func (w *linuxWebviewWindow) maximise() { - windowMaximize(w.window) -} - -func (w *linuxWebviewWindow) minimise() { - windowMinimize(w.window) + w.present() } func (w *linuxWebviewWindow) flash(enabled bool) { @@ -189,59 +137,22 @@ func (w *linuxWebviewWindow) windowZoom() { w.zoom() // FIXME> This should be removed } -func (w *linuxWebviewWindow) close() { - windowClose(w.window) - getNativeApplication().unregisterWindow(windowPointer(w.window)) -} - -func (w *linuxWebviewWindow) zoomIn() { - windowZoomIn(w.webview) -} - -func (w *linuxWebviewWindow) zoomOut() { - windowZoomOut(w.webview) -} - -func (w *linuxWebviewWindow) zoomReset() { - windowZoomSet(w.webview, 1.0) -} - -func (w *linuxWebviewWindow) reload() { - windowReload(w.webview, "wails://") -} - func (w *linuxWebviewWindow) forceReload() { w.reload() } func (w *linuxWebviewWindow) center() { - x, y, width, height, _ := windowGetCurrentMonitorGeometry(w.window) + x, y, width, height, _ := w.getCurrentMonitorGeometry() if x == -1 && y == -1 && width == -1 && height == -1 { return } windowWidth, windowHeight := windowGetSize(w.window) - newX := ((width - int(windowWidth)) / 2) + x - newY := ((height - int(windowHeight)) / 2) + y + newX := ((width - windowWidth) / 2) + x + newY := ((height - windowHeight) / 2) + y // Place the window at the center of the monitor - windowMove(w.window, newX, newY) -} - -func (w *linuxWebviewWindow) isMinimised() bool { - return windowIsMinimized(w.window) -} - -func (w *linuxWebviewWindow) isMaximised() bool { - return windowIsMaximized(w.window) -} - -func (w *linuxWebviewWindow) isFocused() bool { - return windowIsFocused(w.window) -} - -func (w *linuxWebviewWindow) isFullscreen() bool { - return windowIsFullscreen(w.window) + w.move(newX, newY) } func (w *linuxWebviewWindow) restore() { @@ -249,18 +160,6 @@ func (w *linuxWebviewWindow) restore() { // FIXME: never called! - remove from webviewImpl interface } -func (w *linuxWebviewWindow) execJS(js string) { - windowExecJS(w.webview, js) -} - -func (w *linuxWebviewWindow) setURL(uri string) { - windowSetURL(w.webview, uri) -} - -func (w *linuxWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) { - windowSetKeepAbove(w.window, alwaysOnTop) -} - func newWindowImpl(parent *WebviewWindow) *linuxWebviewWindow { // (*C.struct__GtkWidget)(m.native) //var menubar *C.struct__GtkWidget @@ -272,16 +171,6 @@ func newWindowImpl(parent *WebviewWindow) *linuxWebviewWindow { return result } -func (w *linuxWebviewWindow) setTitle(title string) { - if !w.parent.options.Frameless { - windowSetTitle(w.window, title) - } -} - -func (w *linuxWebviewWindow) setSize(width, height int) { - windowResize(w.window, width, height) -} - func (w *linuxWebviewWindow) setMinMaxSize(minWidth, minHeight, maxWidth, maxHeight int) { if minWidth == 0 { minWidth = -1 @@ -290,10 +179,10 @@ func (w *linuxWebviewWindow) setMinMaxSize(minWidth, minHeight, maxWidth, maxHei minHeight = -1 } if maxWidth == 0 { - maxWidth = -1 + maxWidth = math.MaxInt } if maxHeight == 0 { - maxHeight = -1 + maxHeight = math.MaxInt } windowSetGeometryHints(w.window, minWidth, minHeight, maxWidth, maxHeight) } @@ -306,10 +195,6 @@ 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) { - windowSetResizable(w.window, resizable) -} - func (w *linuxWebviewWindow) showDevTools() { windowShowDevTools(w.webview) } @@ -323,8 +208,8 @@ func (w *linuxWebviewWindow) size() (int, int) { } func (w *linuxWebviewWindow) setRelativePosition(x, y int) { - mx, my, _, _, _ := windowGetCurrentMonitorGeometry(w.window) - windowMove(w.window, x+mx, y+my) + mx, my, _, _, _ := w.getCurrentMonitorGeometry() + w.move(x+mx, y+my) } func (w *linuxWebviewWindow) width() int { @@ -339,13 +224,7 @@ func (w *linuxWebviewWindow) height() int { func (w *linuxWebviewWindow) setAbsolutePosition(x int, y int) { // Set the window's absolute position - windowMove(w.window, x, y) -} - -func (w *linuxWebviewWindow) absolutePosition() (int, int) { - var x, y int - x, y = windowGetAbsolutePosition(w.window) - return x, y + w.move(x, y) } func (w *linuxWebviewWindow) run() { @@ -459,20 +338,6 @@ func (w *linuxWebviewWindow) run() { } } -func (w *linuxWebviewWindow) setTransparent() { - windowSetTransparent(w.window) -} - -func (w *linuxWebviewWindow) setBackgroundColour(colour RGBA) { - windowSetBackgroundColour(w.vbox, w.webview, colour) -} - -func (w *linuxWebviewWindow) relativePosition() (int, int) { - var x, y int - x, y = windowGetRelativePosition(w.window) - return x, y -} - func (w *linuxWebviewWindow) destroy() { w.parent.markAsDestroyed() // Free menu @@ -487,10 +352,6 @@ func (w *linuxWebviewWindow) setEnabled(enabled bool) { widgetSetSensitive(w.window, enabled) } -func (w *linuxWebviewWindow) setHTML(html string) { - windowSetHTML(w.webview, html) -} - func (w *linuxWebviewWindow) startResize(border string) error { // FIXME: what do we need to do here? return nil