Add Win32 binding for foreground window and minimize
This commit is contained in:
@@ -7,6 +7,7 @@ require (
|
|||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/jezek/xgb v1.3.1
|
github.com/jezek/xgb v1.3.1
|
||||||
github.com/jezek/xgbutil v0.0.0-20260124183602-9fd151d6a51a
|
github.com/jezek/xgbutil v0.0.0-20260124183602-9fd151d6a51a
|
||||||
|
golang.org/x/sys v0.41.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -36,7 +37,6 @@ require (
|
|||||||
golang.org/x/arch v0.22.0 // indirect
|
golang.org/x/arch v0.22.0 // indirect
|
||||||
golang.org/x/crypto v0.48.0 // indirect
|
golang.org/x/crypto v0.48.0 // indirect
|
||||||
golang.org/x/net v0.51.0 // indirect
|
golang.org/x/net v0.51.0 // indirect
|
||||||
golang.org/x/sys v0.41.0 // indirect
|
|
||||||
golang.org/x/text v0.34.0 // indirect
|
golang.org/x/text v0.34.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.10 // indirect
|
google.golang.org/protobuf v1.36.10 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package winapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
user32 = windows.NewLazySystemDLL("user32.dll")
|
||||||
|
procGetWindowTextW = user32.NewProc("GetWindowTextW")
|
||||||
|
procShowWindow = user32.NewProc("ShowWindow")
|
||||||
|
)
|
||||||
|
|
||||||
|
// ForegroundWindow returns the current foreground window's handle (as a uintptr
|
||||||
|
// so platform-neutral callers need not import windows), its title, and its
|
||||||
|
// on-task class (process exe base name; see ClassFromImagePath). ok is false
|
||||||
|
// when there is no foreground window (e.g. secure desktop / lock screen).
|
||||||
|
func ForegroundWindow() (hwnd uintptr, title, class string, ok bool) {
|
||||||
|
h := windows.GetForegroundWindow()
|
||||||
|
if h == 0 {
|
||||||
|
return 0, "", "", false
|
||||||
|
}
|
||||||
|
return uintptr(h), windowTitle(h), windowClass(h), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func windowTitle(h windows.HWND) string {
|
||||||
|
const max = 512
|
||||||
|
buf := make([]uint16, max)
|
||||||
|
n, _, _ := procGetWindowTextW.Call(
|
||||||
|
uintptr(h),
|
||||||
|
uintptr(unsafe.Pointer(&buf[0])),
|
||||||
|
uintptr(max),
|
||||||
|
)
|
||||||
|
return windows.UTF16ToString(buf[:n])
|
||||||
|
}
|
||||||
|
|
||||||
|
func windowClass(h windows.HWND) string {
|
||||||
|
var pid uint32
|
||||||
|
if _, err := windows.GetWindowThreadProcessId(h, &pid); err != nil || pid == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
proc, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, pid)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
defer windows.CloseHandle(proc)
|
||||||
|
|
||||||
|
buf := make([]uint16, windows.MAX_PATH)
|
||||||
|
size := uint32(len(buf))
|
||||||
|
if err := windows.QueryFullProcessImageName(proc, 0, &buf[0], &size); err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return ClassFromImagePath(windows.UTF16ToString(buf[:size]))
|
||||||
|
}
|
||||||
|
|
||||||
|
// MinimizeForeground minimizes the current foreground window. It returns nil
|
||||||
|
// when nothing is focused. ShowWindow's BOOL return reports prior visibility,
|
||||||
|
// not success, so there is nothing to error-check; minimize is best-effort by
|
||||||
|
// the Guard contract.
|
||||||
|
func MinimizeForeground() error {
|
||||||
|
h := windows.GetForegroundWindow()
|
||||||
|
if h == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
procShowWindow.Call(uintptr(h), uintptr(windows.SW_MINIMIZE))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user