4ae6c99c6b
Summary: We have duplicated code in InternalClient and XdgShellClient to create decorations. In order to get rid of the code duplication, this change introduces a method that AbstractClient subclasses can call to create a window decoration. Test Plan: Tests pass. Reviewers: #kwin, apol Reviewed By: apol Subscribers: apol, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D27822
269 lines
11 KiB
C++
269 lines
11 KiB
C++
/********************************************************************
|
|
KWin - the KDE window manager
|
|
This file is part of the KDE project.
|
|
|
|
Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org>
|
|
Copyright (C) 2018 David Edmundson <davidedmundson@kde.org>
|
|
Copyright (C) 2019 Vlad Zahorodnii <vlad.zahorodnii@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/>.
|
|
*********************************************************************/
|
|
|
|
#pragma once
|
|
|
|
#include "abstract_client.h"
|
|
|
|
#include <KWayland/Server/xdgshell_interface.h>
|
|
|
|
namespace KWayland
|
|
{
|
|
namespace Server
|
|
{
|
|
class ServerSideDecorationInterface;
|
|
class ServerSideDecorationPaletteInterface;
|
|
class AppMenuInterface;
|
|
class PlasmaShellSurfaceInterface;
|
|
class XdgDecorationInterface;
|
|
}
|
|
}
|
|
|
|
namespace KWin
|
|
{
|
|
|
|
/**
|
|
* @brief The reason for which the server pinged a client surface
|
|
*/
|
|
enum class PingReason {
|
|
CloseWindow = 0,
|
|
FocusWindow
|
|
};
|
|
|
|
class KWIN_EXPORT XdgShellClient : public AbstractClient
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
XdgShellClient(KWayland::Server::XdgShellSurfaceInterface *surface);
|
|
XdgShellClient(KWayland::Server::XdgShellPopupInterface *surface);
|
|
~XdgShellClient() override;
|
|
|
|
QRect inputGeometry() const override;
|
|
QRect bufferGeometry() const override;
|
|
QStringList activities() const override;
|
|
QPoint clientContentPos() const override;
|
|
QSize clientSize() const override;
|
|
QSize minSize() const override;
|
|
QSize maxSize() const override;
|
|
QRect transparentRect() const override;
|
|
NET::WindowType windowType(bool direct = false, int supported_types = 0) const override;
|
|
void debug(QDebug &stream) const override;
|
|
double opacity() const override;
|
|
void setOpacity(double opacity) override;
|
|
QByteArray windowRole() const override;
|
|
void blockActivityUpdates(bool b = true) override;
|
|
QString captionNormal() const override;
|
|
QString captionSuffix() const override;
|
|
void closeWindow() override;
|
|
AbstractClient *findModal(bool allow_itself = false) override;
|
|
bool isCloseable() const override;
|
|
bool isFullScreenable() const override;
|
|
bool isFullScreen() const override;
|
|
bool isMaximizable() const override;
|
|
bool isMinimizable() const override;
|
|
bool isMovable() const override;
|
|
bool isMovableAcrossScreens() const override;
|
|
bool isResizable() const override;
|
|
bool isShown(bool shaded_is_shown) const override;
|
|
bool isHiddenInternal() const override;
|
|
void hideClient(bool hide) override;
|
|
MaximizeMode maximizeMode() const override;
|
|
MaximizeMode requestedMaximizeMode() const override;
|
|
bool noBorder() 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 takeFocus() override;
|
|
bool userCanSetFullScreen() const override;
|
|
bool userCanSetNoBorder() const override;
|
|
bool wantsInput() const override;
|
|
bool dockWantsInput() const override;
|
|
using AbstractClient::resizeWithChecks;
|
|
void resizeWithChecks(int w, int h, ForceGeometry_t force = NormalGeometrySet) override;
|
|
using AbstractClient::setFrameGeometry;
|
|
void setFrameGeometry(int x, int y, int w, int h, ForceGeometry_t force = NormalGeometrySet) override;
|
|
bool hasStrut() const override;
|
|
quint32 windowId() const override;
|
|
pid_t pid() const override;
|
|
bool isLockScreen() const override;
|
|
bool isInputMethod() const override;
|
|
bool isInitialPositionSet() const override;
|
|
bool isTransient() const override;
|
|
bool hasTransientPlacementHint() const override;
|
|
QRect transientPlacement(const QRect &bounds) const override;
|
|
QMatrix4x4 inputTransformation() const override;
|
|
void showOnScreenEdge() override;
|
|
bool hasPopupGrab() const override;
|
|
void popupDone() override;
|
|
void updateColorScheme() override;
|
|
bool isPopupWindow() const override;
|
|
void killWindow() override;
|
|
bool isLocalhost() const override;
|
|
bool supportsWindowRules() const override;
|
|
void destroyClient() override;
|
|
|
|
void installPlasmaShellSurface(KWayland::Server::PlasmaShellSurfaceInterface *surface);
|
|
void installServerSideDecoration(KWayland::Server::ServerSideDecorationInterface *decoration);
|
|
void installAppMenu(KWayland::Server::AppMenuInterface *appmenu);
|
|
void installPalette(KWayland::Server::ServerSideDecorationPaletteInterface *palette);
|
|
void installXdgDecoration(KWayland::Server::XdgDecorationInterface *decoration);
|
|
|
|
protected:
|
|
void addDamage(const QRegion &damage) override;
|
|
bool belongsToSameApplication(const AbstractClient *other, SameApplicationChecks checks) const override;
|
|
void doSetActive() override;
|
|
bool belongsToDesktop() const override;
|
|
Layer layerForDock() const override;
|
|
void changeMaximize(bool horizontal, bool vertical, bool adjust) override;
|
|
void doResizeSync() override;
|
|
bool acceptsFocus() const override;
|
|
void doMinimize() override;
|
|
void updateCaption() override;
|
|
void doMove(int x, int y) override;
|
|
|
|
private Q_SLOTS:
|
|
void handleConfigureAcknowledged(quint32 serial);
|
|
void handleTransientForChanged();
|
|
void handleWindowClassChanged(const QByteArray &windowClass);
|
|
void handleWindowGeometryChanged(const QRect &windowGeometry);
|
|
void handleWindowTitleChanged(const QString &title);
|
|
void handleMoveRequested(KWayland::Server::SeatInterface *seat, quint32 serial);
|
|
void handleResizeRequested(KWayland::Server::SeatInterface *seat, quint32 serial, Qt::Edges edges);
|
|
void handleMinimizeRequested();
|
|
void handleMaximizeRequested(bool maximized);
|
|
void handleFullScreenRequested(bool fullScreen, KWayland::Server::OutputInterface *output);
|
|
void handleWindowMenuRequested(KWayland::Server::SeatInterface *seat, quint32 serial, const QPoint &surfacePos);
|
|
void handleGrabRequested(KWayland::Server::SeatInterface *seat, quint32 serial);
|
|
void handlePingDelayed(quint32 serial);
|
|
void handlePingTimeout(quint32 serial);
|
|
void handlePongReceived(quint32 serial);
|
|
void handleCommitted();
|
|
|
|
private:
|
|
/**
|
|
* Called when the shell is created.
|
|
*/
|
|
void init();
|
|
/**
|
|
* Called for the XDG case when the shell surface is committed to the surface.
|
|
* At this point all initial properties should have been set by the client.
|
|
*/
|
|
void finishInit();
|
|
void createWindowId();
|
|
void updateIcon();
|
|
bool shouldExposeToWindowManagement();
|
|
void updateClientOutputs();
|
|
KWayland::Server::XdgShellSurfaceInterface::States xdgSurfaceStates() const;
|
|
void updateShowOnScreenEdge();
|
|
void updateMaximizeMode(MaximizeMode maximizeMode);
|
|
// called on surface commit and processes all m_pendingConfigureRequests up to m_lastAckedConfigureReqest
|
|
void updatePendingGeometry();
|
|
QPoint popupOffset(const QRect &anchorRect, const Qt::Edges anchorEdge, const Qt::Edges gravity, const QSize popupSize) const;
|
|
void requestGeometry(const QRect &rect);
|
|
void doSetGeometry(const QRect &rect);
|
|
void unmap();
|
|
void markAsMapped();
|
|
QRect determineBufferGeometry() const;
|
|
void ping(PingReason reason);
|
|
static void deleteClient(XdgShellClient *c);
|
|
|
|
QRect adjustMoveGeometry(const QRect &rect) const;
|
|
QRect adjustResizeGeometry(const QRect &rect) const;
|
|
|
|
KWayland::Server::XdgShellSurfaceInterface *m_xdgShellToplevel;
|
|
KWayland::Server::XdgShellPopupInterface *m_xdgShellPopup;
|
|
|
|
QRect m_bufferGeometry;
|
|
QRect m_windowGeometry;
|
|
bool m_hasWindowGeometry = false;
|
|
|
|
// last size we requested or empty if we haven't sent an explicit request to the client
|
|
// if empty the client should choose their own default size
|
|
QSize m_requestedClientSize = QSize(0, 0);
|
|
|
|
struct PendingConfigureRequest {
|
|
//note for wl_shell we have no serial, so serialId and m_lastAckedConfigureRequest will always be 0
|
|
//meaning we treat a surface commit as having processed all requests
|
|
quint32 serialId = 0;
|
|
// position to apply after a resize operation has been completed
|
|
QPoint positionAfterResize;
|
|
MaximizeMode maximizeMode;
|
|
};
|
|
QVector<PendingConfigureRequest> m_pendingConfigureRequests;
|
|
quint32 m_lastAckedConfigureRequest = 0;
|
|
|
|
//mode in use by the current buffer
|
|
MaximizeMode m_maximizeMode = MaximizeRestore;
|
|
//mode we currently want to be, could be pending on client updating, could be not sent yet
|
|
MaximizeMode m_requestedMaximizeMode = MaximizeRestore;
|
|
|
|
QRect m_geomFsRestore; //size and position of the window before it was set to fullscreen
|
|
bool m_closing = false;
|
|
quint32 m_windowId = 0;
|
|
bool m_unmapped = true;
|
|
NET::WindowType m_windowType = NET::Normal;
|
|
QPointer<KWayland::Server::PlasmaShellSurfaceInterface> m_plasmaShellSurface;
|
|
QPointer<KWayland::Server::AppMenuInterface> m_appMenuInterface;
|
|
QPointer<KWayland::Server::ServerSideDecorationPaletteInterface> m_paletteInterface;
|
|
KWayland::Server::ServerSideDecorationInterface *m_serverDecoration = nullptr;
|
|
KWayland::Server::XdgDecorationInterface *m_xdgDecoration = nullptr;
|
|
bool m_userNoBorder = false;
|
|
bool m_fullScreen = false;
|
|
bool m_transient = false;
|
|
bool m_hidden = false;
|
|
bool m_hasPopupGrab = false;
|
|
qreal m_opacity = 1.0;
|
|
|
|
class RequestGeometryBlocker { //TODO rename ConfigureBlocker when this class is Xdg only
|
|
public:
|
|
RequestGeometryBlocker(XdgShellClient *client)
|
|
: m_client(client)
|
|
{
|
|
m_client->m_requestGeometryBlockCounter++;
|
|
}
|
|
~RequestGeometryBlocker()
|
|
{
|
|
m_client->m_requestGeometryBlockCounter--;
|
|
if (m_client->m_requestGeometryBlockCounter == 0) {
|
|
m_client->requestGeometry(m_client->m_blockedRequestGeometry);
|
|
}
|
|
}
|
|
private:
|
|
XdgShellClient *m_client;
|
|
};
|
|
friend class RequestGeometryBlocker;
|
|
int m_requestGeometryBlockCounter = 0;
|
|
QRect m_blockedRequestGeometry;
|
|
QString m_caption;
|
|
QString m_captionSuffix;
|
|
QHash<quint32, PingReason> m_pingSerials;
|
|
|
|
bool m_isInitialized = false;
|
|
|
|
friend class Workspace;
|
|
};
|
|
|
|
}
|
|
|
|
Q_DECLARE_METATYPE(KWin::XdgShellClient *)
|