KWin
Loading...
Searching...
No Matches
thumbnailaside.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2007 Lubos Lunak <l.lunak@kde.org>
6 SPDX-FileCopyrightText: 2007 Christian Nitschkowski <christian.nitschkowski@kdemail.net>
7
8 SPDX-License-Identifier: GPL-2.0-or-later
9*/
10
11#include "thumbnailaside.h"
12#include "core/renderviewport.h"
14// KConfigSkeleton
15#include "thumbnailasideconfig.h"
16
17#include <KGlobalAccel>
18#include <KLocalizedString>
19
20#include <QAction>
21#include <QMatrix4x4>
22
23namespace KWin
24{
25
27{
28 ThumbnailAsideConfig::instance(effects->config());
29 QAction *a = new QAction(this);
30 a->setObjectName(QStringLiteral("ToggleCurrentThumbnail"));
31 a->setText(i18n("Toggle Thumbnail for Current Window"));
32 KGlobalAccel::self()->setDefaultShortcut(a, QList<QKeySequence>() << (Qt::META | Qt::CTRL | Qt::Key_T));
33 KGlobalAccel::self()->setShortcut(a, QList<QKeySequence>() << (Qt::META | Qt::CTRL | Qt::Key_T));
34 connect(a, &QAction::triggered, this, &ThumbnailAsideEffect::toggleCurrentThumbnail);
35
36 connect(effects, &EffectsHandler::windowAdded, this, &ThumbnailAsideEffect::slotWindowAdded);
37 connect(effects, &EffectsHandler::windowClosed, this, &ThumbnailAsideEffect::slotWindowClosed);
38 connect(effects, &EffectsHandler::screenLockingChanged, this, &ThumbnailAsideEffect::repaintAll);
39
40 const auto windows = effects->stackingOrder();
41 for (EffectWindow *window : windows) {
42 slotWindowAdded(window);
43 }
44
46}
47
49{
50 ThumbnailAsideConfig::self()->read();
51 maxwidth = ThumbnailAsideConfig::maxWidth();
52 spacing = ThumbnailAsideConfig::spacing();
53 opacity = ThumbnailAsideConfig::opacity() / 100.0;
54 screen = ThumbnailAsideConfig::screen(); // Xinerama screen TODO add gui option
55 arrange();
56}
57
58void ThumbnailAsideEffect::paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion &region, Output *screen)
59{
60 painted = QRegion();
61 effects->paintScreen(renderTarget, viewport, mask, region, screen);
62
63 for (const Data &d : std::as_const(windows)) {
64 if (painted.intersects(d.rect)) {
65 WindowPaintData data(viewport.projectionMatrix());
67 QRect region;
68 setPositionTransformations(data, region, d.window, d.rect, Qt::KeepAspectRatio);
69 effects->drawWindow(renderTarget, viewport, d.window, PAINT_WINDOW_OPAQUE | PAINT_WINDOW_TRANSLUCENT | PAINT_WINDOW_TRANSFORMED, region, data);
70 }
71 }
72}
73
74void ThumbnailAsideEffect::paintWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, QRegion region, WindowPaintData &data)
75{
76 effects->paintWindow(renderTarget, viewport, w, mask, region, data);
77 painted += region;
78}
79
80void ThumbnailAsideEffect::slotWindowDamaged(EffectWindow *w)
81{
82 for (const Data &d : std::as_const(windows)) {
83 if (d.window == w) {
84 effects->addRepaint(d.rect);
85 }
86 }
87}
88
89void ThumbnailAsideEffect::slotWindowFrameGeometryChanged(EffectWindow *w, const QRectF &old)
90{
91 for (const Data &d : std::as_const(windows)) {
92 if (d.window == w) {
93 if (w->size() == old.size()) {
94 effects->addRepaint(d.rect);
95 } else {
96 arrange();
97 }
98 return;
99 }
100 }
101}
102
103void ThumbnailAsideEffect::slotWindowAdded(EffectWindow *w)
104{
105 connect(w, &EffectWindow::windowFrameGeometryChanged, this, &ThumbnailAsideEffect::slotWindowFrameGeometryChanged);
106 connect(w, &EffectWindow::windowDamaged, this, &ThumbnailAsideEffect::slotWindowDamaged);
107}
108
109void ThumbnailAsideEffect::slotWindowClosed(EffectWindow *w)
110{
111 removeThumbnail(w);
112}
113
114void ThumbnailAsideEffect::toggleCurrentThumbnail()
115{
116 EffectWindow *active = effects->activeWindow();
117 if (active == nullptr) {
118 return;
119 }
120 if (windows.contains(active)) {
121 removeThumbnail(active);
122 } else {
123 addThumbnail(active);
124 }
125}
126
127void ThumbnailAsideEffect::addThumbnail(EffectWindow *w)
128{
129 repaintAll(); // repaint old areas
130 Data d;
131 d.window = w;
132 d.index = windows.count();
133 windows[w] = d;
134 arrange();
135}
136
137void ThumbnailAsideEffect::removeThumbnail(EffectWindow *w)
138{
139 if (!windows.contains(w)) {
140 return;
141 }
142 repaintAll(); // repaint old areas
143 int index = windows[w].index;
144 windows.remove(w);
145 for (QHash<EffectWindow *, Data>::Iterator it = windows.begin();
146 it != windows.end();
147 ++it) {
148 Data &d = *it;
149 if (d.index > index) {
150 --d.index;
151 }
152 }
153 arrange();
154}
155
156void ThumbnailAsideEffect::arrange()
157{
158 if (windows.size() == 0) {
159 return;
160 }
161 int height = 0;
162 QList<int> pos(windows.size());
163 qreal mwidth = 0;
164 for (const Data &d : std::as_const(windows)) {
165 height += d.window->height();
166 mwidth = std::max(mwidth, d.window->width());
167 pos[d.index] = d.window->height();
168 }
169 Output *effectiveScreen = effects->findScreen(screen);
170 if (!effectiveScreen) {
171 effectiveScreen = effects->activeScreen();
172 }
173 QRectF area = effects->clientArea(MaximizeArea, effectiveScreen, effects->currentDesktop());
174 double scale = area.height() / double(height);
175 scale = std::min(scale, maxwidth / double(mwidth)); // don't be wider than maxwidth pixels
176 int add = 0;
177 for (int i = 0;
178 i < windows.size();
179 ++i) {
180 pos[i] = int(pos[i] * scale);
181 pos[i] += spacing + add; // compute offset of each item
182 add = pos[i];
183 }
184 for (QHash<EffectWindow *, Data>::Iterator it = windows.begin();
185 it != windows.end();
186 ++it) {
187 Data &d = *it;
188 int width = int(d.window->width() * scale);
189 d.rect = QRect(area.right() - width, area.bottom() - pos[d.index], width, int(d.window->height() * scale));
190 }
191 repaintAll();
192}
193
194void ThumbnailAsideEffect::repaintAll()
195{
196 for (const Data &d : std::as_const(windows)) {
197 effects->addRepaint(d.rect);
198 }
199}
200
202{
203 return !windows.isEmpty() && !effects->isScreenLocked();
204}
205
206} // namespace
207
208#include "moc_thumbnailaside.cpp"
Representation of a window used by/for Effect classes.
void windowDamaged(KWin::EffectWindow *w)
void windowFrameGeometryChanged(KWin::EffectWindow *window, const QRectF &oldGeometry)
void drawWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion &region, WindowPaintData &data)
void screenLockingChanged(bool locked)
void windowClosed(KWin::EffectWindow *w)
void paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion &region, Output *screen)
QList< EffectWindow * > stackingOrder
Q_SCRIPTABLE void addRepaint(const QRectF &r)
Output * findScreen(const QString &name) const
void paintWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion &region, WindowPaintData &data)
KWin::VirtualDesktop * currentDesktop
KWin::EffectWindow * activeWindow
QRectF clientArea(clientAreaOption, const Output *screen, const VirtualDesktop *desktop) const
KSharedConfigPtr config() const
KWin::Output * activeScreen
void windowAdded(KWin::EffectWindow *w)
QMatrix4x4 projectionMatrix() const
void paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion &region, Output *screen) override
bool isActive() const override
void reconfigure(ReconfigureFlags) override
void paintWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, QRegion region, WindowPaintData &data) override
static void setPositionTransformations(WindowPaintData &data, QRect &region, EffectWindow *w, const QRect &r, Qt::AspectRatioMode aspect)
Definition effect.cpp:462
qreal multiplyOpacity(qreal factor)
Definition effect.cpp:309
@ PAINT_WINDOW_TRANSFORMED
Definition effect.h:552
@ PAINT_WINDOW_OPAQUE
Definition effect.h:544
@ PAINT_WINDOW_TRANSLUCENT
Definition effect.h:548
@ ReconfigureAll
Definition effect.h:601
@ MaximizeArea
Definition globals.h:51
EffectsHandler * effects