Add windows runner
Move windows runner from plasma-workspace to kwin (convert it to dbus runner) This will allow to interract with windows on wayland too
This commit is contained in:
parent
648dab44da
commit
cf4335ca62
9 changed files with 728 additions and 2 deletions
|
@ -111,6 +111,13 @@ set_package_properties(KF5DocTools PROPERTIES
|
|||
)
|
||||
add_feature_info("KF5DocTools" KF5DocTools_FOUND "Enable building documentation")
|
||||
|
||||
find_package(KF5Runner ${KF5_MIN_VERSION} CONFIG)
|
||||
set_package_properties(KF5Runner PROPERTIES
|
||||
PURPOSE "Enable building of KWin with krunner support"
|
||||
TYPE OPTIONAL
|
||||
)
|
||||
add_feature_info("KF5Runner" KF5Runner_FOUND "Enable building of KWin with krunner support")
|
||||
|
||||
find_package(KF5Kirigami2 ${KF5_MIN_VERSION} CONFIG)
|
||||
set_package_properties(KF5Kirigami2 PROPERTIES
|
||||
DESCRIPTION "A QtQuick based components set"
|
||||
|
@ -336,6 +343,7 @@ option(KWIN_BUILD_KCMS "Enable building of KWin configuration modules." ON)
|
|||
option(KWIN_BUILD_TABBOX "Enable building of KWin Tabbox functionality" ON)
|
||||
option(KWIN_BUILD_XRENDER_COMPOSITING "Enable building of KWin with XRender Compositing support" ON)
|
||||
cmake_dependent_option(KWIN_BUILD_ACTIVITIES "Enable building of KWin with kactivities support" ON "KF5Activities_FOUND" OFF)
|
||||
cmake_dependent_option(KWIN_BUILD_RUNNERS "Enable building of KWin with krunner support" ON "KF5Runner_FOUND" OFF)
|
||||
|
||||
# Binary name of KWin
|
||||
set(KWIN_NAME "kwin")
|
||||
|
@ -590,6 +598,12 @@ if (KWIN_BUILD_ACTIVITIES)
|
|||
)
|
||||
endif()
|
||||
|
||||
if (KWIN_BUILD_RUNNERS)
|
||||
set(kwin_SRCS ${kwin_SRCS}
|
||||
runners/windowsrunnerinterface.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if (HAVE_LINUX_VT_H)
|
||||
set(kwin_SRCS ${kwin_SRCS}
|
||||
virtual_terminal.cpp
|
||||
|
@ -619,6 +633,9 @@ qt5_add_dbus_adaptor(kwin_SRCS org.kde.kwin.ColorCorrect.xml colorcorrection/col
|
|||
qt5_add_dbus_adaptor(kwin_SRCS ${kwin_effects_dbus_xml} effects.h KWin::EffectsHandlerImpl)
|
||||
qt5_add_dbus_adaptor(kwin_SRCS org.kde.KWin.VirtualDesktopManager.xml dbusinterface.h KWin::VirtualDesktopManagerDBusInterface)
|
||||
qt5_add_dbus_adaptor(kwin_SRCS org.kde.KWin.Session.xml sm.h KWin::SessionManager)
|
||||
if (KWIN_BUILD_RUNNERS)
|
||||
qt5_add_dbus_adaptor(kwin_SRCS "runners/org.kde.krunner1.xml" runners/windowsrunnerinterface.h KWin::WindowsRunner)
|
||||
endif()
|
||||
|
||||
qt5_add_dbus_interface(kwin_SRCS ${KSCREENLOCKER_DBUS_INTERFACES_DIR}/kf5_org.freedesktop.ScreenSaver.xml screenlocker_interface)
|
||||
qt5_add_dbus_interface(kwin_SRCS ${KSCREENLOCKER_DBUS_INTERFACES_DIR}/org.kde.screensaver.xml kscreenlocker_interface)
|
||||
|
@ -695,6 +712,10 @@ if (KWIN_BUILD_ACTIVITIES)
|
|||
set(kwin_KDE_LIBS ${kwin_KDE_LIBS} KF5::Activities)
|
||||
endif()
|
||||
|
||||
if (KWIN_BUILD_RUNNERS)
|
||||
set(kwin_KDE_LIBS ${kwin_KDE_LIBS} KF5::Runner)
|
||||
endif()
|
||||
|
||||
set(kwinLibs
|
||||
${kwin_OWN_LIBS}
|
||||
${kwin_QT_LIBS}
|
||||
|
@ -826,6 +847,11 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kwin_export.h DESTINATION ${INCLUDE_IN
|
|||
# Install the KWin/Script service type
|
||||
install(FILES scripting/kwinscript.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR})
|
||||
|
||||
# install KWin krunner runner
|
||||
if (KWIN_BUILD_RUNNERS)
|
||||
install(FILES runners/kwin-runner-windows.desktop DESTINATION ${KDE_INSTALL_DATAROOTDIR}/krunner/dbusplugins)
|
||||
endif()
|
||||
|
||||
add_subdirectory(qml)
|
||||
|
||||
if (BUILD_TESTING)
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#! /usr/bin/env bash
|
||||
$EXTRACTRC *.kcfg *.ui >> rc.cpp
|
||||
$XGETTEXT *.h *.cpp colorcorrection/*.cpp helpers/killer/*.cpp plugins/scenes/opengl/*.cpp tabbox/*.cpp scripting/*.cpp -o $podir/kwin.pot
|
||||
$XGETTEXT *.h *.cpp colorcorrection/*.cpp helpers/killer/*.cpp plugins/scenes/opengl/*.cpp tabbox/*.cpp scripting/*.cpp runners/*.cpp -o $podir/kwin.pot
|
||||
|
|
91
runners/dbusutils_p.h
Normal file
91
runners/dbusutils_p.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2017 David Edmundson <kde@davidedmundson.co.uk>
|
||||
SPDX-FileCopyrightText: 2018 Laurent Montel <montel@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QDBusArgument>
|
||||
#include <QVariantMap>
|
||||
#include <KRunner/QueryMatch>
|
||||
|
||||
struct RemoteMatch
|
||||
{
|
||||
//sssuda{sv}
|
||||
QString id;
|
||||
QString text;
|
||||
QString iconName;
|
||||
Plasma::QueryMatch::Type type = Plasma::QueryMatch::NoMatch;
|
||||
qreal relevance = 0;
|
||||
QVariantMap properties;
|
||||
};
|
||||
|
||||
typedef QList<RemoteMatch> RemoteMatches;
|
||||
|
||||
struct RemoteAction
|
||||
{
|
||||
QString id;
|
||||
QString text;
|
||||
QString iconName;
|
||||
};
|
||||
|
||||
typedef QList<RemoteAction> RemoteActions;
|
||||
|
||||
inline QDBusArgument &operator<< (QDBusArgument &argument, const RemoteMatch &match) {
|
||||
argument.beginStructure();
|
||||
argument << match.id;
|
||||
argument << match.text;
|
||||
argument << match.iconName;
|
||||
argument << match.type;
|
||||
argument << match.relevance;
|
||||
argument << match.properties;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
inline const QDBusArgument &operator>>(const QDBusArgument &argument, RemoteMatch &match) {
|
||||
argument.beginStructure();
|
||||
argument >> match.id;
|
||||
argument >> match.text;
|
||||
argument >> match.iconName;
|
||||
uint type;
|
||||
argument >> type;
|
||||
match.type = (Plasma::QueryMatch::Type)type;
|
||||
argument >> match.relevance;
|
||||
argument >> match.properties;
|
||||
argument.endStructure();
|
||||
|
||||
return argument;
|
||||
}
|
||||
|
||||
inline QDBusArgument &operator<< (QDBusArgument &argument, const RemoteAction &action)
|
||||
{
|
||||
argument.beginStructure();
|
||||
argument << action.id;
|
||||
argument << action.text;
|
||||
argument << action.iconName;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
inline const QDBusArgument &operator>>(const QDBusArgument &argument, RemoteAction &action) {
|
||||
argument.beginStructure();
|
||||
argument >> action.id;
|
||||
argument >> action.text;
|
||||
argument >> action.iconName;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(RemoteMatch)
|
||||
Q_DECLARE_METATYPE(RemoteMatches)
|
||||
Q_DECLARE_METATYPE(RemoteAction)
|
||||
Q_DECLARE_METATYPE(RemoteActions)
|
||||
|
154
runners/kwin-runner-windows.desktop
Normal file
154
runners/kwin-runner-windows.desktop
Normal file
|
@ -0,0 +1,154 @@
|
|||
[Desktop Entry]
|
||||
# ctxt: plasma runner
|
||||
Name=Windows
|
||||
Name[ar]=النوافذ
|
||||
Name[ast]=Ventanes
|
||||
Name[az]=Pəncərələr
|
||||
Name[bg]=Прозорци
|
||||
Name[bn]=উইণ্ডো
|
||||
Name[bs]=Prozori
|
||||
Name[ca]=Finestres
|
||||
Name[ca@valencia]=Finestres
|
||||
Name[cs]=Okna
|
||||
Name[csb]=Òkna
|
||||
Name[da]=Vinduer
|
||||
Name[de]=Fenster
|
||||
Name[el]=Παράθυρα
|
||||
Name[en_GB]=Windows
|
||||
Name[eo]=Fenestroj
|
||||
Name[es]=Ventanas
|
||||
Name[et]=Aknad
|
||||
Name[eu]=Leihoak
|
||||
Name[fa]=پنجرهها
|
||||
Name[fi]=Ikkunat
|
||||
Name[fr]=Fenêtres
|
||||
Name[fy]=Finsters
|
||||
Name[ga]=Fuinneoga
|
||||
Name[gl]=Xanelas
|
||||
Name[gu]=વિન્ડોઝ
|
||||
Name[he]=חלונות
|
||||
Name[hi]=विंडोज़
|
||||
Name[hr]=Prozori
|
||||
Name[hu]=Ablakok
|
||||
Name[ia]=Fenestras
|
||||
Name[id]=Windows
|
||||
Name[is]=Gluggar
|
||||
Name[it]=Finestre
|
||||
Name[ja]=ウィンドウ
|
||||
Name[kk]=Терезелер
|
||||
Name[km]=បង្អួច
|
||||
Name[kn]=ಕಿಟಕಿಗಳು
|
||||
Name[ko]=창
|
||||
Name[lt]=Langai
|
||||
Name[lv]=Logi
|
||||
Name[mk]=Прозорци
|
||||
Name[ml]=ജാലകങ്ങള്
|
||||
Name[mr]=चौकटी
|
||||
Name[nb]=Vinduer
|
||||
Name[nds]=Finstern
|
||||
Name[nl]=Vensters
|
||||
Name[nn]=Vindauge
|
||||
Name[pa]=ਵਿੰਡੋਆਂ
|
||||
Name[pl]=Okna
|
||||
Name[pt]=Janelas
|
||||
Name[pt_BR]=Janelas
|
||||
Name[ro]=Ferestre
|
||||
Name[ru]=Окна
|
||||
Name[si]=කවුළු
|
||||
Name[sk]=Okná
|
||||
Name[sl]=Okna
|
||||
Name[sr]=прозори
|
||||
Name[sr@ijekavian]=прозори
|
||||
Name[sr@ijekavianlatin]=prozori
|
||||
Name[sr@latin]=prozori
|
||||
Name[sv]=Fönster
|
||||
Name[th]=หน้าต่างต่าง ๆ
|
||||
Name[tr]=Pencereler
|
||||
Name[ug]=كۆزنەكلەر
|
||||
Name[uk]=Вікна
|
||||
Name[wa]=Finiesses
|
||||
Name[x-test]=xxWindowsxx
|
||||
Name[zh_CN]=窗口
|
||||
Name[zh_TW]=視窗
|
||||
Comment=List windows and desktops and switch them
|
||||
Comment[ar]=اسرد النوافذ وأسطح المكتب وبدّل بينها
|
||||
Comment[az]=Pəncərələrin, İş Masalarının siyahısı və onlar arası keçid
|
||||
Comment[bg]=Показване и превключване на прозорци и работни плотове
|
||||
Comment[bs]=Nabrajanje i prebacivanje između prozora i površî
|
||||
Comment[ca]=Llista finestres i escriptoris, i canvia entre ells
|
||||
Comment[ca@valencia]=Llista finestres i escriptoris i canvia entre ells
|
||||
Comment[cs]=Seznam oken a ploch k přepínání
|
||||
Comment[da]=Oplist vinduer og skriveborde og skift mellem dem
|
||||
Comment[de]=Listet Fenster und Arbeitsflächen auf und wechselt zwischen ihnen.
|
||||
Comment[el]=Εμφάνιση λίστας παραθύρων και επιφανειών εργασίας για εναλλαγή
|
||||
Comment[en_GB]=List windows and desktops and switch them
|
||||
Comment[eo]=Listi fenestrojn kaj labortablojn kaj ŝanĝi ilin
|
||||
Comment[es]=Lista ventanas y escritorios y cambia entre ellos
|
||||
Comment[et]=Akende ja töölauade näitamine võimalusega neile lülituda
|
||||
Comment[eu]=Zerrendatu leihoak eta mahaigainak, eta batetik bestera aldatu
|
||||
Comment[fi]=Luettele ikkunat ja työpöydät ja vaihda niitä
|
||||
Comment[fr]=Liste les fenêtres / bureaux et passe de l'un à l'autre
|
||||
Comment[fy]=Sommet finsters en buroblêden en wikselt har
|
||||
Comment[ga]=Taispeáin fuinneoga agus deasca agus athraigh eatarthu
|
||||
Comment[gl]=Lista as xanelas e escritorio e salta entre eles
|
||||
Comment[he]=משמש להצגת חלונות ושולחנות עבודה ולהחלפה ביניהם
|
||||
Comment[hr]=Popis prozora i radnih površina za laku promjenu među njima
|
||||
Comment[hu]=Kilistázza az ablakokat és asztalokat, és vált rájuk
|
||||
Comment[ia]=Lista fenestras e scriptorios e commuta los
|
||||
Comment[id]=Daftar window dan desktop dan alihkan mereka
|
||||
Comment[is]=Telur upp glugga og skjáborð og skiptir á milli þeirra
|
||||
Comment[it]=Elenca e passa tra le finestre ed i desktop
|
||||
Comment[ja]=ウィンドウとデスクトップの一覧表示と切り替えを行います
|
||||
Comment[kk]=Бар терезе мен үстелдерді ұсынып оларға ауысу
|
||||
Comment[km]=រាយបង្អួច និងផ្ទៃតុ ហើយប្ដូរពួកវា
|
||||
Comment[kn]=ವಿಂಡೊ ಹಾಗು ಗಣಕತೆರೆಗಳನ್ನು ಪಟ್ಟಿಮಾಡು ಹಾಗು ಅವುಗಳನ್ನು ಬದಲಾಯಿಸು
|
||||
Comment[ko]=창 및 바탕 화면 목록을 보여 주고 전환합니다
|
||||
Comment[lt]=Išvardyti langus ir darbalaukius bei perjungti į juos
|
||||
Comment[lv]=Parāda logus un darbvirsmas un pārslēdz tos
|
||||
Comment[mk]=Приказ на прозорци и раб. површини и преминување меѓу нив
|
||||
Comment[ml]=ജാലകങ്ങളും പണിയിടങ്ങളും പട്ടികയായി കണ്ടു് പരസ്പരം മാറുക
|
||||
Comment[mr]=वेगळ्या चौकट व डेस्कटॉप वर जाण्यासाठी यादी दर्शवा व बदला
|
||||
Comment[nb]=List vinduer og skrivebord og bytt mellom dem
|
||||
Comment[nds]=Finstern un Schriefdischen oplisten un wesseln
|
||||
Comment[nl]=Toon vensters en bureaubladen en schakel ze om
|
||||
Comment[nn]=Vis vindauge og skrivebord, og byt mellom dei
|
||||
Comment[pa]=ਵਿੰਡੋ ਅਤੇ ਡੈਸਕਟਾਪ ਦੀ ਲਿਸਟ ਅਤੇ ਉਹਨਾਂ ਵਿੱਚ ਬਦਲੋ
|
||||
Comment[pl]=Wypisuje okna i pulpity oraz przełącza pomiędzy nimi
|
||||
Comment[pt]=Listar as janelas e ecrãs e mudar entre eles
|
||||
Comment[pt_BR]=Lista as janelas e áreas de trabalho e alterna entre elas
|
||||
Comment[ro]=Enumeră ferestre și birouri și le comută
|
||||
Comment[ru]=Список окон и рабочих столов с возможностью переключения между ними
|
||||
Comment[si]=කවුළු හා වැඩතල ලැයිස්තුගත කර ඒවා මාරුකරන්න
|
||||
Comment[sk]=Zoznam okien a plôch a ich prepínanie
|
||||
Comment[sl]=Seznam oken in namizij ter preklop med njimi
|
||||
Comment[sr]=Набрајање и пребацивање између прозора и површи̂
|
||||
Comment[sr@ijekavian]=Набрајање и пребацивање између прозора и површи̂
|
||||
Comment[sr@ijekavianlatin]=Nabrajanje i prebacivanje između prozora i površî
|
||||
Comment[sr@latin]=Nabrajanje i prebacivanje između prozora i površî
|
||||
Comment[sv]=Lista fönster och skrivbord, och byt mellan dem
|
||||
Comment[th]=รายการหน้าต่างและพื้นที่ทำงานต่าง ๆ ที่สามารถสลับไปใช้งานได้
|
||||
Comment[tr]=Pencereleri ve masaüstlerini listele ve seç
|
||||
Comment[ug]=ھەممە كۆزنەكلەر ۋە ئۈستەلئۈستى تىزىمىنى كۆرسىتىپ، ئۇلارنى ئالماشتۇرىدۇ
|
||||
Comment[uk]=Показує список вікон і стільниць і перемикає їх
|
||||
Comment[vi]=Liệt kê các cửa sổ, màn hình làm việc và chuyển đổi chúng
|
||||
Comment[wa]=Fé l' djivêye des fniesses eyet des scribannes eyet passer d' n' onk a l' ôte
|
||||
Comment[x-test]=xxList windows and desktops and switch themxx
|
||||
Comment[zh_CN]=列出所有窗口和桌面,并可供切换
|
||||
Comment[zh_TW]=列出視窗與桌面並切換
|
||||
X-KDE-ServiceTypes=Plasma/Runner
|
||||
Type=Service
|
||||
Icon=preferences-system-windows
|
||||
X-KDE-PluginInfo-Author=Martin Gräßlin
|
||||
X-KDE-PluginInfo-Email=kde@martin-graesslin.com
|
||||
X-KDE-PluginInfo-Name=windows
|
||||
X-KDE-PluginInfo-Version=1.0
|
||||
X-KDE-PluginInfo-License=GPL
|
||||
X-KDE-PluginInfo-EnabledByDefault=true
|
||||
X-Plasma-AdvertiseSingleRunnerQueryMode=true
|
||||
X-Plasma-API=DBus
|
||||
X-Plasma-DBusRunner-Service=org.kde.KWin
|
||||
X-Plasma-DBusRunner-Path=/WindowsRunner
|
||||
X-Plasma-Request-Actions-Once=true
|
||||
X-Plasma-Runner-Min-Letter-Count=3
|
||||
X-Plasma-Runner-Syntaxes=:q:,:q:,:q:,window,desktop
|
||||
X-Plasma-Runner-Syntax-Descriptions=Finds windows whose name or window application match :q:. It is possible to interact with the windows by using one of the following keywords: activate\\, close\\, min(imize)\\, max(imize)\\, fullscreen\\, shade\\, keep above and keep below.,Finds windows which are on desktop named :q:,Switch to desktop named :q:,Lists all windows and allows to activate them.,Lists all other desktops and allows to switch to them.
|
55
runners/org.kde.krunner1.xml
Normal file
55
runners/org.kde.krunner1.xml
Normal file
|
@ -0,0 +1,55 @@
|
|||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.kde.krunner1">
|
||||
|
||||
<!--
|
||||
Returns a list of actions supported by this runner.
|
||||
For example, a song match returned by a music player runner can be queued, added to the playlist, or played.
|
||||
This should be constant
|
||||
Structure is:
|
||||
- ID
|
||||
- Text
|
||||
- IconName
|
||||
-->
|
||||
<method name="Actions">
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="RemoteActions" />
|
||||
<arg name="matches" type="a(sss)" direction="out">
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
Execute an action
|
||||
-->
|
||||
<method name="Run">
|
||||
<!--
|
||||
The Unique ID from Match.
|
||||
-->
|
||||
<arg name="matchId" type="s" direction="in"/>
|
||||
<!--
|
||||
The action ID to run. For the default action this will be empty.
|
||||
-->
|
||||
<arg name="actionId" type="s" direction="in"/>
|
||||
</method>
|
||||
<!--
|
||||
Fetch matching results for a given query.
|
||||
|
||||
Note: Multiple Match calls may be made with new queries before a call has returned
|
||||
has returned.
|
||||
-->
|
||||
<method name="Match">
|
||||
<arg name="query" type="s" direction="in"/>
|
||||
<!--
|
||||
Return a list of items that match the
|
||||
Structure is:
|
||||
- Id
|
||||
- Text
|
||||
- IconName
|
||||
- Type (see PlasmaQuery::Type)
|
||||
- Relevance
|
||||
- Properties (VariantMap)
|
||||
-->
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="RemoteMatches"/>
|
||||
<arg name="matches" type="a(sssuda{sv})" direction="out"/>
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
330
runners/windowsrunnerinterface.cpp
Normal file
330
runners/windowsrunnerinterface.cpp
Normal file
|
@ -0,0 +1,330 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2009 Martin Gräßlin <kde@martin-graesslin.com>
|
||||
SPDX-FileCopyrightText: 2020 Benjamin Port <benjamin.port@enioka.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "windowsrunnerinterface.h"
|
||||
|
||||
#include "abstract_client.h"
|
||||
#include "workspace.h"
|
||||
|
||||
#include "krunner1adaptor.h"
|
||||
#include <KLocalizedString>
|
||||
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
WindowsRunner::WindowsRunner(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
new Krunner1Adaptor(this);
|
||||
qDBusRegisterMetaType<RemoteMatch>();
|
||||
qDBusRegisterMetaType<RemoteMatches>();
|
||||
qDBusRegisterMetaType<RemoteAction>();
|
||||
qDBusRegisterMetaType<RemoteActions>();
|
||||
QDBusConnection::sessionBus().registerObject(QStringLiteral("/WindowsRunner"), this);
|
||||
QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.KWin"));
|
||||
}
|
||||
|
||||
WindowsRunner::~WindowsRunner()
|
||||
{
|
||||
}
|
||||
|
||||
RemoteActions WindowsRunner::Actions()
|
||||
{
|
||||
RemoteActions actions;
|
||||
return actions;
|
||||
}
|
||||
|
||||
RemoteMatches WindowsRunner::Match(const QString &searchTerm)
|
||||
{
|
||||
RemoteMatches matches;
|
||||
|
||||
auto term = searchTerm;
|
||||
WindowsRunnerAction action = ActivateAction;
|
||||
if (term.endsWith(i18nc("Note this is a KRunner keyword", "activate") , Qt::CaseInsensitive)) {
|
||||
action = ActivateAction;
|
||||
term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "activate")) - 1);
|
||||
} else if (term.endsWith(i18nc("Note this is a KRunner keyword", "close") , Qt::CaseInsensitive)) {
|
||||
action = CloseAction;
|
||||
term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "close")) - 1);
|
||||
} else if (term.endsWith(i18nc("Note this is a KRunner keyword", "min") , Qt::CaseInsensitive)) {
|
||||
action = MinimizeAction;
|
||||
term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "min")) - 1);
|
||||
} else if (term.endsWith(i18nc("Note this is a KRunner keyword", "minimize") , Qt::CaseInsensitive)) {
|
||||
action = MinimizeAction;
|
||||
term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "minimize")) - 1);
|
||||
} else if (term.endsWith(i18nc("Note this is a KRunner keyword", "max") , Qt::CaseInsensitive)) {
|
||||
action = MaximizeAction;
|
||||
term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "max")) - 1);
|
||||
} else if (term.endsWith(i18nc("Note this is a KRunner keyword", "maximize") , Qt::CaseInsensitive)) {
|
||||
action = MaximizeAction;
|
||||
term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "maximize")) - 1);
|
||||
} else if (term.endsWith(i18nc("Note this is a KRunner keyword", "fullscreen") , Qt::CaseInsensitive)) {
|
||||
action = FullscreenAction;
|
||||
term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "fullscreen")) - 1);
|
||||
} else if (term.endsWith(i18nc("Note this is a KRunner keyword", "shade") , Qt::CaseInsensitive)) {
|
||||
action = ShadeAction;
|
||||
term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "shade")) - 1);
|
||||
} else if (term.endsWith(i18nc("Note this is a KRunner keyword", "keep above") , Qt::CaseInsensitive)) {
|
||||
action = KeepAboveAction;
|
||||
term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "keep above")) - 1);
|
||||
} else if (term.endsWith(i18nc("Note this is a KRunner keyword", "keep below") , Qt::CaseInsensitive)) {
|
||||
action = KeepBelowAction;
|
||||
term = term.left(term.lastIndexOf(i18nc("Note this is a KRunner keyword", "keep below")) - 1);
|
||||
}
|
||||
|
||||
// keyword match: when term starts with "window" we list all windows
|
||||
// the list can be restricted to windows matching a given name, class, role or desktop
|
||||
if (term.startsWith(i18nc("Note this is a KRunner keyword", "window") , Qt::CaseInsensitive)) {
|
||||
const QStringList keywords = term.split(QLatin1Char(' '));
|
||||
QString windowName;
|
||||
QString windowAppName;
|
||||
VirtualDesktop *targetDesktop = nullptr;
|
||||
QVariant desktopId;
|
||||
for (const QString& keyword : keywords) {
|
||||
if (keyword.endsWith(QLatin1Char('='))) {
|
||||
continue;
|
||||
}
|
||||
if (keyword.startsWith(i18nc("Note this is a KRunner keyword", "name") + QStringLiteral("=") , Qt::CaseInsensitive)) {
|
||||
windowName = keyword.split(QStringLiteral("="))[1];
|
||||
} else if (keyword.startsWith(i18nc("Note this is a KRunner keyword", "appname") + QStringLiteral("=") , Qt::CaseInsensitive)) {
|
||||
windowAppName = keyword.split(QStringLiteral("="))[1];
|
||||
} else if (keyword.startsWith(i18nc("Note this is a KRunner keyword", "desktop") + QStringLiteral("=") , Qt::CaseInsensitive)) {
|
||||
desktopId = keyword.split(QStringLiteral("="))[1];
|
||||
for (const auto desktop : VirtualDesktopManager::self()->desktops()) {
|
||||
if (desktop->name().contains(desktopId.toString(), Qt::CaseInsensitive) || desktop->x11DesktopNumber() == desktopId.toUInt()) {
|
||||
targetDesktop = desktop;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// not a keyword - use as name if name is unused, but another option is set
|
||||
if (windowName.isEmpty() && !keyword.contains(QLatin1Char('=')) && (!windowAppName.isEmpty() || targetDesktop)) {
|
||||
windowName = keyword;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const AbstractClient *client : Workspace::self()->allClientList()) {
|
||||
if (!client->isNormalWindow()) {
|
||||
continue;
|
||||
}
|
||||
const QString appName = client->resourceClass();
|
||||
const QString name = client->caption();
|
||||
if (!windowName.isEmpty() && !name.startsWith(windowName, Qt::CaseInsensitive)) {
|
||||
continue;
|
||||
}
|
||||
if (!windowAppName.isEmpty() && !appName.contains(windowAppName, Qt::CaseInsensitive)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (targetDesktop && !client->desktops().contains(targetDesktop) && !client->isOnAllDesktops()) {
|
||||
continue;
|
||||
}
|
||||
// check for windows when no keywords were used
|
||||
// check the name and app name for containing the query without the keyword
|
||||
if (windowName.isEmpty() && windowAppName.isEmpty() && !targetDesktop) {
|
||||
const QString& test = term.mid(keywords[0].length() + 1);
|
||||
if (!name.contains(test, Qt::CaseInsensitive) && !appName.contains(test, Qt::CaseInsensitive)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// blacklisted everything else: we have a match
|
||||
if (actionSupported(client, action)){
|
||||
matches << windowsMatch(client, action);
|
||||
}
|
||||
}
|
||||
|
||||
if (!matches.isEmpty()) {
|
||||
// the window keyword found matches - do not process other syntax possibilities
|
||||
return matches;
|
||||
}
|
||||
}
|
||||
|
||||
bool desktopAdded = false;
|
||||
// check for desktop keyword
|
||||
if (term.startsWith(i18nc("Note this is a KRunner keyword", "desktop") , Qt::CaseInsensitive)) {
|
||||
const QStringList parts = term.split(QLatin1Char(' '));
|
||||
if (parts.size() == 1) {
|
||||
// only keyword - list all desktops
|
||||
for (auto desktop : VirtualDesktopManager::self()->desktops()) {
|
||||
matches << desktopMatch(desktop);
|
||||
desktopAdded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for matching desktops by name
|
||||
for (const AbstractClient *client : Workspace::self()->allClientList()) {
|
||||
if (!client->isNormalWindow()) {
|
||||
continue;
|
||||
}
|
||||
const QString appName = client->resourceClass();
|
||||
const QString name = client->caption();
|
||||
if (name.startsWith(term, Qt::CaseInsensitive) || appName.startsWith(term, Qt::CaseInsensitive)) {
|
||||
matches << windowsMatch(client, action, 0.8, Plasma::QueryMatch::ExactMatch);
|
||||
} else if ((name.contains(term, Qt::CaseInsensitive) || appName.contains(term, Qt::CaseInsensitive)) && actionSupported(client, action)) {
|
||||
matches << windowsMatch(client, action, 0.7, Plasma::QueryMatch::PossibleMatch);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto *desktop : VirtualDesktopManager::self()->desktops()) {
|
||||
if (desktop->name().contains(term, Qt::CaseInsensitive)) {
|
||||
if (!desktopAdded && desktop != VirtualDesktopManager::self()->currentDesktop()) {
|
||||
matches << desktopMatch(desktop, ActivateDesktopAction, 0.8);
|
||||
}
|
||||
// search for windows on desktop and list them with less relevance
|
||||
for (const AbstractClient *client : Workspace::self()->allClientList()) {
|
||||
if (!client->isNormalWindow()) {
|
||||
continue;
|
||||
}
|
||||
if ((client->desktops().contains(desktop) || client->isOnAllDesktops()) && actionSupported(client, action)) {
|
||||
matches << windowsMatch(client, action, 0.5, Plasma::QueryMatch::PossibleMatch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
void WindowsRunner::Run(const QString &id, const QString &actionId)
|
||||
{
|
||||
// Split id to get actionId and realId. We don't use actionId because our actions list is not constant
|
||||
const QStringList parts = id.split(QLatin1Char('_'));
|
||||
auto action = WindowsRunnerAction(parts[0].toInt());
|
||||
auto objectId = parts[1];
|
||||
|
||||
if (action == ActivateDesktopAction) {
|
||||
QByteArray desktopId = objectId.toLocal8Bit();
|
||||
auto desktop = VirtualDesktopManager::self()->desktopForId(desktopId);
|
||||
VirtualDesktopManager::self()->setCurrent(desktop);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const auto uuid = QUuid::fromString(objectId);
|
||||
const auto client = workspace()->findAbstractClient(uuid);
|
||||
switch (action) {
|
||||
case ActivateAction:
|
||||
workspace()->activateClient(client);
|
||||
break;
|
||||
case CloseAction:
|
||||
client->closeWindow();
|
||||
break;
|
||||
case MinimizeAction:
|
||||
client->setMinimized(!client->isMinimized());
|
||||
break;
|
||||
case MaximizeAction:
|
||||
client->setMaximize(client->maximizeMode() == MaximizeRestore, client->maximizeMode() == MaximizeRestore);
|
||||
break;
|
||||
case FullscreenAction:
|
||||
client->setFullScreen(!client->isFullScreen());
|
||||
break;
|
||||
case ShadeAction:
|
||||
client->toggleShade();
|
||||
break;
|
||||
case KeepAboveAction:
|
||||
client->setKeepAbove(!client->keepAbove());
|
||||
break;
|
||||
case KeepBelowAction:
|
||||
client->setKeepBelow(!client->keepBelow());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RemoteMatch WindowsRunner::desktopMatch(const VirtualDesktop *desktop, const WindowsRunnerAction action, qreal relevance) const
|
||||
{
|
||||
RemoteMatch match;
|
||||
match.id = QString::number((int)action) + QLatin1Char('_') + desktop->id();
|
||||
match.type = Plasma::QueryMatch::ExactMatch;
|
||||
match.iconName = QStringLiteral("user-desktop");
|
||||
match.text = desktop->name();
|
||||
match.relevance = relevance;
|
||||
|
||||
QVariantMap properties;
|
||||
|
||||
properties[QStringLiteral("subtext")] = i18n("Switch to desktop %1", desktop->name());
|
||||
match.properties = properties;
|
||||
return match;
|
||||
}
|
||||
|
||||
RemoteMatch WindowsRunner::windowsMatch(const AbstractClient *client, const WindowsRunnerAction action, qreal relevance, Plasma::QueryMatch::Type type) const
|
||||
{
|
||||
RemoteMatch match;
|
||||
match.id = QString::number((int)action) + QLatin1Char('_') + client->internalId().toString();
|
||||
match.text = client->caption();
|
||||
match.iconName = client->icon().name();
|
||||
match.relevance = relevance;
|
||||
match.type = type;
|
||||
QVariantMap properties;
|
||||
|
||||
const QVector<VirtualDesktop *> desktops = client->desktops();
|
||||
bool allDesktops = client->isOnAllDesktops();
|
||||
|
||||
const VirtualDesktop *targetDesktop = VirtualDesktopManager::self()->currentDesktop();
|
||||
// Show on current desktop unless window is only attached to other desktop, in this case show on the first attached desktop
|
||||
if (!allDesktops && !client->isOnCurrentDesktop() && !desktops.isEmpty()) {
|
||||
targetDesktop = desktops.first();
|
||||
}
|
||||
|
||||
const QString desktopName = targetDesktop->name();
|
||||
switch (action) {
|
||||
case CloseAction:
|
||||
properties[QStringLiteral("subtext")] = i18n("Close running window on %1", desktopName);
|
||||
break;
|
||||
case MinimizeAction:
|
||||
properties[QStringLiteral("subtext")] = i18n("(Un)minimize running window on %1", desktopName);
|
||||
break;
|
||||
case MaximizeAction:
|
||||
properties[QStringLiteral("subtext")] = i18n("Maximize/restore running window on %1", desktopName);
|
||||
break;
|
||||
case FullscreenAction:
|
||||
properties[QStringLiteral("subtext")] = i18n("Toggle fullscreen for running window on %1", desktopName);
|
||||
break;
|
||||
case ShadeAction:
|
||||
properties[QStringLiteral("subtext")] = i18n("(Un)shade running window on %1", desktopName);
|
||||
break;
|
||||
case KeepAboveAction:
|
||||
properties[QStringLiteral("subtext")] = i18n("Toggle keep above for running window on %1", desktopName);
|
||||
break;
|
||||
case KeepBelowAction:
|
||||
properties[QStringLiteral("subtext")] = i18n("Toggle keep below running window on %1", desktopName);
|
||||
break;
|
||||
case ActivateAction:
|
||||
default:
|
||||
properties[QStringLiteral("subtext")] = i18n("Activate running window on %1", desktopName);
|
||||
break;
|
||||
}
|
||||
match.properties = properties;
|
||||
return match;
|
||||
}
|
||||
|
||||
bool WindowsRunner::actionSupported(const AbstractClient *client, const WindowsRunnerAction action) const
|
||||
{
|
||||
switch (action) {
|
||||
case CloseAction:
|
||||
return client->isCloseable();
|
||||
case MinimizeAction:
|
||||
return client->isMinimizable();
|
||||
case MaximizeAction:
|
||||
return client->isMaximizable();
|
||||
case ShadeAction:
|
||||
return client->isShadeable();
|
||||
case FullscreenAction:
|
||||
return client->isFullScreenable();
|
||||
case KeepAboveAction:
|
||||
case KeepBelowAction:
|
||||
case ActivateAction:
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
63
runners/windowsrunnerinterface.h
Normal file
63
runners/windowsrunnerinterface.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2009 Martin Gräßlin <kde@martin-graesslin.com>
|
||||
SPDX-FileCopyrightText: 2020 Benjamin Port <benjamin.port@enioka.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef WINDOWSRUNNER_H
|
||||
#define WINDOWSRUNNER_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QDBusContext>
|
||||
#include <QDBusMessage>
|
||||
#include <QString>
|
||||
#include <QDBusArgument>
|
||||
|
||||
#include <KRunner/QueryMatch>
|
||||
#include "dbusutils_p.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
class VirtualDesktop;
|
||||
class AbstractClient;
|
||||
|
||||
class WindowsRunner : public QObject, protected QDBusContext
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.kde.KWin.WindowsRunner")
|
||||
public:
|
||||
explicit WindowsRunner(QObject *parent = nullptr);
|
||||
~WindowsRunner() override;
|
||||
|
||||
RemoteActions Actions();
|
||||
RemoteMatches Match(const QString &searchTerm);
|
||||
void Run(const QString &id, const QString &actionId);
|
||||
|
||||
private:
|
||||
enum WindowsRunnerAction {
|
||||
// Windows related actions
|
||||
ActivateAction,
|
||||
CloseAction,
|
||||
MinimizeAction,
|
||||
MaximizeAction,
|
||||
FullscreenAction,
|
||||
ShadeAction,
|
||||
KeepAboveAction,
|
||||
KeepBelowAction,
|
||||
// Desktop related actions
|
||||
ActivateDesktopAction
|
||||
};
|
||||
|
||||
RemoteMatch desktopMatch(const VirtualDesktop *desktop, const WindowsRunnerAction action = ActivateDesktopAction, qreal relevance = 1.0) const;
|
||||
RemoteMatch windowsMatch(const AbstractClient *client, const WindowsRunnerAction action = ActivateAction, qreal relevance = 1.0, Plasma::QueryMatch::Type type = Plasma::QueryMatch::ExactMatch) const;
|
||||
bool actionSupported(const AbstractClient *client, const WindowsRunnerAction action) const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // WINDOWSRUNNER_H
|
|
@ -59,6 +59,7 @@
|
|||
#include <KStartupInfo>
|
||||
// Qt
|
||||
#include <QtConcurrentRun>
|
||||
#include <runners/windowsrunnerinterface.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
@ -197,7 +198,7 @@ Workspace::Workspace()
|
|||
});
|
||||
|
||||
new DBusInterface(this);
|
||||
|
||||
new WindowsRunner(this);
|
||||
Outline::create(this);
|
||||
|
||||
initShortcuts();
|
||||
|
@ -1689,6 +1690,11 @@ AbstractClient *Workspace::findAbstractClient(std::function<bool (const Abstract
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
AbstractClient *Workspace::findAbstractClient(const QUuid &internalId) const
|
||||
{
|
||||
return qobject_cast<AbstractClient *>(findToplevel(internalId));
|
||||
}
|
||||
|
||||
Unmanaged *Workspace::findUnmanaged(std::function<bool (const Unmanaged*)> func) const
|
||||
{
|
||||
return Toplevel::findInList(m_unmanaged, func);
|
||||
|
|
|
@ -115,6 +115,7 @@ public:
|
|||
*/
|
||||
X11Client *findClient(std::function<bool (const X11Client *)> func) const;
|
||||
AbstractClient *findAbstractClient(std::function<bool (const AbstractClient*)> func) const;
|
||||
AbstractClient *findAbstractClient(const QUuid &internalId) const;
|
||||
/**
|
||||
* @brief Finds the Client matching the given match @p predicate for the given window.
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue