diff --git a/component/power/event.go b/component/power/event.go new file mode 100644 index 000000000..f59c2ad43 --- /dev/null +++ b/component/power/event.go @@ -0,0 +1,22 @@ +package power + +type Type uint8 + +const ( + SUSPEND Type = iota + RESUME + RESUMEAUTOMATIC // Because the user is not present, most applications should do nothing. +) + +func (t Type) String() string { + switch t { + case SUSPEND: + return "SUSPEND" + case RESUME: + return "RESUME" + case RESUMEAUTOMATIC: + return "RESUMEAUTOMATIC" + default: + return "" + } +} diff --git a/component/power/event_other.go b/component/power/event_other.go new file mode 100644 index 000000000..3a41d9e02 --- /dev/null +++ b/component/power/event_other.go @@ -0,0 +1,9 @@ +//go:build !windows + +package power + +import "errors" + +func NewEventListener(cb func(Type)) (func(), error) { + return nil, errors.New("not support on this platform") +} diff --git a/component/power/event_windows.go b/component/power/event_windows.go new file mode 100644 index 000000000..126556952 --- /dev/null +++ b/component/power/event_windows.go @@ -0,0 +1,74 @@ +package power + +// modify from https://github.com/golang/go/blob/b634f6fdcbebee23b7da709a243f3db217b64776/src/runtime/os_windows.go#L257 + +import ( + "runtime" + "unsafe" + + "golang.org/x/sys/windows" +) + +var ( + libPowrProf = windows.NewLazySystemDLL("powrprof.dll") + powerRegisterSuspendResumeNotification = libPowrProf.NewProc("PowerRegisterSuspendResumeNotification") + powerUnregisterSuspendResumeNotification = libPowrProf.NewProc("PowerUnregisterSuspendResumeNotification") +) + +func NewEventListener(cb func(Type)) (func(), error) { + if err := powerRegisterSuspendResumeNotification.Find(); err != nil { + return nil, err // Running on Windows 7, where we don't need it anyway. + } + if err := powerUnregisterSuspendResumeNotification.Find(); err != nil { + return nil, err // Running on Windows 7, where we don't need it anyway. + } + + // Defines the type of event + const ( + PBT_APMSUSPEND uint32 = 4 + PBT_APMRESUMESUSPEND uint32 = 7 + PBT_APMRESUMEAUTOMATIC uint32 = 18 + ) + + const ( + _DEVICE_NOTIFY_CALLBACK = 2 + ) + type _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS struct { + callback uintptr + context uintptr + } + + var fn interface{} = func(context uintptr, changeType uint32, setting uintptr) uintptr { + switch changeType { + case PBT_APMSUSPEND: + cb(SUSPEND) + case PBT_APMRESUMESUSPEND: + cb(RESUME) + case PBT_APMRESUMEAUTOMATIC: + cb(RESUMEAUTOMATIC) + } + return 0 + } + + params := _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS{ + callback: windows.NewCallback(fn), + } + handle := uintptr(0) + + _, _, err := powerRegisterSuspendResumeNotification.Call( + _DEVICE_NOTIFY_CALLBACK, + uintptr(unsafe.Pointer(¶ms)), + uintptr(unsafe.Pointer(&handle)), + ) + if err != nil { + return nil, err + } + + return func() { + _, _, _ = powerUnregisterSuspendResumeNotification.Call( + uintptr(unsafe.Pointer(&handle)), + ) + runtime.KeepAlive(params) + runtime.KeepAlive(handle) + }, nil +}