Skip to content

Host interfaces ​

A host is the native side of an app: it opens WebView windows, carries messages between the page and Go, and talks to the OS. Vitra ships one for each OS (platform/linux, platform/darwin, platform/windows). You write your own only for a new platform, an embedded WebView, or tests.

Every interface a host can implement is in package platform. A host implements the core, plus only the capabilities it supports.

The core ​

platform.DesktopHost is what app.Run needs. app.Options.Host takes it (app.DesktopHost is an alias).

MethodWhat it does
OS(), Features()The OS family and the feature matrix (see below)
CreateWindow, NavigateWindow, CloseWindowWindow lifecycle (platform.Host)
PostMessageSend a reply or event to a window's page
Open(spec, uri, preload)Create a window, inject the preload before any page script, load uri
SetInvokeHandlerReceive page calls. The host stamps the window and origin; it never reads them from the message
SetNavPolicyCheck every top-level navigation; cancel it when the check returns false
SetDestroyHandlerReport a window the user closed natively
Run, QuitThe UI loop

Optional capabilities ​

The app checks for each of these with a type assertion when a command needs it. If the host lacks it, the command fails with *platform.ErrUnsupported naming the feature. It never succeeds without doing the work.

InterfaceMethodsUsed by
ClipboardClipboardGet, ClipboardSetclipboard.read, clipboard.write
DialogsOpenFileDialog, SaveFileDialog, OpenDirectoryDialog, MessageDialogdialog.*
MultiFileOpenerOpenFilesDialogdialog.open with multiple: true
NotifierShowNotificationnotifications.show
MenuBarSetMenuBar, plus ActionReportermenu.set, menu.clear
TraySetTray(TraySpec), ClearTray, plus ActionReportertray.set, tray.clear, App.SetTray
TrayClickReporterSetTrayClickHandlertray.click event, App.OnTrayClick (with TraySpec.ClickActivates)
TrayAnchorerTrayAnchorApp.TrayAnchor
GlobalShortcutsRegisterGlobalShortcut, UnregisterGlobalShortcut, plus ActionReportershortcut.*
ActionReporterSetActionHandlermenu.action, tray.action, shortcut.action events
DragDropEnableDragDrop, SetDragDropHandlerdragdrop.receive, dragdrop.drop event
WindowControlsApplyWindowChrome, ReadWindowChrome, FocusWindow, BlurWindowwindow.* except create and close
URLOpenerOpenURLbrowser.open
PathOpenerOpenPathpath.open

These are for your own Go code, not official commands:

InterfaceMethodsFor
SingleInstanceTrySingleInstance, StartDeepLinkBridge, ForwardToPrimaryOne running instance; handing deep links to it
PanelsShowPanel, HidePanel, PanelShownWindowKindPanel windows, TraySpec.Panel
PresentationSetterSetPresentationapp.Options.Presentation (menu bar apps)
LoginItemsLoginItemEnabled, SetLoginItemApp.SetLoginItem, app.loginItem, app.setLoginItem
URLSchemeRegistrarRegisterURLSchemevitra register-scheme
FileAssociationRegistrarRegisterFileAssociationsvitra register-files
ScriptEvaluatorEvalTests and automation. Script run this way has the page's bridge access
FileDropInjectorInjectFileDropSimulating a file drop in tests and demos

Hooks ​

The app installs these when the host has them. Without them it falls back to the core.

InterfaceMethodWithout it
DevToolsSetterSetDevToolsThe inspector never opens, even with Options.DevTools
MessageReporterSetMessageHandlerCalls arrive through SetInvokeHandler, and the app trusts the origin it last recorded for the window instead of checking each message's sender URL
RejectReporterSetRejectHandlerMessages the host drops itself are not audited

The native hosts implement MessageReporter; implement it in yours too, so every call's sender is checked.

Implementing an interface vs. supporting a feature ​

Implementing an interface says the host has the code. Features() says whether it works on this machine, which can depend on the OS version, the desktop session, or a system library. The OS hosts implement every interface in all builds; without -tags vitra_native their feature matrix marks everything unavailable. A command needs both, and fails with ErrUnsupported if either is missing.

A minimal host ​

A host for tests that runs an app and has a clipboard:

go
type testHost struct {
	// OS, Features, CreateWindow, NavigateWindow, PostMessage, CloseWindow,
	// Open, SetInvokeHandler, SetNavPolicy, SetDestroyHandler, Run, Quit
	core
	text string
}

func (h *testHost) ClipboardGet() (string, error) { return h.text, nil }
func (h *testHost) ClipboardSet(s string) error  { h.text = s; return nil }

var (
	_ platform.DesktopHost = (*testHost)(nil)
	_ platform.Clipboard   = (*testHost)(nil)
)

With this host, clipboard.read works and tray.set fails with ErrUnsupported for tray. Assert each interface you mean to implement, as above, so a changed signature fails to compile instead of silently dropping the capability.

Apache-2.0 licensed.