trayhost: github.com/shurcooL/trayhost Index | Examples | Files

package trayhost

import "github.com/shurcooL/trayhost"

Package trayhost is a cross-platform Go library to place an icon in the host operating system's taskbar.

Platform Support

- macOS - Fully implemented and supported by @shurcooL.

- Linux - Partially implemented, but unsupported (needs an owner/maintainer).

- Windows - Partially implemented, but unsupported (needs an owner/maintainer).

Notes

On macOS, for Notification Center user notifications to work, your Go binary that uses trayhost must be a part of a standard macOS app bundle.

Most other functionality of trayhost will be available if the binary is not a part of app bundle, but you will get a terminal pop up, and you will not be able to configure some aspects of the app.

Here's a minimal layout of an app bundle:

$ tree "Trayhost Example.app"
Trayhost\ Example.app
└── Contents
    ├── Info.plist
    ├── MacOS
    │   └── example
    └── Resources
        └── Icon.icns

Here's a minimal Info.plist file as reference (only the entries that are needed, nothing extra):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleExecutable</key>
	<string>example</string>
	<key>CFBundleIconFile</key>
	<string>Icon</string>
	<key>CFBundleIdentifier</key>
	<string>ExampleApp</string>
	<key>NSHighResolutionCapable</key>
	<true/>
	<key>LSUIElement</key>
	<string>1</string>
</dict>
</plist>

- CFBundleIdentifier needs to be set to some value for Notification Center to work.

- The binary must be inside Contents/MacOS directory for Notification Center to work.

- NSHighResolutionCapable to enable Retina mode.

- LSUIElement is needed to make the app not appear in Cmd+Tab list and the dock while still being able to show a tooltip in the menu bar.

On macOS, when you run an app bundle, the working directory of the executed process is the root directory (/), not the app bundle's Contents/Resources directory. Change directory to Resources if you need to load resources from there.

ep, err := os.Executable()
if err != nil {
	log.Fatalln("os.Executable:", err)
}
err = os.Chdir(filepath.Join(filepath.Dir(ep), "..", "Resources"))
if err != nil {
	log.Fatalln("os.Chdir:", err)
}

Code:

menuItems := []trayhost.MenuItem{
    {
        Title: "Example Item",
        Handler: func() {
            fmt.Println("do stuff")
        },
    },
    {
        Title: "Get Clipboard Content",
        Handler: func() {
            cc, err := trayhost.GetClipboardContent()
            if err != nil {
                fmt.Printf("GetClipboardContent() error: %v\n", err)
                return
            }

            fmt.Printf("Text: %q\n", cc.Text)
            fmt.Printf("Image: %v len(%v)\n", cc.Image.Kind, len(cc.Image.Bytes))
            fmt.Printf("Files: len(%v) %v\n", len(cc.Files), cc.Files)
        },
    },
    {
        Title: "Set Clipboard Text",
        Handler: func() {
            const text = "this text gets copied"

            trayhost.SetClipboardText(text)
            fmt.Printf("Text %q got copied into your clipboard.\n", text)
        },
    },
    {
        // Displaying notifications requires a proper app bundle and won't work without one.
        // See https://godoc.org/github.com/shurcooL/trayhost#hdr-Notes.

        Title: "Display Notification",
        Handler: func() {
            notification := trayhost.Notification{
                Title:   "Example Notification",
                Body:    "Notification body text is here.",
                Timeout: 3 * time.Second,
                Handler: func() {
                    fmt.Println("do stuff when notification is clicked")
                },
            }
            if cc, err := trayhost.GetClipboardContent(); err == nil && cc.Image.Kind != "" {
                // Use image from clipboard as notification image.
                notification.Image = cc.Image
            }
            notification.Display()
        },
    },
    trayhost.SeparatorMenuItem(),
    {
        Title:   "Quit",
        Handler: trayhost.Exit,
    },
}

// On macOS, when you run an app bundle, the working directory of the executed process
// is the root directory (/), not the app bundle's Contents/Resources directory.
// Change directory to Resources so that we can load resources from there.
ep, err := os.Executable()
if err != nil {
    log.Fatalln("os.Executable:", err)
}
err = os.Chdir(filepath.Join(filepath.Dir(ep), "..", "Resources"))
if err != nil {
    log.Fatalln("os.Chdir:", err)
}

// Load tray icon.
iconData, err := ioutil.ReadFile("icon@2x.png")
if err != nil {
    log.Fatalln(err)
}

trayhost.Initialize("Example App", iconData, menuItems)

trayhost.EnterLoop()

Index

Examples

Package Files

doc.go trayhost.go trayhost_exports.go trayhost_generic.go

func EnterLoop Uses

func EnterLoop()

EnterLoop enters main loop.

func Exit Uses

func Exit()

Exit exits the application. It can be called from a MenuItem handler.

func Initialize Uses

func Initialize(title string, imageData []byte, items []MenuItem)

Initialize sets up the application properties.

func SetClipboardText Uses

func SetClipboardText(text string)

SetClipboardText sets the system clipboard to the specified UTF-8 encoded string.

This function may only be called from the main thread.

func UpdateMenu Uses

func UpdateMenu(newMenu []MenuItem)

UpdateMenu removes all current menu items, and adds new menu items.

type ClipboardContent Uses

type ClipboardContent struct {
    Text  string
    Image Image
    Files []string
}

ClipboardContent holds the contents of system clipboard.

func GetClipboardContent Uses

func GetClipboardContent() (ClipboardContent, error)

GetClipboardContent returns the contents of the system clipboard, if it contains or is convertible to a UTF-8 encoded string, image, and/or files.

This function may only be called from the main thread.

type Image Uses

type Image struct {
    Kind  ImageKind
    Bytes []byte
}

Image is an encoded image of certain kind.

type ImageKind Uses

type ImageKind string

ImageKind is a file extension in lower case: "png", "jpg", "tiff", etc. Empty string means no image.

type MenuItem struct {
    // Title is the title of menu item.
    //
    // If empty, it acts as a separator. SeparatorMenuItem can be used
    // to create such separator menu items.
    Title string

    // Enabled can optionally control if this menu item is enabled or disabled.
    //
    // nil means always enabled.
    Enabled func() bool

    // Handler is triggered when the item is activated. nil means no handler.
    Handler func()
}

MenuItem is a menu item.

func SeparatorMenuItem Uses

func SeparatorMenuItem() MenuItem

SeparatorMenuItem creates a separator MenuItem.

type Notification Uses

type Notification struct {
    Title string // Title of user notification.
    Body  string // Body of user notification.
    Image Image  // Image shown in the content of user notification.

    // Timeout specifies time after which the notification is cleared.
    //
    // A Timeout of zero means no timeout.
    Timeout time.Duration

    // Activation (click) handler.
    //
    // nil means no handler.
    Handler func()
}

Notification represents a user notification.

func (Notification) Display Uses

func (n Notification) Display()

Display displays the user notification.

Package trayhost imports 9 packages (graph) and is imported by 2 packages. Updated 2017-02-20. Refresh now. Tools for package owners.