From 01c17723fa4f91c40ac946e9d02bd55be85c1f75 Mon Sep 17 00:00:00 2001 From: yangxianzhao Date: Thu, 6 Apr 2023 10:06:18 +0800 Subject: [PATCH] Fix-the-system-monitor-displaying-a-scene --- dock/dock_manager_entries.go | 3 +- dock/dock_manager_xevent.go | 13 ++++--- dock/identify_window.go | 70 ++++++++++++++++++++++++------------ 3 files changed, 58 insertions(+), 28 deletions(-) diff --git a/dock/dock_manager_entries.go b/dock/dock_manager_entries.go index ad758c8..bf4c1d5 100644 --- a/dock/dock_manager_entries.go +++ b/dock/dock_manager_entries.go @@ -83,6 +83,7 @@ func (m *Manager) attachOrDetachWindow(winInfo *WindowInfo) { } else { if winInfo.entryInnerId == "" { + logger.Debugf("winInfo.entryInnerId is empty, call identifyWindow, win: %d", winInfo.window) winInfo.entryInnerId, winInfo.appInfo = m.identifyWindow(winInfo) m.markAppLaunched(winInfo.appInfo) } else { @@ -173,7 +174,7 @@ func (m *Manager) attachWindow(winInfo *WindowInfo) { func (m *Manager) detachWindow(winInfo *WindowInfo) { entry := m.Entries.getByWindowId(winInfo.window) if entry == nil { - logger.Warningf("entry of window '%x' is nil", winInfo.window) + logger.Warningf("entry of window %d is nil", winInfo.window) return } needRemove := entry.detachWindow(winInfo) diff --git a/dock/dock_manager_xevent.go b/dock/dock_manager_xevent.go index 17468bf..c67a776 100644 --- a/dock/dock_manager_xevent.go +++ b/dock/dock_manager_xevent.go @@ -21,6 +21,7 @@ package dock import ( "sort" + "strings" "time" x "github.com/linuxdeepin/go-x11-client" @@ -76,12 +77,13 @@ func (m *Manager) handleClientListChanged() { for _, win := range add { window0 := win addFunc := func() { - logger.Debugf("client list add: %x", window0) + logger.Debugf("client list add: %d", window0) winInfo := m.registerWindow(window0) logger.Infof("%v", m.windowInfoMap) repeatCount := 0 for { if repeatCount > 10 { + logger.Debugf("give up identify window %d", window0) return } good := isGoodWindow(window0) @@ -90,7 +92,9 @@ func (m *Manager) handleClientListChanged() { } pid := getWmPid(window0) wmClass, _ := getWmClass(window0) - if pid != 0 || wmClass != nil { + wmName := getWmName(window0) + wmCmd, _ := getWmCommand(window0) + if pid != 0 || wmClass != nil || wmName != "" || strings.Join(wmCmd, "") != "" { m.attachOrDetachWindow(winInfo) return } @@ -106,7 +110,7 @@ func (m *Manager) handleClientListChanged() { for _, win := range remove { window0 := win removeFunc := func() { - logger.Debugf("client list remove: %x", window0) + logger.Debugf("client list remove: %d", window0) m.windowInfoMapMutex.RLock() logger.Infof("%v", m.windowInfoMap) winInfo := m.windowInfoMap[window0] @@ -115,7 +119,7 @@ func (m *Manager) handleClientListChanged() { m.detachWindow(winInfo) winInfo.entryInnerId = "" } else { - logger.Warningf("window info of '%x' is nil", window0) + logger.Warningf("window info of %d is nil", window0) entry := m.Entries.getByWindowId(window0) m.removeAppEntry(entry) } @@ -198,6 +202,7 @@ func (m *Manager) handleMapNotifyEvent(ev *x.MapNotifyEvent) { logger.Debug("MapNotifyEvent window:", ev.Window) winInfo := m.registerWindow(ev.Window) time.AfterFunc(2*time.Second, func() { + logger.Warningf("mapNotifyEvent after 2s, call identifyWindow, win: %d", winInfo.window) _, appInfo := m.identifyWindow(winInfo) m.markAppLaunched(appInfo) }) diff --git a/dock/identify_window.go b/dock/identify_window.go index 9b433ed..e4f178e 100644 --- a/dock/identify_window.go +++ b/dock/identify_window.go @@ -20,9 +20,11 @@ package dock import ( + "fmt" "path/filepath" "strconv" "strings" + "time" "pkg.deepin.io/lib/procfs" ) @@ -59,18 +61,18 @@ func (m *Manager) identifyWindow(winInfo *WindowInfo) (innerId string, appInfo * logger.Debugf("identifyWindow: window id: %v, window innerId: %q", winInfo.window, winInfo.innerId) if winInfo.innerId == "" { - logger.Debug("identifyWindow: winInfo.innerId is empty") + logger.Debugf("identifyWindow: win %d winInfo.innerId is empty", winInfo.window) return } for idx, item := range m.identifyWindowFuns { name := item.Name - logger.Debugf("identifyWindow: try %s:%d", name, idx) + logger.Debugf("identifyWindow %d try %s:%d", winInfo.window, name, idx) innerId, appInfo = item.Fn(m, winInfo) if innerId != "" { // success - logger.Debugf("identifyWindow by %s success, innerId: %q, appInfo: %v", - name, innerId, appInfo) + logger.Debugf("identifyWindow %d by %s success, innerId: %q, appInfo: %v", + winInfo.window, name, innerId, appInfo) // NOTE: if name == "Pid", appInfo may be nil if appInfo != nil { fixedAppInfo := fixAutostartAppInfo(appInfo) @@ -101,8 +103,9 @@ func fixAutostartAppInfo(appInfo *AppInfo) *AppInfo { } func identifyWindowByScratch(m *Manager, winInfo *WindowInfo) (string, *AppInfo) { + msgPrefix := fmt.Sprintf("identifyWindowByScratch win: %d ", winInfo.window) desktopFile := filepath.Join(scratchDir, addDesktopExt(winInfo.innerId)) - logger.Debugf("try scratch desktop file: %q", desktopFile) + logger.Debugf("%s try scratch desktop file: %q", msgPrefix, desktopFile) appInfo := NewAppInfoFromFile(desktopFile) if appInfo != nil { // success @@ -113,8 +116,9 @@ func identifyWindowByScratch(m *Manager, winInfo *WindowInfo) (string, *AppInfo) } func identifyWindowByPid(m *Manager, winInfo *WindowInfo) (string, *AppInfo) { + msgPrefix := fmt.Sprintf("identifyWindowByPid win: %d ", winInfo.window) if winInfo.pid > 10 { - logger.Debugf("identifyWindowByPid: pid: %d", winInfo.pid) + logger.Debugf("%s pid: %d", msgPrefix, winInfo.pid) entry := m.Entries.GetByWindowPid(winInfo.pid) if entry != nil { // success @@ -126,8 +130,9 @@ func identifyWindowByPid(m *Manager, winInfo *WindowInfo) (string, *AppInfo) { } func identifyWindowByGtkAppId(m *Manager, winInfo *WindowInfo) (string, *AppInfo) { + msgPrefix := fmt.Sprintf("identifyWindowByGtkAppId win: %d ", winInfo.window) gtkAppId := winInfo.gtkAppId - logger.Debugf("identifyWindowByGtkAppId: gtkAppId: %q", gtkAppId) + logger.Debugf("%s gtkAppId: %q", msgPrefix, gtkAppId) if gtkAppId != "" { appInfo := NewAppInfo(gtkAppId) if appInfo != nil { @@ -140,8 +145,9 @@ func identifyWindowByGtkAppId(m *Manager, winInfo *WindowInfo) (string, *AppInfo } func identifyWindowByFlatpakAppID(m *Manager, winInfo *WindowInfo) (string, *AppInfo) { + msgPrefix := fmt.Sprintf("identifyWindowByFlatpakAppID win: %d ", winInfo.window) flatpakRef := winInfo.flatpakAppID - logger.Debugf("identifyWindowByFlatpakAppID: flatpak ref is %q", flatpakRef) + logger.Debugf("%s flatpak ref is %q", msgPrefix, flatpakRef) if strings.HasPrefix(flatpakRef, "app/") { parts := strings.Split(flatpakRef, "/") if len(parts) > 1 { @@ -204,12 +210,13 @@ var crxAppIdMap = map[string]string{ } func identifyWindowByCrxId(m *Manager, winInfo *WindowInfo) (string, *AppInfo) { + msgPrefix := fmt.Sprintf("identifyWindowByCrxId win: %d ", winInfo.window) if winInfo.wmClass != nil && strings.EqualFold(winInfo.wmClass.Class, "chromium-browser") && strings.HasPrefix(winInfo.wmClass.Instance, "crx_") { appId, ok := crxAppIdMap[winInfo.wmClass.Instance] - logger.Debug("identifyWindowByCrxId", appId) + logger.Debug(msgPrefix, "appId:", appId) if ok { appInfo := NewAppInfo(appId) if appInfo != nil { @@ -223,6 +230,7 @@ func identifyWindowByCrxId(m *Manager, winInfo *WindowInfo) (string, *AppInfo) { } func identifyWindowByCmdlineTurboBooster(m *Manager, winInfo *WindowInfo) (string, *AppInfo) { + msgPrefix := fmt.Sprintf("identifyWindowByCmdlineTurboBooster win: %d ", winInfo.window) pid := winInfo.pid process := winInfo.process if process != nil && pid != 0 { @@ -233,7 +241,7 @@ func identifyWindowByCmdlineTurboBooster(m *Manager, winInfo *WindowInfo) (strin } else if strings.Contains(process.cmdline[0], "/applications/") { matches, err := filepath.Glob(process.cmdline[0] + "*") if err != nil { - logger.Warning("filepath.Glob err:", err) + logger.Warning(msgPrefix, "filepath.Glob err:", err) return "", nil } if len(matches) > 0 && strings.HasSuffix(matches[0], desktopExt) { @@ -242,7 +250,7 @@ func identifyWindowByCmdlineTurboBooster(m *Manager, winInfo *WindowInfo) (strin } if desktopFile != "" { - logger.Debugf("identifyWindowByCmdlineTurboBooster: desktopFile: %s", desktopFile) + logger.Debugf("%s desktopFile: %s", msgPrefix, desktopFile) appInfo := NewAppInfoFromFile(desktopFile) if appInfo != nil { // success @@ -257,6 +265,7 @@ func identifyWindowByCmdlineTurboBooster(m *Manager, winInfo *WindowInfo) (strin } func identifyWindowByPidEnv(m *Manager, winInfo *WindowInfo) (string, *AppInfo) { + msgPrefix := fmt.Sprintf("identifyWindowByPidEnv win: %d ", winInfo.window) pid := winInfo.pid process := winInfo.process if process != nil && pid != 0 { @@ -264,18 +273,22 @@ func identifyWindowByPidEnv(m *Manager, winInfo *WindowInfo) (string, *AppInfo) launchedDesktopFilePid, _ := strconv.ParseUint( process.environ.Get("GIO_LAUNCHED_DESKTOP_FILE_PID"), 10, 32) - logger.Debugf("identifyWindowByPidEnv: launchedDesktopFile: %q, pid: %d", - launchedDesktopFile, launchedDesktopFilePid) + logger.Debugf("%s launchedDesktopFile: %q, pid: %d", + msgPrefix, launchedDesktopFile, launchedDesktopFilePid) + // 以下 2 种情况下,才能信任环境变量 GIO_LAUNCHED_DESKTOP_FILE。 + // 1. 当窗口 pid 和 launchedDesktopFilePid 相同时; + // 2. 当窗口的进程的父进程 id(即 ppid)和 launchedDesktopFilePid 相同, + // 并且该父进程是 sh 或 bash 时。 var try bool - if uint(launchedDesktopFilePid) == pid || process.ppid == 1 { // launchedDesktopFilePid可能被销毁,process变成孤儿进程 + if uint(launchedDesktopFilePid) == pid { try = true } else if uint(launchedDesktopFilePid) == process.ppid && process.ppid != 0 { - logger.Debug("ppid equal") + logger.Debug(msgPrefix, "ppid equal") parentProcess := procfs.Process(process.ppid) cmdline, err := parentProcess.Cmdline() if err == nil && len(cmdline) > 0 { - logger.Debugf("parent process cmdline: %#v", cmdline) + logger.Debugf("%s parent process cmdline: %#v", msgPrefix, cmdline) base := filepath.Base(cmdline[0]) if base == "sh" || base == "bash" { try = true @@ -296,11 +309,12 @@ func identifyWindowByPidEnv(m *Manager, winInfo *WindowInfo) (string, *AppInfo) } func identifyWindowByRule(m *Manager, winInfo *WindowInfo) (string, *AppInfo) { + msgPrefix := fmt.Sprintf("identifyWindowByRule win: %d ", winInfo.window) ret := m.windowPatterns.Match(winInfo) if ret == "" { return "", nil } - logger.Debug("identifyWindowByRule ret:", ret) + logger.Debug(msgPrefix, "patterns match result:", ret) // parse ret // id=$appId or env var appInfo *AppInfo @@ -356,12 +370,21 @@ func identifyWindowByWmClass(m *Manager, winInfo *WindowInfo) (string, *AppInfo) } func identifyWindowByBamf(m *Manager, winInfo *WindowInfo) (string, *AppInfo) { - // bamf + msgPrefix := fmt.Sprintf("identifyWindowByBamf win: %d ", winInfo.window) win := winInfo.window - desktop, err := getDesktopFromWindowByBamf(win) - if err != nil { - logger.Warning(err) - return "", nil + desktop := "" + // 重试 bamf 识别,yozo office 的窗口经常要第二次时才能识别到。 + for i := 0; i < 3; i++ { + var err error + desktop, err = getDesktopFromWindowByBamf(win) + logger.Debugf("%s get desktop i: %d, desktop: %q", msgPrefix, i, desktop) + if err != nil { + logger.Warning(msgPrefix, "get desktop failed:", err) + } + if desktop != "" { + break + } + time.Sleep(100 * time.Millisecond) } if desktop != "" { @@ -375,6 +398,7 @@ func identifyWindowByBamf(m *Manager, winInfo *WindowInfo) (string, *AppInfo) { } func identifyWindowByCmdlineXWalk(m *Manager, winInfo *WindowInfo) (string, *AppInfo) { + msgPrefix := fmt.Sprintf("identifyWindowByCmdlineXWalk win: %d ", winInfo.window) process := winInfo.process if process == nil || winInfo.pid == 0 { return "", nil @@ -386,7 +410,7 @@ func identifyWindowByCmdlineXWalk(m *Manager, winInfo *WindowInfo) (string, *App return "", nil } lastArg := args[len(args)-1] - logger.Debugf("lastArg: %q", lastArg) + logger.Debugf("%s lastArg: %q", msgPrefix, lastArg) if filepath.Base(lastArg) == "manifest.json" { appId := filepath.Base(filepath.Dir(lastArg)) -- 2.18.4