1 /*
2     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
3 
4     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
5 */
6 #include "previewclient.h"
7 #include <KDecoration2/Decoration>
8 #include <KDecoration2/DecoratedClient>
9 
10 #include <QDebug>
11 #include <QCoreApplication>
12 #include <QEvent>
13 #include <QModelIndex>
14 
15 namespace KDecoration2
16 {
17 namespace Preview
18 {
19 
PreviewClient(DecoratedClient * c,Decoration * decoration)20 PreviewClient::PreviewClient(DecoratedClient *c, Decoration *decoration)
21     : QObject(decoration)
22     , ApplicationMenuEnabledDecoratedClientPrivate(c, decoration)
23     , m_icon(QIcon::fromTheme(QStringLiteral("start-here-kde")))
24     , m_iconName(m_icon.name())
25     , m_palette(QStringLiteral("kdeglobals"))
26     , m_active(true)
27     , m_closeable(true)
28     , m_keepBelow(false)
29     , m_keepAbove(false)
30     , m_maximizable(true)
31     , m_maximizedHorizontally(false)
32     , m_maximizedVertically(false)
33     , m_minimizable(true)
34     , m_modal(false)
35     , m_movable(true)
36     , m_resizable(true)
37     , m_shadeable(true)
38     , m_shaded(false)
39     , m_providesContextHelp(false)
40     , m_desktop(1)
41     , m_width(0)
42     , m_height(0)
43     , m_bordersTopEdge(false)
44     , m_bordersLeftEdge(false)
45     , m_bordersRightEdge(false)
46     , m_bordersBottomEdge(false)
47 {
48     connect(this, &PreviewClient::captionChanged,               c, &DecoratedClient::captionChanged);
49     connect(this, &PreviewClient::activeChanged,                c, &DecoratedClient::activeChanged);
50     connect(this, &PreviewClient::closeableChanged,             c, &DecoratedClient::closeableChanged);
51     connect(this, &PreviewClient::keepAboveChanged,             c, &DecoratedClient::keepAboveChanged);
52     connect(this, &PreviewClient::keepBelowChanged,             c, &DecoratedClient::keepBelowChanged);
53     connect(this, &PreviewClient::maximizableChanged,           c, &DecoratedClient::maximizeableChanged);
54     connect(this, &PreviewClient::maximizedChanged,             c, &DecoratedClient::maximizedChanged);
55     connect(this, &PreviewClient::maximizedVerticallyChanged,   c, &DecoratedClient::maximizedVerticallyChanged);
56     connect(this, &PreviewClient::maximizedHorizontallyChanged, c, &DecoratedClient::maximizedHorizontallyChanged);
57     connect(this, &PreviewClient::minimizableChanged,           c, &DecoratedClient::minimizeableChanged);
58     connect(this, &PreviewClient::movableChanged,               c, &DecoratedClient::moveableChanged);
59     connect(this, &PreviewClient::onAllDesktopsChanged,         c, &DecoratedClient::onAllDesktopsChanged);
60     connect(this, &PreviewClient::resizableChanged,             c, &DecoratedClient::resizeableChanged);
61     connect(this, &PreviewClient::shadeableChanged,             c, &DecoratedClient::shadeableChanged);
62     connect(this, &PreviewClient::shadedChanged,                c, &DecoratedClient::shadedChanged);
63     connect(this, &PreviewClient::providesContextHelpChanged,   c, &DecoratedClient::providesContextHelpChanged);
64     connect(this, &PreviewClient::onAllDesktopsChanged,         c, &DecoratedClient::onAllDesktopsChanged);
65     connect(this, &PreviewClient::widthChanged,                 c, &DecoratedClient::widthChanged);
66     connect(this, &PreviewClient::heightChanged,                c, &DecoratedClient::heightChanged);
67     connect(this, &PreviewClient::iconChanged,                  c, &DecoratedClient::iconChanged);
68     connect(this, &PreviewClient::paletteChanged,               c, &DecoratedClient::paletteChanged);
69     connect(this, &PreviewClient::maximizedVerticallyChanged, this,
70         [this]() {
71             Q_EMIT maximizedChanged(isMaximized());
72         }
73     );
74     connect(this, &PreviewClient::maximizedHorizontallyChanged, this,
75         [this]() {
76             Q_EMIT maximizedChanged(isMaximized());
77         }
78     );
79     connect(this, &PreviewClient::iconNameChanged, this,
80         [this]() {
81             m_icon = QIcon::fromTheme(m_iconName);
82             Q_EMIT iconChanged(m_icon);
83         }
84     );
85     connect(this, &PreviewClient::desktopChanged, this,
86         [this]() {
87             Q_EMIT onAllDesktopsChanged(isOnAllDesktops());
88         }
89     );
90     connect(&m_palette, &KWin::Decoration::DecorationPalette::changed, this, [this]() {
91         Q_EMIT paletteChanged(m_palette.palette());
92     });
93     auto emitEdgesChanged = [this, c]() {
94         Q_EMIT c->adjacentScreenEdgesChanged(adjacentScreenEdges());
95     };
96     connect(this, &PreviewClient::bordersTopEdgeChanged,    this, emitEdgesChanged);
97     connect(this, &PreviewClient::bordersLeftEdgeChanged,   this, emitEdgesChanged);
98     connect(this, &PreviewClient::bordersRightEdgeChanged,  this, emitEdgesChanged);
99     connect(this, &PreviewClient::bordersBottomEdgeChanged, this, emitEdgesChanged);
100     auto emitSizeChanged = [c]() {
101         Q_EMIT c->sizeChanged(c->size());
102     };
103     connect(this, &PreviewClient::widthChanged, this, emitSizeChanged);
104     connect(this, &PreviewClient::heightChanged, this, emitSizeChanged);
105 
106     qApp->installEventFilter(this);
107 }
108 
109 PreviewClient::~PreviewClient() = default;
110 
setIcon(const QIcon & pixmap)111 void PreviewClient::setIcon(const QIcon &pixmap)
112 {
113     m_icon = pixmap;
114     Q_EMIT iconChanged(m_icon);
115 }
116 
width() const117 int PreviewClient::width() const
118 {
119     return m_width;
120 }
121 
height() const122 int PreviewClient::height() const
123 {
124     return m_height;
125 }
126 
size() const127 QSize PreviewClient::size() const
128 {
129     return QSize(m_width, m_height);
130 }
131 
caption() const132 QString PreviewClient::caption() const
133 {
134     return m_caption;
135 }
136 
decorationId() const137 WId PreviewClient::decorationId() const
138 {
139     return 0;
140 }
141 
desktop() const142 int PreviewClient::desktop() const
143 {
144     return m_desktop;
145 }
146 
setDesktop(int desktop)147 void PreviewClient::setDesktop(int desktop)
148 {
149     if (desktop == 0) {
150         desktop = 1;
151     }
152     if (m_desktop == desktop) {
153         return;
154     }
155     m_desktop = desktop;
156     Q_EMIT desktopChanged(m_desktop);
157 }
158 
icon() const159 QIcon PreviewClient::icon() const
160 {
161     return m_icon;
162 }
163 
iconName() const164 QString PreviewClient::iconName() const
165 {
166     return m_iconName;
167 }
168 
isActive() const169 bool PreviewClient::isActive() const
170 {
171     return m_active;
172 }
173 
isCloseable() const174 bool PreviewClient::isCloseable() const
175 {
176     return m_closeable;
177 }
178 
isKeepAbove() const179 bool PreviewClient::isKeepAbove() const
180 {
181     return m_keepAbove;
182 }
183 
isKeepBelow() const184 bool PreviewClient::isKeepBelow() const
185 {
186     return m_keepBelow;
187 }
188 
isMaximizeable() const189 bool PreviewClient::isMaximizeable() const
190 {
191     return m_maximizable;
192 }
193 
isMaximized() const194 bool PreviewClient::isMaximized() const
195 {
196     return isMaximizedHorizontally() && isMaximizedVertically();
197 }
198 
isMaximizedHorizontally() const199 bool PreviewClient::isMaximizedHorizontally() const
200 {
201     return m_maximizedHorizontally;
202 }
203 
isMaximizedVertically() const204 bool PreviewClient::isMaximizedVertically() const
205 {
206     return m_maximizedVertically;
207 }
208 
isMinimizeable() const209 bool PreviewClient::isMinimizeable() const
210 {
211     return m_minimizable;
212 }
213 
isModal() const214 bool PreviewClient::isModal() const
215 {
216     return m_modal;
217 }
218 
isMoveable() const219 bool PreviewClient::isMoveable() const
220 {
221     return m_movable;
222 }
223 
isOnAllDesktops() const224 bool PreviewClient::isOnAllDesktops() const
225 {
226     return desktop() == -1;
227 }
228 
isResizeable() const229 bool PreviewClient::isResizeable() const
230 {
231     return m_resizable;
232 }
233 
isShadeable() const234 bool PreviewClient::isShadeable() const
235 {
236     return m_shadeable;
237 }
238 
isShaded() const239 bool PreviewClient::isShaded() const
240 {
241     return m_shaded;
242 }
243 
providesContextHelp() const244 bool PreviewClient::providesContextHelp() const
245 {
246     return m_providesContextHelp;
247 }
248 
windowId() const249 WId PreviewClient::windowId() const
250 {
251     return 0;
252 }
253 
palette() const254 QPalette PreviewClient::palette() const
255 {
256     return m_palette.palette();
257 }
258 
color(ColorGroup group,ColorRole role) const259 QColor PreviewClient::color(ColorGroup group, ColorRole role) const
260 {
261     return m_palette.color(group, role);
262 }
263 
adjacentScreenEdges() const264 Qt::Edges PreviewClient::adjacentScreenEdges() const
265 {
266     Qt::Edges edges;
267     if (m_bordersBottomEdge) {
268         edges |= Qt::BottomEdge;
269     }
270     if (m_bordersLeftEdge) {
271         edges |= Qt::LeftEdge;
272     }
273     if (m_bordersRightEdge) {
274         edges |= Qt::RightEdge;
275     }
276     if (m_bordersTopEdge) {
277         edges |= Qt::TopEdge;
278     }
279     return edges;
280 }
281 
hasApplicationMenu() const282 bool PreviewClient::hasApplicationMenu() const
283 {
284     return true;
285 }
286 
isApplicationMenuActive() const287 bool PreviewClient::isApplicationMenuActive() const
288 {
289     return false;
290 }
291 
bordersBottomEdge() const292 bool PreviewClient::bordersBottomEdge() const
293 {
294     return m_bordersBottomEdge;
295 }
296 
bordersLeftEdge() const297 bool PreviewClient::bordersLeftEdge() const
298 {
299     return m_bordersLeftEdge;
300 }
301 
bordersRightEdge() const302 bool PreviewClient::bordersRightEdge() const
303 {
304     return m_bordersRightEdge;
305 }
306 
bordersTopEdge() const307 bool PreviewClient::bordersTopEdge() const
308 {
309     return m_bordersTopEdge;
310 }
311 
setBordersBottomEdge(bool enabled)312 void PreviewClient::setBordersBottomEdge(bool enabled)
313 {
314     if (m_bordersBottomEdge == enabled) {
315         return;
316     }
317     m_bordersBottomEdge = enabled;
318     Q_EMIT bordersBottomEdgeChanged(enabled);
319 }
320 
setBordersLeftEdge(bool enabled)321 void PreviewClient::setBordersLeftEdge(bool enabled)
322 {
323     if (m_bordersLeftEdge == enabled) {
324         return;
325     }
326     m_bordersLeftEdge = enabled;
327     Q_EMIT bordersLeftEdgeChanged(enabled);
328 }
329 
setBordersRightEdge(bool enabled)330 void PreviewClient::setBordersRightEdge(bool enabled)
331 {
332     if (m_bordersRightEdge == enabled) {
333         return;
334     }
335     m_bordersRightEdge = enabled;
336     Q_EMIT bordersRightEdgeChanged(enabled);
337 }
338 
setBordersTopEdge(bool enabled)339 void PreviewClient::setBordersTopEdge(bool enabled)
340 {
341     if (m_bordersTopEdge == enabled) {
342         return;
343     }
344     m_bordersTopEdge = enabled;
345     Q_EMIT bordersTopEdgeChanged(enabled);
346 }
347 
requestShowToolTip(const QString & text)348 void PreviewClient::requestShowToolTip(const QString &text)
349 {
350     Q_UNUSED(text);
351 }
352 
requestHideToolTip()353 void PreviewClient::requestHideToolTip()
354 {
355 }
356 
requestClose()357 void PreviewClient::requestClose()
358 {
359     Q_EMIT closeRequested();
360 }
361 
requestContextHelp()362 void PreviewClient::requestContextHelp()
363 {
364 }
365 
requestToggleMaximization(Qt::MouseButtons buttons)366 void PreviewClient::requestToggleMaximization(Qt::MouseButtons buttons)
367 {
368     if (buttons.testFlag(Qt::LeftButton)) {
369         const bool set = !isMaximized();
370         setMaximizedHorizontally(set);
371         setMaximizedVertically(set);
372     } else if (buttons.testFlag(Qt::RightButton)) {
373         setMaximizedHorizontally(!isMaximizedHorizontally());
374     } else if (buttons.testFlag(Qt::MiddleButton)) {
375         setMaximizedVertically(!isMaximizedVertically());
376     }
377 }
378 
requestMinimize()379 void PreviewClient::requestMinimize()
380 {
381     Q_EMIT minimizeRequested();
382 }
383 
requestToggleKeepAbove()384 void PreviewClient::requestToggleKeepAbove()
385 {
386     setKeepAbove(!isKeepAbove());
387 }
388 
requestToggleKeepBelow()389 void PreviewClient::requestToggleKeepBelow()
390 {
391     setKeepBelow(!isKeepBelow());
392 }
393 
requestShowWindowMenu(const QRect & rect)394 void PreviewClient::requestShowWindowMenu(const QRect &rect)
395 {
396     Q_UNUSED(rect)
397     Q_EMIT showWindowMenuRequested();
398 }
399 
requestShowApplicationMenu(const QRect & rect,int actionId)400 void PreviewClient::requestShowApplicationMenu(const QRect &rect, int actionId)
401 {
402     Q_UNUSED(rect);
403     Q_UNUSED(actionId);
404 }
405 
showApplicationMenu(int actionId)406 void PreviewClient::showApplicationMenu(int actionId)
407 {
408     Q_UNUSED(actionId)
409 }
410 
requestToggleOnAllDesktops()411 void PreviewClient::requestToggleOnAllDesktops()
412 {
413     setDesktop(isOnAllDesktops() ? 1 : -1);
414 }
415 
requestToggleShade()416 void PreviewClient::requestToggleShade()
417 {
418     setShaded(!isShaded());
419 }
420 
421 #define SETTER(type, name, variable) \
422 void PreviewClient::name(type variable) \
423 { \
424     if (m_##variable == variable) { \
425         return; \
426     } \
427     m_##variable = variable; \
428     Q_EMIT variable##Changed(m_##variable); \
429 }
430 
431 #define SETTER2(name, variable) SETTER(bool, name, variable)
432 
433 SETTER(const QString &, setCaption, caption)
434 SETTER(const QString &, setIconName, iconName)
435 SETTER(int, setWidth, width)
436 SETTER(int, setHeight, height)
437 
438 SETTER2(setActive, active)
439 SETTER2(setCloseable, closeable)
440 SETTER2(setMaximizable, maximizable)
441 SETTER2(setKeepBelow, keepBelow)
442 SETTER2(setKeepAbove, keepAbove)
443 SETTER2(setMaximizedHorizontally, maximizedHorizontally)
444 SETTER2(setMaximizedVertically, maximizedVertically)
445 SETTER2(setMinimizable, minimizable)
446 SETTER2(setModal, modal)
447 SETTER2(setMovable, movable)
448 SETTER2(setResizable, resizable)
449 SETTER2(setShadeable, shadeable)
450 SETTER2(setShaded, shaded)
451 SETTER2(setProvidesContextHelp, providesContextHelp)
452 
453 #undef SETTER2
454 #undef SETTER
455 
456 } // namespace Preview
457 } // namespace KDecoration2
458