Introduces a new `core/windows` module (`Nebula.Windows`) with `WindowService`, window/workspace models, and a Sway IPC backend for live window tracking and control (focus, close, move/resize, snap, maximize/restore, minimize, workspace switch). The desktop shell now links this module, uses compositor focus for top-bar active app text, and adds an Open Windows section in the launcher with focus/close actions. Also updates application metadata handling to parse `StartupWMClass` and map window `app_id`/class to friendly names and icons, and revises Sway config/docs for the new floating-first Desktop 0.2 behavior with temporary compositor-provided decorations.
115 lines
3.0 KiB
C++
115 lines
3.0 KiB
C++
#include "WindowModel.hpp"
|
|
|
|
#include <utility>
|
|
|
|
WindowModel::WindowModel(QObject *parent)
|
|
: QAbstractListModel(parent)
|
|
{
|
|
}
|
|
|
|
int WindowModel::rowCount(const QModelIndex &parent) const
|
|
{
|
|
if (parent.isValid())
|
|
return 0;
|
|
return m_windows.size();
|
|
}
|
|
|
|
int WindowModel::count() const
|
|
{
|
|
return m_windows.size();
|
|
}
|
|
|
|
QVariant WindowModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
if (!index.isValid() || index.row() < 0 || index.row() >= m_windows.size())
|
|
return {};
|
|
|
|
const WindowInfo &window = m_windows.at(index.row());
|
|
switch (role) {
|
|
case WindowIdRole:
|
|
return QString::number(window.id);
|
|
case TitleRole:
|
|
return window.title;
|
|
case AppIdRole:
|
|
return window.appId;
|
|
case WindowClassRole:
|
|
return window.windowClass;
|
|
case WorkspaceRole:
|
|
return window.workspace;
|
|
case FocusedRole:
|
|
return window.focused;
|
|
case FloatingRole:
|
|
return window.floating;
|
|
case FullscreenRole:
|
|
return window.fullscreen;
|
|
case XRole:
|
|
return window.x;
|
|
case YRole:
|
|
return window.y;
|
|
case WidthRole:
|
|
return window.width;
|
|
case HeightRole:
|
|
return window.height;
|
|
case DisplayNameRole:
|
|
case Qt::DisplayRole:
|
|
return window.displayName.isEmpty() ? window.title : window.displayName;
|
|
case IconNameRole:
|
|
return window.iconName;
|
|
case MinimizedRole:
|
|
return window.minimized;
|
|
case MaximizedRole:
|
|
return window.maximized;
|
|
case OutputRole:
|
|
return window.output;
|
|
default:
|
|
return {};
|
|
}
|
|
}
|
|
|
|
QHash<int, QByteArray> WindowModel::roleNames() const
|
|
{
|
|
return {
|
|
{WindowIdRole, QByteArrayLiteral("windowId")},
|
|
{TitleRole, QByteArrayLiteral("title")},
|
|
{AppIdRole, QByteArrayLiteral("appId")},
|
|
{WindowClassRole, QByteArrayLiteral("windowClass")},
|
|
{WorkspaceRole, QByteArrayLiteral("workspace")},
|
|
{FocusedRole, QByteArrayLiteral("focused")},
|
|
{FloatingRole, QByteArrayLiteral("floating")},
|
|
{FullscreenRole, QByteArrayLiteral("fullscreen")},
|
|
{XRole, QByteArrayLiteral("x")},
|
|
{YRole, QByteArrayLiteral("y")},
|
|
{WidthRole, QByteArrayLiteral("width")},
|
|
{HeightRole, QByteArrayLiteral("height")},
|
|
{DisplayNameRole, QByteArrayLiteral("displayName")},
|
|
{IconNameRole, QByteArrayLiteral("iconName")},
|
|
{MinimizedRole, QByteArrayLiteral("minimized")},
|
|
{MaximizedRole, QByteArrayLiteral("maximized")},
|
|
{OutputRole, QByteArrayLiteral("output")},
|
|
};
|
|
}
|
|
|
|
void WindowModel::setWindows(QVector<WindowInfo> windows)
|
|
{
|
|
beginResetModel();
|
|
m_windows = std::move(windows);
|
|
endResetModel();
|
|
emit countChanged();
|
|
}
|
|
|
|
const WindowInfo *WindowModel::windowAt(int row) const
|
|
{
|
|
if (row < 0 || row >= m_windows.size())
|
|
return nullptr;
|
|
return &m_windows.at(row);
|
|
}
|
|
|
|
const WindowInfo *WindowModel::windowById(qint64 windowId) const
|
|
{
|
|
for (const WindowInfo &window : m_windows) {
|
|
if (window.id == windowId)
|
|
return &window;
|
|
}
|
|
return nullptr;
|
|
}
|