diff --git a/cmd/zenity/main.go b/cmd/zenity/main.go index 8008832..774343c 100644 --- a/cmd/zenity/main.go +++ b/cmd/zenity/main.go @@ -15,6 +15,7 @@ import ( "path/filepath" "runtime" "runtime/debug" + "strconv" "strings" "syscall" "time" @@ -51,6 +52,7 @@ var ( text string icon string windowIcon string + attach string multiple bool defaultCancel bool @@ -209,6 +211,8 @@ func setupFlags() { flag.Func("extra-button", "Add an extra `button`", setExtraButton) flag.StringVar(&text, "text", "", "Set the dialog `text`") flag.StringVar(&windowIcon, "window-icon", "", "Set the window `icon` (error, info, question, warning)") + flag.StringVar(&attach, "attach", "", "Set the parent `window` to attach to") + flag.Bool("modal", true, "Set the modal hint") flag.BoolVar(&multiple, "multiple", false, "Allow multiple items to be selected") flag.BoolVar(&defaultCancel, "default-cancel", false, "Give Cancel button focus by default") @@ -443,6 +447,14 @@ func loadFlags() []zenity.Option { opts = append(opts, zenity.WindowIcon(ingestPath(windowIcon))) } + if attach != "" { + if i, err := strconv.ParseUint(attach, 0, 64); err != nil { + opts = append(opts, zenity.Attach(attach)) + } else { + opts = append(opts, zenity.Attach(i)) + } + } + // Message options if noWrap { diff --git a/color_darwin.go b/color_darwin.go index a63e856..810d2d1 100644 --- a/color_darwin.go +++ b/color_darwin.go @@ -8,7 +8,9 @@ import ( func selectColor(opts options) (color.Color, error) { var data zenutil.Color - if i, ok := opts.windowIcon.(string); ok { + if opts.attach != nil { + data.Application = opts.attach + } else if i, ok := opts.windowIcon.(string); ok { data.WindowIcon = i } diff --git a/entry_darwin.go b/entry_darwin.go index 53a69a8..5d4dddd 100644 --- a/entry_darwin.go +++ b/entry_darwin.go @@ -14,7 +14,9 @@ func entry(text string, opts options) (string, error) { data.Options.Answer = &opts.entryText data.Options.Hidden = opts.hideText data.Options.Timeout = zenutil.Timeout - if i, ok := opts.windowIcon.(string); ok { + if opts.attach != nil { + data.Application = opts.attach + } else if i, ok := opts.windowIcon.(string); ok { data.WindowIcon = i } switch i := opts.icon.(type) { diff --git a/file_darwin.go b/file_darwin.go index 62a2cbb..e8d5c64 100644 --- a/file_darwin.go +++ b/file_darwin.go @@ -7,7 +7,9 @@ func selectFile(opts options) (string, error) { data.Options.Prompt = opts.title data.Options.Invisibles = opts.showHidden data.Options.Location, _ = splitDirAndName(opts.filename) - if i, ok := opts.windowIcon.(string); ok { + if opts.attach != nil { + data.Application = opts.attach + } else if i, ok := opts.windowIcon.(string); ok { data.WindowIcon = i } @@ -29,7 +31,9 @@ func selectFileMultiple(opts options) ([]string, error) { data.Options.Location, _ = splitDirAndName(opts.filename) data.Options.Multiple = true data.Separator = zenutil.Separator - if i, ok := opts.windowIcon.(string); ok { + if opts.attach != nil { + data.Application = opts.attach + } else if i, ok := opts.windowIcon.(string); ok { data.WindowIcon = i } @@ -49,7 +53,9 @@ func selectFileSave(opts options) (string, error) { data.Options.Prompt = opts.title data.Options.Invisibles = opts.showHidden data.Options.Location, data.Options.Name = splitDirAndName(opts.filename) - if i, ok := opts.windowIcon.(string); ok { + if opts.attach != nil { + data.Application = opts.attach + } else if i, ok := opts.windowIcon.(string); ok { data.WindowIcon = i } diff --git a/go.mod b/go.mod index 6440e03..357a5e5 100644 --- a/go.mod +++ b/go.mod @@ -8,8 +8,8 @@ require ( github.com/ncruces/go-strftime v0.1.8 github.com/randall77/makefat v0.0.0-20210315173500-7ddd0e42c844 go.uber.org/goleak v1.1.12 // test - golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 - golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba + golang.org/x/image v0.0.0-20220601225756-64ec528b34cd + golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a ) require ( diff --git a/go.sum b/go.sum index 9ab6230..1a948ca 100644 --- a/go.sum +++ b/go.sum @@ -24,8 +24,8 @@ go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 h1:LRtI4W37N+KFebI/qV0OFiLUv4GLOWeEW5hn/KEJvxE= -golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20220601225756-64ec528b34cd h1:9NbNcTg//wfC5JskFW4Z3sqwVnjmJKHxLAol1bW2qgw= +golang.org/x/image v0.0.0-20220601225756-64ec528b34cd/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= @@ -42,12 +42,12 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba h1:AyHWHCBVlIYI5rgEM3o+1PLd0sLPcIAoaUckGQMaWtw= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= diff --git a/internal/zenutil/env.go b/internal/zenutil/env.go index 4242b67..ecb8288 100644 --- a/internal/zenutil/env.go +++ b/internal/zenutil/env.go @@ -20,6 +20,9 @@ var ( DateParse = func(s string) (time.Time, error) { return time.Parse("2006-01-02", s) } ) +// Remove after 1.18. +type any = interface{} + type stringErr string func (e stringErr) Error() string { return string(e) } diff --git a/internal/zenutil/osa_generated.go b/internal/zenutil/osa_generated.go index 705847a..d7b5c4f 100644 --- a/internal/zenutil/osa_generated.go +++ b/internal/zenutil/osa_generated.go @@ -8,7 +8,7 @@ import ( "text/template" ) -var scripts = template.Must(template.New("").Funcs(template.FuncMap{"json": func(v interface{}) (string, error) { +var scripts = template.Must(template.New("").Funcs(template.FuncMap{"json": func(v any) (string, error) { b, err := json.Marshal(v) return string(b), err }}).Parse(` @@ -22,16 +22,18 @@ $.exit(-1)} {'rgb('+res.map(x=>Math.round(x*255))+')'} {{- end}} {{define "common" -}} -{var app=Application.currentApplication() -app.includeStandardAdditions=true -{{- if .WindowIcon}} -ObjC.import('Cocoa') +{{- if .Application}} +var app=Application({{json .Application}}) +{{- else}} +var app=Application.currentApplication() +{{- end}} +{{- if .WindowIcon}}{ObjC.import('Cocoa') let nsapp=$.NSApplication.sharedApplication let nsimg=$.NSImage.alloc.initWithContentsOfFile({{json .WindowIcon}}) nsapp.setActivationPolicy($.NSApplicationActivationPolicyRegular) -nsapp.setApplicationIconImage(nsimg) -{{- end}} -app.activate()} +nsapp.setApplicationIconImage(nsimg)}{{- end}} +app.includeStandardAdditions=true +app.activate() {{- end}} {{define "date" -}} ObjC.import('Cocoa') diff --git a/internal/zenutil/osa_generator.go b/internal/zenutil/osa_generator.go index 5d7decb..b8c11bf 100644 --- a/internal/zenutil/osa_generator.go +++ b/internal/zenutil/osa_generator.go @@ -111,7 +111,7 @@ import ( "text/template" ) -var scripts = template.Must(template.New("").Funcs(template.FuncMap{"json": func(v interface{}) (string, error) { +var scripts = template.Must(template.New("").Funcs(template.FuncMap{"json": func(v any) (string, error) { b, err := json.Marshal(v) return string(b), err }}).Parse(` + "`{{.}}`))\n")) diff --git a/internal/zenutil/osascripts/common.gojs b/internal/zenutil/osascripts/common.gojs index 2aa9e84..08928e8 100644 --- a/internal/zenutil/osascripts/common.gojs +++ b/internal/zenutil/osascripts/common.gojs @@ -1,14 +1,16 @@ -{ +{{- if .Application}} + var app = Application({{json .Application}}) +{{- else}} var app = Application.currentApplication() - app.includeStandardAdditions = true +{{- end}} - {{- if .WindowIcon}} - ObjC.import('Cocoa') - let nsapp = $.NSApplication.sharedApplication - let nsimg = $.NSImage.alloc.initWithContentsOfFile({{json .WindowIcon}}) - nsapp.setActivationPolicy($.NSApplicationActivationPolicyRegular) - nsapp.setApplicationIconImage(nsimg) - {{- end}} +{{- if .WindowIcon}}{ + ObjC.import('Cocoa') + let nsapp = $.NSApplication.sharedApplication + let nsimg = $.NSImage.alloc.initWithContentsOfFile({{json .WindowIcon}}) + nsapp.setActivationPolicy($.NSApplicationActivationPolicyRegular) + nsapp.setApplicationIconImage(nsimg) +}{{- end}} - app.activate() -} \ No newline at end of file +app.includeStandardAdditions = true +app.activate() \ No newline at end of file diff --git a/internal/zenutil/run_darwin.go b/internal/zenutil/run_darwin.go index ece8dc5..65ad218 100644 --- a/internal/zenutil/run_darwin.go +++ b/internal/zenutil/run_darwin.go @@ -10,7 +10,7 @@ import ( ) // Run is internal. -func Run(ctx context.Context, script string, data interface{}) ([]byte, error) { +func Run(ctx context.Context, script string, data any) ([]byte, error) { var buf bytes.Buffer err := scripts.ExecuteTemplate(&buf, script, data) if err != nil { @@ -124,7 +124,8 @@ func RunProgress(ctx context.Context, max int, data Progress) (dlg *progressDial } type common struct { - WindowIcon string + Application any + WindowIcon string } // Dialog is internal. diff --git a/list_darwin.go b/list_darwin.go index cd89708..f1a15d1 100644 --- a/list_darwin.go +++ b/list_darwin.go @@ -22,7 +22,9 @@ func list(text string, items []string, opts options) (string, error) { data.Options.Cancel = opts.cancelLabel data.Options.Default = opts.defaultItems data.Options.Empty = !opts.disallowEmpty - if i, ok := opts.windowIcon.(string); ok { + if opts.attach != nil { + data.Application = opts.attach + } else if i, ok := opts.windowIcon.(string); ok { data.WindowIcon = i } diff --git a/msg_darwin.go b/msg_darwin.go index 3e0edd2..d5980fa 100644 --- a/msg_darwin.go +++ b/msg_darwin.go @@ -10,7 +10,9 @@ func message(kind messageKind, text string, opts options) error { var data zenutil.Dialog data.Text = text data.Options.Timeout = zenutil.Timeout - if i, ok := opts.windowIcon.(string); ok { + if opts.attach != nil { + data.Application = opts.attach + } else if i, ok := opts.windowIcon.(string); ok { data.WindowIcon = i } diff --git a/pwd_darwin.go b/pwd_darwin.go index cb5688c..6fcb03c 100644 --- a/pwd_darwin.go +++ b/pwd_darwin.go @@ -18,7 +18,9 @@ func password(opts options) (string, string, error) { data.Separator = zenutil.Separator data.Options.Title = opts.title data.Options.Timeout = zenutil.Timeout - if i, ok := opts.windowIcon.(string); ok { + if opts.attach != nil { + data.Application = opts.attach + } else if i, ok := opts.windowIcon.(string); ok { data.WindowIcon = i } switch i := opts.icon.(type) {