Commit cc3eb54b authored by Vlad Zahorodnii's avatar Vlad Zahorodnii Committed by Vlad Zahorodnii
Browse files

Introduce the client geometry in Toplevel

In most cases, we don't need to react to client geometry changes, but in
code that deals with server-side window decorations, we need to react to
client geometry changes. The problem is that frame and client geometry
updates are not correlated even though there is a connection between the
frame geometry and the client geometry.

This change introduces the client geometry in the Toplevel class in order
to allow monitoring client geometry updates from DecoratedClientImpl.
parent 68ec39f4
......@@ -1984,10 +1984,16 @@ QRect AbstractClient::frameGeometryBeforeUpdateBlocking() const
return m_frameGeometryBeforeUpdateBlocking;
}
QRect AbstractClient::clientGeometryBeforeUpdateBlocking() const
{
return m_clientGeometryBeforeUpdateBlocking;
}
void AbstractClient::updateGeometryBeforeUpdateBlocking()
{
m_bufferGeometryBeforeUpdateBlocking = bufferGeometry();
m_frameGeometryBeforeUpdateBlocking = frameGeometry();
m_clientGeometryBeforeUpdateBlocking = clientGeometry();
}
void AbstractClient::doMove(int, int)
......
......@@ -1040,6 +1040,7 @@ protected:
void setPendingGeometryUpdate(PendingGeometry_t update);
QRect bufferGeometryBeforeUpdateBlocking() const;
QRect frameGeometryBeforeUpdateBlocking() const;
QRect clientGeometryBeforeUpdateBlocking() const;
void updateGeometryBeforeUpdateBlocking();
/**
* Schedules a repaint for the visibleRect before and after a
......@@ -1270,6 +1271,7 @@ private:
QRect m_visibleRectBeforeGeometryUpdate;
QRect m_bufferGeometryBeforeUpdateBlocking;
QRect m_frameGeometryBeforeUpdateBlocking;
QRect m_clientGeometryBeforeUpdateBlocking;
QRect m_virtualKeyboardGeometry;
QRect m_keyboardGeometryRestore;
QRect m_maximizeGeometryRestore;
......
......@@ -206,11 +206,6 @@ QPoint Deleted::clientPos() const
return contentsRect.topLeft();
}
QSize Deleted::clientSize() const
{
return contentsRect.size();
}
void Deleted::debug(QDebug& stream) const
{
stream << "\'ID:" << window() << "\' (deleted)";
......
......@@ -51,7 +51,6 @@ public:
QStringList activities() const override;
QVector<VirtualDesktop *> desktops() const override;
QPoint clientPos() const override;
QSize clientSize() const override;
QPoint clientContentPos() const override {
return m_contentPos;
}
......
......@@ -1294,6 +1294,7 @@ void Unmanaged::configureNotifyEvent(xcb_configure_notify_event_t *e)
if (newgeom != m_frameGeometry) {
addWorkspaceRepaint(visibleRect()); // damage old area
QRect old = m_frameGeometry;
m_clientGeometry = newgeom;
m_frameGeometry = newgeom;
emit frameGeometryChanged(this, old); // update shadow region
addRepaintFull();
......
......@@ -38,7 +38,6 @@ namespace KWin
InternalClient::InternalClient(QWindow *window)
: m_internalWindow(window)
, m_clientSize(window->size())
, m_windowId(window->winId())
, m_internalWindowFlags(window->flags())
{
......@@ -139,11 +138,6 @@ QPoint InternalClient::clientContentPos() const
return -1 * clientPos();
}
QSize InternalClient::clientSize() const
{
return m_clientSize;
}
QSize InternalClient::minSize() const
{
return m_internalWindow->minimumSize();
......@@ -334,7 +328,7 @@ void InternalClient::setFrameGeometry(const QRect &rect, ForceGeometry_t force)
const QRect newClientGeometry = frameRectToClientRect(rect);
if (m_clientSize == newClientGeometry.size()) {
if (clientSize() == newClientGeometry.size()) {
commitGeometry(rect);
} else {
requestGeometry(rect);
......@@ -530,13 +524,15 @@ void InternalClient::commitGeometry(const QRect &rect)
return;
}
m_clientGeometry = frameRectToClientRect(rect);
m_frameGeometry = rect;
m_clientSize = frameRectToClientRect(frameGeometry()).size();
addWorkspaceRepaint(visibleRect());
syncGeometryToInternalWindow();
if (clientGeometryBeforeUpdateBlocking() != clientGeometry()) {
emit clientGeometryChanged(this, clientGeometryBeforeUpdateBlocking());
}
if (frameGeometryBeforeUpdateBlocking() != frameGeometry()) {
emit frameGeometryChanged(this, frameGeometryBeforeUpdateBlocking());
}
......
......@@ -42,7 +42,6 @@ public:
QString captionNormal() const override;
QString captionSuffix() const override;
QPoint clientContentPos() const override;
QSize clientSize() const override;
QSize minSize() const override;
QSize maxSize() const override;
void debug(QDebug &stream) const override;
......@@ -101,7 +100,6 @@ private:
void updateInternalWindowGeometry();
QWindow *m_internalWindow = nullptr;
QSize m_clientSize = QSize(0, 0);
QString m_captionNormal;
QString m_captionSuffix;
double m_opacity = 1.0;
......
......@@ -92,6 +92,7 @@ void Toplevel::copyToDeleted(Toplevel* c)
{
m_internalId = c->internalId();
m_frameGeometry = c->m_frameGeometry;
m_clientGeometry = c->m_clientGeometry;
m_visual = c->m_visual;
bit_depth = c->bit_depth;
info = c->info;
......
......@@ -327,6 +327,10 @@ public:
* server-side and client-side drop shadows, etc.
*/
QRect frameGeometry() const;
/**
* Returns the geometry of the client window, in global screen coordinates.
*/
QRect clientGeometry() const;
/**
* Returns the extents of the server-side decoration.
*
......@@ -372,7 +376,7 @@ public:
* The default implementation is a 1:1 mapping meaning the frame is part of the content.
*/
virtual QPoint clientContentPos() const;
virtual QSize clientSize() const = 0;
QSize clientSize() const;
/**
* Returns a rectangle that the window occupies on the screen, including drop-shadows.
*/
......@@ -657,6 +661,10 @@ Q_SIGNALS:
* This signal is emitted when the Toplevel's frame geometry changes.
*/
void frameGeometryChanged(KWin::Toplevel *toplevel, const QRect &oldGeometry);
/**
* This signal is emitted when the Toplevel's client geometry has changed.
*/
void clientGeometryChanged(KWin::Toplevel *toplevel, const QRect &oldGeometry);
protected Q_SLOTS:
/**
......@@ -705,6 +713,7 @@ protected:
void deleteEffectWindow();
void setDepth(int depth);
QRect m_frameGeometry;
QRect m_clientGeometry;
xcb_visualid_t m_visual;
int bit_depth;
NETWinInfo* info;
......@@ -754,6 +763,16 @@ inline void Toplevel::setWindowHandles(xcb_window_t w)
m_client.reset(w, false);
}
inline QRect Toplevel::clientGeometry() const
{
return m_clientGeometry;
}
inline QSize Toplevel::clientSize() const
{
return m_clientGeometry.size();
}
inline QRect Toplevel::frameGeometry() const
{
return m_frameGeometry;
......
......@@ -152,11 +152,6 @@ QPoint Unmanaged::clientPos() const
return QPoint(0, 0); // unmanaged windows don't have decorations
}
QSize Unmanaged::clientSize() const
{
return size();
}
QRect Unmanaged::transparentRect() const
{
return QRect(clientPos(), clientSize());
......
......@@ -43,7 +43,6 @@ public:
QStringList activities() const override;
QVector<VirtualDesktop *> desktops() const override;
QPoint clientPos() const override;
QSize clientSize() const override;
QRect transparentRect() const override;
Layer layer() const override {
return UnmanagedLayer;
......
......@@ -160,6 +160,7 @@ X11Client::X11Client()
//client constructed be connected to the workspace wrapper
m_frameGeometry = QRect(0, 0, 100, 100); // So that decorations don't start with size being (0,0)
m_clientGeometry = QRect(0, 0, 100, 100);
connect(clientMachine(), &ClientMachine::localhostChanged, this, &X11Client::updateCaption);
connect(options, &Options::condensedTitleChanged, this, &X11Client::updateCaption);
......@@ -2898,6 +2899,9 @@ void X11Client::move(int x, int y, ForceGeometry_t force)
screens()->setCurrent(this);
workspace()->updateStackingOrder();
// client itself is not damaged
if (clientGeometryBeforeUpdateBlocking() != clientGeometry()) {
emit clientGeometryChanged(this, clientGeometryBeforeUpdateBlocking());
}
if (frameGeometryBeforeUpdateBlocking() != frameGeometry()) {
emit frameGeometryChanged(this, frameGeometryBeforeUpdateBlocking());
}
......@@ -4190,6 +4194,9 @@ void X11Client::setFrameGeometry(const QRect &rect, ForceGeometry_t force)
if (bufferGeometryBeforeUpdateBlocking().size() != m_bufferGeometry.size()) {
discardWindowPixmap();
}
if (clientGeometryBeforeUpdateBlocking() != m_clientGeometry) {
emit clientGeometryChanged(this, clientGeometryBeforeUpdateBlocking());
}
if (frameGeometryBeforeUpdateBlocking() != m_frameGeometry) {
emit frameGeometryChanged(this, frameGeometryBeforeUpdateBlocking());
}
......@@ -4247,6 +4254,9 @@ void X11Client::plainResize(int w, int h, ForceGeometry_t force)
if (bufferGeometryBeforeUpdateBlocking().size() != m_bufferGeometry.size()) {
discardWindowPixmap();
}
if (clientGeometryBeforeUpdateBlocking() != clientGeometry()) {
emit clientGeometryChanged(this, clientGeometryBeforeUpdateBlocking());
}
if (frameGeometryBeforeUpdateBlocking() != frameGeometry()) {
emit frameGeometryChanged(this, frameGeometryBeforeUpdateBlocking());
}
......
......@@ -123,7 +123,6 @@ public:
QSize minSize() const override;
QSize maxSize() const override;
QSize basicUnit() const;
QSize clientSize() const override;
QPoint inputPos() const { return input_offset; } // Inside of geometry()
bool windowEvent(xcb_generic_event_t *e);
......@@ -508,7 +507,6 @@ private:
MaximizeMode max_mode;
QRect m_bufferGeometry = QRect(0, 0, 100, 100);
QRect m_clientGeometry = QRect(0, 0, 100, 100);
QRect geom_fs_restore;
xcb_colormap_t m_colormap;
QString cap_normal, cap_iconic, cap_suffix;
......@@ -624,11 +622,6 @@ inline bool X11Client::isManaged() const
return m_managed;
}
inline QSize X11Client::clientSize() const
{
return m_clientGeometry.size();
}
inline void X11Client::plainResize(const QSize& s, ForceGeometry_t force)
{
plainResize(s.width(), s.height(), force);
......
......@@ -49,6 +49,12 @@ using namespace KWaylandServer;
namespace KWin
{
enum XdgSurfaceGeometryType {
XdgSurfaceGeometryClient = 0x1,
XdgSurfaceGeometryFrame = 0x2,
XdgSurfaceGeometryBuffer = 0x4,
};
XdgSurfaceClient::XdgSurfaceClient(XdgSurfaceInterface *shellSurface)
: WaylandClient(shellSurface->surface())
, m_shellSurface(shellSurface)
......@@ -156,11 +162,6 @@ QRect XdgSurfaceClient::clientGeometry() const
return m_clientGeometry;
}
QSize XdgSurfaceClient::clientSize() const
{
return m_clientGeometry.size();
}
QMatrix4x4 XdgSurfaceClient::inputTransformation() const
{
QMatrix4x4 transformation;
......@@ -437,20 +438,39 @@ void XdgSurfaceClient::requestGeometry(const QRect &rect)
void XdgSurfaceClient::updateGeometry(const QRect &rect)
{
const QRect oldClientGeometry = m_clientGeometry;
const QRect oldFrameGeometry = m_frameGeometry;
const QRect oldBufferGeometry = m_bufferGeometry;
m_clientGeometry = frameRectToClientRect(rect);
m_frameGeometry = rect;
m_bufferGeometry = frameRectToBufferRect(rect);
m_clientGeometry = frameRectToClientRect(rect);
if (oldFrameGeometry == m_frameGeometry) {
uint changedGeometries = 0;
if (m_clientGeometry != oldClientGeometry) {
changedGeometries |= XdgSurfaceGeometryClient;
}
if (m_frameGeometry != oldFrameGeometry) {
changedGeometries |= XdgSurfaceGeometryFrame;
}
if (m_bufferGeometry != oldBufferGeometry) {
changedGeometries |= XdgSurfaceGeometryBuffer;
}
if (!changedGeometries) {
return;
}
updateWindowRules(Rules::Position | Rules::Size);
updateGeometryBeforeUpdateBlocking();
emit frameGeometryChanged(this, oldFrameGeometry);
if (changedGeometries & XdgSurfaceGeometryClient) {
emit clientGeometryChanged(this, oldClientGeometry);
}
if (changedGeometries & XdgSurfaceGeometryFrame) {
emit frameGeometryChanged(this, oldFrameGeometry);
}
emit geometryShapeChanged(this, oldFrameGeometry);
addRepaintDuringGeometryUpdates();
......
......@@ -66,7 +66,6 @@ public:
QRect inputGeometry() const override;
QRect bufferGeometry() const override;
QSize clientSize() const override;
QMatrix4x4 inputTransformation() const override;
void setFrameGeometry(const QRect &rect, ForceGeometry_t force = NormalGeometrySet) override;
using AbstractClient::move;
......@@ -122,7 +121,6 @@ private:
QRect m_requestedFrameGeometry;
QRect m_bufferGeometry;
QRect m_requestedClientGeometry;
QRect m_clientGeometry;
bool m_isClosing = false;
bool m_isHidden = false;
bool m_haveNextWindowGeometry = false;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment