diff --git a/abstract_client.cpp b/abstract_client.cpp
index cbe5eb6a06..37f6d34247 100644
--- a/abstract_client.cpp
+++ b/abstract_client.cpp
@@ -34,6 +34,8 @@ along with this program. If not, see .
#include "wayland_server.h"
#include
+#include
+
namespace KWin
{
@@ -60,6 +62,7 @@ AbstractClient::AbstractClient()
AbstractClient::~AbstractClient()
{
assert(m_blockGeometryUpdates == 0);
+ Q_ASSERT(m_decoration == nullptr);
}
void AbstractClient::updateMouseGrab()
@@ -1075,11 +1078,6 @@ QSize AbstractClient::sizeForClientSize(const QSize &wsize, Sizemode mode, bool
return wsize;
}
-bool AbstractClient::isDecorated() const
-{
- return false;
-}
-
void AbstractClient::addRepaintDuringGeometryUpdates()
{
const QRect deco_rect = visibleRect();
@@ -1307,4 +1305,10 @@ void AbstractClient::endMoveResize()
updateCursor();
}
+void AbstractClient::destroyDecoration()
+{
+ delete m_decoration;
+ m_decoration = nullptr;
+}
+
}
diff --git a/abstract_client.h b/abstract_client.h
index 3e363ddec4..f39ff98c7d 100644
--- a/abstract_client.h
+++ b/abstract_client.h
@@ -35,6 +35,11 @@ class PlasmaWindowInterface;
}
}
+namespace KDecoration2
+{
+class Decoration;
+}
+
namespace KWin
{
@@ -331,7 +336,6 @@ public:
virtual void blockActivityUpdates(bool b = true) = 0;
QPalette palette() const;
const Decoration::DecorationPalette *decorationPalette() const;
- virtual bool isDecorated() const;
virtual bool isResizable() const = 0;
virtual bool isMovable() const = 0;
virtual bool isMovableAcrossScreens() const = 0;
@@ -477,6 +481,17 @@ public:
Options::MouseCommand getMouseCommand(Qt::MouseButton button, bool *handled) const;
Options::MouseCommand getWheelCommand(Qt::Orientation orientation, bool *handled) const;
+ // decoration related
+ KDecoration2::Decoration *decoration() {
+ return m_decoration;
+ }
+ const KDecoration2::Decoration *decoration() const {
+ return m_decoration;
+ }
+ bool isDecorated() const {
+ return m_decoration != nullptr;
+ }
+
// TODO: remove boolean trap
static bool belongToSameApplication(const AbstractClient* c1, const AbstractClient* c2, bool active_hack = false);
@@ -777,6 +792,11 @@ protected:
s_haveResizeEffect = false;
}
+ void setDecoration(KDecoration2::Decoration *decoration) {
+ m_decoration = decoration;
+ }
+ virtual void destroyDecoration();
+
private:
void handlePaletteChange();
QSharedPointer m_tabBoxClient;
@@ -838,6 +858,8 @@ private:
QTimer *delayedTimer = nullptr;
} m_moveResize;
+ KDecoration2::Decoration *m_decoration = nullptr;
+
static bool s_haveResizeEffect;
};
diff --git a/client.cpp b/client.cpp
index e2d31ddcbd..846ed7307b 100644
--- a/client.cpp
+++ b/client.cpp
@@ -97,7 +97,6 @@ Client::Client()
, m_client()
, m_wrapper()
, m_frame()
- , m_decoration(nullptr)
, m_activityUpdatesBlocked(false)
, m_blockedActivityUpdatesRequireTransients(false)
, m_moveResizeGrabWindow()
@@ -191,7 +190,6 @@ Client::~Client()
assert(m_client == XCB_WINDOW_NONE);
assert(m_wrapper == XCB_WINDOW_NONE);
//assert( frameId() == None );
- Q_ASSERT(m_decoration == nullptr);
assert(!check_active_modal);
for (auto it = m_connections.constBegin(); it != m_connections.constEnd(); ++it) {
disconnect(*it);
@@ -320,8 +318,8 @@ void Client::updateInputWindow()
QRegion region;
- if (!noBorder() && m_decoration) {
- const QMargins &r = m_decoration->resizeOnlyBorders();
+ if (!noBorder() && isDecorated()) {
+ const QMargins &r = decoration()->resizeOnlyBorders();
const int left = r.left();
const int top = r.top();
const int right = r.right();
@@ -329,9 +327,9 @@ void Client::updateInputWindow()
if (left != 0 || top != 0 || right != 0 || bottom != 0) {
region = QRegion(-left,
-top,
- m_decoration->size().width() + left + right,
- m_decoration->size().height() + top + bottom);
- region = region.subtracted(m_decoration->rect());
+ decoration()->size().width() + left + right,
+ decoration()->size().height() + top + bottom);
+ region = region.subtracted(decoration()->rect());
}
}
@@ -373,7 +371,7 @@ void Client::updateInputWindow()
void Client::updateDecoration(bool check_workspace_pos, bool force)
{
if (!force &&
- ((m_decoration == NULL && noBorder()) || (m_decoration != NULL && !noBorder())))
+ ((!isDecorated() && noBorder()) || (isDecorated() && !noBorder())))
return;
QRect oldgeom = geometry();
QRect oldClientGeom = oldgeom.adjusted(borderLeft(), borderTop(), -borderRight(), -borderBottom());
@@ -394,12 +392,12 @@ void Client::updateDecoration(bool check_workspace_pos, bool force)
void Client::createDecoration(const QRect& oldgeom)
{
- m_decoration = Decoration::DecorationBridge::self()->createDecoration(this);
- if (m_decoration) {
- QMetaObject::invokeMethod(m_decoration, "update", Qt::QueuedConnection);
- connect(m_decoration, &KDecoration2::Decoration::shadowChanged, this, &Toplevel::getShadow);
- connect(m_decoration, &KDecoration2::Decoration::resizeOnlyBordersChanged, this, &Client::updateInputWindow);
- connect(m_decoration, &KDecoration2::Decoration::bordersChanged, this,
+ 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::resizeOnlyBordersChanged, this, &Client::updateInputWindow);
+ connect(decoration, &KDecoration2::Decoration::bordersChanged, this,
[this]() {
updateFrameExtents();
GeometryUpdatesBlocker blocker(this);
@@ -415,6 +413,7 @@ void Client::createDecoration(const QRect& oldgeom)
}
);
}
+ setDecoration(decoration);
move(calculateGravitation(false));
plainResize(sizeForClientSize(clientSize()), ForceGeometrySet);
@@ -427,10 +426,9 @@ void Client::createDecoration(const QRect& oldgeom)
void Client::destroyDecoration()
{
QRect oldgeom = geometry();
- if (m_decoration) {
+ if (isDecorated()) {
QPoint grav = calculateGravitation(true);
- delete m_decoration;
- m_decoration = nullptr;
+ AbstractClient::destroyDecoration();
plainResize(sizeForClientSize(clientSize()), ForceGeometrySet);
move(grav);
if (compositing())
@@ -444,17 +442,17 @@ void Client::destroyDecoration()
void Client::triggerDecorationRepaint()
{
- if (m_decoration) {
- m_decoration->update();
+ if (isDecorated()) {
+ decoration()->update();
}
}
void Client::layoutDecorationRects(QRect &left, QRect &top, QRect &right, QRect &bottom) const
{
- if (!m_decoration) {
+ if (!isDecorated()) {
return;
}
- QRect r = m_decoration->rect();
+ QRect r = decoration()->rect();
NETStrut strut = info->frameOverlap();
@@ -571,9 +569,7 @@ void Client::detectGtkFrameExtents()
*/
void Client::resizeDecoration()
{
- if (m_decoration) {
- m_decoration->update();
- }
+ triggerDecorationRepaint();
updateInputWindow();
}
@@ -784,7 +780,7 @@ void Client::setShade(ShadeMode mode)
return; // No real change in shaded state
}
- assert(m_decoration != NULL); // noborder windows can't be shaded
+ assert(isDecorated()); // noborder windows can't be shaded
GeometryUpdatesBlocker blocker(this);
// TODO: All this unmapping, resizing etc. feels too much duplicated from elsewhere
@@ -1850,8 +1846,8 @@ void Client::setBlockingCompositing(bool block)
Client::Position Client::mousePosition() const
{
- if (m_decoration) {
- switch (m_decoration->sectionUnderMouse()) {
+ if (isDecorated()) {
+ switch (decoration()->sectionUnderMouse()) {
case Qt::BottomLeftSection:
return PositionBottomLeft;
case Qt::BottomRightSection:
@@ -2066,7 +2062,7 @@ NET::WindowType Client::windowType(bool direct, int supportedTypes) const
bool Client::decorationHasAlpha() const
{
- if (!m_decoration || m_decoration->isOpaque()) {
+ if (!isDecorated() || decoration()->isOpaque()) {
// either no decoration or decoration has alpha disabled
return false;
}
@@ -2171,7 +2167,7 @@ void Client::showOnScreenEdge()
#define BORDER(which) \
int Client::border##which() const \
{ \
- return m_decoration ? m_decoration->border##which() : 0; \
+ return isDecorated() ? decoration()->border##which() : 0; \
}
BORDER(Bottom)
@@ -2219,8 +2215,8 @@ bool Client::processDecorationButtonPress(QMouseEvent *event)
void Client::processDecorationButtonRelease(QMouseEvent *event)
{
- if (m_decoration) {
- if (!event->isAccepted() && m_decoration->titleBar().contains(event->pos()) && event->button() == Qt::LeftButton) {
+ if (isDecorated()) {
+ if (!event->isAccepted() && decoration()->titleBar().contains(event->pos()) && event->button() == Qt::LeftButton) {
m_decorationDoubleClickTimer.start();
}
}
diff --git a/client.h b/client.h
index c6b598dd64..1556c64d6b 100644
--- a/client.h
+++ b/client.h
@@ -45,11 +45,6 @@ class KStartupInfoId;
struct xcb_sync_alarm_notify_event_t;
-namespace KDecoration2
-{
-class Decoration;
-}
-
namespace KWin
{
@@ -356,16 +351,7 @@ public:
bool hasOffscreenXineramaStrut() const;
// Decorations <-> Effects
- KDecoration2::Decoration *decoration() {
- return m_decoration;
- }
- const KDecoration2::Decoration *decoration() const {
- return m_decoration;
- }
QPointer decoratedClient() const;
- bool isDecorated() const override {
- return m_decoration != nullptr;
- }
void setDecoratedClient(QPointer client);
QRect decorationRect() const;
@@ -550,7 +536,7 @@ private:
Xcb::Property fetchGtkFrameExtents() const;
void readGtkFrameExtents(Xcb::Property &prop);
void detectGtkFrameExtents();
- void destroyDecoration();
+ void destroyDecoration() override;
void updateFrameExtents();
void internalShow();
@@ -582,7 +568,6 @@ private:
Xcb::Window m_client;
Xcb::Window m_wrapper;
Xcb::Window m_frame;
- KDecoration2::Decoration *m_decoration;
QPointer m_decoratedClient;
QElapsedTimer m_decorationDoubleClickTimer;
QStringList activityList;
diff --git a/events.cpp b/events.cpp
index 508934727b..6324d15032 100644
--- a/events.cpp
+++ b/events.cpp
@@ -1006,10 +1006,10 @@ void Client::leaveNotifyEvent(xcb_leave_notify_event_t *e)
shadeHoverTimer->setSingleShot(true);
shadeHoverTimer->start(options->shadeHoverInterval());
}
- if (m_decoration) {
+ if (isDecorated()) {
// sending a move instead of a leave. With leave we need to send proper coords, with move it's handled internally
QHoverEvent leaveEvent(QEvent::HoverMove, QPointF(-1, -1), QPointF(-1, -1), Qt::NoModifier);
- QCoreApplication::sendEvent(m_decoration, &leaveEvent);
+ QCoreApplication::sendEvent(decoration(), &leaveEvent);
}
}
if (options->focusPolicy() == Options::FocusStrictlyUnderMouse && isActive() && lostMouse) {
@@ -1170,7 +1170,7 @@ bool Client::buttonPressEvent(xcb_window_t w, int button, int state, int x, int
// New API processes core events FIRST and only passes unused ones to the decoration
return processDecorationButtonPress(button, state, x, y, x_root, y_root, true);
}
- if (w == frameId() && m_decoration) {
+ if (w == frameId() && isDecorated()) {
if (button >= 4 && button <= 7) {
const Qt::KeyboardModifiers modifiers = x11ToQtKeyboardModifiers(state);
// Logic borrowed from qapplication_x11.cpp
@@ -1188,9 +1188,9 @@ bool Client::buttonPressEvent(xcb_window_t w, int button, int state, int x, int
x11ToQtMouseButtons(state),
modifiers);
event.setAccepted(false);
- QCoreApplication::sendEvent(m_decoration, &event);
+ QCoreApplication::sendEvent(decoration(), &event);
if (!event.isAccepted() && !hor) {
- if (m_decoration->titleBar().contains(x, y)) {
+ if (decoration()->titleBar().contains(x, y)) {
performMouseCommand(options->operationTitlebarMouseWheel(delta), QPoint(x_root, y_root));
}
}
@@ -1198,7 +1198,7 @@ bool Client::buttonPressEvent(xcb_window_t w, int button, int state, int x, int
QMouseEvent event(QEvent::MouseButtonPress, QPointF(x, y), QPointF(x_root, y_root),
x11ToQtMouseButton(button), x11ToQtMouseButtons(state), x11ToQtKeyboardModifiers(state));
event.setAccepted(false);
- QCoreApplication::sendEvent(m_decoration, &event);
+ QCoreApplication::sendEvent(decoration(), &event);
if (!event.isAccepted()) {
processDecorationButtonPress(button, state, x, y, x_root, y_root);
}
@@ -1222,7 +1222,7 @@ bool Client::processDecorationButtonPress(int button, int /*state*/, int x, int
// check whether it is a double click
if (button == XCB_BUTTON_INDEX_1) {
if (m_decorationDoubleClickTimer.isValid() &&
- m_decoration->titleBar().contains(x, y) &&
+ decoration()->titleBar().contains(x, y) &&
!m_decorationDoubleClickTimer.hasExpired(QGuiApplication::styleHints()->mouseDoubleClickInterval())) {
Workspace::self()->performWindowOperation(this, options->operationTitlebarDblClick());
dontMoveResize();
@@ -1268,7 +1268,7 @@ bool Client::processDecorationButtonPress(int button, int /*state*/, int x, int
// return value matters only when filtering events before decoration gets them
bool Client::buttonReleaseEvent(xcb_window_t w, int button, int state, int x, int y, int x_root, int y_root)
{
- if (w == frameId() && m_decoration) {
+ if (w == frameId() && isDecorated()) {
// wheel handled on buttonPress
if (button < 4 || button > 7) {
QMouseEvent event(QEvent::MouseButtonRelease,
@@ -1278,8 +1278,8 @@ bool Client::buttonReleaseEvent(xcb_window_t w, int button, int state, int x, in
x11ToQtMouseButtons(state) & ~x11ToQtMouseButton(button),
x11ToQtKeyboardModifiers(state));
event.setAccepted(false);
- QCoreApplication::sendEvent(m_decoration, &event);
- if (!event.isAccepted() && m_decoration->titleBar().contains(x, y) && button == XCB_BUTTON_INDEX_1) {
+ QCoreApplication::sendEvent(decoration(), &event);
+ if (!event.isAccepted() && decoration()->titleBar().contains(x, y) && button == XCB_BUTTON_INDEX_1) {
m_decorationDoubleClickTimer.start();
}
}
@@ -1314,10 +1314,10 @@ bool Client::buttonReleaseEvent(xcb_window_t w, int button, int state, int x, in
// return value matters only when filtering events before decoration gets them
bool Client::motionNotifyEvent(xcb_window_t w, int state, int x, int y, int x_root, int y_root)
{
- if (w == frameId() && m_decoration && !isMinimized()) {
+ if (w == frameId() && isDecorated() && !isMinimized()) {
// TODO Mouse move event dependent on state
QHoverEvent event(QEvent::HoverMove, QPointF(x, y), QPointF(x, y));
- QCoreApplication::instance()->sendEvent(m_decoration, &event);
+ QCoreApplication::instance()->sendEvent(decoration(), &event);
}
if (w != frameId() && w != inputId() && w != moveResizeGrabWindow())
return true; // care only about the whole frame
@@ -1326,9 +1326,9 @@ bool Client::motionNotifyEvent(xcb_window_t w, int state, int x, int y, int x_ro
int x = x_root - geometry().x();// + padding_left;
int y = y_root - geometry().y();// + padding_top;
- if (m_decoration) {
+ if (isDecorated()) {
QHoverEvent event(QEvent::HoverMove, QPointF(x, y), QPointF(x, y));
- QCoreApplication::instance()->sendEvent(m_decoration, &event);
+ QCoreApplication::instance()->sendEvent(decoration(), &event);
}
}
Position newmode = modKeyDown(state) ? PositionCenter : mousePosition();
diff --git a/geometry.cpp b/geometry.cpp
index ab73001b0f..0ba2c6dc88 100644
--- a/geometry.cpp
+++ b/geometry.cpp
@@ -1311,7 +1311,7 @@ QSize Client::sizeForClientSize(const QSize& wsize, Sizemode mode, bool noframe)
// even if they're not set in flags - see getWmNormalHints()
QSize min_size = tabGroup() ? tabGroup()->minSize() : minSize();
QSize max_size = tabGroup() ? tabGroup()->maxSize() : maxSize();
- if (m_decoration != NULL) {
+ if (isDecorated()) {
QSize decominsize(0, 0);
QSize border_size(borderLeft() + borderRight(), borderTop() + borderBottom());
if (border_size.width() > decominsize.width()) // just in case
@@ -2237,9 +2237,9 @@ void Client::changeMaximize(bool vertical, bool horizontal, bool adjust)
}
// call into decoration update borders
- if (m_decoration && m_decoration->client() && !(options->borderlessMaximizedWindows() && max_mode == KWin::MaximizeFull)) {
+ if (isDecorated() && decoration()->client() && !(options->borderlessMaximizedWindows() && max_mode == KWin::MaximizeFull)) {
changeMaximizeRecursion = true;
- const auto c = m_decoration->client().data();
+ const auto c = decoration()->client().data();
if ((max_mode & MaximizeVertical) != (old_mode & MaximizeVertical)) {
emit c->maximizedVerticallyChanged(max_mode & MaximizeVertical);
}
@@ -2260,7 +2260,7 @@ void Client::changeMaximize(bool vertical, bool horizontal, bool adjust)
changeMaximizeRecursion = false;
}
- const ForceGeometry_t geom_mode = m_decoration ? ForceGeometrySet : NormalGeometrySet;
+ const ForceGeometry_t geom_mode = isDecorated() ? ForceGeometrySet : NormalGeometrySet;
// Conditional quick tiling exit points
if (quickTileMode() != QuickTileNone) {