Add window decoration to ShellClient
If a ShellClient supports the ServerSideDecoration interface we can create a server decoration for it. For that updateDecoration is added as a pure virtual method in AbstractClient and a more-or-less code copy from Client is added to ShellClient. Geometry handling is adjusted to consider the window decoration offsets.
This commit is contained in:
parent
5cfe9428aa
commit
5e96f65224
5 changed files with 91 additions and 10 deletions
|
@ -523,6 +523,11 @@ public:
|
|||
bool processDecorationButtonPress(QMouseEvent *event, bool ignoreMenu = false);
|
||||
void processDecorationButtonRelease(QMouseEvent *event);
|
||||
|
||||
/**
|
||||
* TODO: fix boolean traps
|
||||
**/
|
||||
virtual void updateDecoration(bool check_workspace_pos, bool force = false) = 0;
|
||||
|
||||
/**
|
||||
* Returns whether the window provides context help or not. If it does,
|
||||
* you should show a help menu item or a help button like '?' and call
|
||||
|
|
2
client.h
2
client.h
|
@ -209,7 +209,7 @@ public:
|
|||
|
||||
void takeFocus() override;
|
||||
|
||||
void updateDecoration(bool check_workspace_pos, bool force = false);
|
||||
void updateDecoration(bool check_workspace_pos, bool force = false) override;
|
||||
|
||||
void updateShape();
|
||||
|
||||
|
|
|
@ -26,6 +26,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "workspace.h"
|
||||
#include "virtualdesktops.h"
|
||||
#include "workspace.h"
|
||||
#include "decorations/decorationbridge.h"
|
||||
#include "decorations/decoratedclient.h"
|
||||
#include <KDecoration2/Decoration>
|
||||
#include <KDecoration2/DecoratedClient>
|
||||
|
||||
#include <KWayland/Client/surface.h>
|
||||
#include <KWayland/Server/seat_interface.h>
|
||||
|
@ -78,7 +82,7 @@ ShellClient::ShellClient(ShellSurfaceInterface *surface)
|
|||
connect(surface->surface(), &SurfaceInterface::sizeChanged, this,
|
||||
[this] {
|
||||
m_clientSize = m_shellSurface->surface()->buffer()->size();
|
||||
doSetGeometry(QRect(geom.topLeft(), m_clientSize));
|
||||
doSetGeometry(QRect(geom.topLeft(), m_clientSize + QSize(borderLeft() + borderRight(), borderTop() + borderBottom())));
|
||||
discardWindowPixmap();
|
||||
}
|
||||
);
|
||||
|
@ -153,6 +157,8 @@ ShellClient::ShellClient(ShellSurfaceInterface *surface)
|
|||
if (ServerSideDecorationInterface *deco = ServerSideDecorationInterface::get(surface->surface())) {
|
||||
installServerSideDecoration(deco);
|
||||
}
|
||||
|
||||
updateColorScheme(QString());
|
||||
}
|
||||
|
||||
ShellClient::~ShellClient() = default;
|
||||
|
@ -165,6 +171,7 @@ void ShellClient::destroyClient()
|
|||
del = Deleted::create(this);
|
||||
}
|
||||
emit windowClosed(this, del);
|
||||
destroyDecoration();
|
||||
|
||||
if (workspace()) {
|
||||
StackingUpdatesBlocker blocker(workspace());
|
||||
|
@ -276,7 +283,7 @@ void ShellClient::addDamage(const QRegion &damage)
|
|||
position = m_positionAfterResize.point();
|
||||
m_positionAfterResize.clear();
|
||||
}
|
||||
doSetGeometry(QRect(position, m_clientSize));
|
||||
doSetGeometry(QRect(position, m_clientSize + QSize(borderLeft() + borderRight(), borderTop() + borderBottom())));
|
||||
}
|
||||
markAsMapped();
|
||||
setDepth(m_shellSurface->surface()->buffer()->hasAlphaChannel() ? 32 : 24);
|
||||
|
@ -301,11 +308,56 @@ void ShellClient::markAsMapped()
|
|||
if (!m_unmapped) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_unmapped = false;
|
||||
setReadyForPainting();
|
||||
setupWindowManagementInterface();
|
||||
}
|
||||
|
||||
void ShellClient::createDecoration(const QRect &oldGeom)
|
||||
{
|
||||
KDecoration2::Decoration *decoration = Decoration::DecorationBridge::self()->createDecoration(this);
|
||||
if (decoration) {
|
||||
QMetaObject::invokeMethod(decoration, "update", Qt::QueuedConnection);
|
||||
connect(decoration, &KDecoration2::Decoration::shadowChanged, this, &Toplevel::getShadow);
|
||||
connect(decoration, &KDecoration2::Decoration::bordersChanged, this,
|
||||
[this]() {
|
||||
GeometryUpdatesBlocker blocker(this);
|
||||
QRect oldgeom = geometry();
|
||||
if (!isShade())
|
||||
checkWorkspacePosition(oldgeom);
|
||||
emit geometryShapeChanged(this, oldgeom);
|
||||
}
|
||||
);
|
||||
}
|
||||
setDecoration(decoration);
|
||||
|
||||
emit geometryShapeChanged(this, oldGeom);
|
||||
}
|
||||
|
||||
void ShellClient::updateDecoration(bool check_workspace_pos, bool force)
|
||||
{
|
||||
if (!force &&
|
||||
((!isDecorated() && noBorder()) || (isDecorated() && !noBorder())))
|
||||
return;
|
||||
QRect oldgeom = geometry();
|
||||
QRect oldClientGeom = oldgeom.adjusted(borderLeft(), borderTop(), -borderRight(), -borderBottom());
|
||||
blockGeometryUpdates(true);
|
||||
if (force)
|
||||
destroyDecoration();
|
||||
if (!noBorder()) {
|
||||
createDecoration(oldgeom);
|
||||
} else
|
||||
destroyDecoration();
|
||||
if (m_serverDecoration && isDecorated()) {
|
||||
m_serverDecoration->setMode(KWayland::Server::ServerSideDecorationManagerInterface::Mode::Server);
|
||||
}
|
||||
getShadow();
|
||||
if (check_workspace_pos)
|
||||
checkWorkspacePosition(oldgeom, -2, oldClientGeom);
|
||||
blockGeometryUpdates(false);
|
||||
}
|
||||
|
||||
void ShellClient::setGeometry(int x, int y, int w, int h, ForceGeometry_t force)
|
||||
{
|
||||
Q_UNUSED(force)
|
||||
|
@ -339,6 +391,7 @@ void ShellClient::doSetGeometry(const QRect &rect)
|
|||
if (!m_unmapped) {
|
||||
addWorkspaceRepaint(visibleRect());
|
||||
}
|
||||
triggerDecorationRepaint();
|
||||
emit geometryShapeChanged(this, old);
|
||||
}
|
||||
|
||||
|
@ -492,6 +545,14 @@ MaximizeMode ShellClient::maximizeMode() const
|
|||
|
||||
bool ShellClient::noBorder() const
|
||||
{
|
||||
if (isInternal()) {
|
||||
return true;
|
||||
}
|
||||
if (m_serverDecoration) {
|
||||
if (m_serverDecoration->mode() == ServerSideDecorationManagerInterface::Mode::Server) {
|
||||
return m_userNoBorder;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -509,7 +570,16 @@ void ShellClient::setFullScreen(bool set, bool user)
|
|||
|
||||
void ShellClient::setNoBorder(bool set)
|
||||
{
|
||||
Q_UNUSED(set)
|
||||
if (!userCanSetNoBorder()) {
|
||||
return;
|
||||
}
|
||||
set = rules()->checkNoBorder(set);
|
||||
if (m_userNoBorder == set) {
|
||||
return;
|
||||
}
|
||||
m_userNoBorder = set;
|
||||
updateDecoration(true, false);
|
||||
updateWindowRules(Rules::NoBorder);
|
||||
}
|
||||
|
||||
void ShellClient::setOnAllActivities(bool set)
|
||||
|
@ -662,7 +732,7 @@ xcb_window_t ShellClient::window() const
|
|||
void ShellClient::requestGeometry(const QRect &rect)
|
||||
{
|
||||
m_positionAfterResize.setPoint(rect.topLeft());
|
||||
m_shellSurface->requestSize(rect.size());
|
||||
m_shellSurface->requestSize(rect.size() - QSize(borderLeft() + borderRight(), borderTop() + borderBottom()));
|
||||
}
|
||||
|
||||
void ShellClient::clientFullScreenChanged(bool fullScreen)
|
||||
|
@ -717,7 +787,7 @@ void ShellClient::installPlasmaShellSurface(PlasmaShellSurfaceInterface *surface
|
|||
{
|
||||
m_plasmaShellSurface = surface;
|
||||
auto updatePosition = [this, surface] {
|
||||
doSetGeometry(QRect(surface->position(), m_clientSize));
|
||||
doSetGeometry(QRect(surface->position(), m_clientSize + QSize(borderLeft() + borderRight(), borderTop() + borderBottom())));
|
||||
};
|
||||
auto updateRole = [this, surface] {
|
||||
NET::WindowType type = NET::Unknown;
|
||||
|
@ -860,18 +930,20 @@ void ShellClient::installServerSideDecoration(KWayland::Server::ServerSideDecora
|
|||
m_serverDecoration = deco;
|
||||
connect(m_serverDecoration, &ServerSideDecorationInterface::destroyed, this,
|
||||
[this] {
|
||||
// TODO: update decoration
|
||||
m_serverDecoration = nullptr;
|
||||
updateDecoration(true);
|
||||
}
|
||||
);
|
||||
// TODO: update decoration
|
||||
if (!m_unmapped) {
|
||||
updateDecoration(true);
|
||||
}
|
||||
connect(m_serverDecoration, &ServerSideDecorationInterface::modeRequested, this,
|
||||
[this] (ServerSideDecorationManagerInterface::Mode mode) {
|
||||
const bool changed = mode != m_serverDecoration->mode();
|
||||
// always acknowledge the requested mode
|
||||
m_serverDecoration->setMode(mode);
|
||||
if (changed) {
|
||||
// TODO: update decoration
|
||||
if (changed && !m_unmapped) {
|
||||
updateDecoration(false);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -81,6 +81,7 @@ public:
|
|||
const WindowRules *rules() const override;
|
||||
void setFullScreen(bool set, bool user = true) override;
|
||||
void setNoBorder(bool set) override;
|
||||
void updateDecoration(bool check_workspace_pos, bool force = false) override;
|
||||
void setOnAllActivities(bool set) override;
|
||||
void setShortcut(const QString &cut) override;
|
||||
const QKeySequence &shortcut() const override;
|
||||
|
@ -139,6 +140,7 @@ private Q_SLOTS:
|
|||
private:
|
||||
void requestGeometry(const QRect &rect);
|
||||
void doSetGeometry(const QRect &rect);
|
||||
void createDecoration(const QRect &oldgeom);
|
||||
void destroyClient();
|
||||
void unmap();
|
||||
void createWindowId();
|
||||
|
@ -164,6 +166,7 @@ private:
|
|||
QPointer<KWayland::Server::PlasmaShellSurfaceInterface> m_plasmaShellSurface;
|
||||
QPointer<KWayland::Server::QtExtendedSurfaceInterface> m_qtExtendedSurface;
|
||||
KWayland::Server::ServerSideDecorationInterface *m_serverDecoration = nullptr;
|
||||
bool m_userNoBorder = false;
|
||||
bool m_fullScreen = false;
|
||||
bool m_transient = false;
|
||||
};
|
||||
|
|
|
@ -372,6 +372,7 @@ void Workspace::init()
|
|||
if (auto w = waylandServer()) {
|
||||
connect(w, &WaylandServer::shellClientAdded, this,
|
||||
[this] (ShellClient *c) {
|
||||
c->updateDecoration(false);
|
||||
updateClientLayer(c);
|
||||
if (!c->isInternal()) {
|
||||
QRect area = clientArea(PlacementArea, Screens::self()->current(), c->desktop());
|
||||
|
|
Loading…
Reference in a new issue