Parent window id (windows).
This commit is contained in:
parent
e6b85bb427
commit
6899d6b87c
21 changed files with 102 additions and 68 deletions
|
@ -41,7 +41,7 @@ func selectColor(opts options) (color.Color, error) {
|
|||
args.Flags |= win.CC_FULLOPEN
|
||||
}
|
||||
|
||||
defer setup()()
|
||||
defer setup(args.Owner)()
|
||||
unhook, err := hookDialog(opts.ctx, opts.windowIcon, opts.title, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -37,7 +37,8 @@ type calendarDialog struct {
|
|||
}
|
||||
|
||||
func (dlg *calendarDialog) setup(text string, opts options) (time.Time, error) {
|
||||
defer setup()()
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
defer setup(owner)()
|
||||
dlg.font = getFont()
|
||||
defer dlg.font.delete()
|
||||
icon := getIcon(opts.windowIcon)
|
||||
|
@ -58,7 +59,6 @@ func (dlg *calendarDialog) setup(text string, opts options) (time.Time, error) {
|
|||
}
|
||||
defer win.UnregisterClass(cls, instance)
|
||||
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
dlg.wnd, _ = win.CreateWindowEx(_WS_EX_ZEN_DIALOG,
|
||||
cls, strptr(*opts.title), _WS_ZEN_DIALOG,
|
||||
win.CW_USEDEFAULT, win.CW_USEDEFAULT,
|
||||
|
|
|
@ -36,7 +36,8 @@ type entryDialog struct {
|
|||
}
|
||||
|
||||
func (dlg *entryDialog) setup(text string, opts options) (string, error) {
|
||||
defer setup()()
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
defer setup(owner)()
|
||||
dlg.font = getFont()
|
||||
defer dlg.font.delete()
|
||||
icon := getIcon(opts.windowIcon)
|
||||
|
@ -57,7 +58,6 @@ func (dlg *entryDialog) setup(text string, opts options) (string, error) {
|
|||
}
|
||||
defer win.UnregisterClass(cls, instance)
|
||||
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
dlg.wnd, _ = win.CreateWindowEx(_WS_EX_ZEN_DIALOG,
|
||||
cls, strptr(*opts.title), _WS_ZEN_DIALOG,
|
||||
win.CW_USEDEFAULT, win.CW_USEDEFAULT,
|
||||
|
|
|
@ -36,7 +36,7 @@ func selectFile(opts options) (string, error) {
|
|||
args.MaxFile = uint32(len(res))
|
||||
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
|
||||
|
||||
defer setup()()
|
||||
defer setup(args.Owner)()
|
||||
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -79,7 +79,7 @@ func selectFileMultiple(opts options) ([]string, error) {
|
|||
args.MaxFile = uint32(len(res))
|
||||
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
|
||||
|
||||
defer setup()()
|
||||
defer setup(args.Owner)()
|
||||
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -153,7 +153,7 @@ func selectFileSave(opts options) (string, error) {
|
|||
args.MaxFile = uint32(len(res))
|
||||
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
|
||||
|
||||
defer setup()()
|
||||
defer setup(args.Owner)()
|
||||
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -171,7 +171,8 @@ func selectFileSave(opts options) (string, error) {
|
|||
}
|
||||
|
||||
func pickFolders(opts options, multi bool) (string, []string, error) {
|
||||
defer setup()()
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
defer setup(owner)()
|
||||
|
||||
err := win.CoInitializeEx(0, win.COINIT_APARTMENTTHREADED|win.COINIT_DISABLE_OLE1DDE)
|
||||
if err != win.RPC_E_CHANGED_MODE {
|
||||
|
@ -230,7 +231,6 @@ func pickFolders(opts options, multi bool) (string, []string, error) {
|
|||
defer unhook()
|
||||
}
|
||||
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
err = dialog.Show(owner)
|
||||
if opts.ctx != nil && opts.ctx.Err() != nil {
|
||||
return "", nil, opts.ctx.Err()
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
package win
|
||||
|
||||
const (
|
||||
// InitCommonControlsEx flags
|
||||
ICC_LISTVIEW_CLASSES = 0x00000001
|
||||
ICC_TREEVIEW_CLASSES = 0x00000002
|
||||
ICC_BAR_CLASSES = 0x00000004
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
// ChooseColor flags
|
||||
CC_RGBINIT = 0x00000001
|
||||
CC_FULLOPEN = 0x00000002
|
||||
CC_PREVENTFULLOPEN = 0x00000004
|
||||
|
|
|
@ -5,6 +5,7 @@ package win
|
|||
import "golang.org/x/sys/windows"
|
||||
|
||||
const (
|
||||
// CreateActCtx flags
|
||||
ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID = 0x001
|
||||
ACTCTX_FLAG_LANGID_VALID = 0x002
|
||||
ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID = 0x004
|
||||
|
@ -12,6 +13,13 @@ const (
|
|||
ACTCTX_FLAG_SET_PROCESS_DEFAULT = 0x010
|
||||
ACTCTX_FLAG_APPLICATION_NAME_VALID = 0x020
|
||||
ACTCTX_FLAG_HMODULE_VALID = 0x080
|
||||
|
||||
// Control signals
|
||||
CTRL_C_EVENT = 0
|
||||
CTRL_BREAK_EVENT = 1
|
||||
CTRL_CLOSE_EVENT = 2
|
||||
CTRL_LOGOFF_EVENT = 5
|
||||
CTRL_SHUTDOWN_EVENT = 6
|
||||
)
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-actctxw
|
||||
|
@ -33,6 +41,7 @@ func GetSystemDirectory() (string, error) { return windows.GetSystemDirectory()
|
|||
//sys ActivateActCtx(actCtx Handle, cookie *uintptr) (err error) = kernel32.ActivateActCtx
|
||||
//sys CreateActCtx(actCtx *ACTCTX) (ret Handle, err error) = kernel32.CreateActCtxW
|
||||
//sys DeactivateActCtx(flags uint32, cookie uintptr) (err error) = kernel32.DeactivateActCtx
|
||||
//sys GenerateConsoleCtrlEvent(ctrlEvent uint32, processGroupId int) (err error) = kernel32.GenerateConsoleCtrlEvent
|
||||
//sys GetConsoleWindow() (ret HWND) = kernel32.GetConsoleWindow
|
||||
//sys GetModuleHandle(moduleName *uint16) (ret Handle, err error) = kernel32.GetModuleHandleW
|
||||
//sys ReleaseActCtx(actCtx Handle) = kernel32.ReleaseActCtx
|
||||
|
|
|
@ -71,6 +71,7 @@ const (
|
|||
FOS_FORCEPREVIEWPANEON = 0x40000000
|
||||
FOS_SUPPORTSTREAMABLEITEMS = 0x80000000
|
||||
|
||||
// IShellItem.GetDisplayName forms
|
||||
SIGDN_NORMALDISPLAY = 0x00000000
|
||||
SIGDN_PARENTRELATIVEPARSING = ^(^0x18001 + 0x80000000)
|
||||
SIGDN_DESKTOPABSOLUTEPARSING = ^(^0x28000 + 0x80000000)
|
||||
|
|
|
@ -58,6 +58,7 @@ var (
|
|||
procActivateActCtx = modkernel32.NewProc("ActivateActCtx")
|
||||
procCreateActCtxW = modkernel32.NewProc("CreateActCtxW")
|
||||
procDeactivateActCtx = modkernel32.NewProc("DeactivateActCtx")
|
||||
procGenerateConsoleCtrlEvent = modkernel32.NewProc("GenerateConsoleCtrlEvent")
|
||||
procGetConsoleWindow = modkernel32.NewProc("GetConsoleWindow")
|
||||
procGetModuleHandleW = modkernel32.NewProc("GetModuleHandleW")
|
||||
procReleaseActCtx = modkernel32.NewProc("ReleaseActCtx")
|
||||
|
@ -179,6 +180,14 @@ func DeactivateActCtx(flags uint32, cookie uintptr) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func GenerateConsoleCtrlEvent(ctrlEvent uint32, processGroupId int) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procGenerateConsoleCtrlEvent.Addr(), 2, uintptr(ctrlEvent), uintptr(processGroupId), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetConsoleWindow() (ret HWND) {
|
||||
r0, _, _ := syscall.Syscall(procGetConsoleWindow.Addr(), 0, 0, 0, 0)
|
||||
ret = HWND(r0)
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
package zencmd
|
||||
|
||||
import "github.com/ncruces/zenity/internal/win"
|
||||
|
||||
// KillParent is internal.
|
||||
func KillParent() {}
|
||||
func KillParent() {
|
||||
win.GenerateConsoleCtrlEvent(win.CTRL_BREAK_EVENT, 0)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package zencmd
|
|||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/ncruces/zenity/internal/win"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
|
@ -13,6 +14,6 @@ func ParseWindowId(id string) windows.HWND {
|
|||
}
|
||||
|
||||
// GetParentWindowId is internal.
|
||||
func GetParentWindowId(pid int) int {
|
||||
return 0
|
||||
func GetParentWindowId(pid int) windows.HWND {
|
||||
return win.GetConsoleWindow()
|
||||
}
|
||||
|
|
|
@ -53,7 +53,8 @@ type listDialog struct {
|
|||
}
|
||||
|
||||
func (dlg *listDialog) setup(text string, opts options) ([]string, error) {
|
||||
defer setup()()
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
defer setup(owner)()
|
||||
dlg.font = getFont()
|
||||
defer dlg.font.delete()
|
||||
icon := getIcon(opts.windowIcon)
|
||||
|
@ -74,7 +75,6 @@ func (dlg *listDialog) setup(text string, opts options) ([]string, error) {
|
|||
}
|
||||
defer win.UnregisterClass(cls, instance)
|
||||
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
dlg.wnd, _ = win.CreateWindowEx(_WS_EX_ZEN_DIALOG,
|
||||
cls, strptr(*opts.title), _WS_ZEN_DIALOG,
|
||||
win.CW_USEDEFAULT, win.CW_USEDEFAULT,
|
||||
|
|
|
@ -52,7 +52,8 @@ func message(kind messageKind, text string, opts options) error {
|
|||
}
|
||||
}
|
||||
|
||||
defer setup()()
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
defer setup(owner)()
|
||||
unhook, err := hookMessageDialog(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -64,7 +65,6 @@ func message(kind messageKind, text string, opts options) error {
|
|||
title = strptr(*opts.title)
|
||||
}
|
||||
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
s, err := win.MessageBox(owner, strptr(text), title, flags)
|
||||
|
||||
if opts.ctx != nil && opts.ctx.Err() != nil {
|
||||
|
|
|
@ -116,7 +116,8 @@ func (dlg *progressDialog) setup(opts options) error {
|
|||
var once sync.Once
|
||||
defer once.Do(dlg.init.Done)
|
||||
|
||||
defer setup()()
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
defer setup(owner)()
|
||||
dlg.font = getFont()
|
||||
defer dlg.font.delete()
|
||||
icon := getIcon(opts.windowIcon)
|
||||
|
@ -137,7 +138,6 @@ func (dlg *progressDialog) setup(opts options) error {
|
|||
}
|
||||
defer win.UnregisterClass(cls, instance)
|
||||
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
dlg.wnd, _ = win.CreateWindowEx(_WS_EX_ZEN_DIALOG,
|
||||
cls, strptr(*opts.title), _WS_ZEN_DIALOG,
|
||||
win.CW_USEDEFAULT, win.CW_USEDEFAULT,
|
||||
|
|
|
@ -46,7 +46,8 @@ type passwordDialog struct {
|
|||
}
|
||||
|
||||
func (dlg *passwordDialog) setup(opts options) (string, string, error) {
|
||||
defer setup()()
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
defer setup(owner)()
|
||||
dlg.font = getFont()
|
||||
defer dlg.font.delete()
|
||||
icon := getIcon(opts.windowIcon)
|
||||
|
@ -67,7 +68,6 @@ func (dlg *passwordDialog) setup(opts options) (string, string, error) {
|
|||
}
|
||||
defer win.UnregisterClass(cls, instance)
|
||||
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
dlg.wnd, _ = win.CreateWindowEx(_WS_EX_ZEN_DIALOG,
|
||||
cls, strptr(*opts.title), _WS_ZEN_DIALOG,
|
||||
win.CW_USEDEFAULT, win.CW_USEDEFAULT,
|
||||
|
|
|
@ -5,7 +5,6 @@ package zenity
|
|||
import (
|
||||
"bytes"
|
||||
"os/exec"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -99,10 +98,6 @@ func pwdResult(sep string, opts options, out []byte, err error) (string, string,
|
|||
return "", str, err
|
||||
}
|
||||
|
||||
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) {
|
||||
if i := strings.Index(s, sep); i >= 0 {
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
@ -26,13 +25,10 @@ const (
|
|||
func intptr(i int64) uintptr { return uintptr(i) }
|
||||
func strptr(s string) *uint16 { return syscall.StringToUTF16Ptr(s) }
|
||||
|
||||
func hwnd(v reflect.Value) win.HWND {
|
||||
return win.HWND(uintptr(v.Uint()))
|
||||
}
|
||||
|
||||
func setup() context.CancelFunc {
|
||||
var wnd win.HWND
|
||||
func setup(wnd win.HWND) context.CancelFunc {
|
||||
if wnd == 0 {
|
||||
win.EnumWindows(syscall.NewCallback(setupEnumCallback), unsafe.Pointer(&wnd))
|
||||
}
|
||||
if wnd == 0 {
|
||||
wnd = win.GetConsoleWindow()
|
||||
}
|
||||
|
|
34
zenity.go
34
zenity.go
|
@ -13,8 +13,6 @@ package zenity
|
|||
import (
|
||||
"context"
|
||||
"image/color"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/ncruces/zenity/internal/zenutil"
|
||||
|
@ -191,38 +189,6 @@ func CustomIcon(path string) Option {
|
|||
return Icon(path)
|
||||
}
|
||||
|
||||
// Attach returns an Option to set the parent window to attach to.
|
||||
//
|
||||
// Attach accepts:
|
||||
// - a window id (int) on Unix
|
||||
// - a window handle (~uintptr) on Windows
|
||||
// - an application name (string) or process id (int) on macOS
|
||||
func Attach(id any) Option {
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
if v := reflect.ValueOf(id); v.Kind() == reflect.Uintptr {
|
||||
id = hwnd(v)
|
||||
} else {
|
||||
panic("interface conversion: expected uintptr")
|
||||
}
|
||||
|
||||
case "darwin":
|
||||
switch id.(type) {
|
||||
case int, string:
|
||||
default:
|
||||
panic("interface conversion: expected int or string")
|
||||
}
|
||||
|
||||
default:
|
||||
switch id.(type) {
|
||||
case int:
|
||||
default:
|
||||
panic("interface conversion: expected int")
|
||||
}
|
||||
}
|
||||
return funcOption(func(o *options) { o.attach = id })
|
||||
}
|
||||
|
||||
// Modal returns an Option to set the modal hint.
|
||||
func Modal() Option {
|
||||
return funcOption(func(o *options) { o.modal = true })
|
||||
|
|
16
zenity_darwin.go
Normal file
16
zenity_darwin.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package zenity
|
||||
|
||||
// Attach returns an Option to set the parent window to attach to.
|
||||
//
|
||||
// Attach accepts:
|
||||
// - a window id (int) on Unix
|
||||
// - a window handle (~uintptr) on Windows
|
||||
// - an application name (string) or process id (int) on macOS
|
||||
func Attach(id any) Option {
|
||||
switch id.(type) {
|
||||
case int, string:
|
||||
default:
|
||||
panic("interface conversion: expected int or string")
|
||||
}
|
||||
return funcOption(func(o *options) { o.attach = id })
|
||||
}
|
13
zenity_unix.go
Normal file
13
zenity_unix.go
Normal file
|
@ -0,0 +1,13 @@
|
|||
//go:build !windows && !darwin
|
||||
|
||||
package zenity
|
||||
|
||||
// Attach returns an Option to set the parent window to attach to.
|
||||
//
|
||||
// Attach accepts:
|
||||
// - a window id (int) on Unix
|
||||
// - a window handle (~uintptr) on Windows
|
||||
// - an application name (string) or process id (int) on macOS
|
||||
func Attach(id int) Option {
|
||||
return funcOption(func(o *options) { o.attach = id })
|
||||
}
|
22
zenity_windows.go
Normal file
22
zenity_windows.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package zenity
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/ncruces/zenity/internal/win"
|
||||
)
|
||||
|
||||
// Attach returns an Option to set the parent window to attach to.
|
||||
//
|
||||
// Attach accepts:
|
||||
// - a window id (int) on Unix
|
||||
// - a window handle (~uintptr) on Windows
|
||||
// - an application name (string) or process id (int) on macOS
|
||||
func Attach(id any) Option {
|
||||
if v := reflect.ValueOf(id); v.Kind() == reflect.Uintptr {
|
||||
id = win.HWND(uintptr(v.Uint()))
|
||||
} else {
|
||||
panic("interface conversion: expected uintptr")
|
||||
}
|
||||
return funcOption(func(o *options) { o.attach = id })
|
||||
}
|
Loading…
Reference in a new issue