File indexing completed on 2024-05-19 16:34:02
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include "decoratedclient.h" 0010 #include "cursor.h" 0011 #include "decorationbridge.h" 0012 #include "decorationpalette.h" 0013 #include "window.h" 0014 #include "workspace.h" 0015 0016 #include <KDecoration2/DecoratedClient> 0017 #include <KDecoration2/Decoration> 0018 0019 #include <QDebug> 0020 #include <QStyle> 0021 #include <QToolTip> 0022 0023 namespace KWin 0024 { 0025 namespace Decoration 0026 { 0027 0028 DecoratedClientImpl::DecoratedClientImpl(Window *window, KDecoration2::DecoratedClient *decoratedClient, KDecoration2::Decoration *decoration) 0029 : QObject() 0030 , ApplicationMenuEnabledDecoratedClientPrivate(decoratedClient, decoration) 0031 , m_window(window) 0032 , m_clientSize(window->clientSize().toSize()) 0033 { 0034 window->setDecoratedClient(QPointer<DecoratedClientImpl>(this)); 0035 connect(window, &Window::activeChanged, this, [decoratedClient, window]() { 0036 Q_EMIT decoratedClient->activeChanged(window->isActive()); 0037 }); 0038 connect(window, &Window::clientGeometryChanged, this, [decoratedClient, this]() { 0039 if (m_window->clientSize() == m_clientSize) { 0040 return; 0041 } 0042 const auto oldSize = m_clientSize; 0043 m_clientSize = m_window->clientSize().toSize(); 0044 if (oldSize.width() != m_clientSize.width()) { 0045 Q_EMIT decoratedClient->widthChanged(m_clientSize.width()); 0046 } 0047 if (oldSize.height() != m_clientSize.height()) { 0048 Q_EMIT decoratedClient->heightChanged(m_clientSize.height()); 0049 } 0050 Q_EMIT decoratedClient->sizeChanged(m_clientSize); 0051 }); 0052 connect(window, &Window::desktopChanged, this, [decoratedClient, window]() { 0053 Q_EMIT decoratedClient->onAllDesktopsChanged(window->isOnAllDesktops()); 0054 }); 0055 connect(window, &Window::captionChanged, this, [decoratedClient, window]() { 0056 Q_EMIT decoratedClient->captionChanged(window->caption()); 0057 }); 0058 connect(window, &Window::iconChanged, this, [decoratedClient, window]() { 0059 Q_EMIT decoratedClient->iconChanged(window->icon()); 0060 }); 0061 connect(window, &Window::shadeChanged, this, &Decoration::DecoratedClientImpl::signalShadeChange); 0062 connect(window, &Window::keepAboveChanged, decoratedClient, &KDecoration2::DecoratedClient::keepAboveChanged); 0063 connect(window, &Window::keepBelowChanged, decoratedClient, &KDecoration2::DecoratedClient::keepBelowChanged); 0064 connect(window, &Window::quickTileModeChanged, decoratedClient, [this, decoratedClient]() { 0065 Q_EMIT decoratedClient->adjacentScreenEdgesChanged(adjacentScreenEdges()); 0066 }); 0067 connect(window, &Window::closeableChanged, decoratedClient, &KDecoration2::DecoratedClient::closeableChanged); 0068 connect(window, &Window::shadeableChanged, decoratedClient, &KDecoration2::DecoratedClient::shadeableChanged); 0069 connect(window, &Window::minimizeableChanged, decoratedClient, &KDecoration2::DecoratedClient::minimizeableChanged); 0070 connect(window, &Window::maximizeableChanged, decoratedClient, &KDecoration2::DecoratedClient::maximizeableChanged); 0071 0072 connect(window, &Window::paletteChanged, decoratedClient, &KDecoration2::DecoratedClient::paletteChanged); 0073 0074 connect(window, &Window::hasApplicationMenuChanged, decoratedClient, &KDecoration2::DecoratedClient::hasApplicationMenuChanged); 0075 connect(window, &Window::applicationMenuActiveChanged, decoratedClient, &KDecoration2::DecoratedClient::applicationMenuActiveChanged); 0076 0077 m_toolTipWakeUp.setSingleShot(true); 0078 connect(&m_toolTipWakeUp, &QTimer::timeout, this, [this]() { 0079 int fallAsleepDelay = QApplication::style()->styleHint(QStyle::SH_ToolTip_FallAsleepDelay); 0080 this->m_toolTipFallAsleep.setRemainingTime(fallAsleepDelay); 0081 0082 QToolTip::showText(Cursors::self()->mouse()->pos(), this->m_toolTipText); 0083 m_toolTipShowing = true; 0084 }); 0085 } 0086 0087 DecoratedClientImpl::~DecoratedClientImpl() 0088 { 0089 if (m_toolTipShowing) { 0090 requestHideToolTip(); 0091 } 0092 } 0093 0094 void DecoratedClientImpl::signalShadeChange() 0095 { 0096 Q_EMIT decoratedClient()->shadedChanged(m_window->isShade()); 0097 } 0098 0099 #define DELEGATE(type, name, clientName) \ 0100 type DecoratedClientImpl::name() const \ 0101 { \ 0102 return m_window->clientName(); \ 0103 } 0104 0105 #define DELEGATE2(type, name) DELEGATE(type, name, name) 0106 0107 DELEGATE2(QString, caption) 0108 DELEGATE2(bool, isActive) 0109 DELEGATE2(bool, isCloseable) 0110 DELEGATE(bool, isMaximizeable, isMaximizable) 0111 DELEGATE(bool, isMinimizeable, isMinimizable) 0112 DELEGATE2(bool, isModal) 0113 DELEGATE(bool, isMoveable, isMovable) 0114 DELEGATE(bool, isResizeable, isResizable) 0115 DELEGATE2(bool, isShadeable) 0116 DELEGATE2(bool, providesContextHelp) 0117 DELEGATE2(int, desktop) 0118 DELEGATE2(bool, isOnAllDesktops) 0119 DELEGATE2(QPalette, palette) 0120 DELEGATE2(QIcon, icon) 0121 0122 #undef DELEGATE2 0123 #undef DELEGATE 0124 0125 #define DELEGATE(type, name, clientName) \ 0126 type DecoratedClientImpl::name() const \ 0127 { \ 0128 return m_window->clientName(); \ 0129 } 0130 0131 DELEGATE(bool, isKeepAbove, keepAbove) 0132 DELEGATE(bool, isKeepBelow, keepBelow) 0133 DELEGATE(bool, isShaded, isShade) 0134 DELEGATE(WId, windowId, window) 0135 DELEGATE(WId, decorationId, frameId) 0136 0137 #undef DELEGATE 0138 0139 #define DELEGATE(name, op) \ 0140 void DecoratedClientImpl::name() \ 0141 { \ 0142 Workspace::self()->performWindowOperation(m_window, Options::op); \ 0143 } 0144 0145 DELEGATE(requestToggleShade, ShadeOp) 0146 DELEGATE(requestToggleOnAllDesktops, OnAllDesktopsOp) 0147 DELEGATE(requestToggleKeepAbove, KeepAboveOp) 0148 DELEGATE(requestToggleKeepBelow, KeepBelowOp) 0149 0150 #undef DELEGATE 0151 0152 #define DELEGATE(name, clientName) \ 0153 void DecoratedClientImpl::name() \ 0154 { \ 0155 m_window->clientName(); \ 0156 } 0157 0158 DELEGATE(requestContextHelp, showContextHelp) 0159 DELEGATE(requestMinimize, minimize) 0160 0161 #undef DELEGATE 0162 0163 void DecoratedClientImpl::requestClose() 0164 { 0165 QMetaObject::invokeMethod(m_window, &Window::closeWindow, Qt::QueuedConnection); 0166 } 0167 0168 QColor DecoratedClientImpl::color(KDecoration2::ColorGroup group, KDecoration2::ColorRole role) const 0169 { 0170 auto dp = m_window->decorationPalette(); 0171 if (dp) { 0172 return dp->color(group, role); 0173 } 0174 0175 return QColor(); 0176 } 0177 0178 void DecoratedClientImpl::requestShowToolTip(const QString &text) 0179 { 0180 if (!workspace()->decorationBridge()->showToolTips()) { 0181 return; 0182 } 0183 0184 m_toolTipText = text; 0185 0186 int wakeUpDelay = QApplication::style()->styleHint(QStyle::SH_ToolTip_WakeUpDelay); 0187 m_toolTipWakeUp.start(m_toolTipFallAsleep.hasExpired() ? wakeUpDelay : 20); 0188 } 0189 0190 void DecoratedClientImpl::requestHideToolTip() 0191 { 0192 m_toolTipWakeUp.stop(); 0193 QToolTip::hideText(); 0194 m_toolTipShowing = false; 0195 } 0196 0197 void DecoratedClientImpl::requestShowWindowMenu(const QRect &rect) 0198 { 0199 Workspace::self()->showWindowMenu(QRectF(m_window->pos() + rect.topLeft(), m_window->pos() + rect.bottomRight()).toRect(), m_window); 0200 } 0201 0202 void DecoratedClientImpl::requestShowApplicationMenu(const QRect &rect, int actionId) 0203 { 0204 Workspace::self()->showApplicationMenu(rect, m_window, actionId); 0205 } 0206 0207 void DecoratedClientImpl::showApplicationMenu(int actionId) 0208 { 0209 decoration()->showApplicationMenu(actionId); 0210 } 0211 0212 void DecoratedClientImpl::requestToggleMaximization(Qt::MouseButtons buttons) 0213 { 0214 auto operation = options->operationMaxButtonClick(buttons); 0215 QMetaObject::invokeMethod( 0216 this, [this, operation] { 0217 delayedRequestToggleMaximization(operation); 0218 }, 0219 Qt::QueuedConnection); 0220 } 0221 0222 void DecoratedClientImpl::delayedRequestToggleMaximization(Options::WindowOperation operation) 0223 { 0224 Workspace::self()->performWindowOperation(m_window, operation); 0225 } 0226 0227 int DecoratedClientImpl::width() const 0228 { 0229 return m_clientSize.width(); 0230 } 0231 0232 int DecoratedClientImpl::height() const 0233 { 0234 return m_clientSize.height(); 0235 } 0236 0237 QSize DecoratedClientImpl::size() const 0238 { 0239 return m_clientSize; 0240 } 0241 0242 bool DecoratedClientImpl::isMaximizedVertically() const 0243 { 0244 return m_window->requestedMaximizeMode() & MaximizeVertical; 0245 } 0246 0247 bool DecoratedClientImpl::isMaximized() const 0248 { 0249 return isMaximizedHorizontally() && isMaximizedVertically(); 0250 } 0251 0252 bool DecoratedClientImpl::isMaximizedHorizontally() const 0253 { 0254 return m_window->requestedMaximizeMode() & MaximizeHorizontal; 0255 } 0256 0257 Qt::Edges DecoratedClientImpl::adjacentScreenEdges() const 0258 { 0259 Qt::Edges edges; 0260 const QuickTileMode mode = m_window->quickTileMode(); 0261 if (mode.testFlag(QuickTileFlag::Left)) { 0262 edges |= Qt::LeftEdge; 0263 if (!mode.testFlag(QuickTileFlag::Top) && !mode.testFlag(QuickTileFlag::Bottom)) { 0264 // using complete side 0265 edges |= Qt::TopEdge | Qt::BottomEdge; 0266 } 0267 } 0268 if (mode.testFlag(QuickTileFlag::Top)) { 0269 edges |= Qt::TopEdge; 0270 } 0271 if (mode.testFlag(QuickTileFlag::Right)) { 0272 edges |= Qt::RightEdge; 0273 if (!mode.testFlag(QuickTileFlag::Top) && !mode.testFlag(QuickTileFlag::Bottom)) { 0274 // using complete side 0275 edges |= Qt::TopEdge | Qt::BottomEdge; 0276 } 0277 } 0278 if (mode.testFlag(QuickTileFlag::Bottom)) { 0279 edges |= Qt::BottomEdge; 0280 } 0281 return edges; 0282 } 0283 0284 bool DecoratedClientImpl::hasApplicationMenu() const 0285 { 0286 return m_window->hasApplicationMenu(); 0287 } 0288 0289 bool DecoratedClientImpl::isApplicationMenuActive() const 0290 { 0291 return m_window->applicationMenuActive(); 0292 } 0293 0294 QString DecoratedClientImpl::windowClass() const 0295 { 0296 return m_window->resourceName() + QLatin1Char(' ') + m_window->resourceClass(); 0297 } 0298 0299 } 0300 }