Avoid closures in syscall.NewCallback, #20.
This commit is contained in:
parent
fca9f5c3ce
commit
a806229364
4 changed files with 56 additions and 40 deletions
|
@ -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)
|
||||||
|
|
|
@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue