110 lines
2.4 KiB
Go
110 lines
2.4 KiB
Go
package zenity
|
|
|
|
import (
|
|
"math/rand"
|
|
"runtime"
|
|
"syscall"
|
|
"time"
|
|
"unsafe"
|
|
|
|
"github.com/ncruces/zenity/internal/win"
|
|
"github.com/ncruces/zenity/internal/zenutil"
|
|
)
|
|
|
|
func notify(text string, opts options) error {
|
|
if opts.ctx != nil && opts.ctx.Err() != nil {
|
|
return opts.ctx.Err()
|
|
}
|
|
|
|
var args win.NOTIFYICONDATA
|
|
args.StructSize = uint32(unsafe.Sizeof(args))
|
|
args.ID = rand.Uint32()
|
|
args.Flags = 0x00000010 // NIF_INFO
|
|
args.State = 0x00000001 // NIS_HIDDEN
|
|
|
|
info := syscall.StringToUTF16(text)
|
|
copy(args.Info[:len(args.Info)-1], info)
|
|
|
|
if opts.title != nil {
|
|
title := syscall.StringToUTF16(*opts.title)
|
|
copy(args.InfoTitle[:len(args.InfoTitle)-1], title)
|
|
}
|
|
|
|
switch opts.icon {
|
|
case InfoIcon, QuestionIcon:
|
|
args.InfoFlags |= 0x1 // NIIF_INFO
|
|
case WarningIcon:
|
|
args.InfoFlags |= 0x2 // NIIF_WARNING
|
|
case ErrorIcon:
|
|
args.InfoFlags |= 0x3 // NIIF_ERROR
|
|
default:
|
|
icon := getIcon(opts.icon)
|
|
if icon.handle != 0 {
|
|
defer icon.delete()
|
|
args.Icon = win.Handle(icon.handle)
|
|
args.Flags |= 0x00000002 // NIF_ICON
|
|
args.InfoFlags |= 0x4 // NIIF_USER
|
|
}
|
|
}
|
|
|
|
runtime.LockOSThread()
|
|
defer runtime.UnlockOSThread()
|
|
|
|
s, err := win.ShellNotifyIcon(win.NIM_ADD, &args)
|
|
if s == 0 {
|
|
if errno, ok := err.(syscall.Errno); ok && errno == 0 {
|
|
return wtsMessage(text, opts)
|
|
}
|
|
return err
|
|
}
|
|
|
|
major, minor, _ := win.RtlGetNtVersionNumbers()
|
|
// On Windows 7 (6.1) and lower, wait up to 10 seconds to clean up.
|
|
if major < 6 || major == 6 && minor < 2 {
|
|
if opts.ctx != nil {
|
|
select {
|
|
case <-opts.ctx.Done():
|
|
case <-time.After(10 * time.Second):
|
|
}
|
|
} else {
|
|
time.Sleep(10 * time.Second)
|
|
}
|
|
}
|
|
|
|
win.ShellNotifyIcon(win.NIM_DELETE, &args)
|
|
return nil
|
|
}
|
|
|
|
func wtsMessage(text string, opts options) error {
|
|
var flags uint32
|
|
|
|
switch opts.icon {
|
|
case ErrorIcon:
|
|
flags |= win.MB_ICONERROR
|
|
case QuestionIcon:
|
|
flags |= win.MB_ICONQUESTION
|
|
case WarningIcon:
|
|
flags |= win.MB_ICONWARNING
|
|
case InfoIcon:
|
|
flags |= win.MB_ICONINFORMATION
|
|
}
|
|
|
|
title := opts.title
|
|
if title == nil {
|
|
title = stringPtr("Notification")
|
|
}
|
|
|
|
timeout := zenutil.Timeout
|
|
if timeout == 0 {
|
|
timeout = 10
|
|
}
|
|
|
|
ptext := syscall.StringToUTF16(text)
|
|
ptitle := syscall.StringToUTF16(*title)
|
|
|
|
var res uint32
|
|
return win.WTSSendMessage(
|
|
win.WTS_CURRENT_SERVER_HANDLE, win.WTS_CURRENT_SESSION,
|
|
&ptitle[0], 2*len(ptitle), &ptext[0], 2*len(ptext),
|
|
flags, timeout, &res, false)
|
|
}
|