[v3] Merge feature Window interface

This commit is contained in:
Travis McLane 2023-09-28 11:52:23 -05:00
commit a0953fea93
21 changed files with 251 additions and 116 deletions

View file

@ -146,7 +146,7 @@ type (
}
runnable interface {
run()
Run()
}
)
@ -219,7 +219,7 @@ type App struct {
applicationEventHooksLock sync.RWMutex
// Windows
windows map[uint]*WebviewWindow
windows map[uint]Window
windowsLock sync.Mutex
// System Trays
@ -257,7 +257,7 @@ type App struct {
startURL string
// Hooks
windowCreatedCallbacks []func(window *WebviewWindow)
windowCreatedCallbacks []func(window Window)
pid int
// Capabilities
@ -270,7 +270,7 @@ type App struct {
func (a *App) init() {
a.applicationEventListeners = make(map[uint][]*EventListener)
a.windows = make(map[uint]*WebviewWindow)
a.windows = make(map[uint]Window)
a.systemTrays = make(map[uint]*SystemTray)
a.contextMenus = make(map[string]*Menu)
a.keyBindings = make(map[string]func(window *WebviewWindow))
@ -285,7 +285,7 @@ func (a *App) getSystemTrayID() uint {
return a.systemTrayID
}
func (a *App) getWindowForID(id uint) *WebviewWindow {
func (a *App) getWindowForID(id uint) Window {
a.windowsLock.Lock()
defer a.windowsLock.Unlock()
return a.windows[id]
@ -340,7 +340,7 @@ func (a *App) RegisterHook(eventType events.ApplicationEventType, callback func(
}
}
func (a *App) NewWebviewWindow() *WebviewWindow {
func (a *App) NewWebviewWindow() Window {
return a.NewWebviewWindowWithOptions(WebviewWindowOptions{})
}
@ -376,9 +376,9 @@ func (a *App) error(message string, args ...any) {
}
}
func (a *App) NewWebviewWindowWithOptions(windowOptions WebviewWindowOptions) *WebviewWindow {
newWindow := newWindow(windowOptions)
id := newWindow.id
func (a *App) NewWebviewWindowWithOptions(windowOptions WebviewWindowOptions) Window {
newWindow := NewWindow(windowOptions)
id := newWindow.ID()
a.windowsLock.Lock()
a.windows[id] = newWindow
@ -460,8 +460,13 @@ func (a *App) Run() error {
a.runLock.Lock()
a.running = true
// run windows
for _, window := range a.windows {
go window.Run()
}
for _, systray := range a.pendingRun {
go systray.run()
go systray.Run()
}
a.pendingRun = nil
@ -519,7 +524,7 @@ func (a *App) handleDragAndDropMessage(event *dragAndDropMessage) {
return
}
// Get callback from window
window.handleDragAndDropMessage(event)
window.HandleDragAndDropMessage(event.filenames)
}
func (a *App) handleWindowMessage(event *windowMessage) {
@ -532,7 +537,7 @@ func (a *App) handleWindowMessage(event *windowMessage) {
return
}
// Get callback from window
window.handleMessage(event.message)
window.HandleMessage(event.message)
}
func (a *App) handleWebViewRequest(request *webViewAssetRequest) {
@ -545,10 +550,10 @@ func (a *App) handleWindowEvent(event *windowEvent) {
window, ok := a.windows[event.WindowID]
a.windowsLock.Unlock()
if !ok {
log.Printf("WebviewWindow #%d not found", event.WindowID)
log.Printf("Window #%d not found", event.WindowID)
return
}
window.handleWindowEvent(event.EventID)
window.HandleWindowEvent(event.EventID)
}
func (a *App) handleMenuItemClicked(menuItemID uint) {
@ -560,7 +565,7 @@ func (a *App) handleMenuItemClicked(menuItemID uint) {
menuItem.handleClick()
}
func (a *App) CurrentWindow() *WebviewWindow {
func (a *App) CurrentWindow() Window {
if a.impl == nil {
return nil
}
@ -672,7 +677,7 @@ func SaveFileDialogWithOptions(s *SaveFileDialogOptions) *SaveFileDialogStruct {
func (a *App) dispatchEventToWindows(event *WailsEvent) {
for _, window := range a.windows {
window.dispatchWailsEvent(event)
window.DispatchWailsEvent(event)
}
}
@ -709,11 +714,11 @@ func (a *App) getContextMenu(name string) (*Menu, bool) {
}
func (a *App) OnWindowCreation(callback func(window *WebviewWindow)) {
func (a *App) OnWindowCreation(callback func(window Window)) {
a.windowCreatedCallbacks = append(a.windowCreatedCallbacks, callback)
}
func (a *App) GetWindowByName(name string) *WebviewWindow {
func (a *App) GetWindowByName(name string) Window {
a.windowsLock.Lock()
defer a.windowsLock.Unlock()
for _, window := range a.windows {
@ -733,7 +738,7 @@ func (a *App) runOrDeferToAppRun(r runnable) {
a.runLock.Unlock()
if running {
r.run()
r.Run()
}
}
@ -765,5 +770,26 @@ func (a *App) handleWindowKeyEvent(event *windowKeyEvent) {
return
}
// Get callback from window
window.handleKeyEvent(event.acceleratorString)
window.HandleKeyEvent(event.acceleratorString)
}
func (a *App) AssetServerHandler() func(rw http.ResponseWriter, req *http.Request) {
return a.assets.ServeHTTP
}
func (a *App) RegisterWindow(window Window) uint {
id := getWindowID()
if a.windows == nil {
a.windows = make(map[uint]Window)
}
a.windowsLock.Lock()
defer a.windowsLock.Unlock()
a.windows[id] = window
return id
}
func (a *App) UnregisterWindow(id uint) {
a.windowsLock.Lock()
defer a.windowsLock.Unlock()
delete(a.windows, id)
}

View file

@ -2,11 +2,12 @@ package application
import (
"fmt"
"github.com/wailsapp/wails/v3/internal/hash"
"reflect"
"runtime"
"strings"
"github.com/wailsapp/wails/v3/internal/hash"
"github.com/samber/lo"
)

View file

@ -76,7 +76,7 @@ type MessageDialogOptions struct {
Message string
Buttons []*Button
Icon []byte
window *WebviewWindow
window Window
}
type MessageDialog struct {
@ -132,7 +132,7 @@ func (d *MessageDialog) AddButtons(buttons []*Button) *MessageDialog {
return d
}
func (d *MessageDialog) AttachToWindow(window *WebviewWindow) *MessageDialog {
func (d *MessageDialog) AttachToWindow(window Window) *MessageDialog {
d.window = window
return d
}
@ -179,7 +179,7 @@ type OpenFileDialogOptions struct {
TreatsFilePackagesAsDirectories bool
AllowsOtherFileTypes bool
Filters []FileFilter
Window *WebviewWindow
Window Window
Title string
Message string
@ -205,7 +205,7 @@ type OpenFileDialogStruct struct {
message string
buttonText string
directory string
window *WebviewWindow
window Window
impl openFileDialogImpl
}
@ -245,7 +245,7 @@ func (d *OpenFileDialogStruct) TreatsFilePackagesAsDirectories(treatsFilePackage
return d
}
func (d *OpenFileDialogStruct) AttachToWindow(window *WebviewWindow) *OpenFileDialogStruct {
func (d *OpenFileDialogStruct) AttachToWindow(window Window) *OpenFileDialogStruct {
d.window = window
return d
}
@ -361,7 +361,7 @@ type SaveFileDialogOptions struct {
Filename string
ButtonText string
Filters []FileFilter
Window *WebviewWindow
Window Window
}
type SaveFileDialogStruct struct {
@ -378,7 +378,7 @@ type SaveFileDialogStruct struct {
buttonText string
filters []FileFilter
window *WebviewWindow
window Window
impl saveFileDialogImpl
title string
@ -439,7 +439,7 @@ func (d *SaveFileDialogStruct) SetDirectory(directory string) *SaveFileDialogStr
return d
}
func (d *SaveFileDialogStruct) AttachToWindow(window *WebviewWindow) *SaveFileDialogStruct {
func (d *SaveFileDialogStruct) AttachToWindow(window Window) *SaveFileDialogStruct {
d.window = window
return d
}

View file

@ -4,7 +4,7 @@ func (m *linuxApp) showAboutDialog(title string, message string, icon []byte) {
window := globalApplication.getWindowForID(m.getCurrentWindowID())
var parent pointer
if window != nil {
parent = window.impl.(*linuxWebviewWindow).window
parent = (window.(*WebviewWindow).impl).(*linuxWebviewWindow).window
}
about := newMessageDialog(InfoDialogType)
about.SetTitle(title).
@ -25,7 +25,7 @@ func (m *linuxDialog) show() {
window := globalApplication.getWindowForID(windowId)
var parent pointer
if window != nil {
parent = window.impl.(*linuxWebviewWindow).window
parent = (window.(*WebviewWindow).impl).(*linuxWebviewWindow).window
}
response := runQuestionDialog(parent, m.dialog)

View file

@ -50,7 +50,7 @@ func (e *WailsEvent) Cancel() {
e.Cancelled = true
}
func (e WailsEvent) toJSON() string {
func (e WailsEvent) ToJSON() string {
marshal, err := json.Marshal(&e)
if err != nil {
// TODO: Fatal error? log?

View file

@ -762,7 +762,10 @@ func windowSetURL(webview pointer, uri string) {
func emit(we *C.WindowEvent) {
window := globalApplication.getWindowForID(uint(we.id))
if window != nil {
window.emit(events.WindowEventType(we.event))
windowEvents <- &windowEvent{
WindowID: window.ID(),
EventID: uint(events.WindowEventType(we.event)),
}
}
}
@ -846,7 +849,7 @@ func onButtonEvent(_ *C.GtkWidget, event *C.GdkEventButton, data unsafe.Pointer)
if window == nil {
return C.gboolean(0)
}
lw, ok := (window.impl).(*linuxWebviewWindow)
lw, ok := (window.(*WebviewWindow).impl).(*linuxWebviewWindow)
if !ok {
return C.gboolean(0)
}
@ -1031,7 +1034,7 @@ func runOpenFileDialog(dialog *OpenFileDialogStruct) ([]string, error) {
window := nilPointer
if dialog.window != nil {
window = (dialog.window.impl).(*linuxWebviewWindow).window
window = (dialog.window.(*WebviewWindow).impl).(*linuxWebviewWindow).window
}
buttonText := dialog.buttonText

View file

@ -1087,7 +1087,7 @@ func runOpenFileDialog(dialog *OpenFileDialogStruct) ([]string, error) {
window := pointer(0)
if dialog.window != nil {
window = (dialog.window.impl).(*linuxWebviewWindow).window
window = (dialog.window.(*WebviewWindow).impl).(*linuxWebviewWindow).window
}
buttonText := dialog.buttonText

View file

@ -40,7 +40,7 @@ func (m *MessageProcessor) httpError(rw http.ResponseWriter, message string, arg
rw.Write([]byte(fmt.Sprintf(message, args...)))
}
func (m *MessageProcessor) getTargetWindow(r *http.Request) *WebviewWindow {
func (m *MessageProcessor) getTargetWindow(r *http.Request) Window {
windowName := r.Header.Get(webViewRequestHeaderWindowName)
if windowName != "" {
return globalApplication.GetWindowByName(windowName)

View file

@ -16,8 +16,7 @@ var applicationMethodNames = map[int]string{
ApplicationShow: "Show",
}
func (m *MessageProcessor) processApplicationMethod(method int, rw http.ResponseWriter, r *http.Request, window *WebviewWindow, params QueryParams) {
func (m *MessageProcessor) processApplicationMethod(method int, rw http.ResponseWriter, r *http.Request, window Window, params QueryParams) {
switch method {
case ApplicationQuit:
globalApplication.Quit()

View file

@ -4,31 +4,29 @@ import (
"encoding/json"
"fmt"
"net/http"
"strconv"
)
const (
CallBinding = 0
)
func (m *MessageProcessor) callErrorCallback(window *WebviewWindow, message string, callID *string, err error) {
func (m *MessageProcessor) callErrorCallback(window Window, message string, callID *string, err error) {
errorMsg := fmt.Sprintf(message, err)
m.Error(errorMsg)
msg := "_wails.callErrorCallback('" + *callID + "', " + strconv.Quote(errorMsg) + ");"
window.ExecJS(msg)
window.CallError(*callID, errorMsg)
}
func (m *MessageProcessor) callCallback(window *WebviewWindow, callID *string, result string, isJSON bool) {
msg := fmt.Sprintf("_wails.callCallback('%s', %s, %v);", *callID, strconv.Quote(result), isJSON)
window.ExecJS(msg)
func (m *MessageProcessor) callCallback(window Window, callID *string, result string, isJSON bool) {
window.CallResponse(*callID, result)
}
func (m *MessageProcessor) processCallMethod(method int, rw http.ResponseWriter, r *http.Request, window *WebviewWindow, params QueryParams) {
func (m *MessageProcessor) processCallMethod(method int, rw http.ResponseWriter, r *http.Request, window Window, params QueryParams) {
args, err := params.Args()
if err != nil {
m.httpError(rw, "Unable to parse arguments: %s", err.Error())
return
}
fmt.Println("processCallMethod", args)
callID := args.String("call-id")
if callID == nil {
m.Error("call-id is required")

View file

@ -14,7 +14,7 @@ var clipboardMethods = map[int]string{
ClipboardText: "Text",
}
func (m *MessageProcessor) processClipboardMethod(method int, rw http.ResponseWriter, _ *http.Request, _ *WebviewWindow, params QueryParams) {
func (m *MessageProcessor) processClipboardMethod(method int, rw http.ResponseWriter, _ *http.Request, _ Window, params QueryParams) {
args, err := params.Args()
if err != nil {

View file

@ -19,7 +19,7 @@ var contextmenuMethodNames = map[int]string{
ContextMenuOpen: "Open",
}
func (m *MessageProcessor) processContextMenuMethod(method int, rw http.ResponseWriter, _ *http.Request, window *WebviewWindow, params QueryParams) {
func (m *MessageProcessor) processContextMenuMethod(method int, rw http.ResponseWriter, _ *http.Request, window Window, params QueryParams) {
switch method {
case ContextMenuOpen:
@ -29,7 +29,7 @@ func (m *MessageProcessor) processContextMenuMethod(method int, rw http.Response
m.httpError(rw, "error parsing contextmenu message: %s", err.Error())
return
}
window.openContextMenu(&data)
window.OpenContextMenu(&data)
m.ok(rw)
default:
m.httpError(rw, "Unknown contextmenu method: %d", method)

View file

@ -5,7 +5,6 @@ import (
"fmt"
"net/http"
"runtime"
"strconv"
)
const (
@ -26,20 +25,17 @@ var dialogMethodNames = map[int]string{
DialogSaveFile: "SaveFile",
}
func (m *MessageProcessor) dialogErrorCallback(window *WebviewWindow, message string, dialogID *string, err error) {
func (m *MessageProcessor) dialogErrorCallback(window Window, message string, dialogID *string, err error) {
errorMsg := fmt.Sprintf(message, err)
m.Error(errorMsg)
msg := "_wails.dialogErrorCallback('" + *dialogID + "', " + strconv.Quote(errorMsg) + ");"
window.ExecJS(msg)
m.Error(message, "error", err)
window.DialogError(*dialogID, errorMsg)
}
func (m *MessageProcessor) dialogCallback(window *WebviewWindow, dialogID *string, result string, isJSON bool) {
msg := fmt.Sprintf("_wails.dialogCallback('%s', %s, %v);", *dialogID, strconv.Quote(result), isJSON)
window.ExecJS(msg)
func (m *MessageProcessor) dialogCallback(window Window, dialogID *string, result string, isJSON bool) {
window.DialogResponse(*dialogID, result)
}
func (m *MessageProcessor) processDialogMethod(method int, rw http.ResponseWriter, r *http.Request, window *WebviewWindow, params QueryParams) {
func (m *MessageProcessor) processDialogMethod(method int, rw http.ResponseWriter, r *http.Request, window Window, params QueryParams) {
args, err := params.Args()
if err != nil {

View file

@ -12,7 +12,7 @@ var eventsMethodNames = map[int]string{
EventsEmit: "Emit",
}
func (m *MessageProcessor) processEventsMethod(method int, rw http.ResponseWriter, _ *http.Request, window *WebviewWindow, params QueryParams) {
func (m *MessageProcessor) processEventsMethod(method int, rw http.ResponseWriter, _ *http.Request, window Window, params QueryParams) {
var event WailsEvent

View file

@ -16,7 +16,7 @@ var screensMethodNames = map[int]string{
ScreensGetCurrent: "GetCurrent",
}
func (m *MessageProcessor) processScreensMethod(method int, rw http.ResponseWriter, _ *http.Request, _ *WebviewWindow, _ QueryParams) {
func (m *MessageProcessor) processScreensMethod(method int, rw http.ResponseWriter, _ *http.Request, _ Window, _ QueryParams) {
switch method {
case ScreensGetAll:

View file

@ -12,7 +12,7 @@ var systemMethodNames = map[int]string{
SystemIsDarkMode: "IsDarkMode",
}
func (m *MessageProcessor) processSystemMethod(method int, rw http.ResponseWriter, r *http.Request, window *WebviewWindow, params QueryParams) {
func (m *MessageProcessor) processSystemMethod(method int, rw http.ResponseWriter, r *http.Request, window Window, params QueryParams) {
switch method {
case SystemIsDarkMode:

View file

@ -70,7 +70,7 @@ var windowMethodNames = map[int]string{
WindowSetZoomLevel: "SetZoomLevel",
}
func (m *MessageProcessor) processWindowMethod(method int, rw http.ResponseWriter, _ *http.Request, window *WebviewWindow, params QueryParams) {
func (m *MessageProcessor) processWindowMethod(method int, rw http.ResponseWriter, _ *http.Request, window Window, params QueryParams) {
args, err := params.Args()
if err != nil {

View file

@ -94,7 +94,7 @@ func (s *SystemTray) Label() string {
return s.label
}
func (s *SystemTray) run() {
func (s *SystemTray) Run() {
s.impl = newSystemTrayImpl(s)
if s.attachedWindow.Window != nil {

View file

@ -1,6 +1,7 @@
package application
import (
"encoding/json"
"errors"
"fmt"
"runtime"
@ -125,6 +126,7 @@ func getWindowID() uint {
return windowID
}
// FIXME: This should like be an interface method (TDM)
// Use onApplicationEvent to register a callback for an application event from a window.
// This will handle tidying up the callback when the window is destroyed
func (w *WebviewWindow) onApplicationEvent(eventType events.ApplicationEventType, callback func(*Event)) {
@ -156,8 +158,8 @@ func (w *WebviewWindow) setupEventMapping() {
}
}
// newWindow creates a new window with the given options
func newWindow(options WebviewWindowOptions) *WebviewWindow {
// NewWindow creates a new window with the given options
func NewWindow(options WebviewWindowOptions) Window {
if options.Width == 0 {
options.Width = 800
}
@ -219,8 +221,45 @@ func (w *WebviewWindow) addCancellationFunction(canceller func()) {
w.cancellers = append(w.cancellers, canceller)
}
// formatJS ensures the 'data' provided marshals to valid json or panics
func (w *WebviewWindow) formatJS(f string, callID string, data string) string {
j, err := json.Marshal(data)
if err != nil {
panic(err)
}
return fmt.Sprintf(f, callID, j)
}
func (w *WebviewWindow) CallError(callID string, result string) {
if w.impl != nil {
w.impl.execJS(w.formatJS("_wails.callErrorCallback('%s', %s);", callID, result))
}
}
func (w *WebviewWindow) CallResponse(callID string, result string) {
if w.impl != nil {
w.impl.execJS(w.formatJS("_wails.callCallback('%s', %s, true);", callID, result))
}
}
func (w *WebviewWindow) DialogError(dialogID string, result string) {
if w.impl != nil {
w.impl.execJS(w.formatJS("_wails.dialogErrorCallback('%s', %s);", dialogID, result))
}
}
func (w *WebviewWindow) DialogResponse(dialogID string, result string) {
if w.impl != nil {
w.impl.execJS(w.formatJS("_wails.dialogCallback('%s', %s, true);", dialogID, result))
}
}
func (w *WebviewWindow) ID() uint {
return w.id
}
// SetTitle sets the title of the window
func (w *WebviewWindow) SetTitle(title string) *WebviewWindow {
func (w *WebviewWindow) SetTitle(title string) Window {
w.options.Title = title
if w.impl != nil {
InvokeSync(func() {
@ -236,7 +275,7 @@ func (w *WebviewWindow) Name() string {
}
// SetSize sets the size of the window
func (w *WebviewWindow) SetSize(width, height int) *WebviewWindow {
func (w *WebviewWindow) SetSize(width, height int) Window {
// Don't set size if fullscreen
if w.IsFullscreen() {
return w
@ -278,7 +317,7 @@ func (w *WebviewWindow) SetSize(width, height int) *WebviewWindow {
return w
}
func (w *WebviewWindow) run() {
func (w *WebviewWindow) Run() {
if w.impl != nil {
return
}
@ -287,7 +326,7 @@ func (w *WebviewWindow) run() {
}
// SetAlwaysOnTop sets the window to be always on top.
func (w *WebviewWindow) SetAlwaysOnTop(b bool) *WebviewWindow {
func (w *WebviewWindow) SetAlwaysOnTop(b bool) Window {
w.options.AlwaysOnTop = b
if w.impl != nil {
InvokeSync(func() {
@ -298,12 +337,12 @@ func (w *WebviewWindow) SetAlwaysOnTop(b bool) *WebviewWindow {
}
// Show shows the window.
func (w *WebviewWindow) Show() *WebviewWindow {
func (w *WebviewWindow) Show() Window {
if globalApplication.impl == nil {
return w
}
if w.impl == nil {
InvokeSync(w.run)
InvokeSync(w.Run)
return w
}
InvokeSync(w.impl.show)
@ -312,7 +351,7 @@ func (w *WebviewWindow) Show() *WebviewWindow {
}
// Hide hides the window.
func (w *WebviewWindow) Hide() *WebviewWindow {
func (w *WebviewWindow) Hide() Window {
w.options.Hidden = true
if w.impl != nil {
InvokeSync(w.impl.hide)
@ -321,7 +360,7 @@ func (w *WebviewWindow) Hide() *WebviewWindow {
return w
}
func (w *WebviewWindow) SetURL(s string) *WebviewWindow {
func (w *WebviewWindow) SetURL(s string) Window {
w.options.URL = s
if w.impl != nil {
InvokeSync(func() {
@ -332,7 +371,7 @@ func (w *WebviewWindow) SetURL(s string) *WebviewWindow {
}
// SetZoom sets the zoom level of the window.
func (w *WebviewWindow) SetZoom(magnification float64) *WebviewWindow {
func (w *WebviewWindow) SetZoom(magnification float64) Window {
w.options.Zoom = magnification
if w.impl != nil {
InvokeSync(func() {
@ -351,7 +390,7 @@ func (w *WebviewWindow) GetZoom() float64 {
}
// SetResizable sets whether the window is resizable.
func (w *WebviewWindow) SetResizable(b bool) *WebviewWindow {
func (w *WebviewWindow) SetResizable(b bool) Window {
w.options.DisableResize = !b
if w.impl != nil {
InvokeSync(func() {
@ -367,7 +406,7 @@ func (w *WebviewWindow) Resizable() bool {
}
// SetMinSize sets the minimum size of the window.
func (w *WebviewWindow) SetMinSize(minWidth, minHeight int) *WebviewWindow {
func (w *WebviewWindow) SetMinSize(minWidth, minHeight int) Window {
w.options.MinWidth = minWidth
w.options.MinHeight = minHeight
@ -399,7 +438,7 @@ func (w *WebviewWindow) SetMinSize(minWidth, minHeight int) *WebviewWindow {
}
// SetMaxSize sets the maximum size of the window.
func (w *WebviewWindow) SetMaxSize(maxWidth, maxHeight int) *WebviewWindow {
func (w *WebviewWindow) SetMaxSize(maxWidth, maxHeight int) Window {
w.options.MaxWidth = maxWidth
w.options.MaxHeight = maxHeight
@ -431,7 +470,7 @@ func (w *WebviewWindow) SetMaxSize(maxWidth, maxHeight int) *WebviewWindow {
}
// ExecJS executes the given javascript in the context of the window.
func (w *WebviewWindow) ExecJS(js string) {
func (w *WebviewWindow) ExecJS(_callID, js string) {
if w.impl == nil {
return
}
@ -439,19 +478,19 @@ func (w *WebviewWindow) ExecJS(js string) {
}
// Fullscreen sets the window to fullscreen mode. Min/Max size constraints are disabled.
func (w *WebviewWindow) Fullscreen() *WebviewWindow {
func (w *WebviewWindow) Fullscreen() Window {
if w.impl == nil {
w.options.StartState = WindowStateFullscreen
return w
}
if !w.IsFullscreen() {
w.disableSizeConstraints()
w.DisableSizeConstraints()
InvokeSync(w.impl.fullscreen)
}
return w
}
func (w *WebviewWindow) SetFullscreenButtonEnabled(enabled bool) *WebviewWindow {
func (w *WebviewWindow) SetFullscreenButtonEnabled(enabled bool) Window {
w.options.FullscreenButtonEnabled = enabled
if w.impl != nil {
InvokeSync(func() {
@ -524,7 +563,7 @@ func (w *WebviewWindow) IsFullscreen() bool {
}
// SetBackgroundColour sets the background colour of the window
func (w *WebviewWindow) SetBackgroundColour(colour RGBA) *WebviewWindow {
func (w *WebviewWindow) SetBackgroundColour(colour RGBA) Window {
w.options.BackgroundColour = colour
if w.impl != nil {
InvokeSync(func() {
@ -534,37 +573,32 @@ func (w *WebviewWindow) SetBackgroundColour(colour RGBA) *WebviewWindow {
return w
}
func (w *WebviewWindow) handleMessage(message string) {
func (w *WebviewWindow) HandleMessage(message string) {
// Check for special messages
if message == "drag" {
if !w.IsFullscreen() {
InvokeSync(func() {
err := w.startDrag()
if err != nil {
w.error("Failed to start drag: %s", err)
w.Error("Failed to start drag: %s", err)
}
})
}
return
}
if strings.HasPrefix(message, "resize:") {
if !w.IsFullscreen() {
sl := strings.Split(message, ":")
if len(sl) != 2 {
w.error("Unknown message returned from dispatcher: %+v", message)
w.Error("Unknown message returned from dispatcher: %+v", message)
return
}
err := w.startResize(sl[1])
if err != nil {
w.error(err.Error())
w.Error(err.Error())
}
}
return
}
w.info("ProcessMessage from front end: %s", message)
}
func (w *WebviewWindow) startResize(border string) error {
@ -622,7 +656,7 @@ func (w *WebviewWindow) RegisterHook(eventType events.WindowEventType, callback
}
}
func (w *WebviewWindow) handleWindowEvent(id uint) {
func (w *WebviewWindow) HandleWindowEvent(id uint) {
w.eventListenersLock.RLock()
defer w.eventListenersLock.RUnlock()
@ -738,7 +772,7 @@ func (w *WebviewWindow) ToggleDevTools() {
}
// ZoomReset resets the zoom level of the webview content to 100%
func (w *WebviewWindow) ZoomReset() *WebviewWindow {
func (w *WebviewWindow) ZoomReset() Window {
if w.impl != nil {
InvokeSync(w.impl.zoomReset)
w.emit(events.Common.WindowZoomReset)
@ -783,7 +817,7 @@ func (w *WebviewWindow) Zoom() {
}
// SetHTML sets the HTML of the window to the given html string.
func (w *WebviewWindow) SetHTML(html string) *WebviewWindow {
func (w *WebviewWindow) SetHTML(html string) Window {
w.options.HTML = html
if w.impl != nil {
InvokeSync(func() {
@ -794,7 +828,7 @@ func (w *WebviewWindow) SetHTML(html string) *WebviewWindow {
}
// SetRelativePosition sets the position of the window.
func (w *WebviewWindow) SetRelativePosition(x, y int) *WebviewWindow {
func (w *WebviewWindow) SetRelativePosition(x, y int) Window {
w.options.X = x
w.options.Y = y
if w.impl != nil {
@ -806,7 +840,7 @@ func (w *WebviewWindow) SetRelativePosition(x, y int) *WebviewWindow {
}
// Minimise minimises the window.
func (w *WebviewWindow) Minimise() *WebviewWindow {
func (w *WebviewWindow) Minimise() Window {
if w.impl == nil {
w.options.StartState = WindowStateMinimised
return w
@ -819,13 +853,13 @@ func (w *WebviewWindow) Minimise() *WebviewWindow {
}
// Maximise maximises the window. Min/Max size constraints are disabled.
func (w *WebviewWindow) Maximise() *WebviewWindow {
func (w *WebviewWindow) Maximise() Window {
if w.impl == nil {
w.options.StartState = WindowStateMaximised
return w
}
if !w.IsMaximised() {
w.disableSizeConstraints()
w.DisableSizeConstraints()
InvokeSync(w.impl.maximise)
w.emit(events.Common.WindowMaximise)
}
@ -849,7 +883,7 @@ func (w *WebviewWindow) UnMaximise() {
return
}
if w.IsMaximised() {
w.enableSizeConstraints()
w.EnableSizeConstraints()
InvokeSync(w.impl.unmaximise)
w.emit(events.Common.WindowUnMaximise)
}
@ -861,7 +895,7 @@ func (w *WebviewWindow) UnFullscreen() {
return
}
if w.IsFullscreen() {
w.enableSizeConstraints()
w.EnableSizeConstraints()
InvokeSync(w.impl.unfullscreen)
w.emit(events.Common.WindowUnFullscreen)
}
@ -884,7 +918,7 @@ func (w *WebviewWindow) Restore() {
})
}
func (w *WebviewWindow) disableSizeConstraints() {
func (w *WebviewWindow) DisableSizeConstraints() {
if w.impl == nil {
return
}
@ -898,7 +932,7 @@ func (w *WebviewWindow) disableSizeConstraints() {
})
}
func (w *WebviewWindow) enableSizeConstraints() {
func (w *WebviewWindow) EnableSizeConstraints() {
if w.impl == nil {
return
}
@ -921,7 +955,7 @@ func (w *WebviewWindow) GetScreen() (*Screen, error) {
}
// SetFrameless removes the window frame and title bar
func (w *WebviewWindow) SetFrameless(frameless bool) *WebviewWindow {
func (w *WebviewWindow) SetFrameless(frameless bool) Window {
w.options.Frameless = frameless
if w.impl != nil {
InvokeSync(func() {
@ -931,9 +965,9 @@ func (w *WebviewWindow) SetFrameless(frameless bool) *WebviewWindow {
return w
}
func (w *WebviewWindow) dispatchWailsEvent(event *WailsEvent) {
msg := fmt.Sprintf("_wails.dispatchWailsEvent(%s);", event.toJSON())
w.ExecJS(msg)
func (w *WebviewWindow) DispatchWailsEvent(event *WailsEvent) {
msg := fmt.Sprintf("_wails.dispatchWailsEvent(%s);", event.ToJSON())
w.ExecJS("", msg)
}
func (w *WebviewWindow) dispatchWindowEvent(id uint) {
@ -942,40 +976,40 @@ func (w *WebviewWindow) dispatchWindowEvent(id uint) {
jsEvent := &WailsEvent{
Name: events.JSEvent(id),
}
w.dispatchWailsEvent(jsEvent)
w.DispatchWailsEvent(jsEvent)
}
func (w *WebviewWindow) info(message string, args ...any) {
func (w *WebviewWindow) Info(message string, args ...any) {
var messageArgs []interface{}
messageArgs = append(messageArgs, args...)
messageArgs = append(messageArgs, "sender", w.Name())
globalApplication.info(message, messageArgs...)
}
func (w *WebviewWindow) error(message string, args ...any) {
func (w *WebviewWindow) Error(message string, args ...any) {
var messageArgs []interface{}
messageArgs = append(messageArgs, args...)
messageArgs = append(messageArgs, "sender", w.Name())
globalApplication.error(message, messageArgs...)
}
func (w *WebviewWindow) handleDragAndDropMessage(event *dragAndDropMessage) {
func (w *WebviewWindow) HandleDragAndDropMessage(filenames []string) {
thisEvent := NewWindowEvent()
ctx := newWindowEventContext()
ctx.setDroppedFiles(event.filenames)
ctx.setDroppedFiles(filenames)
thisEvent.ctx = ctx
for _, listener := range w.eventListeners[uint(events.FilesDropped)] {
listener.callback(thisEvent)
}
}
func (w *WebviewWindow) openContextMenu(data *ContextMenuData) {
func (w *WebviewWindow) OpenContextMenu(data *ContextMenuData) {
menu, ok := w.contextMenus[data.Id]
if !ok {
// try application level context menu
menu, ok = globalApplication.getContextMenu(data.Id)
if !ok {
w.error("No context menu found for id: %s", data.Id)
w.Error("No context menu found for id: %s", data.Id)
return
}
}
@ -1067,7 +1101,7 @@ func (w *WebviewWindow) processKeyBinding(acceleratorString string) bool {
return true
}
func (w *WebviewWindow) handleKeyEvent(acceleratorString string) {
func (w *WebviewWindow) HandleKeyEvent(acceleratorString string) {
if w.impl == nil {
return
}

View file

@ -43,7 +43,7 @@ func (w *linuxWebviewWindow) startDrag() error {
}
func (w *linuxWebviewWindow) endDrag(button uint, x, y int) {
fmt.Println("endDrag", button, x, y)
}
func (w *linuxWebviewWindow) enableDND() {

View file

@ -0,0 +1,78 @@
package application
import (
"github.com/wailsapp/wails/v3/pkg/events"
)
type Callback interface {
CallError(callID string, result string)
CallResponse(callID string, result string)
DialogError(dialogID string, result string)
DialogResponse(dialogID string, result string)
}
type Window interface {
Callback
AbsolutePosition() (int, int)
Center()
Close()
Destroy()
DisableSizeConstraints()
DispatchWailsEvent(event *WailsEvent)
EnableSizeConstraints()
Error(message string, args ...any)
ExecJS(callID, js string)
Focus()
ForceReload()
Fullscreen() Window
GetScreen() (*Screen, error)
GetZoom() float64
HandleDragAndDropMessage(filenames []string)
HandleMessage(message string)
HandleWindowEvent(id uint)
Height() int
Hide() Window
ID() uint
Info(message string, args ...any)
IsFullscreen() bool
IsMaximised() bool
IsMinimised() bool
HandleKeyEvent(acceleratorString string)
Maximise() Window
Minimise() Window
Name() string
On(eventType events.WindowEventType, callback func(event *WindowEvent)) func()
OpenContextMenu(data *ContextMenuData)
RegisterContextMenu(name string, menu *Menu)
RelativePosition() (int, int)
Reload()
Resizable() bool
Restore()
Run()
SetAbsolutePosition(x, y int)
SetAlwaysOnTop(b bool) Window
SetBackgroundColour(colour RGBA) Window
SetFrameless(frameless bool) Window
SetFullscreenButtonEnabled(enabled bool) Window
SetHTML(html string) Window
SetMaxSize(maxWidth, maxHeight int) Window
SetMinSize(minWidth, minHeight int) Window
SetRelativePosition(x, y int) Window
SetResizable(b bool) Window
SetSize(width, height int) Window
SetTitle(title string) Window
SetURL(s string) Window
SetZoom(magnification float64) Window
Show() Window
Size() (width int, height int)
ToggleDevTools()
ToggleFullscreen()
UnFullscreen()
UnMaximise()
UnMinimise()
Width() int
Zoom()
ZoomIn()
ZoomOut()
ZoomReset() Window
}