Parent window id (unix).

This commit is contained in:
Nuno Cruces 2022-06-17 01:55:02 +01:00
parent b5c699b40d
commit 176a3d48a1
4 changed files with 86 additions and 13 deletions

View file

@ -452,10 +452,13 @@ func loadFlags() []zenity.Option {
if attach != "" { if attach != "" {
opts = append(opts, zenity.Attach(zenutil.ParseWindowId(attach))) opts = append(opts, zenity.Attach(zenutil.ParseWindowId(attach)))
} else if modal { } else if modal {
if pid := zenutil.GetParentWindowId(); pid != 0 { if id := zenutil.GetParentWindowId(os.Getppid()); id != 0 {
opts = append(opts, zenity.Attach(pid)) opts = append(opts, zenity.Attach(id))
} }
} }
if modal {
opts = append(opts, zenity.Modal())
}
// Message options // Message options

View file

@ -1,7 +1,6 @@
package zenutil package zenutil
import ( import (
"os"
"strconv" "strconv"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
@ -16,8 +15,7 @@ func ParseWindowId(id string) any {
} }
// GetParentWindowId is internal. // GetParentWindowId is internal.
func GetParentWindowId() int { func GetParentWindowId(pid int) int {
pid := os.Getppid()
for { for {
kinfo, err := unix.SysctlKinfoProc("kern.proc.pid", pid) kinfo, err := unix.SysctlKinfoProc("kern.proc.pid", pid)
if err != nil { if err != nil {

View file

@ -8,6 +8,7 @@ import (
"io" "io"
"os/exec" "os/exec"
"strconv" "strconv"
"strings"
) )
// ParseWindowId is internal. // ParseWindowId is internal.
@ -17,14 +18,38 @@ func ParseWindowId(id string) int {
} }
// GetParentWindowId is internal. // GetParentWindowId is internal.
func GetParentWindowId() int { func GetParentWindowId(pid int) int {
buf, err := exec.Command("ps", "-xo", "pid=,ppid=").CombinedOutput() winids, err := getPidToWindowMap()
if err != nil { if err != nil {
return 0 return 0
} }
ppids, err := getPidToPpidMap()
if err != nil {
return 0
}
for {
if winid, ok := winids[pid]; ok {
id, _ := strconv.Atoi(winid)
return id
}
if ppid, ok := ppids[pid]; ok {
pid = ppid
} else {
return 0
}
}
}
func getPidToPpidMap() (map[int]int, error) {
out, err := exec.Command("ps", "-xo", "pid=,ppid=").Output()
if err != nil {
return nil, err
}
ppids := map[int]int{} ppids := map[int]int{}
reader := bytes.NewReader(buf) reader := bytes.NewReader(out)
for { for {
var pid, ppid int var pid, ppid int
_, err := fmt.Fscan(reader, &pid, &ppid) _, err := fmt.Fscan(reader, &pid, &ppid)
@ -32,11 +57,58 @@ func GetParentWindowId() int {
break break
} }
if err != nil { if err != nil {
return 0 return nil, err
} }
ppids[pid] = ppid ppids[pid] = ppid
} }
return ppids, nil
// Find the relevant pid and window id. }
return 0
func getPidToWindowMap() (map[int]string, error) {
ids, err := getWindowIDs()
if err != nil {
return nil, err
}
var pid int
winids := map[int]string{}
for _, id := range ids {
pid, err = getWindowPid(id)
if err != nil {
continue
}
winids[pid] = id
}
if err != nil && len(winids) == 0 {
return nil, err
}
return winids, nil
}
func getWindowIDs() ([]string, error) {
out, err := exec.Command("xprop", "-root", "0i", "\t$0+", "_NET_CLIENT_LIST").Output()
if err != nil {
return nil, err
}
if i := bytes.IndexByte(out, '\t'); i < 0 {
return nil, fmt.Errorf("xprop: unexpected output: %q", out)
} else {
out = out[i+1:]
}
return strings.Split(string(out), ", "), nil
}
func getWindowPid(id string) (int, error) {
out, err := exec.Command("xprop", "-id", id, "0i", "\t$0", "_NET_WM_PID").Output()
if err != nil {
return 0, err
}
if i := bytes.IndexByte(out, '\t'); i < 0 {
return 0, fmt.Errorf("xprop: unexpected output: %q", out)
} else {
out = out[i+1:]
}
return strconv.Atoi(string(out))
} }

View file

@ -9,6 +9,6 @@ func ParseWindowId(id string) uintptr {
} }
// GetParentWindowId is internal. // GetParentWindowId is internal.
func GetParentWindowId() int { func GetParentWindowId(pid int) int {
return 0 return 0
} }