diff options
| author | fffw | 2015-02-13 15:20:13 +0800 | 
|---|---|---|
| committer | fffw | 2015-02-13 15:20:13 +0800 | 
| commit | c00cfb38ee3aee8da409898fed17e80716095e89 (patch) | |
| tree | e6997d1ab53bfb8e1dfeafec7e239f8cfbc35838 /systray_windows.go | |
| parent | 85d3e528d5a1d1ef8b60dcafc901c633343b4a37 (diff) | |
| parent | 6a81309bde4a67b2d5d1cb57b2e89945ba63fde6 (diff) | |
| download | systray-issue-2143-lib.tar.bz2 | |
merge xcompileissue-2143-lib
Diffstat (limited to 'systray_windows.go')
| -rw-r--r-- | systray_windows.go | 151 | 
1 files changed, 151 insertions, 0 deletions
| diff --git a/systray_windows.go b/systray_windows.go new file mode 100644 index 0000000..9ae9520 --- /dev/null +++ b/systray_windows.go @@ -0,0 +1,151 @@ +package systray + +import ( +	"fmt" +	"io/ioutil" +	"os" +	"path" +	"syscall" +	"unsafe" + +	"github.com/getlantern/tarfs" +) + +var ( +	iconFiles = make([]*os.File, 0) +	dllDir    = path.Join(os.Getenv("APPDATA"), "systray") +	dllFile   = path.Join(dllDir, "systray.dll") + +	mod                      = syscall.NewLazyDLL(dllFile) +	_nativeLoop              = mod.NewProc("nativeLoop") +	_quit                    = mod.NewProc("quit") +	_setIcon                 = mod.NewProc("setIcon") +	_setTitle                = mod.NewProc("setTitle") +	_setTooltip              = mod.NewProc("setTooltip") +	_add_or_update_menu_item = mod.NewProc("add_or_update_menu_item") +) + +func init() { +	// Write DLL to file +	fs, err := tarfs.New(systraydll, "") +	if err != nil { +		panic(fmt.Errorf("Unable to open systray.dll: %v", err)) +	} + +	b, err := fs.Get("systray.dll") +	if err != nil { +		panic(fmt.Errorf("Unable to read systray.dll: %v", err)) +	} + +	err = os.MkdirAll(dllDir, 755) +	if err != nil { +		panic(fmt.Errorf("Unable to create directory %v to hold systray.dll: %v", dllDir, err)) +	} + +	err = ioutil.WriteFile(dllFile, b, 0644) +	if err != nil { +		panic(fmt.Errorf("Unable to save systray.dll to %v: %v", dllFile, err)) +	} +} + +func nativeLoop() { +	_nativeLoop.Call( +		syscall.NewCallback(systray_ready), +		syscall.NewCallback(systray_menu_item_selected)) +} + +func quit() { +	_quit.Call() +	for _, f := range iconFiles { +		err := os.Remove(f.Name()) +		if err != nil { +			log.Debugf("Unable to delete temporary icon file %v: %v", f.Name(), err) +		} +	} +} + +// SetIcon sets the systray icon. +// iconBytes should be the content of .ico for windows and .ico/.jpg/.png +// for other platforms. +func SetIcon(iconBytes []byte) { +	f, err := ioutil.TempFile("", "systray_temp_icon") +	if err != nil { +		log.Errorf("Unable to create temp icon: %v", err) +		return +	} +	defer f.Close() +	_, err = f.Write(iconBytes) +	if err != nil { +		log.Errorf("Unable to write icon to temp file %v: %v", f.Name(), f) +		return +	} +	f.Close() +	name, err := strPtr(f.Name()) +	if err != nil { +		log.Errorf("Unable to convert name to string pointer: %v", err) +		return +	} +	_setIcon.Call(name) +} + +// SetTitle sets the systray title, only available on Mac. +func SetTitle(title string) { +	// do nothing +} + +// SetTooltip sets the systray tooltip to display on mouse hover of the tray icon, +// only available on Mac and Windows. +func SetTooltip(tooltip string) { +	t, err := strPtr(tooltip) +	if err != nil { +		log.Errorf("Unable to convert tooltip to string pointer: %v", err) +		return +	} +	_setTooltip.Call(t) +} + +func addOrUpdateMenuItem(item *MenuItem) { +	var disabled = 0 +	if item.disabled { +		disabled = 1 +	} +	var checked = 0 +	if item.checked { +		checked = 1 +	} +	title, err := strPtr(item.title) +	if err != nil { +		log.Errorf("Unable to convert title to string pointer: %v", err) +		return +	} +	tooltip, err := strPtr(item.tooltip) +	if err != nil { +		log.Errorf("Unable to convert tooltip to string pointer: %v", err) +		return +	} +	_add_or_update_menu_item.Call( +		uintptr(item.id), +		title, +		tooltip, +		uintptr(disabled), +		uintptr(checked), +	) +} + +func strPtr(s string) (uintptr, error) { +	bp, err := syscall.BytePtrFromString(s) +	if err != nil { +		return 0, err +	} +	return uintptr(unsafe.Pointer(bp)), nil +} + +func systray_ready() uintptr { +	systrayReady() +	return 0 +} + +func systray_menu_item_selected(id uintptr) uintptr { +	systrayMenuItemSelected(int32(id)) +	return 0 +} | 
