[wayland] Add support for the PlasmaShell interface
The PlasmaShell interface allows to create a PlasmaShellSurface for a given Surface. Through this interface the Surface can request: * a specific position * a window type So far only the window types Normal, Panel and Desktop are supported which is a sufficient subset for getting plasmashell to work. In future there should be security checks so that only the dedicated desktop shell can bind these interfaces.
This commit is contained in:
parent
2bdabe62aa
commit
124bd8aaed
5 changed files with 103 additions and 1 deletions
|
@ -30,6 +30,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <KWayland/Server/shell_interface.h>
|
||||
#include <KWayland/Server/surface_interface.h>
|
||||
#include <KWayland/Server/buffer_interface.h>
|
||||
#include <KWayland/Server/plasmashell_interface.h>
|
||||
|
||||
#include <QWindow>
|
||||
|
||||
|
@ -125,6 +126,20 @@ void ShellClient::debug(QDebug &stream) const
|
|||
Layer ShellClient::layer() const
|
||||
{
|
||||
// TODO: implement the rest
|
||||
if (isDesktop())
|
||||
return workspace()->showingDesktop() ? AboveLayer : DesktopLayer;
|
||||
if (isDock()) {
|
||||
if (workspace()->showingDesktop())
|
||||
return NotificationLayer;
|
||||
// slight hack for the 'allow window to cover panel' Kicker setting
|
||||
// don't move keepbelow docks below normal window, but only to the same
|
||||
// layer, so that both may be raised to cover the other
|
||||
if (keepBelow())
|
||||
return NormalLayer;
|
||||
if (keepAbove()) // slight hack for the autohiding panels
|
||||
return AboveLayer;
|
||||
return DockLayer;
|
||||
}
|
||||
if (isFullScreen() && isActive())
|
||||
return ActiveLayer;
|
||||
return KWin::NormalLayer;
|
||||
|
@ -517,4 +532,43 @@ void ShellClient::unmap()
|
|||
workspace()->clientHidden(this);
|
||||
}
|
||||
|
||||
void ShellClient::installPlasmaShellSurface(PlasmaShellSurfaceInterface *surface)
|
||||
{
|
||||
m_plasmaShellSurface = surface;
|
||||
auto updatePosition = [this, surface] {
|
||||
setGeometry(QRect(surface->position(), m_clientSize));
|
||||
};
|
||||
auto updateRole = [this, surface] {
|
||||
NET::WindowType type = NET::Unknown;
|
||||
switch (surface->role()) {
|
||||
case PlasmaShellSurfaceInterface::Role::Desktop:
|
||||
type = NET::Desktop;
|
||||
break;
|
||||
case PlasmaShellSurfaceInterface::Role::Panel:
|
||||
type = NET::Dock;
|
||||
break;
|
||||
case PlasmaShellSurfaceInterface::Role::Normal:
|
||||
default:
|
||||
type = NET::Normal;
|
||||
break;
|
||||
}
|
||||
if (type != m_windowType) {
|
||||
m_windowType = type;
|
||||
workspace()->updateClientArea();
|
||||
}
|
||||
};
|
||||
connect(surface, &PlasmaShellSurfaceInterface::positionChanged, this, updatePosition);
|
||||
connect(surface, &PlasmaShellSurfaceInterface::roleChanged, this, updateRole);
|
||||
updatePosition();
|
||||
updateRole();
|
||||
}
|
||||
|
||||
bool ShellClient::isInitialPositionSet() const
|
||||
{
|
||||
if (m_plasmaShellSurface) {
|
||||
return m_plasmaShellSurface->isPositionSet();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace KWayland
|
|||
namespace Server
|
||||
{
|
||||
class ShellSurfaceInterface;
|
||||
class PlasmaShellSurfaceInterface;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,6 +102,10 @@ public:
|
|||
return m_internalWindow;
|
||||
}
|
||||
|
||||
void installPlasmaShellSurface(KWayland::Server::PlasmaShellSurfaceInterface *surface);
|
||||
|
||||
bool isInitialPositionSet() const;
|
||||
|
||||
protected:
|
||||
void addDamage(const QRegion &damage) override;
|
||||
bool belongsToSameApplication(const AbstractClient *other, bool active_hack) const override;
|
||||
|
@ -130,6 +135,7 @@ private:
|
|||
MaximizeMode m_maximizeMode = MaximizeRestore;
|
||||
QRect m_geomMaximizeRestore; // size and position of the window before it was set to maximize
|
||||
NET::WindowType m_windowType = NET::Normal;
|
||||
QPointer<KWayland::Server::PlasmaShellSurfaceInterface> m_plasmaShellSurface;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <KWayland/Server/datadevicemanager_interface.h>
|
||||
#include <KWayland/Server/display.h>
|
||||
#include <KWayland/Server/output_interface.h>
|
||||
#include <KWayland/Server/plasmashell_interface.h>
|
||||
#include <KWayland/Server/seat_interface.h>
|
||||
#include <KWayland/Server/shell_interface.h>
|
||||
|
||||
|
@ -136,6 +137,15 @@ void WaylandServer::init(const QByteArray &socketName)
|
|||
m_seat = m_display->createSeat(m_display);
|
||||
m_seat->create();
|
||||
m_display->createDataDeviceManager(m_display)->create();
|
||||
m_plasmaShell = m_display->createPlasmaShell(m_display);
|
||||
m_plasmaShell->create();
|
||||
connect(m_plasmaShell, &PlasmaShellInterface::surfaceCreated,
|
||||
[this] (PlasmaShellSurfaceInterface *surface) {
|
||||
if (ShellClient *client = findClient(surface->surface())) {
|
||||
client->installPlasmaShellSurface(surface);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void WaylandServer::initOutputs()
|
||||
|
@ -285,6 +295,19 @@ static ShellClient *findClientInList(const QList<ShellClient*> &clients, quint32
|
|||
return *it;
|
||||
}
|
||||
|
||||
static ShellClient *findClientInList(const QList<ShellClient*> &clients, KWayland::Server::SurfaceInterface *surface)
|
||||
{
|
||||
auto it = std::find_if(clients.begin(), clients.end(),
|
||||
[surface] (ShellClient *c) {
|
||||
return c->surface() == surface;
|
||||
}
|
||||
);
|
||||
if (it == clients.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return *it;
|
||||
}
|
||||
|
||||
ShellClient *WaylandServer::findClient(quint32 id) const
|
||||
{
|
||||
if (id == 0) {
|
||||
|
@ -299,6 +322,20 @@ ShellClient *WaylandServer::findClient(quint32 id) const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
ShellClient *WaylandServer::findClient(SurfaceInterface *surface) const
|
||||
{
|
||||
if (!surface) {
|
||||
return nullptr;
|
||||
}
|
||||
if (ShellClient *c = findClientInList(m_clients, surface)) {
|
||||
return c;
|
||||
}
|
||||
if (ShellClient *c = findClientInList(m_internalClients, surface)) {
|
||||
return c;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
quint32 WaylandServer::createWindowId(SurfaceInterface *surface)
|
||||
{
|
||||
auto it = m_clientIds.constFind(surface->client());
|
||||
|
|
|
@ -43,6 +43,7 @@ class ShellInterface;
|
|||
class SeatInterface;
|
||||
class SurfaceInterface;
|
||||
class OutputInterface;
|
||||
class PlasmaShellInterface;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,6 +81,7 @@ public:
|
|||
}
|
||||
void removeClient(ShellClient *c);
|
||||
ShellClient *findClient(quint32 id) const;
|
||||
ShellClient *findClient(KWayland::Server::SurfaceInterface *surface) const;
|
||||
|
||||
AbstractBackend *backend() const {
|
||||
return m_backend;
|
||||
|
@ -128,6 +130,7 @@ private:
|
|||
KWayland::Server::CompositorInterface *m_compositor = nullptr;
|
||||
KWayland::Server::SeatInterface *m_seat = nullptr;
|
||||
KWayland::Server::ShellInterface *m_shell = nullptr;
|
||||
KWayland::Server::PlasmaShellInterface *m_plasmaShell = nullptr;
|
||||
KWayland::Server::ClientConnection *m_xwaylandConnection = nullptr;
|
||||
KWayland::Server::ClientConnection *m_qtConnection = nullptr;
|
||||
KWayland::Client::ConnectionThread *m_qtClientConnection = nullptr;
|
||||
|
|
|
@ -380,7 +380,9 @@ void Workspace::init()
|
|||
[this] (ShellClient *c) {
|
||||
if (!c->isInternal()) {
|
||||
QRect area = clientArea(PlacementArea, Screens::self()->current(), c->desktop());
|
||||
Placement::self()->place(c, area);
|
||||
if (!c->isInitialPositionSet()) {
|
||||
Placement::self()->place(c, area);
|
||||
}
|
||||
if (!unconstrained_stacking_order.contains(c))
|
||||
unconstrained_stacking_order.append(c); // Raise if it hasn't got any stacking position yet
|
||||
if (!stacking_order.contains(c)) // It'll be updated later, and updateToolWindows() requires
|
||||
|
|
Loading…
Reference in a new issue