kwin/xdgshellclient.h

274 lines
11 KiB
C
Raw Normal View History

/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org>
2018-10-05 14:36:02 +00:00
Copyright (C) 2018 David Edmundson <davidedmundson@kde.org>
2020-01-14 16:17:18 +00:00
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
};
2019-01-28 00:28:48 +00:00
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;
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;
QRect geometryRestore() 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;
2015-09-11 10:11:01 +00:00
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 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);
void placeIn(const QRect &area);
protected:
void addDamage(const QRegion &damage) override;
Allow a cross-process check for same applications Summary: Commit 5d9027b110 introduced a regression in TabBox by using the generic framework inside KWin to test for same application. What I did not consider was that the code in TabBox was "broken by design". It didn't use the generic check as that is too strict and considers windows from different processes as not belonging to the same application. But this is not wanted in the case of TabBox. On the other hand the change itself is an improvement to also support Wayland in a better way and not have special handling situations. Thus just reverting would not help. Instead this change addresses the problem by extending the internal API and to allow more adjustements. So far there was already an "active_hack" boolean flag. This is extended to proper flags with an additional flag to allow cross application checks. The checks in Client which would filter out different applications check for this flag and are skipped if set. In addition ShellClient also adds support for this flag and compares for the desktop file name. Thus we get in TabBox the same behavior as before with the advantage of having a better shared code base working on both X11 and Wayland. BUG: 386043 FIXED-IN: 5.11.4 Test Plan: Started two kwrite processes on X11, clicked new in one of them, used Alt+` and verified that there are three windows shown. Reviewers: #kwin, #plasma Subscribers: plasma-devel, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D8661
2017-11-05 09:10:17 +00:00
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 setGeometryRestore(const QRect &geo) 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 createDecoration(const QRect &oldgeom);
void destroyClient();
void createWindowId();
void updateIcon();
bool shouldExposeToWindowManagement();
void updateClientOutputs();
KWayland::Server::XdgShellSurfaceInterface::States xdgSurfaceStates() const;
void updateShowOnScreenEdge();
2018-10-05 14:36:02 +00:00
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;
2018-10-05 14:36:02 +00:00
MaximizeMode maximizeMode;
};
QVector<PendingConfigureRequest> m_pendingConfigureRequests;
quint32 m_lastAckedConfigureRequest = 0;
2018-10-05 14:36:02 +00:00
//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;
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;
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;
2016-02-18 07:27:02 +00:00
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 *)