Skip to content

Official plugins ​

plugin/official declares the built-in desktop commands. official.All() returns every plugin; each also has its own constructor. A plugin declares commands and permissions only. app.App.UseOfficialPlugins binds them to the native host in one call; see Desktop features.

PluginConstructorPermissionsCommandsEvents
vitra.fsofficial.FS()fs.read, fs.write (path-scoped)fs.read, fs.writefs.changed
vitra.dialogofficial.Dialog()dialog.open, dialog.save, dialog.openDirectory, dialog.messagesame as permissions
vitra.clipboardofficial.Clipboard()clipboard.read, clipboard.writesame as permissions
vitra.browserofficial.Browser()browser.openbrowser.open (http, https, mailto)
vitra.osofficial.OS()os.infoos.info
vitra.notificationofficial.Notification()notifications.shownotifications.show
vitra.pathofficial.Path()path.open (path-scoped)path.open
vitra.windowofficial.Window()window.create, window.close, window.chromewindow.create, window.close; with window.chrome: window.chrome, window.getChrome, window.focus, window.blur, window.hide, window.show, window.minimize, window.maximize, window.unmaximize, window.fullscreen, window.unfullscreen, window.setAlwaysOnTop, window.restore, window.setTitle, window.setSize, window.setIcon
vitra.menuofficial.Menu()menu.setmenu.set, menu.clearmenu.action
vitra.trayofficial.Tray()tray.settray.set, tray.cleartray.action, tray.click
vitra.dragdropofficial.DragDrop()dragdrop.receivedragdrop.receivedragdrop.drop
vitra.shortcutofficial.Shortcut()shortcut.registershortcut.register, shortcut.unregistershortcut.action
vitra.appofficial.App()app.quit, app.login_itemapp.quit, app.loginItem, app.setLoginItem
vitra.deeplinkofficial.DeepLink()deeplink.handledeeplink.open

dialog.open takes {"multiple": true} to select several files and returns every selected path; a host that cannot select several files returns platform.ErrUnsupported. See Picking files.

The permission constants live in desktop (desktop.PermFSRead, desktop.PermClipboardWrite, …).

Inputs and outputs ​

UseOfficialPlugins binds every command as a typed command (vitra.Bind) with the types below, from plugin/official. Input is decoded strictly: an unknown field, a wrong type, or a missing required value fails with a validation error (denial code error) before the host is touched. The generated client uses these types; commands with output vitra.Void send null and are typed Promise<void>.

CommandInputOutput
fs.readpath stringstring
fs.writeWriteFileInput {path, data}Void
dialog.openDialogOptions {title?, defaultPath?, filters?, multiple?} or null[]string (null when cancelled)
dialog.save, dialog.openDirectoryDialogOptions or nullstring
dialog.messageMessageDialogInput {title?, message, kind?}bool
clipboard.readnonestring
clipboard.writetext stringVoid
browser.openURL stringVoid
os.infononedesktop.OsInfo
notifications.showNotificationInput {title?, body}Void
path.openpath stringVoid
window.createWindowCreateInput {id, title?, path?, width?, height?}WindowCreated {id}
window.chromeWindowChromeInput {id, title?, width?, height?, maximized?, fullscreen?, alwaysOnTop?, minimized?, hidden?, iconPath?}Void
window.getChromeWindowRef {id}platform.WindowChrome
window.setAlwaysOnTopWindowAlwaysOnTopInput {id, alwaysOnTop}Void
window.setTitleWindowTitleInput {id, title}Void
window.setSizeWindowSizeInput {id, width, height}Void
window.setIconWindowIconInput {id, iconPath}Void
window.close, window.focus, window.blur, window.hide, window.show, window.minimize, window.maximize, window.unmaximize, window.fullscreen, window.unfullscreen, window.restoreWindowRef {id}Void
menu.setMenuInput {items: [MenuItem]}; MenuItem is {id, label, menu?, shortcut?, disabled?, checked?} or a separator {separator: true, menu?}Void
tray.setTrayInput {tooltip?, title?, icon?, template?, clickActivates?, panel?, items?}Void
menu.clear, tray.clear, app.quitnoneVoid
app.loginItemnoneLoginItem {enabled}
app.setLoginItemLoginItem {enabled} (required)Void
dragdrop.receiveDragDropInput {id?, enabled?} (window "main", enabled true by default)Void
shortcut.registerShortcutInput {accelerator, action}Void
shortcut.unregisterShortcutRef {accelerator}Void

The tray icon is the path of a PNG (at most 256 KiB) inside the app's assets, as the page would request it ("/icons/tray.png" or "icons/tray.png"). Paths with .., ., empty segments, backslashes or a drive letter are rejected, so the page can never point the tray at a file outside the app. title is text next to the icon where the platform has it (the tray.title feature); elsewhere it is shown in the tooltip. A menu separator takes no id, label, shortcut, disabled or checked; every other item needs id and label. Disabled items never fire, and a checked item stays checked until the menu is set again. With clickActivates, a left click on the icon emits tray.click ({"anchor": {x, y, width, height}}, or {"anchor": null} when the host cannot tell where the icon is) and the menu opens on a right click; tray.click reaches the primary window and the tray panel only. panel names a panel window (opened by Go with WindowKindPanel) that the left click shows under the icon and hides again; it implies clickActivates.

Window sizes must be whole numbers no larger than 2^53 (window.setSize: positive; window.create and window.chrome: 0 or absent leaves the size alone). Anything else is rejected, never rounded or ignored.

The client uses the object form of each input. window.vitra.invoke also accepts the older shorthands: a bare id string for WindowRef and window.create, a bare string for the dialog.message message, the notifications.show body, and the shortcut.unregister accelerator, a bare item array for menu.set and tray.set, a bare boolean for dragdrop.receive, window as an alias of id in dragdrop.receive, and actionID or id as aliases of action in shortcut.register.

Writing a plugin ​

A plugin implements plugin.Plugin:

go
type Plugin interface {
    Manifest() plugin.Manifest          // ID, name, version, permissions, minimum kernel
    Contribute() (plugin.Contribution, error) // commands and events
}

rt.RegisterPlugin checks the kernel version and refuses a plugin that declares a permission another plugin already owns. Bind typed handlers to its commands with vitra.Bind (or untyped executors with rt.BindExecutor), and grant its permissions like any other. See Typing a plugin's commands.

Apache-2.0 licensed.