diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/applicationmanager.cpp | 127 | ||||
-rw-r--r-- | src/applicationmanager.h | 43 | ||||
-rw-r--r-- | src/debug.cpp | 6 | ||||
-rw-r--r-- | src/debug.h | 11 | ||||
-rw-r--r-- | src/main.cpp | 70 | ||||
-rw-r--r-- | src/org.freedesktop.DBus.xml | 17 | ||||
-rw-r--r-- | src/vnc-keyboard-unstable-v1.cpp | 146 | ||||
-rw-r--r-- | src/vnc-keyboard-unstable-v1.h | 46 | ||||
-rw-r--r-- | src/waylandentries.cpp | 159 | ||||
-rw-r--r-- | src/waylandentries.h | 53 | ||||
-rw-r--r-- | src/waylandentriesfiltered.cpp | 63 | ||||
-rw-r--r-- | src/waylandentriesfiltered.h | 41 |
12 files changed, 782 insertions, 0 deletions
diff --git a/src/applicationmanager.cpp b/src/applicationmanager.cpp new file mode 100644 index 0000000..13158f3 --- /dev/null +++ b/src/applicationmanager.cpp @@ -0,0 +1,127 @@ +#include "applicationmanager.h" +#include "waylandentries.h" +#include <QWaylandXdgSurface> +#include <QWaylandXdgToplevel> + +ApplicationManager::ApplicationManager(QObject *parent) + : QObject(parent) +{ + +} + +bool ApplicationManager::isHome() const +{ + return m_isHome; +} + +QObject *ApplicationManager::currentSurface() const +{ + return m_currentSurface; +} + +void ApplicationManager::setCurrentSurface(QObject *newCurrentSurface) +{ + if (m_currentSurface == newCurrentSurface) + { + emit currentSurfaceChanged(); + return; + } + m_currentSurface = newCurrentSurface; + emit currentSurfaceChanged(); +} + +int ApplicationManager::count() +{ + WaylandEntries *entries = WaylandEntries::getInstance(); + if(!entries) + return 0; + return entries->rowCount(); +} + +QString ApplicationManager::applicationName(int id) +{ + WaylandEntries *entries = WaylandEntries::getInstance(); + if(!entries) + return ""; + return entries->data(entries->index(id), WaylandEntries::TitleRole).toString(); +} + +int ApplicationManager::applicationPid(int id) +{ + WaylandEntries *entries = WaylandEntries::getInstance(); + if(!entries) + return 0; + return entries->data(entries->index(id), WaylandEntries::PidRole).toInt(); +} + +int ApplicationManager::applicationFocus(int id) +{ + WaylandEntries *entries = WaylandEntries::getInstance(); + if(!entries) + return -1; + if(id >= entries->rowCount()) + return -2; + QVariant d = entries->data(entries->index(id), WaylandEntries::SurfaceRole); + if(!d.isValid()) + return -3; + QWaylandXdgSurface *surface = qvariant_cast<QWaylandXdgSurface *>(d); + if(surface) + { + setCurrentSurface(surface); + return 0; + } + return -4; +} + +int ApplicationManager::currentApplicationPid() +{ + if(isHome()) + return -1; + WaylandEntries *entries = WaylandEntries::getInstance(); + for(int i = 0; i < entries->rowCount(); i++) + { + QVariant d = entries->data(entries->index(i), WaylandEntries::SurfaceRole); + QWaylandXdgSurface *surface = qvariant_cast<QWaylandXdgSurface *>(d); + QWaylandXdgSurface *current = qobject_cast<QWaylandXdgSurface*>(currentSurface()); + if(surface != current) + continue; + return entries->data(entries->index(i), WaylandEntries::PidRole).toInt(); + } + return -2; +} + +void ApplicationManager::hideApplicationPid(qint64 pid) +{ + WaylandEntries *entries = WaylandEntries::getInstance(); + entries->addHidePid(pid); +} + +void ApplicationManager::raiseApplicationPid(qint64 pid) +{ + WaylandEntries *entries = WaylandEntries::getInstance(); + QObject *d = entries->getSurface(pid); + QWaylandXdgSurface *surface = qobject_cast<QWaylandXdgSurface *>(d); + if(surface) + { + setCurrentSurface(surface); + } +} + +void ApplicationManager::backHome() +{ + emit gotoHome(); +} + +void ApplicationManager::setIsHome(bool isHome) +{ + if (m_isHome == isHome) + return; + + m_isHome = isHome; + emit isHomeChanged(m_isHome); +} + +QString ApplicationManager::virtualkeyboard() +{ + return qgetenv("QT_IM_MODULE"); +} diff --git a/src/applicationmanager.h b/src/applicationmanager.h new file mode 100644 index 0000000..b4568f0 --- /dev/null +++ b/src/applicationmanager.h @@ -0,0 +1,43 @@ +#ifndef APPLICATIONMANAGER_H +#define APPLICATIONMANAGER_H + +#include <QObject> + +class ApplicationManager : public QObject +{ + Q_OBJECT + Q_PROPERTY(QObject *currentSurface READ currentSurface WRITE setCurrentSurface NOTIFY currentSurfaceChanged) + Q_PROPERTY(bool isHome READ isHome WRITE setIsHome NOTIFY isHomeChanged) + Q_PROPERTY(QString virtualkeyboard READ virtualkeyboard CONSTANT) + + QObject *m_currentSurface {nullptr}; + bool m_isHome; + +public: + explicit ApplicationManager(QObject *parent = nullptr); + + bool isHome() const; + +public slots: + QObject *currentSurface() const; + void setCurrentSurface(QObject *newCurrentSurface); + + int count(); + QString applicationName(int id); + int applicationPid(int id); + int applicationFocus(int id); + int currentApplicationPid(); + void hideApplicationPid(qint64 pid); + void raiseApplicationPid(qint64 pid); + void backHome(); + void setIsHome(bool isHome); + + QString virtualkeyboard(); + +signals: + void currentSurfaceChanged(); + void gotoHome(); + void isHomeChanged(bool isHome); +}; + +#endif // APPLICATIONMANAGER_H diff --git a/src/debug.cpp b/src/debug.cpp new file mode 100644 index 0000000..a07d815 --- /dev/null +++ b/src/debug.cpp @@ -0,0 +1,6 @@ +#include "debug.h" + +Q_LOGGING_CATEGORY(DESKTOP_MGR_CORE, "desktopmgr.core") +Q_LOGGING_CATEGORY(DESKTOP_MGR_SCREEN_COPY, "desktopmgr.screencopy") +Q_LOGGING_CATEGORY(DESKTOP_MGR_VNC_KEYBOARD, "desktopmgr.vnckeyboard") +Q_LOGGING_CATEGORY(DESKTOP_MGR_VIRTUAL_POINTER, "desktopmgr.virtualpointer") diff --git a/src/debug.h b/src/debug.h new file mode 100644 index 0000000..803192d --- /dev/null +++ b/src/debug.h @@ -0,0 +1,11 @@ +#ifndef DEBUG_H +#define DEBUG_H + +#include <QLoggingCategory> + +Q_DECLARE_LOGGING_CATEGORY(DESKTOP_MGR_CORE) +Q_DECLARE_LOGGING_CATEGORY(DESKTOP_MGR_SCREEN_COPY) +Q_DECLARE_LOGGING_CATEGORY(DESKTOP_MGR_VNC_KEYBOARD) +Q_DECLARE_LOGGING_CATEGORY(DESKTOP_MGR_VIRTUAL_POINTER) + +#endif // DEBUG_H diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..ca19b05 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,70 @@ +#include <QGuiApplication> +#include <QQmlApplicationEngine> +#include <QQmlContext> +#include <QDBusConnection> +#include <QIcon> +#include <QTimer> +#include <QThread> +#include <systemd/sd-daemon.h> +#include <QDir> +#include <QFileInfo> +#include <xdgstatusnotifierwatcher.h> +#include "applicationmanager.h" +#include "applicationsadaptor.h" +#include "waylandentries.h" +#include "waylandentriesfiltered.h" + +int main(int argc, char *argv[]) +{ + qputenv("QT_IM_MODULE", "qtvirtualkeyboard"); + QDBusConnection bus = QDBusConnection::sessionBus(); + QGuiApplication app(argc, argv); + ApplicationManager manager; + QTimer watchdog; + uint64_t watchdogPeriodUSec; + + QFileInfo volatilapps("/var/volatile/applications"); + if(!volatilapps.exists()) + { + QDir().mkdir("/var/volatile/applications"); + } + + qmlRegisterType<WaylandEntries>("org.kazoe.desktop", 1, 0, "WaylandEntries"); + qmlRegisterType<WaylandEntriesFiltered>("org.kazoe.desktop", 1, 0, "WaylandEntriesFiltered"); + + if (!bus.isConnected()) { + qWarning("Cannot connect to the D-Bus session bus.\n" + "Please check your system settings and try again.\n"); + return 1; + } + + QQmlApplicationEngine engine; + new ApplicationsAdaptor(&manager); + bus.registerObject("/applications", &manager); + + + bool conres = bus.registerService("org.kazoe.desktop"); + if(!conres) qWarning() << "Can't register dbus service org.kazoe.desktop"; + + KaZoe::StatusNotifierWatcher notifierWatcher; + + engine.rootContext()->setContextProperty("manager", &manager); + engine.loadFromModule("org.kazoe.desktop", "Main"); + + // signal systemd that the app the ready + QTimer::singleShot(0, [] () { + sd_notify(0, "READY=1"); + } + ); + + // setup a timer to refresh the systemd'd watchdog if needed + if (sd_watchdog_enabled(0,&watchdogPeriodUSec) > 0) { + QObject::connect(&watchdog, &QTimer::timeout, [] () { + sd_notify(0, "WATCHDOG=1"); + } + ); + } + // configure the period of the QT timer for a half period of the watchdog timer + watchdog.start(watchdogPeriodUSec / 2000); + return app.exec(); +} diff --git a/src/org.freedesktop.DBus.xml b/src/org.freedesktop.DBus.xml new file mode 100644 index 0000000..68d5262 --- /dev/null +++ b/src/org.freedesktop.DBus.xml @@ -0,0 +1,17 @@ +<!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.freedesktop.DBus.Properties"> + <method name="GetAll"> + <arg name="interface_name" type="s" direction="in"/> + <arg name="properties" type="a{sv}" direction="out"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/> + </method> + <signal name="PropertiesChanged"> + <arg name="interface_name" type="s" direction="out"/> + <arg name="changed_properties" type="a{sv}" direction="out"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="QVariantMap"/> + <arg name="invalidated_properties" type="as" direction="out"/> + </signal> + </interface> +</node> diff --git a/src/vnc-keyboard-unstable-v1.cpp b/src/vnc-keyboard-unstable-v1.cpp new file mode 100644 index 0000000..5dc8dd7 --- /dev/null +++ b/src/vnc-keyboard-unstable-v1.cpp @@ -0,0 +1,146 @@ +#include <QDebug> +#include <QGuiApplication> +#include <wayland-server-protocol.h> +#include <linux/input-event-codes.h> +#include "vnc-keyboard-unstable-v1.h" + + +void toQtKey(uint32_t key, uint32_t *pkeycode, uint32_t *punicode) +{ + static const QMap<int, int> keyMap { + { 0xff08, Qt::Key_Backspace }, + { 0xff09, Qt::Key_Tab }, + { 0xff0d, Qt::Key_Return }, + { 0xff1b, Qt::Key_Escape }, + { 0xff63, Qt::Key_Insert }, + { 0xffff, Qt::Key_Delete }, + { 0xff50, Qt::Key_Home }, + { 0xff57, Qt::Key_End }, + { 0xff55, Qt::Key_PageUp }, + { 0xff56, Qt::Key_PageDown }, + { 0xff51, Qt::Key_Left }, + { 0xff52, Qt::Key_Up }, + { 0xff53, Qt::Key_Right }, + { 0xff54, Qt::Key_Down }, + { 0xffbe, Qt::Key_F1 }, + { 0xffbf, Qt::Key_F2 }, + { 0xffc0, Qt::Key_F3 }, + { 0xffc1, Qt::Key_F4 }, + { 0xffc2, Qt::Key_F5 }, + { 0xffc3, Qt::Key_F6 }, + { 0xffc4, Qt::Key_F7 }, + { 0xffc5, Qt::Key_F8 }, + { 0xffc6, Qt::Key_F9 }, + { 0xffc7, Qt::Key_F10 }, + { 0xffc8, Qt::Key_F11 }, + { 0xffc9, Qt::Key_F12 }, + { 0xffe1, Qt::Key_Shift }, + { 0xffe2, Qt::Key_Shift }, + { 0xffe3, Qt::Key_Control }, + { 0xffe4, Qt::Key_Control }, + { 0xffe7, Qt::Key_Meta }, + { 0xffe8, Qt::Key_Meta }, + { 0xffe9, Qt::Key_Alt }, + { 0xffea, Qt::Key_Alt }, + + { 0xffb0, Qt::Key_0 }, + { 0xffb1, Qt::Key_1 }, + { 0xffb2, Qt::Key_2 }, + { 0xffb3, Qt::Key_3 }, + { 0xffb4, Qt::Key_4 }, + { 0xffb5, Qt::Key_5 }, + { 0xffb6, Qt::Key_6 }, + { 0xffb7, Qt::Key_7 }, + { 0xffb8, Qt::Key_8 }, + { 0xffb9, Qt::Key_9 }, + + { 0xff8d, Qt::Key_Return }, + { 0xffaa, Qt::Key_Asterisk }, + { 0xffab, Qt::Key_Plus }, + { 0xffad, Qt::Key_Minus }, + { 0xffae, Qt::Key_Period }, + { 0xffaf, Qt::Key_Slash }, + + { 0xff95, Qt::Key_Home }, + { 0xff96, Qt::Key_Left }, + { 0xff97, Qt::Key_Up }, + { 0xff98, Qt::Key_Right }, + { 0xff99, Qt::Key_Down }, + { 0xff9a, Qt::Key_PageUp }, + { 0xff9b, Qt::Key_PageDown }, + { 0xff9c, Qt::Key_End }, + { 0xff9e, Qt::Key_Insert }, + { 0xff9f, Qt::Key_Delete }, + }; + uint32_t unicode = 0; + uint32_t keycode = keyMap.value(key, 0); + + if (keycode >= ' ' && keycode <= '~') + unicode = keycode; + + if (!keycode) { + if (key <= 0xff) { + unicode = key; + if (key >= 'a' && key <= 'z') + keycode = Qt::Key_A + key - 'a'; + else if (key >= ' ' && key <= '~') + keycode = Qt::Key_Space + key - ' '; + } + } + *pkeycode = keycode; + *punicode = unicode; +} + + +VncKeyboardManager::VncKeyboardManager(QWaylandCompositor *compositor) + :QWaylandCompositorExtensionTemplate(compositor) +{ +} + +void VncKeyboardManager::initialize() +{ + QWaylandCompositorExtensionTemplate::initialize(); + QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer()); + init(compositor->display(), 1); +} + +void VncKeyboardManager::vnc_virtual_keyboard_manager_v1_create_virtual_keyboard(Resource *resource, uint32_t id) +{ + new VncKeyboard(m_window, resource->client(), id, 1); +} + +VncKeyboard::VncKeyboard(QQuickWindow *window, struct ::wl_client *client, int id, int version): + QtWaylandServer::vnc_keyboard_v1(client, id, version), + m_window(window), + m_keymod(Qt::NoModifier) +{ +} + +void VncKeyboard::vnc_keyboard_v1_key(Resource *resource, uint32_t time, uint32_t key, uint32_t state) +{ + bool down = !!state; + uint32_t keycode, unicode; + + toQtKey(key, &keycode, &unicode); + + if (keycode == Qt::Key_Shift) + m_keymod = down ? m_keymod | Qt::ShiftModifier : + m_keymod & ~Qt::ShiftModifier; + else if (keycode == Qt::Key_Control) + m_keymod = down ? m_keymod | Qt::ControlModifier : + m_keymod & ~Qt::ControlModifier; + else if (keycode == Qt::Key_Alt) + m_keymod = down ? m_keymod | Qt::AltModifier : + m_keymod & ~Qt::AltModifier; + if (unicode || keycode) { + QKeyEvent event(down ? QEvent::KeyPress : QEvent::KeyRelease, keycode, m_keymod, QString(QChar(unicode))); + QGuiApplication::sendEvent(m_window, &event); + } else { + qDebug() << __func__ << " no unicode or keycode. keysym is " << key << ". state is " << state; + } +} + +void VncKeyboard::vnc_keyboard_v1_destroy(Resource *) +{ + delete this; +} diff --git a/src/vnc-keyboard-unstable-v1.h b/src/vnc-keyboard-unstable-v1.h new file mode 100644 index 0000000..3728b3f --- /dev/null +++ b/src/vnc-keyboard-unstable-v1.h @@ -0,0 +1,46 @@ +#ifndef VIRTUALKEYBOARD_H +#define VIRTUALKEYBOARD_H + +#include "wayland-util.h" +#include <QQuickWindow> +#include <QtWaylandCompositor/QWaylandCompositorExtensionTemplate> +#include <QtWaylandCompositor/QWaylandQuickExtension> +#include <QtWaylandCompositor/QWaylandCompositor> +#include "qwayland-server-vnc-keyboard-unstable-v1.h" + +class VncKeyboardManager : public QWaylandCompositorExtensionTemplate<VncKeyboardManager> + , public QtWaylandServer::vnc_virtual_keyboard_manager_v1 +{ + Q_OBJECT + Q_PROPERTY(QQuickWindow *window MEMBER m_window); + +public: + VncKeyboardManager(QWaylandCompositor *compositor = nullptr); + void initialize() override; + +protected: + void vnc_virtual_keyboard_manager_v1_create_virtual_keyboard(Resource *resource, uint32_t id) override; + +private: + QQuickWindow *m_window; +}; + +class VncKeyboard : public QWaylandCompositorExtensionTemplate<VncKeyboard> + , public QtWaylandServer::vnc_keyboard_v1 +{ + Q_OBJECT +public: + VncKeyboard(QQuickWindow *window, struct ::wl_client *client, int id, int version); + +protected: + void vnc_keyboard_v1_key(Resource *resource, uint32_t time, uint32_t key, uint32_t state) override; + void vnc_keyboard_v1_destroy(Resource *resource) override; + +private: + QQuickWindow *m_window; + Qt::KeyboardModifiers m_keymod; +}; + +Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(VncKeyboardManager) + +#endif // VIRTUALKEYBOARD_H diff --git a/src/waylandentries.cpp b/src/waylandentries.cpp new file mode 100644 index 0000000..42808bb --- /dev/null +++ b/src/waylandentries.cpp @@ -0,0 +1,159 @@ +#include "waylandentries.h" +#include <QWaylandXdgSurface> +#include <QWaylandSurface> +#include <QMutexLocker> +#include <qdebug.h> + +WaylandEntries *m_instance = nullptr; + +WaylandEntries::WaylandEntries(QObject *parent) + : QAbstractListModel(parent) +{ + if(m_instance != nullptr) + { + qWarning() << "Many instance of WaylandEntries"; + } + m_instance = this; +} + +int WaylandEntries::rowCount(const QModelIndex &parent) const +{ + QMutexLocker locker(&m_lock); + return m_surfaces.count(); +} + +QVariant WaylandEntries::data(const QModelIndex &index, int role) const +{ + QMutexLocker locker(&m_lock); + if(index.row() > m_surfaces.count()) + return QVariant(); + + QWaylandXdgSurface *surface = m_surfaces[index.row()]; + if(surface == nullptr) + return QVariant(); + + switch(role) { + case Qt::DisplayRole: + case TitleRole: + return surface->toplevel()->title(); + case AppIdRole: + return surface->toplevel()->appId(); + case SurfaceRole: + return QVariant::fromValue<QWaylandXdgSurface*>(surface); + case PidRole: + return surface->surface()->client()->processId(); + } + + return QVariant(); +} + +QHash<int, QByteArray> WaylandEntries::roleNames() const +{ + QHash<int, QByteArray> roles = QAbstractItemModel::roleNames(); + roles[SurfaceRole] = "wl_surface"; + roles[TitleRole] = "title"; + roles[PidRole] = "pid"; + roles[AppIdRole] = "appId"; + return roles; +} + +// Need only for application manager interface for cli +WaylandEntries *WaylandEntries::getInstance() +{ + return m_instance; +} + +void WaylandEntries::addSurface(QObject *obj) +{ + QMutexLocker locker(&m_lock); + QWaylandXdgSurface *s = qobject_cast<QWaylandXdgSurface*>(obj); + if(s) + { + QObject::connect(s, &QWaylandXdgSurface::destroyed, this, &WaylandEntries::surfaceDestroyed); + if(m_hidden.contains(s->surface()->client()->processId())) + { + m_surfaces_hidden.append(s); + } + else + { + int id = m_surfaces.count(); + beginInsertRows(QModelIndex(), m_surfaces.count(), m_surfaces.count()); + QObject::connect(s->toplevel(), &QWaylandXdgToplevel::titleChanged, this, [this, id](){ + const QVector<int> roles = {TitleRole}; + emit dataChanged(index(id), index(id), roles); + }); + QObject::connect(s->toplevel(), &QWaylandXdgToplevel::appIdChanged, this, [this, id, s](){ + const QVector<int> roles = {AppIdRole}; + + emit topWindowRegistered(s, s->toplevel()->appId()); + emit dataChanged(index(id), index(id), roles); + }); + m_surfaces.append(s); + endInsertRows(); + emit nbAppsChanged(); + } + } +} + +void WaylandEntries::addHidePid(qint64 pid) +{ + QMutexLocker locker(&m_lock); + m_hidden.append(pid); + QWaylandXdgSurface *surfaceToHide = nullptr; + + for(QWaylandXdgSurface *surface: m_surfaces) + { + if(surface->surface()->client()->processId() == pid) + { + surfaceToHide = surface; + break; + } + } + if(surfaceToHide) + { + beginRemoveRows(QModelIndex(), m_surfaces.indexOf(surfaceToHide), m_surfaces.indexOf(surfaceToHide)); + m_surfaces.removeAll(surfaceToHide); + endRemoveRows(); + m_surfaces_hidden.append(surfaceToHide); + emit nbAppsChanged(); + } +} + +void WaylandEntries::surfaceDestroyed() +{ + QObject *obj = QObject::sender(); + QWaylandXdgSurface *s = static_cast<QWaylandXdgSurface*>(obj); + emit topWindowDestroyed(s, s->toplevel()->appId()); + QMutexLocker locker(&m_lock); + beginRemoveRows(QModelIndex(), m_surfaces.indexOf(s), m_surfaces.indexOf(s)); + m_surfaces.removeAll(s); + endRemoveRows(); + emit nbAppsChanged(); +} + +void WaylandEntries::stop(int pid) +{ + kill(pid, SIGTERM); +} + +QObject *WaylandEntries::getSurface(int pid) +{ + QMutexLocker locker(&m_lock); + for(QWaylandXdgSurface *surface: m_surfaces) + { + if(surface->surface()->client()->processId() == pid) + return surface; + } + for(QWaylandXdgSurface *surface: m_surfaces_hidden) + { + if(surface->surface()->client()->processId() == pid) + return surface; + } + return nullptr; +} + +int WaylandEntries::nbApps() const +{ + QMutexLocker locker(&m_lock); + return m_surfaces.count(); +} diff --git a/src/waylandentries.h b/src/waylandentries.h new file mode 100644 index 0000000..ce98ade --- /dev/null +++ b/src/waylandentries.h @@ -0,0 +1,53 @@ +#ifndef WAYLANDENTRIES_H +#define WAYLANDENTRIES_H + +#include <QAbstractListModel> +#include <QRecursiveMutex> +#include <QObject> + +class QWaylandXdgSurface; + +class WaylandEntries : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(int nbApps READ nbApps NOTIFY nbAppsChanged) + + + QList<QWaylandXdgSurface *> m_surfaces; + QList<QWaylandXdgSurface *> m_surfaces_hidden; + QList<qint64> m_hidden; + mutable QRecursiveMutex m_lock; + +public: + explicit WaylandEntries(QObject *parent = nullptr); + + enum WaylandEntryRoles { + SurfaceRole = Qt::UserRole + 1, + TitleRole, + PidRole, + AppIdRole + }; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QHash<int, QByteArray> roleNames() const override; + + static WaylandEntries* getInstance(); + + int nbApps() const; + void setNbApps(int newNbApps); + +public slots: + void addSurface(QObject *obj); + void addHidePid(qint64 pid); + void surfaceDestroyed(); + void stop(int pid); + QObject *getSurface(int pid); + +signals: + void nbAppsChanged(); + void topWindowRegistered(QObject *surface, QString appid); + void topWindowDestroyed(QObject *surface, QString appid); +}; + +#endif // WAYLANDENTRIES_H diff --git a/src/waylandentriesfiltered.cpp b/src/waylandentriesfiltered.cpp new file mode 100644 index 0000000..f1f2ebc --- /dev/null +++ b/src/waylandentriesfiltered.cpp @@ -0,0 +1,63 @@ +#include "waylandentriesfiltered.h" +#include "waylandentries.h" +#include "xdgdesktopentries.h" +#include <QDebug> + +WaylandEntriesFiltered::WaylandEntriesFiltered(QObject *parent) + : QSortFilterProxyModel{parent} +{ + m_entries = new KaZoe::DesktopEntries(this); + QObject::connect(this, &WaylandEntriesFiltered::rowsInserted, this, &WaylandEntriesFiltered::lengthChanged); + QObject::connect(this, &WaylandEntriesFiltered::rowsRemoved, this, &WaylandEntriesFiltered::lengthChanged); +} + +QString WaylandEntriesFiltered::roleFilter() const +{ + return m_roleFilter.join(";"); +} + +void WaylandEntriesFiltered::setRoleFilter(const QString &roles) +{ + QStringList newlist = roles.split(";"); + if (m_roleFilter == newlist) + return; + m_roleFilter = newlist; + emit roleFilterChanged(); +} + +bool WaylandEntriesFiltered::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); + QVariant appid = sourceModel()->data(index, WaylandEntries::AppIdRole); + QString role = m_entries->appIdData(appid.toString(), "Desktop Entry/X-DESKTOPMGR-ROLE"); + + if(appid.isNull()) + return false; + + if(m_roleFilter.contains(role)) + { + return false; + } + return true; +} + +QObject *WaylandEntriesFiltered::model() const +{ + return static_cast<QObject*>(m_model); +} + +void WaylandEntriesFiltered::setModel(QObject *newModel) +{ + WaylandEntries *entries = qobject_cast<WaylandEntries*>(newModel); + if (entries) + { + m_model = entries; + setSourceModel(m_model); + emit modelChanged(m_model); + } +} + +int WaylandEntriesFiltered::length() +{ + return rowCount(); +} diff --git a/src/waylandentriesfiltered.h b/src/waylandentriesfiltered.h new file mode 100644 index 0000000..e562a7d --- /dev/null +++ b/src/waylandentriesfiltered.h @@ -0,0 +1,41 @@ +#ifndef WAYLANDENTIRESFILTERED_H +#define WAYLANDENTIRESFILTERED_H + +#include <QSortFilterProxyModel> +#include <QObject> + +class WaylandEntries; +namespace KaZoe { + class DesktopEntries; +} + +class WaylandEntriesFiltered : public QSortFilterProxyModel +{ + Q_OBJECT + Q_PROPERTY(QObject *model READ model WRITE setModel NOTIFY modelChanged) + Q_PROPERTY(QString roleFilter READ roleFilter WRITE setRoleFilter NOTIFY roleFilterChanged) + Q_PROPERTY(int length READ length NOTIFY lengthChanged) + KaZoe::DesktopEntries *m_entries {nullptr}; + +public: + explicit WaylandEntriesFiltered(QObject *parent = nullptr); + QString roleFilter() const; + void setRoleFilter(const QString &roles); + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; + + QObject *model() const; + void setModel(QObject *newModel); + + int length(); + +signals: + void roleFilterChanged(); + void modelChanged(QObject * model); + void lengthChanged(); + +private: + QStringList m_roleFilter; + WaylandEntries *m_model = nullptr; +}; + +#endif // WAYLANDENTIRESFILTERED_H |