[wayland] Introduce a ShellClient
The ShellClient is a Toplevel subclass for a KWayland::Server::ShellSurfaceInterface. It gets created when a new ShellSurfaceInterface is created and destoryed when it gets unmapped. So far the usage is still rather limited. The ShellClient is opened at position (0/0). While it's possible to pass pointer events to it, it's not yet possible to activate it, so no keyboard focus.
This commit is contained in:
parent
8fad5830f1
commit
d60c377890
9 changed files with 327 additions and 1 deletions
|
@ -442,6 +442,7 @@ if(HAVE_WAYLAND)
|
|||
${kwin_KDEINIT_SRCS}
|
||||
abstract_backend.cpp
|
||||
virtual_terminal.cpp
|
||||
shell_client.cpp
|
||||
wayland_server.cpp
|
||||
)
|
||||
if(HAVE_WAYLAND_CURSOR)
|
||||
|
|
|
@ -39,6 +39,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "xcbutils.h"
|
||||
#if HAVE_WAYLAND
|
||||
#include "abstract_backend.h"
|
||||
#include "shell_client.h"
|
||||
#include "wayland_server.h"
|
||||
#endif
|
||||
#include "decorations/decoratedclient.h"
|
||||
|
@ -743,6 +744,16 @@ bool Compositor::windowRepaintsPending() const
|
|||
foreach (Toplevel * c, Workspace::self()->deletedList())
|
||||
if (!c->repaints().isEmpty())
|
||||
return true;
|
||||
#if HAVE_WAYLAND
|
||||
if (auto w = waylandServer()) {
|
||||
const auto &clients = w->clients();
|
||||
for (auto c : clients) {
|
||||
if (!c->repaints().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
23
effects.cpp
23
effects.cpp
|
@ -57,6 +57,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "xcbutils.h"
|
||||
#if HAVE_WAYLAND
|
||||
#include "abstract_backend.h"
|
||||
#include "shell_client.h"
|
||||
#include "wayland_server.h"
|
||||
#endif
|
||||
|
||||
|
@ -297,6 +298,18 @@ EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, Scene *scene)
|
|||
for (Unmanaged *u : ws->unmanagedList()) {
|
||||
setupUnmanagedConnections(u);
|
||||
}
|
||||
#if HAVE_WAYLAND
|
||||
if (auto w = waylandServer()) {
|
||||
connect(w, &WaylandServer::shellClientAdded, this,
|
||||
[this](ShellClient *c) {
|
||||
if (c->readyForPainting())
|
||||
slotShellClientShown(c);
|
||||
else
|
||||
connect(c, &Toplevel::windowShown, this, &EffectsHandlerImpl::slotShellClientShown);
|
||||
}
|
||||
);
|
||||
}
|
||||
#endif
|
||||
reconfigure();
|
||||
}
|
||||
|
||||
|
@ -565,6 +578,16 @@ void EffectsHandlerImpl::slotClientShown(KWin::Toplevel *t)
|
|||
emit windowAdded(c->effectWindow());
|
||||
}
|
||||
|
||||
void EffectsHandlerImpl::slotShellClientShown(Toplevel *t)
|
||||
{
|
||||
#if HAVE_WAYLAND
|
||||
ShellClient *c = static_cast<ShellClient*>(t);
|
||||
connect(c, &ShellClient::windowClosed, this, &EffectsHandlerImpl::slotWindowClosed);
|
||||
connect(c, &ShellClient::geometryShapeChanged, this, &EffectsHandlerImpl::slotGeometryShapeChanged);
|
||||
emit windowAdded(t->effectWindow());
|
||||
#endif
|
||||
}
|
||||
|
||||
void EffectsHandlerImpl::slotUnmanagedShown(KWin::Toplevel *t)
|
||||
{ // regardless, unmanaged windows are -yet?- not synced anyway
|
||||
Q_ASSERT(dynamic_cast<Unmanaged*>(t));
|
||||
|
|
|
@ -234,6 +234,7 @@ public Q_SLOTS:
|
|||
|
||||
protected Q_SLOTS:
|
||||
void slotClientShown(KWin::Toplevel*);
|
||||
void slotShellClientShown(KWin::Toplevel*);
|
||||
void slotUnmanagedShown(KWin::Toplevel*);
|
||||
void slotWindowClosed(KWin::Toplevel *c);
|
||||
void slotClientMaximized(KWin::Client *c, MaximizeMode maxMode);
|
||||
|
|
161
shell_client.cpp
Normal file
161
shell_client.cpp
Normal file
|
@ -0,0 +1,161 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************/
|
||||
#include "shell_client.h"
|
||||
#include "deleted.h"
|
||||
#include "wayland_server.h"
|
||||
|
||||
#include <KWayland/Server/shell_interface.h>
|
||||
#include <KWayland/Server/surface_interface.h>
|
||||
#include <KWayland/Server/buffer_interface.h>
|
||||
|
||||
using namespace KWayland::Server;
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
ShellClient::ShellClient(ShellSurfaceInterface *surface)
|
||||
: Toplevel()
|
||||
, m_shellSurface(surface)
|
||||
{
|
||||
setSurface(surface->surface());
|
||||
setupCompositing();
|
||||
if (surface->surface()->buffer()) {
|
||||
setReadyForPainting();
|
||||
m_clientSize = surface->surface()->buffer()->size();
|
||||
} else {
|
||||
ready_for_painting = false;
|
||||
}
|
||||
setGeometry(QRect(QPoint(0, 0), m_clientSize));
|
||||
|
||||
connect(surface->surface(), &SurfaceInterface::sizeChanged, this,
|
||||
[this] {
|
||||
m_clientSize = m_shellSurface->surface()->buffer()->size();
|
||||
setGeometry(QRect(QPoint(0, 0), m_clientSize));
|
||||
}
|
||||
);
|
||||
connect(surface, &ShellSurfaceInterface::destroyed, this, &ShellClient::destroyClient);
|
||||
connect(surface->surface(), &SurfaceInterface::unmapped, this, &ShellClient::destroyClient);
|
||||
}
|
||||
|
||||
ShellClient::~ShellClient() = default;
|
||||
|
||||
void ShellClient::destroyClient()
|
||||
{
|
||||
Deleted *del = Deleted::create(this);
|
||||
emit windowClosed(this, del);
|
||||
waylandServer()->removeClient(this);
|
||||
|
||||
del->unrefWindow();
|
||||
m_shellSurface = nullptr;
|
||||
deleteClient(this);
|
||||
}
|
||||
|
||||
void ShellClient::deleteClient(ShellClient *c)
|
||||
{
|
||||
delete c;
|
||||
}
|
||||
|
||||
QStringList ShellClient::activities() const
|
||||
{
|
||||
// TODO: implement
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QPoint ShellClient::clientPos() const
|
||||
{
|
||||
return QPoint(0, 0);
|
||||
}
|
||||
|
||||
QSize ShellClient::clientSize() const
|
||||
{
|
||||
// TODO: connect for changes
|
||||
return m_clientSize;
|
||||
}
|
||||
|
||||
void ShellClient::debug(QDebug &stream) const
|
||||
{
|
||||
// TODO: implement
|
||||
Q_UNUSED(stream)
|
||||
}
|
||||
|
||||
int ShellClient::desktop() const
|
||||
{
|
||||
// TODO: implement
|
||||
return -1;
|
||||
}
|
||||
|
||||
Layer ShellClient::layer() const
|
||||
{
|
||||
// TODO: implement
|
||||
return KWin::NormalLayer;
|
||||
}
|
||||
|
||||
bool ShellClient::shouldUnredirect() const
|
||||
{
|
||||
// TODO: unredirect for fullscreen
|
||||
return false;
|
||||
}
|
||||
|
||||
QRect ShellClient::transparentRect() const
|
||||
{
|
||||
// TODO: implement
|
||||
return QRect();
|
||||
}
|
||||
|
||||
NET::WindowType ShellClient::windowType(bool direct, int supported_types) const
|
||||
{
|
||||
// TODO: implement
|
||||
Q_UNUSED(direct)
|
||||
Q_UNUSED(supported_types)
|
||||
return NET::Normal;
|
||||
}
|
||||
|
||||
double ShellClient::opacity() const
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
void ShellClient::addDamage(const QRegion &damage)
|
||||
{
|
||||
setReadyForPainting();
|
||||
if (m_shellSurface->surface()->buffer()->size().isValid()) {
|
||||
m_clientSize = m_shellSurface->surface()->buffer()->size();
|
||||
setGeometry(QRect(QPoint(0, 0), m_clientSize));
|
||||
}
|
||||
Toplevel::addDamage(damage);
|
||||
}
|
||||
|
||||
void ShellClient::setGeometry(const QRect &rect)
|
||||
{
|
||||
if (geom == rect) {
|
||||
return;
|
||||
}
|
||||
const QRect old = geom;
|
||||
geom = rect;
|
||||
emit geometryChanged();
|
||||
emit geometryShapeChanged(this, old);
|
||||
}
|
||||
|
||||
QByteArray ShellClient::windowRole() const
|
||||
{
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
}
|
73
shell_client.h
Normal file
73
shell_client.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************/
|
||||
#ifndef KWIN_SHELL_CLIENT_H
|
||||
#define KWIN_SHELL_CLIENT_H
|
||||
|
||||
#include "toplevel.h"
|
||||
|
||||
namespace KWayland
|
||||
{
|
||||
namespace Server
|
||||
{
|
||||
class ShellSurfaceInterface;
|
||||
}
|
||||
}
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class ShellClient : public Toplevel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ShellClient(KWayland::Server::ShellSurfaceInterface *surface);
|
||||
virtual ~ShellClient();
|
||||
|
||||
QStringList activities() const override;
|
||||
QPoint clientPos() const override;
|
||||
QSize clientSize() const override;
|
||||
int desktop() const override;
|
||||
Layer layer() const override;
|
||||
QRect transparentRect() const override;
|
||||
bool shouldUnredirect() const override;
|
||||
NET::WindowType windowType(bool direct = false, int supported_types = 0) const override;
|
||||
void debug(QDebug &stream) const override;
|
||||
double opacity() const override;
|
||||
QByteArray windowRole() const override;
|
||||
|
||||
KWayland::Server::ShellSurfaceInterface *shellSurface() const {
|
||||
return m_shellSurface;
|
||||
}
|
||||
|
||||
protected:
|
||||
void addDamage(const QRegion &damage) override;
|
||||
|
||||
private:
|
||||
void setGeometry(const QRect &rect);
|
||||
void destroyClient();
|
||||
static void deleteClient(ShellClient *c);
|
||||
|
||||
KWayland::Server::ShellSurfaceInterface *m_shellSurface;
|
||||
QSize m_clientSize;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -19,8 +19,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*********************************************************************/
|
||||
#include "wayland_server.h"
|
||||
#include "abstract_backend.h"
|
||||
#include "composite.h"
|
||||
#include "screens.h"
|
||||
#include "toplevel.h"
|
||||
#include "shell_client.h"
|
||||
#include "workspace.h"
|
||||
|
||||
// Client
|
||||
|
@ -78,6 +79,20 @@ void WaylandServer::init(const QByteArray &socketName)
|
|||
);
|
||||
m_shell = m_display->createShell(m_display);
|
||||
m_shell->create();
|
||||
connect(m_shell, &ShellInterface::surfaceCreated, this,
|
||||
[this] (ShellSurfaceInterface *surface) {
|
||||
if (surface->client() == m_xwaylandConnection) {
|
||||
// skip Xwayland clients, those are created using standard X11 way
|
||||
return;
|
||||
}
|
||||
auto client = new ShellClient(surface);
|
||||
if (auto c = Compositor::self()) {
|
||||
connect(client, &Toplevel::needsRepaint, c, &Compositor::scheduleRepaint);
|
||||
}
|
||||
m_clients << client;
|
||||
emit shellClientAdded(client);
|
||||
}
|
||||
);
|
||||
m_display->createShm();
|
||||
m_seat = m_display->createSeat(m_display);
|
||||
m_seat->create();
|
||||
|
@ -163,4 +178,10 @@ void WaylandServer::uninstallBackend(AbstractBackend *backend)
|
|||
m_backend = nullptr;
|
||||
}
|
||||
|
||||
void WaylandServer::removeClient(ShellClient *c)
|
||||
{
|
||||
m_clients.removeAll(c);
|
||||
emit shellClientRemoved(c);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ class OutputInterface;
|
|||
|
||||
namespace KWin
|
||||
{
|
||||
class ShellClient;
|
||||
|
||||
class AbstractBackend;
|
||||
|
||||
|
@ -67,6 +68,10 @@ public:
|
|||
KWayland::Server::ShellInterface *shell() {
|
||||
return m_shell;
|
||||
}
|
||||
QList<ShellClient*> clients() const {
|
||||
return m_clients;
|
||||
}
|
||||
void removeClient(ShellClient *c);
|
||||
|
||||
AbstractBackend *backend() const {
|
||||
return m_backend;
|
||||
|
@ -98,6 +103,10 @@ public:
|
|||
return m_internalConnection.client;
|
||||
}
|
||||
|
||||
Q_SIGNALS:
|
||||
void shellClientAdded(ShellClient*);
|
||||
void shellClientRemoved(ShellClient*);
|
||||
|
||||
private:
|
||||
KWayland::Server::Display *m_display = nullptr;
|
||||
KWayland::Server::CompositorInterface *m_compositor = nullptr;
|
||||
|
@ -112,6 +121,7 @@ private:
|
|||
|
||||
} m_internalConnection;
|
||||
AbstractBackend *m_backend = nullptr;
|
||||
QList<ShellClient*> m_clients;
|
||||
KWIN_SINGLETON(WaylandServer)
|
||||
};
|
||||
|
||||
|
|
|
@ -52,6 +52,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "unmanaged.h"
|
||||
#include "useractions.h"
|
||||
#include "virtualdesktops.h"
|
||||
#if HAVE_WAYLAND
|
||||
#include "shell_client.h"
|
||||
#include "wayland_server.h"
|
||||
#endif
|
||||
#include "xcbutils.h"
|
||||
#include "main.h"
|
||||
#include "decorations/decorationbridge.h"
|
||||
|
@ -370,6 +374,27 @@ void Workspace::init()
|
|||
|
||||
Scripting::create(this);
|
||||
|
||||
#if HAVE_WAYLAND
|
||||
if (auto w = waylandServer()) {
|
||||
connect(w, &WaylandServer::shellClientAdded, this,
|
||||
[this] (ShellClient *c) {
|
||||
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
|
||||
stacking_order.append(c); // c to be in stacking_order
|
||||
x_stacking_dirty = true;
|
||||
updateStackingOrder(true);
|
||||
}
|
||||
);
|
||||
connect(w, &WaylandServer::shellClientRemoved, this,
|
||||
[this] {
|
||||
x_stacking_dirty = true;
|
||||
updateStackingOrder(true);
|
||||
}
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
// SELI TODO: This won't work with unreasonable focus policies,
|
||||
// and maybe in rare cases also if the selected client doesn't
|
||||
// want focus
|
||||
|
|
Loading…
Reference in a new issue