Avoid closures in syscall.NewCallback, #20.

This commit is contained in:
Nuno Cruces 2021-09-13 13:17:15 +01:00
parent fca9f5c3ce
commit a806229364
4 changed files with 56 additions and 40 deletions

View file

@ -316,12 +316,7 @@ func browseForFolder(opts options) (string, []string, error) {
} }
if opts.filename != "" { if opts.filename != "" {
args.LParam = strptr(opts.filename) args.LParam = strptr(opts.filename)
args.CallbackFunc = syscall.NewCallback(func(wnd uintptr, msg uint32, lparam, data uintptr) uintptr { args.CallbackFunc = syscall.NewCallback(browseForFolderCallback)
if msg == 1 { // BFFM_INITIALIZED
sendMessage.Call(wnd, 1024+103 /* BFFM_SETSELECTIONW */, 1 /* TRUE */, data)
}
return 0
})
defer runtime.KeepAlive(opts.filename) defer runtime.KeepAlive(opts.filename)
} }
@ -349,6 +344,13 @@ func browseForFolder(opts options) (string, []string, error) {
return str, []string{str}, nil return str, []string{str}, nil
} }
func browseForFolderCallback(wnd uintptr, msg uint32, lparam, data uintptr) uintptr {
if msg == 1 { // BFFM_INITIALIZED
sendMessage.Call(wnd, 1024+103 /* BFFM_SETSELECTIONW */, 1 /* TRUE */, data)
}
return 0
}
func initDirNameExt(filename string, name []uint16) (dir *uint16, ext *uint16) { func initDirNameExt(filename string, name []uint16) (dir *uint16, ext *uint16) {
d, n := splitDirAndName(filename) d, n := splitDirAndName(filename)
e := filepath.Ext(n) e := filepath.Ext(n)

View file

@ -132,3 +132,12 @@ func TestMessage_script(t *testing.T) {
}) })
} }
} }
func TestMessage_callbacks(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel()
for i := 0; i < 2000; i++ {
zenity.Error("text", zenity.Context(ctx))
}
}

View file

@ -79,7 +79,12 @@ func message(kind messageKind, text string, opts options) error {
func hookMessageLabels(kind messageKind, opts options) (unhook context.CancelFunc, err error) { func hookMessageLabels(kind messageKind, opts options) (unhook context.CancelFunc, err error) {
return hookDialog(opts.ctx, func(wnd uintptr) { return hookDialog(opts.ctx, func(wnd uintptr) {
enumChildWindows.Call(wnd, enumChildWindows.Call(wnd,
syscall.NewCallback(func(wnd, lparam uintptr) uintptr { syscall.NewCallback(hookMessageLabelsCallback),
uintptr(unsafe.Pointer(&opts)))
})
}
func hookMessageLabelsCallback(wnd uintptr, lparam *options) uintptr {
var name [8]uint16 var name [8]uint16
getClassName.Call(wnd, uintptr(unsafe.Pointer(&name)), uintptr(len(name))) getClassName.Call(wnd, uintptr(unsafe.Pointer(&name)), uintptr(len(name)))
if syscall.UTF16ToString(name[:]) == "Button" { if syscall.UTF16ToString(name[:]) == "Button" {
@ -87,17 +92,15 @@ func hookMessageLabels(kind messageKind, opts options) (unhook context.CancelFun
var text *string var text *string
switch ctl { switch ctl {
case 1, 6: // IDOK, IDYES case 1, 6: // IDOK, IDYES
text = opts.okLabel text = lparam.okLabel
case 2: // IDCANCEL case 2: // IDCANCEL
text = opts.cancelLabel text = lparam.cancelLabel
case 7: // IDNO case 7: // IDNO
text = opts.extraButton text = lparam.extraButton
} }
if text != nil { if text != nil {
setWindowText.Call(wnd, strptr(*text)) setWindowText.Call(wnd, strptr(*text))
} }
} }
return 1 return 1
}), 0)
})
} }

View file

@ -90,21 +90,13 @@ func strptr(s string) uintptr {
} }
func setup() context.CancelFunc { func setup() context.CancelFunc {
var hwnd uintptr var wnd uintptr
enumWindows.Call(syscall.NewCallback(func(wnd, lparam uintptr) uintptr { enumWindows.Call(syscall.NewCallback(setupEnumCallback), uintptr(unsafe.Pointer(&wnd)))
var pid uintptr if wnd == 0 {
getWindowThreadProcessId.Call(wnd, uintptr(unsafe.Pointer(&pid))) wnd, _, _ = getConsoleWindow.Call()
if int(pid) == os.Getpid() {
hwnd = wnd
return 0
} }
return 1 if wnd != 0 {
}), 0) setForegroundWindow.Call(wnd)
if hwnd == 0 {
hwnd, _, _ = getConsoleWindow.Call()
}
if hwnd != 0 {
setForegroundWindow.Call(hwnd)
} }
runtime.LockOSThread() runtime.LockOSThread()
@ -140,6 +132,16 @@ func setup() context.CancelFunc {
} }
} }
func setupEnumCallback(wnd uintptr, lparam *uintptr) uintptr {
var pid uintptr
getWindowThreadProcessId.Call(wnd, uintptr(unsafe.Pointer(&pid)))
if int(pid) == os.Getpid() {
*lparam = wnd
return 0 // stop enumeration
}
return 1 // continue enumeration
}
func commDlgError() error { func commDlgError() error {
s, _, _ := commDlgExtendedError.Call() s, _, _ := commDlgExtendedError.Call()
if s == 0 { if s == 0 {