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 != "" {
args.LParam = strptr(opts.filename)
args.CallbackFunc = syscall.NewCallback(func(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
})
args.CallbackFunc = syscall.NewCallback(browseForFolderCallback)
defer runtime.KeepAlive(opts.filename)
}
@ -349,6 +344,13 @@ func browseForFolder(opts options) (string, []string, error) {
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) {
d, n := splitDirAndName(filename)
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) {
return hookDialog(opts.ctx, func(wnd uintptr) {
enumChildWindows.Call(wnd,
syscall.NewCallback(func(wnd, lparam uintptr) 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 = 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)
syscall.NewCallback(hookMessageLabelsCallback),
uintptr(unsafe.Pointer(&opts)))
})
}
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 {
var hwnd uintptr
enumWindows.Call(syscall.NewCallback(func(wnd, lparam uintptr) uintptr {
var pid uintptr
getWindowThreadProcessId.Call(wnd, uintptr(unsafe.Pointer(&pid)))
if int(pid) == os.Getpid() {
hwnd = wnd
return 0
}
return 1
}), 0)
if hwnd == 0 {
hwnd, _, _ = getConsoleWindow.Call()
var wnd uintptr
enumWindows.Call(syscall.NewCallback(setupEnumCallback), uintptr(unsafe.Pointer(&wnd)))
if wnd == 0 {
wnd, _, _ = getConsoleWindow.Call()
}
if hwnd != 0 {
setForegroundWindow.Call(hwnd)
if wnd != 0 {
setForegroundWindow.Call(wnd)
}
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 {
s, _, _ := commDlgExtendedError.Call()
if s == 0 {