Refactor (windows).
This commit is contained in:
parent
113333268d
commit
6928e74895
9 changed files with 70 additions and 36 deletions
|
@ -274,7 +274,7 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error)
|
|||
}
|
||||
defer item.Call(item.Release)
|
||||
|
||||
var ptr unsafe.Pointer
|
||||
var ptr win.Pointer
|
||||
hr, _, _ = item.Call(item.GetDisplayName,
|
||||
_SIGDN_FILESYSPATH, uintptr(unsafe.Pointer(&ptr)))
|
||||
if int32(hr) < 0 {
|
||||
|
@ -337,7 +337,7 @@ func browseForFolder(opts options) (string, []string, error) {
|
|||
if opts.ctx != nil && opts.ctx.Err() != nil {
|
||||
return "", nil, opts.ctx.Err()
|
||||
}
|
||||
if ptr == nil {
|
||||
if ptr == nullptr {
|
||||
return "", nil, ErrCanceled
|
||||
}
|
||||
defer win.CoTaskMemFree(ptr)
|
||||
|
|
|
@ -31,8 +31,6 @@ func CoInitializeEx(reserved uintptr, coInit uint32) error {
|
|||
|
||||
func CoUninitialize() { windows.CoUninitialize() }
|
||||
|
||||
func CoTaskMemFree(address unsafe.Pointer) { windows.CoTaskMemFree(address) }
|
||||
|
||||
// https://github.com/wine-mirror/wine/blob/master/include/unknwn.idl
|
||||
|
||||
type IUnknownVtbl struct {
|
||||
|
@ -57,4 +55,5 @@ func (o *COMObject) Call(trap uintptr, a ...uintptr) (r1, r2 uintptr, lastErr er
|
|||
}
|
||||
}
|
||||
|
||||
//sys CoCreateInstance(clsid uintptr, unkOuter unsafe.Pointer, clsContext int32, iid uintptr, address unsafe.Pointer) (res error) = ole32.CoCreateInstance
|
||||
//sys CoCreateInstance(clsid uintptr, unkOuter *COMObject, clsContext int32, iid uintptr, address unsafe.Pointer) (res error) = ole32.CoCreateInstance
|
||||
//sys CoTaskMemFree(address Pointer) = ole32.CoTaskMemFree
|
||||
|
|
|
@ -57,7 +57,7 @@ type _IShellItemVtbl struct {
|
|||
Compare uintptr
|
||||
}
|
||||
|
||||
//sys SHBrowseForFolder(bi *BROWSEINFO) (ret unsafe.Pointer) = shell32.SHBrowseForFolder
|
||||
//sys SHCreateItemFromParsingName(path *uint16, bc unsafe.Pointer, iid uintptr, item **IShellItem) (res error) = shell32.SHCreateItemFromParsingName
|
||||
//sys SHBrowseForFolder(bi *BROWSEINFO) (ret Pointer) = shell32.SHBrowseForFolder
|
||||
//sys SHCreateItemFromParsingName(path *uint16, bc *COMObject, iid uintptr, item **IShellItem) (res error) = shell32.SHCreateItemFromParsingName
|
||||
//sys ShellNotifyIcon(message uint32, data *NOTIFYICONDATA) (ret int, err error) = shell32.Shell_NotifyIconW
|
||||
//sys SHGetPathFromIDListEx(ptr unsafe.Pointer, path *uint16, pathLen int, opts int) (ok bool) = shell32.SHGetPathFromIDListEx
|
||||
//sys SHGetPathFromIDListEx(ptr Pointer, path *uint16, pathLen int, opts int) (ok bool) = shell32.SHGetPathFromIDListEx
|
||||
|
|
|
@ -214,6 +214,9 @@ const (
|
|||
SC_MONITORPOWER = 0xf170
|
||||
SC_CONTEXTHELP = 0xf180
|
||||
|
||||
// SetWindowsHookEx types
|
||||
WH_CALLWNDPROCRET = 12
|
||||
|
||||
USER_DEFAULT_SCREEN_DPI = 96
|
||||
|
||||
DPI_AWARENESS_CONTEXT_UNAWARE = ^uintptr(1) + 1
|
||||
|
@ -350,12 +353,13 @@ type NONCLIENTMETRICS struct {
|
|||
MessageFont LOGFONT
|
||||
}
|
||||
|
||||
//sys CallNextHookEx(hk Handle, code int32, wparam uintptr, lparam unsafe.Pointer) (ret uintptr) = user32.CallNextHookEx
|
||||
//sys CreateIconFromResource(resBits []byte, icon bool, ver uint32) (ret Handle, err error) = user32.CreateIconFromResource
|
||||
//sys CreateWindowEx(exStyle uint32, className *uint16, windowName *uint16, style uint32, x int, y int, width int, height int, parent HWND, menu Handle, instance Handle, param unsafe.Pointer) (ret HWND, err error) = user32.CreateWindowExW
|
||||
//sys DefWindowProc(wnd HWND, msg uint32, wparam uintptr, lparam unsafe.Pointer) (ret uintptr) = user32.DefWindowProcW
|
||||
//sys DestroyIcon(icon Handle) (err error) = user32.DestroyIcon
|
||||
//sys DestroyWindow(wnd HWND) (err error) = user32.DestroyWindow
|
||||
//sys DispatchMessage(msg *MSG) (ret uintptr) = user32.DispatchMessageW
|
||||
//sys DefWindowProc(wnd HWND, msg uint32, wparam uintptr, lparam unsafe.Pointer) (ret uintptr) = user32.DefWindowProcW
|
||||
//sys EnableWindow(wnd HWND, enable bool) (ok bool) = user32.EnableWindow
|
||||
//sys EnumChildWindows(parent HWND, enumFunc uintptr, lparam unsafe.Pointer) = user32.EnumChildWindows
|
||||
//sys EnumWindows(enumFunc uintptr, lparam unsafe.Pointer) (err error) = user32.EnumChildWindows
|
||||
|
@ -379,8 +383,10 @@ type NONCLIENTMETRICS struct {
|
|||
//sys setThreadDpiAwarenessContext(dpiContext uintptr) (ret uintptr) = user32.SetThreadDpiAwarenessContext
|
||||
//sys SetWindowLong(wnd HWND, index int, newLong int) (ret int, err error) = user32.SetWindowLongW
|
||||
//sys SetWindowPos(wnd HWND, wndInsertAfter HWND, x int, y int, cx int, cy int, flags int) (err error) = user32.SetWindowPos
|
||||
//sys SetWindowsHookEx(idHook int, fn uintptr, mod Handle, threadID uint32) (ret Handle, err error) = user32.SetWindowsHookExW
|
||||
//sys SetWindowText(wnd HWND, text *uint16) (err error) = user32.SetWindowTextW
|
||||
//sys ShowWindow(wnd HWND, cmdShow int) (ok bool) = user32.ShowWindow
|
||||
//sys SystemParametersInfo(action int, uiParam uintptr, pvParam unsafe.Pointer, winIni int) (err error) = user32.SystemParametersInfoW
|
||||
//sys TranslateMessage(msg *MSG) (ok bool) = user32.TranslateMessage
|
||||
//sys UnhookWindowsHookEx(hk Handle) (err error) = user32.UnhookWindowsHookEx
|
||||
//sys UnregisterClass(className *uint16, instance Handle) (err error) = user32.UnregisterClassW
|
||||
|
|
|
@ -7,7 +7,7 @@ import "golang.org/x/sys/windows"
|
|||
|
||||
type Handle = windows.Handle
|
||||
type HWND = windows.HWND
|
||||
type Pointer = windows.Pointer
|
||||
type Pointer uintptr
|
||||
|
||||
func RtlGetNtVersionNumbers() (majorVersion, minorVersion, buildNumber uint32) {
|
||||
return windows.RtlGetNtVersionNumbers()
|
||||
|
|
|
@ -62,10 +62,12 @@ var (
|
|||
procGetModuleHandleW = modkernel32.NewProc("GetModuleHandleW")
|
||||
procReleaseActCtx = modkernel32.NewProc("ReleaseActCtx")
|
||||
procCoCreateInstance = modole32.NewProc("CoCreateInstance")
|
||||
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
||||
procSHBrowseForFolder = modshell32.NewProc("SHBrowseForFolder")
|
||||
procSHCreateItemFromParsingName = modshell32.NewProc("SHCreateItemFromParsingName")
|
||||
procSHGetPathFromIDListEx = modshell32.NewProc("SHGetPathFromIDListEx")
|
||||
procShell_NotifyIconW = modshell32.NewProc("Shell_NotifyIconW")
|
||||
procCallNextHookEx = moduser32.NewProc("CallNextHookEx")
|
||||
procCreateIconFromResource = moduser32.NewProc("CreateIconFromResource")
|
||||
procCreateWindowExW = moduser32.NewProc("CreateWindowExW")
|
||||
procDefWindowProcW = moduser32.NewProc("DefWindowProcW")
|
||||
|
@ -95,9 +97,11 @@ var (
|
|||
procSetWindowLongW = moduser32.NewProc("SetWindowLongW")
|
||||
procSetWindowPos = moduser32.NewProc("SetWindowPos")
|
||||
procSetWindowTextW = moduser32.NewProc("SetWindowTextW")
|
||||
procSetWindowsHookExW = moduser32.NewProc("SetWindowsHookExW")
|
||||
procShowWindow = moduser32.NewProc("ShowWindow")
|
||||
procSystemParametersInfoW = moduser32.NewProc("SystemParametersInfoW")
|
||||
procTranslateMessage = moduser32.NewProc("TranslateMessage")
|
||||
procUnhookWindowsHookEx = moduser32.NewProc("UnhookWindowsHookEx")
|
||||
procUnregisterClassW = moduser32.NewProc("UnregisterClassW")
|
||||
procWTSSendMessageW = modwtsapi32.NewProc("WTSSendMessageW")
|
||||
)
|
||||
|
@ -195,29 +199,34 @@ func ReleaseActCtx(actCtx Handle) {
|
|||
return
|
||||
}
|
||||
|
||||
func CoCreateInstance(clsid uintptr, unkOuter unsafe.Pointer, clsContext int32, iid uintptr, address unsafe.Pointer) (res error) {
|
||||
r0, _, _ := syscall.Syscall6(procCoCreateInstance.Addr(), 5, uintptr(clsid), uintptr(unkOuter), uintptr(clsContext), uintptr(iid), uintptr(address), 0)
|
||||
func CoCreateInstance(clsid uintptr, unkOuter *COMObject, clsContext int32, iid uintptr, address unsafe.Pointer) (res error) {
|
||||
r0, _, _ := syscall.Syscall6(procCoCreateInstance.Addr(), 5, uintptr(clsid), uintptr(unsafe.Pointer(unkOuter)), uintptr(clsContext), uintptr(iid), uintptr(address), 0)
|
||||
if r0 != 0 {
|
||||
res = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func SHBrowseForFolder(bi *BROWSEINFO) (ret unsafe.Pointer) {
|
||||
func CoTaskMemFree(address Pointer) {
|
||||
syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(address), 0, 0)
|
||||
return
|
||||
}
|
||||
|
||||
func SHBrowseForFolder(bi *BROWSEINFO) (ret Pointer) {
|
||||
r0, _, _ := syscall.Syscall(procSHBrowseForFolder.Addr(), 1, uintptr(unsafe.Pointer(bi)), 0, 0)
|
||||
ret = unsafe.Pointer(r0)
|
||||
ret = Pointer(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func SHCreateItemFromParsingName(path *uint16, bc unsafe.Pointer, iid uintptr, item **IShellItem) (res error) {
|
||||
r0, _, _ := syscall.Syscall6(procSHCreateItemFromParsingName.Addr(), 4, uintptr(unsafe.Pointer(path)), uintptr(bc), uintptr(iid), uintptr(unsafe.Pointer(item)), 0, 0)
|
||||
func SHCreateItemFromParsingName(path *uint16, bc *COMObject, iid uintptr, item **IShellItem) (res error) {
|
||||
r0, _, _ := syscall.Syscall6(procSHCreateItemFromParsingName.Addr(), 4, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(bc)), uintptr(iid), uintptr(unsafe.Pointer(item)), 0, 0)
|
||||
if r0 != 0 {
|
||||
res = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func SHGetPathFromIDListEx(ptr unsafe.Pointer, path *uint16, pathLen int, opts int) (ok bool) {
|
||||
func SHGetPathFromIDListEx(ptr Pointer, path *uint16, pathLen int, opts int) (ok bool) {
|
||||
r0, _, _ := syscall.Syscall6(procSHGetPathFromIDListEx.Addr(), 4, uintptr(ptr), uintptr(unsafe.Pointer(path)), uintptr(pathLen), uintptr(opts), 0, 0)
|
||||
ok = r0 != 0
|
||||
return
|
||||
|
@ -232,6 +241,12 @@ func ShellNotifyIcon(message uint32, data *NOTIFYICONDATA) (ret int, err error)
|
|||
return
|
||||
}
|
||||
|
||||
func CallNextHookEx(hk Handle, code int32, wparam uintptr, lparam unsafe.Pointer) (ret uintptr) {
|
||||
r0, _, _ := syscall.Syscall6(procCallNextHookEx.Addr(), 4, uintptr(hk), uintptr(code), uintptr(wparam), uintptr(lparam), 0, 0)
|
||||
ret = uintptr(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func CreateIconFromResource(resBits []byte, icon bool, ver uint32) (ret Handle, err error) {
|
||||
var _p0 *byte
|
||||
if len(resBits) > 0 {
|
||||
|
@ -460,6 +475,15 @@ func SetWindowText(wnd HWND, text *uint16) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func SetWindowsHookEx(idHook int, fn uintptr, mod Handle, threadID uint32) (ret Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall6(procSetWindowsHookExW.Addr(), 4, uintptr(idHook), uintptr(fn), uintptr(mod), uintptr(threadID), 0, 0)
|
||||
ret = Handle(r0)
|
||||
if ret == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ShowWindow(wnd HWND, cmdShow int) (ok bool) {
|
||||
r0, _, _ := syscall.Syscall(procShowWindow.Addr(), 2, uintptr(wnd), uintptr(cmdShow), 0)
|
||||
ok = r0 != 0
|
||||
|
@ -480,6 +504,14 @@ func TranslateMessage(msg *MSG) (ok bool) {
|
|||
return
|
||||
}
|
||||
|
||||
func UnhookWindowsHookEx(hk Handle) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procUnhookWindowsHookEx.Addr(), 1, uintptr(hk), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func UnregisterClass(className *uint16, instance Handle) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procUnregisterClassW.Addr(), 2, uintptr(unsafe.Pointer(className)), uintptr(instance), 0)
|
||||
if r1 == 0 {
|
||||
|
|
|
@ -5,6 +5,7 @@ package zenity
|
|||
import (
|
||||
"bytes"
|
||||
"os/exec"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -98,7 +99,9 @@ func pwdResult(sep string, opts options, out []byte, err error) (string, string,
|
|||
return "", str, err
|
||||
}
|
||||
|
||||
func hwnd(i uint64) uintptr { return uintptr(i) }
|
||||
func hwnd(v reflect.Value) uintptr {
|
||||
return uintptr(v.Uint())
|
||||
}
|
||||
|
||||
// Replace with strings.Cut after 1.18.
|
||||
func cut(s, sep string) (before, after string, found bool) {
|
||||
|
|
|
@ -13,15 +13,6 @@ import (
|
|||
"unsafe"
|
||||
|
||||
"github.com/ncruces/zenity/internal/win"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var (
|
||||
user32 = windows.NewLazySystemDLL("user32.dll")
|
||||
|
||||
callNextHookEx = user32.NewProc("CallNextHookEx")
|
||||
setWindowsHookEx = user32.NewProc("SetWindowsHookExW")
|
||||
unhookWindowsHookEx = user32.NewProc("UnhookWindowsHookEx")
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -32,9 +23,14 @@ const (
|
|||
_WS_ZEN_BUTTON = _WS_ZEN_CONTROL
|
||||
)
|
||||
|
||||
const nullptr win.Pointer = 0
|
||||
|
||||
func intptr(i int64) uintptr { return uintptr(i) }
|
||||
func strptr(s string) *uint16 { return syscall.StringToUTF16Ptr(s) }
|
||||
func hwnd(i uint64) win.HWND { return win.HWND(uintptr(i)) }
|
||||
|
||||
func hwnd(v reflect.Value) win.HWND {
|
||||
return win.HWND(uintptr(v.Uint()))
|
||||
}
|
||||
|
||||
func setup() context.CancelFunc {
|
||||
var wnd win.HWND
|
||||
|
@ -99,7 +95,7 @@ type dialogHook struct {
|
|||
ctx context.Context
|
||||
tid uint32
|
||||
wnd uintptr
|
||||
hook uintptr
|
||||
hook win.Handle
|
||||
done chan struct{}
|
||||
icon any
|
||||
title *string
|
||||
|
@ -108,8 +104,8 @@ type dialogHook struct {
|
|||
|
||||
func newDialogHook(ctx context.Context, icon any, title *string, init func(wnd win.HWND)) (*dialogHook, error) {
|
||||
tid := win.GetCurrentThreadId()
|
||||
hk, _, err := setWindowsHookEx.Call(12, // WH_CALLWNDPROCRET
|
||||
syscall.NewCallback(dialogHookProc), 0, uintptr(tid))
|
||||
hk, err := win.SetWindowsHookEx(win.WH_CALLWNDPROCRET,
|
||||
syscall.NewCallback(dialogHookProc), 0, tid)
|
||||
if hk == 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -154,9 +150,7 @@ func dialogHookProc(code int32, wparam uintptr, lparam *_CWPRETSTRUCT) uintptr {
|
|||
}
|
||||
}
|
||||
}
|
||||
next, _, _ := callNextHookEx.Call(
|
||||
0, uintptr(code), wparam, uintptr(unsafe.Pointer(lparam)))
|
||||
return next
|
||||
return win.CallNextHookEx(0, code, wparam, unsafe.Pointer(lparam))
|
||||
}
|
||||
|
||||
func (h *dialogHook) unhook() {
|
||||
|
@ -164,7 +158,7 @@ func (h *dialogHook) unhook() {
|
|||
if h.done != nil {
|
||||
close(h.done)
|
||||
}
|
||||
unhookWindowsHookEx.Call(h.hook)
|
||||
win.UnhookWindowsHookEx(h.hook)
|
||||
}
|
||||
|
||||
func (h *dialogHook) wait() {
|
||||
|
|
|
@ -201,7 +201,7 @@ func Attach(id any) Option {
|
|||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
if v := reflect.ValueOf(id); v.Kind() == reflect.Uintptr {
|
||||
id = hwnd(v.Uint())
|
||||
id = hwnd(v)
|
||||
} else {
|
||||
panic("interface conversion: expected uintptr")
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue