[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.
icc-effect-5.14.5
Martin Gräßlin 2015-06-09 19:10:56 +02:00
parent 2bdabe62aa
commit 124bd8aaed
5 changed files with 103 additions and 1 deletions

View File

@ -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;
}
}

View File

@ -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;
};
}

View File

@ -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());

View File

@ -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;

View File

@ -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