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,25 +79,28 @@ 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),
var name [8]uint16 uintptr(unsafe.Pointer(&opts)))
getClassName.Call(wnd, uintptr(unsafe.Pointer(&name)), uintptr(len(name)))
if syscall.UTF16ToString(name[:]) == "Button" {
ctl, _, _ := getDlgCtrlID.Call(wnd)
var text *string
switch ctl {
case 1, 6: // IDOK, IDYES
text = opts.okLabel
case 2: // IDCANCEL
text = opts.cancelLabel
case 7: // IDNO
text = opts.extraButton
}
if text != nil {
setWindowText.Call(wnd, strptr(*text))
}
}
return 1
}), 0)
}) })
} }
func hookMessageLabelsCallback(wnd uintptr, lparam *options) uintptr {
var name [8]uint16
getClassName.Call(wnd, uintptr(unsafe.Pointer(&name)), uintptr(len(name)))
if syscall.UTF16ToString(name[:]) == "Button" {
ctl, _, _ := getDlgCtrlID.Call(wnd)
var text *string
switch ctl {
case 1, 6: // IDOK, IDYES
text = lparam.okLabel
case 2: // IDCANCEL
text = lparam.cancelLabel
case 7: // IDNO
text = lparam.extraButton
}
if text != nil {
setWindowText.Call(wnd, strptr(*text))
}
}
return 1
}

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
}), 0)
if hwnd == 0 {
hwnd, _, _ = getConsoleWindow.Call()
} }
if hwnd != 0 { if wnd != 0 {
setForegroundWindow.Call(hwnd) setForegroundWindow.Call(wnd)
} }
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 {