diff --git a/.gitignore b/.gitignore index 43a43f4..d274f67 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,8 @@ compile_commands.json # QtCreator local machine specific files for imported projects *creator.user* + +.idea +CMakeFiles +cmake_install.cmake +*_autogen diff --git a/frontend/CMakeLists.txt b/frontend/CMakeLists.txt index c414d0b..75773a4 100644 --- a/frontend/CMakeLists.txt +++ b/frontend/CMakeLists.txt @@ -49,6 +49,13 @@ set(UKUI_SEARCH_SRC view/result-view.cpp view/result-view.h view/result-view-delegate.cpp view/result-view-delegate.h ) +if(COMMAND qt_add_dbus_adaptor) + qt_add_dbus_adaptor(UKUI_SEARCH_SRC org.ukui.search.service.xml ukui-search-dbus-service.h UkuiSearch::UkuiSearchDbusServices) + qt_add_dbus_interface(UKUI_SEARCH_SRC org.ukui.search.service.xml service_interface) +else() + qt5_add_dbus_adaptor(UKUI_SEARCH_SRC org.ukui.search.service.xml ukui-search-dbus-service.h UkuiSearch::UkuiSearchDbusServices) + qt5_add_dbus_interface(UKUI_SEARCH_SRC org.ukui.search.service.xml service_interface) +endif() set(QRC_FILES resource.qrc) diff --git a/frontend/main.cpp b/frontend/main.cpp index ebe1ffb..88508f9 100644 --- a/frontend/main.cpp +++ b/frontend/main.cpp @@ -64,12 +64,17 @@ int main(int argc, char *argv[]) { QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); #endif QString display; - if(KWindowSystem::isPlatformWayland()) { + QString sessionType; + if(QString(getenv("XDG_SESSION_TYPE")) == "wayland") { + sessionType = "wayland"; display = getenv("WAYLAND_DISPLAY"); - } else if (KWindowSystem::isPlatformX11()) { + } else { + sessionType = "x11"; display = getenv("DISPLAY"); } - UkuiSearchGui app(argc, argv, QString("ukui-search-gui-%1").arg(display)); + qDebug() << "Current DISPLAY: " << display; + UkuiSearchGui app(argc, argv, display, sessionType); + if (app.isRunning()) return 0; diff --git a/frontend/org.ukui.search.service.xml b/frontend/org.ukui.search.service.xml new file mode 100644 index 0000000..c0bb900 --- /dev/null +++ b/frontend/org.ukui.search.service.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/ukui-search-dbus-service.cpp b/frontend/ukui-search-dbus-service.cpp index 9d79e93..f6a4ddc 100644 --- a/frontend/ukui-search-dbus-service.cpp +++ b/frontend/ukui-search-dbus-service.cpp @@ -18,42 +18,193 @@ * */ #include "ukui-search-dbus-service.h" +#include +#include +#include "serviceadaptor.h" using namespace UkuiSearch; -void UkuiSearchDbusServices::showWindow(){ - qDebug() << "showWindow called"; - m_mainWindow->bootOptionsFilter("-s"); +void UkuiSearchDbusServices::showWindow() +{ + QString display = checkDisplay(); + qDebug() << "showWindow called, from display:" << display << "current display: " << m_display; + if(!display.isEmpty() && display != m_display) { + Q_EMIT showWindowSignal(display); + return; + } + onShowWindow(m_display); } void UkuiSearchDbusServices::searchKeyword(QString keyword) { - showWindow(); - m_mainWindow->setText(keyword); + QString display = checkDisplay(); + qDebug() << "searchKeyword called, from display:" << display << "current display: " << m_display; + if(!display.isEmpty() && display != m_display) { + Q_EMIT searchKeywordSignal(display, keyword); + return; + } + onSearchKeyword(m_display, keyword); } void UkuiSearchDbusServices::mainWindowSwitch() { - if (m_mainWindow->isActiveWindow()) { - m_mainWindow->tryHide(); + QString display = checkDisplay(); + qDebug() << "mainWindowSwitch called, from display:" << display << "current display: " << m_display; + if(!display.isEmpty() && display != m_display) { + Q_EMIT mainWindowSwitchSignal(display); + return; + } + onMainWindowSwitch(m_display); +} + +UkuiSearchDbusServices::UkuiSearchDbusServices(MainWindow *m, QObject *parent): + QObject(parent), + m_mainWindow(m) +{ + m_mainWindow = m; + m_display = qApp->property("display").toString(); + //注册服务 + bool isServiceRegistered = QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("com.ukui.search.service")); + if(isServiceRegistered) { + initWatcher(); } else { + if(!registerService()) { + initWatcher(); + } + } +} + +UkuiSearchDbusServices::~UkuiSearchDbusServices() +{ + if(m_watcher) { + delete m_watcher; + m_watcher = nullptr; + } + if(m_serviceIface) { + delete m_serviceIface; + m_serviceIface = nullptr; + } +} + +void UkuiSearchDbusServices::initWatcher() +{ + m_watcher = new QDBusServiceWatcher(QStringLiteral("com.ukui.search.service"),QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForOwnerChange); + connect(m_watcher, &QDBusServiceWatcher::serviceOwnerChanged, this, &UkuiSearchDbusServices::onServiceOwnerChanged); + connectToService(); +} + +bool UkuiSearchDbusServices::registerService() +{ + if(!m_adaptor) { + m_adaptor = new ServiceAdaptor(this); + } + QDBusConnection conn = QDBusConnection::sessionBus(); + auto reply = conn.interface()->registerService(QStringLiteral("com.ukui.search.service"), + QDBusConnectionInterface::ReplaceExistingService, + QDBusConnectionInterface::DontAllowReplacement); + if (reply.value() == QDBusConnectionInterface::ServiceNotRegistered) { + return false; + } + + bool res = QDBusConnection::sessionBus().registerObject("/", this); + if (!res) { + QDBusConnection::sessionBus().interface()->unregisterService(QStringLiteral("com.ukui.search.service")); + } + return res; +} + +void +UkuiSearchDbusServices::onServiceOwnerChanged(const QString &service, const QString &oldOwner, const QString &newOwner) +{ + if (newOwner.isEmpty()) { + bool success = registerService(); + if (success) { + disConnectToService(); + m_watcher->deleteLater(); + } + qDebug() << "try to register service:" << success; + return; + } + + uint newOwnerPid = QDBusConnection::sessionBus().interface()->servicePid(newOwner); + qDebug() << "newOwnerPid:" << newOwnerPid << ", myPid:" << QCoreApplication::applicationPid() << ", display:" << m_display; +} + +void UkuiSearchDbusServices::connectToService() +{ + if(!m_serviceIface) { + m_serviceIface = new OrgUkuiSearchServiceInterface(QStringLiteral("com.ukui.search.service"), "/", QDBusConnection::sessionBus()); + } + connect(m_serviceIface, &OrgUkuiSearchServiceInterface::showWindowSignal, this, &UkuiSearchDbusServices::onShowWindow); + connect(m_serviceIface, &OrgUkuiSearchServiceInterface::searchKeywordSignal, this, &UkuiSearchDbusServices::onSearchKeyword); + connect(m_serviceIface, &OrgUkuiSearchServiceInterface::mainWindowSwitchSignal, this, &UkuiSearchDbusServices::onMainWindowSwitch); +} + +void UkuiSearchDbusServices::disConnectToService() +{ + if(m_serviceIface) { + m_serviceIface->disconnect(); + delete m_serviceIface; + m_serviceIface = nullptr; + } +} + +void UkuiSearchDbusServices::onShowWindow(const QString &display) +{ + if(m_display == display) { m_mainWindow->bootOptionsFilter("-s"); } } -UkuiSearchDbusServices::UkuiSearchDbusServices(MainWindow *m) +void UkuiSearchDbusServices::onSearchKeyword(const QString &display, const QString &keyword) { - m_mainWindow = m; - //注册服务 - QDBusConnection sessionBus = QDBusConnection::sessionBus(); - QDBusConnection::sessionBus().unregisterService("com.ukui.search.service"); - if(!sessionBus.registerService("com.ukui.search.service")){ - qWarning() << "ukui-search dbus register service failed reason:" << sessionBus.lastError(); - } - - if(!sessionBus.registerObject("/", this, QDBusConnection::ExportAllSlots)){ - qWarning() << "ukui-search dbus register object failed reason:" << sessionBus.lastError(); + if(m_display == display) { + m_mainWindow->bootOptionsFilter("-s"); + m_mainWindow->setText(keyword); } } -UkuiSearchDbusServices::~UkuiSearchDbusServices(){ +void UkuiSearchDbusServices::onMainWindowSwitch(const QString &display) +{ + if(m_display == display) { + if (m_mainWindow->isActiveWindow()) { + m_mainWindow->tryHide(); + } else { + m_mainWindow->bootOptionsFilter("-s"); + } + } +} + +QString UkuiSearchDbusServices::checkDisplay() +{ + uint pid = 0; + QDBusReply pidReply = connection().interface()->servicePid(message().service()); + qDebug() << "caller pid: " << pidReply.value(); + if(pidReply.isValid()) { + pid = pidReply.value(); + } else { + return {}; + } + return UkuiSearchDbusServices::displayFromPid(pid);; +} + +QString UkuiSearchDbusServices::displayFromPid(uint pid) +{ + QFile environFile(QStringLiteral("/proc/%1/environ").arg(QString::number(pid))); + if (environFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + const QByteArray DISPLAY = qApp->property("sessionType").toString() == "wayland" ? QByteArrayLiteral("WAYLAND_DISPLAY") + : QByteArrayLiteral("DISPLAY"); + const auto lines = environFile.readAll().split('\0'); + for (const QByteArray &line : lines) { + const int equalsIdx = line.indexOf('='); + if (equalsIdx <= 0) { + continue; + } + const QByteArray key = line.left(equalsIdx); + if (key == DISPLAY) { + const QByteArray value = line.mid(equalsIdx + 1); + return value; + } + } + } + return {}; } diff --git a/frontend/ukui-search-dbus-service.h b/frontend/ukui-search-dbus-service.h index 8e33da0..329c4a6 100644 --- a/frontend/ukui-search-dbus-service.h +++ b/frontend/ukui-search-dbus-service.h @@ -22,18 +22,21 @@ #include #include +#include #include "mainwindow.h" +#include "service_interface.h" +class ServiceAdaptor; namespace UkuiSearch { -class UkuiSearchDbusServices: public QObject{ +class UkuiSearchDbusServices: public QObject, public QDBusContext +{ Q_OBJECT - Q_CLASSINFO("D-Bus Interface","org.ukui.search.service") public: - explicit UkuiSearchDbusServices(MainWindow *m); + explicit UkuiSearchDbusServices(MainWindow *m, QObject *parent = nullptr); ~UkuiSearchDbusServices(); public Q_SLOTS: @@ -41,8 +44,32 @@ public Q_SLOTS: void searchKeyword(QString keyword); void mainWindowSwitch(); +Q_SIGNALS: + void showWindowSignal(const QString &display); + void searchKeywordSignal(const QString &display, QString keyword); + void mainWindowSwitchSignal(const QString &display); + +private Q_SLOTS: + void onShowWindow(const QString &display); + void onSearchKeyword(const QString &display, const QString &keyword); + void onMainWindowSwitch(const QString &display); + private: + void initWatcher(); + bool registerService(); + void onServiceOwnerChanged(const QString &service, const QString &oldOwner, const QString &newOwner); + void connectToService(); + void disConnectToService(); + QString checkDisplay(); + QString displayFromPid(uint pid); + MainWindow *m_mainWindow = nullptr; + QDBusServiceWatcher *m_watcher = nullptr; + QString m_display; + OrgUkuiSearchServiceInterface *m_serviceIface = nullptr; + ServiceAdaptor * m_adaptor = nullptr; + + }; } diff --git a/frontend/ukui-search-gui.cpp b/frontend/ukui-search-gui.cpp index 4b6e747..9cd0da3 100644 --- a/frontend/ukui-search-gui.cpp +++ b/frontend/ukui-search-gui.cpp @@ -24,13 +24,19 @@ #include #include #include "plugin-manager.h" -#include "search-plugin-manager.h" #include "icon-loader.h" using namespace UkuiSearch; -UkuiSearchGui::UkuiSearchGui(int &argc, char *argv[], const QString &applicationName): QtSingleApplication (applicationName, argc, argv) +UkuiSearchGui::UkuiSearchGui(int &argc, + char *argv[], + const QString &display, + const QString &sessionType, + const QString &applicationName): + QtSingleApplication (applicationName + display, argc, argv) { - qDebug()<<"ukui search gui constructor start" << applicationName; + qDebug()<<"ukui search gui constructor start, session type:" << sessionType << "display:" << display; + qApp->setProperty("display", display); + qApp->setProperty("sessionType", sessionType); setApplicationVersion(QString("v%1").arg(VERSION)); if (!this->isRunning()) { connect(this, &QtSingleApplication::messageReceived, [=](QString msg) { @@ -39,10 +45,6 @@ UkuiSearchGui::UkuiSearchGui(int &argc, char *argv[], const QString &application setQuitOnLastWindowClosed(false); -// qRegisterMetaType>("QPair"); -// qRegisterMetaType("Document"); - - //load translations. QTranslator *translator = new QTranslator(this); try { @@ -73,7 +75,7 @@ UkuiSearchGui::UkuiSearchGui(int &argc, char *argv[], const QString &application PluginManager::getInstance(); m_mainWindow = new UkuiSearch::MainWindow(); - m_dbusService = new UkuiSearch::UkuiSearchDbusServices(m_mainWindow); + m_dbusService = new UkuiSearch::UkuiSearchDbusServices(m_mainWindow, this); qApp->setWindowIcon(IconLoader::loadIconQt("kylin-search")); this->setActivationWindow(m_mainWindow); } diff --git a/frontend/ukui-search-gui.h b/frontend/ukui-search-gui.h index cafdd83..04dac42 100644 --- a/frontend/ukui-search-gui.h +++ b/frontend/ukui-search-gui.h @@ -31,7 +31,7 @@ class UkuiSearchGui : public QtSingleApplication { Q_OBJECT public: - UkuiSearchGui(int &argc, char *argv[], const QString &applicationName = "ukui-search-gui"); + UkuiSearchGui(int &argc, char *argv[] , const QString &display, const QString &sessionType, const QString &applicationName = "ukui-search-gui"); ~UkuiSearchGui(); protected Q_SLOTS: diff --git a/translations/ukui-search/appwidget/search_bo_CN.ts b/translations/ukui-search/appwidget/search_bo_CN.ts index 52f9a29..b0ba42a 100644 --- a/translations/ukui-search/appwidget/search_bo_CN.ts +++ b/translations/ukui-search/appwidget/search_bo_CN.ts @@ -22,22 +22,27 @@ - - Creating index can help you getting results quickly, whether to create or not? + + close - + + Creating index can help you get results more quickly. Would you like to create one? + + + + Don't remind - + No - + Yes @@ -66,32 +71,32 @@ UkuiSearch::UkuiSearchGui - + Quit ukui-search application - + Show main window - + unregister a plugin with <pluginName> - + register a plugin with <pluginName> - + move <pluginName> to the target pos - + move plugin to <index> diff --git a/translations/ukui-search/appwidget/search_mn.ts b/translations/ukui-search/appwidget/search_mn.ts index 7763ed3..63cabce 100644 --- a/translations/ukui-search/appwidget/search_mn.ts +++ b/translations/ukui-search/appwidget/search_mn.ts @@ -22,22 +22,27 @@ - - Creating index can help you getting results quickly, whether to create or not? + + close - + + Creating index can help you get results more quickly. Would you like to create one? + + + + Don't remind - + No - + Yes @@ -66,32 +71,32 @@ UkuiSearch::UkuiSearchGui - + Quit ukui-search application - + Show main window - + unregister a plugin with <pluginName> - + register a plugin with <pluginName> - + move <pluginName> to the target pos - + move plugin to <index> diff --git a/translations/ukui-search/appwidget/search_zh_CN.ts b/translations/ukui-search/appwidget/search_zh_CN.ts index f8a5697..f26856f 100644 --- a/translations/ukui-search/appwidget/search_zh_CN.ts +++ b/translations/ukui-search/appwidget/search_zh_CN.ts @@ -18,10 +18,6 @@ Search - - Creating index can help you getting results quickly, whether to create or not? - - Don't remind @@ -34,6 +30,14 @@ Yes + + close + + + + Creating index can help you get results more quickly. Would you like to create one? + + UkuiSearch::MainWindow diff --git a/translations/ukui-search/bo_CN.ts b/translations/ukui-search/bo_CN.ts index 67a206c..9bcea0a 100644 --- a/translations/ukui-search/bo_CN.ts +++ b/translations/ukui-search/bo_CN.ts @@ -205,32 +205,32 @@ UkuiSearch::UkuiSearchGui - + Quit ukui-search application ཉེར་སྤྱོད་གོ་རིམ་ལས་ཕྱིར་འཐེན་བྱ། - + Show main window སྒེའུ་ཁུང་གཙོ་བོ་མངོན་པ། - + unregister a plugin with <pluginName> - + register a plugin with <pluginName> - + move <pluginName> to the target pos - + move plugin to <index> diff --git a/translations/ukui-search/mn.ts b/translations/ukui-search/mn.ts index 76c47fc..82e2288 100644 --- a/translations/ukui-search/mn.ts +++ b/translations/ukui-search/mn.ts @@ -205,32 +205,32 @@ UkuiSearch::UkuiSearchGui - + Quit ukui-search application ᠬᠠᠢᠯᠲᠠ᠎ᠶᠢᠨ ᠬᠡᠷᠡᠭᠯᠡᠯᠳᠡ᠎ᠡᠴᠡ ᠪᠤᠴᠠᠵᠤ ᠭᠠᠷᠬᠤ - + Show main window ᠭᠤᠤᠯ ᠨᠢᠭᠤᠷ ᠬᠠᠭᠤᠳᠠᠰᠤ᠎ᠶᠢ ᠢᠯᠡᠷᠡᠬᠦᠯᠬᠦ᠌ - + unregister a plugin with <pluginName> - + register a plugin with <pluginName> - + move <pluginName> to the target pos - + move plugin to <index> diff --git a/translations/ukui-search/tr.ts b/translations/ukui-search/tr.ts index 9823aa4..2602e94 100644 --- a/translations/ukui-search/tr.ts +++ b/translations/ukui-search/tr.ts @@ -541,32 +541,32 @@ UkuiSearch::UkuiSearchGui - + Quit ukui-search application - + Show main window - + unregister a plugin with <pluginName> - + register a plugin with <pluginName> - + move <pluginName> to the target pos - + move plugin to <index> diff --git a/translations/ukui-search/zh_CN.ts b/translations/ukui-search/zh_CN.ts index 19b8e69..56d4c51 100644 --- a/translations/ukui-search/zh_CN.ts +++ b/translations/ukui-search/zh_CN.ts @@ -351,32 +351,32 @@ UkuiSearch::UkuiSearchGui - + Quit ukui-search application 退出搜索应用 - + Show main window 显示主页面 - + unregister a plugin with <pluginName> - + register a plugin with <pluginName> - + move <pluginName> to the target pos - + move plugin to <index>