From 42d50bae4f993de5d2af57e52e105558e5936a28 Mon Sep 17 00:00:00 2001 From: weizhixiang Date: Fri, 27 May 2022 21:03:41 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=87=8D=E5=90=AFAM?= =?UTF-8?q?=E5=90=8E=E6=B5=8F=E8=A7=88=E5=99=A8=E6=B2=A1=E6=9C=89=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E5=9C=A8=E4=BB=BB=E5=8A=A1=E6=A0=8F=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复重启AM后浏览器没有显示在任务栏的问题 Log: Task: https://pms.uniontech.com/task-view-137667.html Influence: 无 Change-Id: I147ff7d2329f0d568496fdb6970925392e485d77 --- src/lib/desktopinfo.cpp | 2 +- src/lib/dstring.cpp | 13 ++++ src/lib/dstring.h | 2 + src/lib/xcbutils.cpp | 25 +++----- src/modules/dock/dbushandler.cpp | 34 +++++----- src/modules/dock/dbushandler.h | 2 - src/modules/dock/processinfo.cpp | 5 ++ src/modules/dock/processinfo.h | 1 + src/modules/dock/windowidentify.cpp | 9 +-- src/modules/dock/windowidentify.h | 1 - src/modules/dock/windowinfox.cpp | 2 +- src/modules/dock/windowpatterns.cpp | 99 +++++++++++++++++++++++++---- src/modules/dock/windowpatterns.h | 2 +- src/modules/dock/x11manager.cpp | 10 ++- 14 files changed, 152 insertions(+), 55 deletions(-) diff --git a/src/lib/desktopinfo.cpp b/src/lib/desktopinfo.cpp index 837dc99..6a3270e 100644 --- a/src/lib/desktopinfo.cpp +++ b/src/lib/desktopinfo.cpp @@ -271,7 +271,7 @@ std::string DesktopInfo::getId() idStr = m_fileName.substr(0, m_fileName.size() - 8); // trim suffix size_t dirPos = idStr.find("/applications/"); if (dirPos == std::string::npos) - return ""; + return idStr; std::string baseDir(idStr.substr(0, dirPos + 14)); // length of "/applications/" is 14 std::vector appDirs = BaseDir::appDirs(); diff --git a/src/lib/dstring.cpp b/src/lib/dstring.cpp index 23793db..9b7bf7e 100644 --- a/src/lib/dstring.cpp +++ b/src/lib/dstring.cpp @@ -145,3 +145,16 @@ void DString::delQuote(std::string &str) str.assign(str.substr(1, str.size() - 2)); } +std::string DString::join(std::vector strs, std::string joinStr) +{ + std::string ret; + for (uint i = 0; i < strs.size(); i++) { + if (i < strs.size() - 1) { + ret += strs[i] + joinStr; + } else { + ret += strs[i]; + } + } + return ret; +} + diff --git a/src/lib/dstring.h b/src/lib/dstring.h index be70127..1c575a5 100644 --- a/src/lib/dstring.h +++ b/src/lib/dstring.h @@ -51,6 +51,8 @@ public: // 去除首尾引用 static char *delQuote(const char *chars); static void delQuote(std::string &str); + // 连接字符串 + static std::string join(std::vector strs, std::string joinStr); }; #endif // DSTRING_H diff --git a/src/lib/xcbutils.cpp b/src/lib/xcbutils.cpp index 76ab665..e0d49ea 100644 --- a/src/lib/xcbutils.cpp +++ b/src/lib/xcbutils.cpp @@ -155,12 +155,12 @@ Geometry XCBUtils::getWindowGeometry(XWindow xid) XWindow XCBUtils::getActiveWindow() { - XWindow ret; - xcb_get_property_cookie_t cookie = xcb_ewmh_get_active_window(&m_ewmh, m_screenNum); - if (!xcb_ewmh_get_active_window_reply(&m_ewmh, cookie, &ret, nullptr)) - std::cout << "getActiveWindow error" << std::endl; + XWindow ret; + xcb_get_property_cookie_t cookie = xcb_ewmh_get_active_window(&m_ewmh, m_screenNum); + if (!xcb_ewmh_get_active_window_reply(&m_ewmh, cookie, &ret, nullptr)) + std::cout << "getActiveWindow error" << std::endl; - return ret; + return ret; } void XCBUtils::setActiveWindow(XWindow xid) @@ -441,17 +441,12 @@ WMClass XCBUtils::getWMClass(XWindow xid) xcb_icccm_get_wm_class_reply_t reply; reply.instance_name = nullptr; reply.class_name = nullptr; - if (!xcb_icccm_get_wm_class_reply(m_connect, cookie, &reply, nullptr)) { - if (reply.class_name) - ret.className.assign(reply.class_name); + xcb_icccm_get_wm_class_reply(m_connect, cookie, &reply, nullptr); // 返回值为0不一定表示失败, 故不做返回值判断 + if (reply.class_name) + ret.className.assign(reply.class_name); - if (reply.instance_name) - ret.instanceName.assign(reply.instance_name); - - //xcb_icccm_get_wm_class_reply_wipe(&reply); - } else { - std::cout << xid << " getWMClass error" << std::endl; - } + if (reply.instance_name) + ret.instanceName.assign(reply.instance_name); return ret; } diff --git a/src/modules/dock/dbushandler.cpp b/src/modules/dock/dbushandler.cpp index dfd02a4..35bb987 100644 --- a/src/modules/dock/dbushandler.cpp +++ b/src/modules/dock/dbushandler.cpp @@ -25,15 +25,14 @@ #include "dbusbamfapplication.h" DBusHandler::DBusHandler(Dock *_dock, QObject *parent) - : QObject(parent) - , dock(_dock) - , session(QDBusConnection::sessionBus()) - , launcherEnd(new LauncherBackEnd("org.deepin.dde.daemon.Launcher1", "/org/deepin/dde/daemon/Launcher1", session, this)) - , launcherFront(new LauncherFront("org.deepin.dde.Launcher1", "/org/deepin/dde/Launcher1", session, this)) - , wm(new com::deepin::WM("com.deepin.wm", "/com/deepin/wm", session, this)) - , wmSwitcher(new com::deepin::WMSwitcher("com.deepin.wmWMSwitcher", "/com/deepin/WMSwitcher", session, this)) - , kwaylandManager(nullptr) - , bamfMatcher(new org::ayatana::bamf::BamfMatcher("org.ayatana.bamf.matcher", "/org/ayatana/bamf/matcher", session, this)) + : QObject(parent) + , dock(_dock) + , session(QDBusConnection::sessionBus()) + , launcherEnd(new LauncherBackEnd("org.deepin.dde.daemon.Launcher1", "/org/deepin/dde/daemon/Launcher1", session, this)) + , launcherFront(new LauncherFront("org.deepin.dde.Launcher1", "/org/deepin/dde/Launcher1", session, this)) + , wm(new com::deepin::WM("com.deepin.wm", "/com/deepin/wm", session, this)) + , wmSwitcher(new com::deepin::WMSwitcher("com.deepin.wmWMSwitcher", "/com/deepin/WMSwitcher", session, this)) + , kwaylandManager(nullptr) { // 关联org.deepin.dde.daemon.Launcher1事件 ItemChanged connect(launcherEnd, &LauncherBackEnd::ItemChanged, this, &DBusHandler::handleLauncherItemChanged); @@ -200,17 +199,22 @@ void DBusHandler::presentWindows(QList windows) wm->PresentWindows(windows); } +// TODO: 待优化点, 查看Bamf根据windowId获取对应应用desktopFile路径实现方式, 移除bamf依赖 QString DBusHandler::getDesktopFromWindowByBamf(XWindow windowId) { - QDBusPendingReply reply = bamfMatcher->ApplicationForXid(windowId); - if (!reply.isValid()) + QDBusInterface interface0 = QDBusInterface("org.ayatana.bamf", "/org/ayatana/bamf/matcher", "org.ayatana.bamf.matcher"); + QDBusReply replyApplication = interface0.call("ApplicationForXid", windowId); + QString appObjPath = replyApplication.value(); + if (!replyApplication.isValid() || appObjPath.isEmpty()) return ""; - QString appObjPath = reply.value(); - org::ayatana::bamf::BamfApplication bamfApp("org.ayatana.bamf.application", appObjPath, session, this); - if (bamfApp.isValid()) - return bamfApp.DesktopFile(); + QDBusInterface interface = QDBusInterface("org.ayatana.bamf", appObjPath, "org.ayatana.bamf.application"); + QDBusReply replyDesktopFile = interface.call("DesktopFile"); + + if (replyDesktopFile.isValid()) + return replyDesktopFile.value(); + return ""; } diff --git a/src/modules/dock/dbushandler.h b/src/modules/dock/dbushandler.h index 28e7321..b655294 100644 --- a/src/modules/dock/dbushandler.h +++ b/src/modules/dock/dbushandler.h @@ -29,7 +29,6 @@ #include "dbuskwaylandwindowmanager.h" #include "windowinfok.h" #include "dbusplasmawindow.h" -#include "dbusbamfmatcher.h" #include #include @@ -86,7 +85,6 @@ private: com::deepin::WM *wm; com::deepin::WMSwitcher *wmSwitcher; com::deepin::daemon::kwayland::WindowManager *kwaylandManager; - org::ayatana::bamf::BamfMatcher *bamfMatcher; }; #endif // DBUSHANDLER_H diff --git a/src/modules/dock/processinfo.cpp b/src/modules/dock/processinfo.cpp index 48a6bbc..fd371cd 100644 --- a/src/modules/dock/processinfo.cpp +++ b/src/modules/dock/processinfo.cpp @@ -116,6 +116,11 @@ int ProcessInfo::getPpid() return process.getPpid(); } +bool ProcessInfo::initWithPid() +{ + return hasPid; +} + std::string ProcessInfo::getExe() { return exe; diff --git a/src/modules/dock/processinfo.h b/src/modules/dock/processinfo.h index 6d18fcb..8a9678c 100644 --- a/src/modules/dock/processinfo.h +++ b/src/modules/dock/processinfo.h @@ -39,6 +39,7 @@ public: std::vector getArgs(); int getPid(); int getPpid(); + bool initWithPid(); std::string getExe(); std::string getOneCommandLine(); std::string getShellScriptLines(); diff --git a/src/modules/dock/windowidentify.cpp b/src/modules/dock/windowidentify.cpp index 5237d4f..88fedc6 100644 --- a/src/modules/dock/windowidentify.cpp +++ b/src/modules/dock/windowidentify.cpp @@ -34,8 +34,6 @@ #define XCB XCBUtils::instance() -WindowPatterns WindowIdentify::patterns; - static QMap crxAppIdMap = { {"crx_onfalgmmmaighfmjgegnamdjmhpjpgpi", "apps.com.aiqiyi"}, {"crx_gfhkopakpiiaeocgofdpcpjpdiglpkjl", "apps.cn.kugou.hd"}, @@ -385,6 +383,7 @@ AppInfo *WindowIdentify::identifyWindowByCrxId(Dock *_dock, WindowInfoX *winInfo AppInfo *WindowIdentify::identifyWindowByRule(Dock *_dock, WindowInfoX *winInfo, QString &innerId) { + static WindowPatterns patterns; qInfo() << "identifyWindowByRule: windowId=" << winInfo->getXid(); AppInfo *ret = nullptr; QString matchStr = patterns.match(winInfo); @@ -417,13 +416,11 @@ AppInfo *WindowIdentify::identifyWindowByBamf(Dock *_dock, WindowInfoX *winInfo, XWindow xid = winInfo->getXid(); qInfo() << "identifyWindowByBamf: windowId=" << xid; QString desktopFile; - // 重试 bamf 识别,yozo office 的窗口经常要第二次时才能识别到。 - for (int i=0; i<3; i++) { + // 重试 bamf 识别,部分的窗口经常要多次调用才能识别到。 + for (int i = 0; i < 3; i++) { desktopFile = _dock->getDesktopFromWindowByBamf(xid); if (!desktopFile.isEmpty()) break; - - QThread::msleep(100); } if (!desktopFile.isEmpty()) { diff --git a/src/modules/dock/windowidentify.h b/src/modules/dock/windowidentify.h index 516391a..63fbd81 100644 --- a/src/modules/dock/windowidentify.h +++ b/src/modules/dock/windowidentify.h @@ -67,7 +67,6 @@ private: static int32_t getAndroidUengineId(XWindow winId); static QString getAndroidUengineName(XWindow winId); - static WindowPatterns patterns; // 根据rule识别 Dock *dock; QMap identifyWindowFuns; }; diff --git a/src/modules/dock/windowinfox.cpp b/src/modules/dock/windowinfox.cpp index 2f5bcf6..dbe70ef 100644 --- a/src/modules/dock/windowinfox.cpp +++ b/src/modules/dock/windowinfox.cpp @@ -350,7 +350,7 @@ void WindowInfoX::updateHasWmTransientFor() } /** - * @brief WindowInfoX::update 更新窗口信息(仅仅执行一次) + * @brief WindowInfoX::update 更新窗口信息(在识别窗口时执行一次) */ void WindowInfoX::update() { diff --git a/src/modules/dock/windowpatterns.cpp b/src/modules/dock/windowpatterns.cpp index 041c08f..bf60433 100644 --- a/src/modules/dock/windowpatterns.cpp +++ b/src/modules/dock/windowpatterns.cpp @@ -21,6 +21,9 @@ #include "windowpatterns.h" #include "common.h" +#include "processinfo.h" +#include "dfile.h" +#include "dstring.h" #include #include @@ -56,53 +59,123 @@ bool equalIgnoreCase(QString key, QString value) { bool regexMatch(QString key, QString value) { QRegExp ruleRegex(value); - return ruleRegex.exactMatch(key); + bool ret = ruleRegex.exactMatch(key); + + // 配置中\.exe$ 在V20中go代码可以匹配以.exe结尾的字符串, Qt中使用\.*exe$匹配以.exe结尾字符串失败,暂时做兼容处理 + if (!ret && value == "\\.exe$") { + ret = key.endsWith(".exe"); + } + return ret; } bool regexMatchIgnoreCase(QString key, QString value) { QRegExp ruleRegex(value, Qt::CaseInsensitive); - return ruleRegex.exactMatch(key); + bool ret = ruleRegex.exactMatch(key); + + // 配置中\.exe$ 在V20中go代码可以匹配以.exe结尾的字符串, Qt中使用\.*exe$匹配以.exe结尾字符串失败,暂时做兼容处理 + if (!ret && value == "\\.exe$") { + QString _key = key.toLower(); + ret = _key.endsWith(".exe"); + } + return ret; } - RuleValueParse::RuleValueParse() - : negative(0) + : negative(false) , type(0) , flags(0) { } -bool RuleValueParse::parse(QString parsedKey) +bool RuleValueParse::match(const WindowInfoX *winInfo) { + QString parsedKey = parseRuleKey(const_cast(winInfo), key); if (!fn) return false; - return negative ? fn(parsedKey, value) : !fn(parsedKey, value); + bool ret = fn(parsedKey, value); + return negative ? !ret : ret; } -bool RuleValueParse::match(const WindowInfoX *winInfo) +QString RuleValueParse::parseRuleKey(WindowInfoX *winInfo, const QString &ruleKey) { - QString parsedKey; + ProcessInfo * process = winInfo->getProcess(); + if (ruleKey == "hasPid") { + if (process && process->initWithPid()) { + return "t"; + } + return "f"; + } else if (ruleKey == "exec") { + if (process) { + // 返回执行文件baseName + auto baseName = DFile::base(process->getExe()); + return baseName.empty() ? "" : baseName.c_str(); + } + } else if (ruleKey == "arg") { + if (process) { + // 返回命令行参数 + auto ret = DString::join(process->getArgs(), ""); + return ret.empty() ? "" : ret.c_str(); + } + } else if (ruleKey == "wmi") { + // 窗口实例 + auto wmClass = winInfo->getWMClass(); + if (!wmClass.instanceName.empty()) + return wmClass.instanceName.c_str(); + } else if (ruleKey == "wmc") { + // 窗口类型 + auto wmClass = winInfo->getWMClass(); + if (!wmClass.className.empty()) + return wmClass.className.c_str(); + } else if (ruleKey == "wmn") { + // 窗口名称 + return winInfo->getWMName(); + } else if (ruleKey == "wmrole") { + // 窗口角色 + return winInfo->getWmRole(); + } else { + const QString envPrefix = "env."; + if (ruleKey.startsWith(envPrefix)) { + QString envName = ruleKey.mid(envPrefix.size()); + if (winInfo->getProcess()) { + auto ret = process->getEnv(envName.toStdString()); + return ret.empty() ? "" : ret.c_str(); + } + } + } - return parse(parsedKey); + return ""; } WindowPatterns::WindowPatterns() { - + loadWindowPatterns(); } /** - * @brief WindowPatterns::match 匹配窗口 + * @brief WindowPatterns::match 匹配窗口类型 * @param winInfo * @return */ QString WindowPatterns::match(WindowInfoX *winInfo) { for (auto pattern : patterns) { + bool patternOk = true; + for (auto rule : pattern.parseRules) { + if (!rule.match(winInfo)) { + patternOk = false; + break; + } + } + if (patternOk) { + // 匹配成功 + return pattern.result; + } } + + // 匹配失败 return ""; } @@ -193,6 +266,7 @@ RuleValueParse WindowPatterns::parseRule(QVector rule) strncpy(orig, ret.original.toStdString().c_str(), size_t(len)); switch (orig[1]) { case ':': + break; case '!': ret.flags |= parsedFlagNegative; ret.negative = true; @@ -227,9 +301,10 @@ RuleValueParse WindowPatterns::parseRule(QVector rule) ret.fn = regexMatchIgnoreCase; break; default: - return ret; + break; } + free(orig); return ret; } diff --git a/src/modules/dock/windowpatterns.h b/src/modules/dock/windowpatterns.h index 05af3c9..d401a98 100644 --- a/src/modules/dock/windowpatterns.h +++ b/src/modules/dock/windowpatterns.h @@ -30,8 +30,8 @@ struct RuleValueParse { RuleValueParse(); - bool parse(QString parsedKey); bool match(const WindowInfoX *winInfo); + static QString parseRuleKey(WindowInfoX *winInfo, const QString &ruleKey); QString key; bool negative; bool (*fn)(QString, QString); diff --git a/src/modules/dock/x11manager.cpp b/src/modules/dock/x11manager.cpp index 5e46421..ca64037 100644 --- a/src/modules/dock/x11manager.cpp +++ b/src/modules/dock/x11manager.cpp @@ -153,7 +153,11 @@ void X11Manager::listenXEventUseXCB() */ } -// 注册X11窗口 +/** + * @brief X11Manager::registerWindow 注册X11窗口 + * @param xid + * @return + */ WindowInfoX *X11Manager::registerWindow(XWindow xid) { qInfo() << "registWindow: windowId=" << xid; @@ -249,6 +253,10 @@ void X11Manager::listenRootWindowXEvent() handleClientListChanged(); } +/** + * @brief X11Manager::listenWindowXEvent 监听窗口事件 + * @param winInfo + */ void X11Manager::listenWindowXEvent(WindowInfoX *winInfo) { uint32_t eventMask = EventMask::XCB_EVENT_MASK_PROPERTY_CHANGE | EventMask::XCB_EVENT_MASK_STRUCTURE_NOTIFY | EventMask::XCB_EVENT_MASK_VISIBILITY_CHANGE;