2020-08-02 22:22:19 +00:00
|
|
|
/*
|
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-FileCopyrightText: 2007 Lubos Lunak <l.lunak@kde.org>
|
|
|
|
SPDX-FileCopyrightText: 2007 Christian Nitschkowski <christian.nitschkowski@kdemail.net>
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#include "thumbnailaside.h"
|
2012-09-19 08:24:04 +00:00
|
|
|
// KConfigSkeleton
|
|
|
|
#include "thumbnailasideconfig.h"
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2014-03-17 15:24:10 +00:00
|
|
|
#include <KGlobalAccel>
|
|
|
|
#include <KLocalizedString>
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2019-05-15 09:04:12 +00:00
|
|
|
#include <QAction>
|
|
|
|
#include <QMatrix4x4>
|
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
namespace KWin
|
|
|
|
{
|
|
|
|
|
|
|
|
ThumbnailAsideEffect::ThumbnailAsideEffect()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2016-12-02 19:27:43 +00:00
|
|
|
initConfig<ThumbnailAsideConfig>();
|
2013-12-10 10:45:33 +00:00
|
|
|
QAction* a = new QAction(this);
|
|
|
|
a->setObjectName(QStringLiteral("ToggleCurrentThumbnail"));
|
2011-01-30 14:34:42 +00:00
|
|
|
a->setText(i18n("Toggle Thumbnail for Current Window"));
|
2013-08-14 19:13:12 +00:00
|
|
|
KGlobalAccel::self()->setDefaultShortcut(a, QList<QKeySequence>() << Qt::META + Qt::CTRL + Qt::Key_T);
|
|
|
|
KGlobalAccel::self()->setShortcut(a, QList<QKeySequence>() << Qt::META + Qt::CTRL + Qt::Key_T);
|
2013-07-10 10:26:50 +00:00
|
|
|
effects->registerGlobalShortcut(Qt::META + Qt::CTRL + Qt::Key_T, a);
|
2019-01-01 20:48:53 +00:00
|
|
|
connect(a, &QAction::triggered, this, &ThumbnailAsideEffect::toggleCurrentThumbnail);
|
2013-08-14 19:13:12 +00:00
|
|
|
|
2019-01-01 20:48:53 +00:00
|
|
|
connect(effects, &EffectsHandler::windowClosed, this, &ThumbnailAsideEffect::slotWindowClosed);
|
2020-02-11 17:04:08 +00:00
|
|
|
connect(effects, &EffectsHandler::windowFrameGeometryChanged, this, &ThumbnailAsideEffect::slotWindowFrameGeometryChanged);
|
2019-01-01 20:48:53 +00:00
|
|
|
connect(effects, &EffectsHandler::windowDamaged, this, &ThumbnailAsideEffect::slotWindowDamaged);
|
|
|
|
connect(effects, &EffectsHandler::screenLockingChanged, this, &ThumbnailAsideEffect::repaintAll);
|
2011-01-30 14:34:42 +00:00
|
|
|
reconfigure(ReconfigureAll);
|
|
|
|
}
|
2007-11-13 16:20:52 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void ThumbnailAsideEffect::reconfigure(ReconfigureFlags)
|
|
|
|
{
|
2014-03-25 15:29:03 +00:00
|
|
|
ThumbnailAsideConfig::self()->read();
|
2012-09-19 08:24:04 +00:00
|
|
|
maxwidth = ThumbnailAsideConfig::maxWidth();
|
|
|
|
spacing = ThumbnailAsideConfig::spacing();
|
|
|
|
opacity = ThumbnailAsideConfig::opacity()/100.0;
|
|
|
|
screen = ThumbnailAsideConfig::screen(); // Xinerama screen TODO add gui option
|
2008-10-02 09:27:32 +00:00
|
|
|
arrange();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2019-10-29 22:04:15 +00:00
|
|
|
void ThumbnailAsideEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2013-01-09 09:09:39 +00:00
|
|
|
painted = QRegion();
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->paintScreen(mask, region, data);
|
2019-05-15 09:04:12 +00:00
|
|
|
|
|
|
|
const QMatrix4x4 projectionMatrix = data.projectionMatrix();
|
2011-01-30 14:34:42 +00:00
|
|
|
foreach (const Data & d, windows) {
|
2013-01-09 09:09:39 +00:00
|
|
|
if (painted.intersects(d.rect)) {
|
2019-05-15 09:04:12 +00:00
|
|
|
WindowPaintData data(d.window, projectionMatrix);
|
2012-07-12 15:20:17 +00:00
|
|
|
data.multiplyOpacity(opacity);
|
2007-04-29 17:35:43 +00:00
|
|
|
QRect region;
|
2011-01-30 14:34:42 +00:00
|
|
|
setPositionTransformations(data, region, d.window, d.rect, Qt::KeepAspectRatio);
|
|
|
|
effects->drawWindow(d.window, PAINT_WINDOW_OPAQUE | PAINT_WINDOW_TRANSLUCENT | PAINT_WINDOW_TRANSFORMED | PAINT_WINDOW_LANCZOS,
|
|
|
|
region, data);
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2013-01-09 09:09:39 +00:00
|
|
|
void ThumbnailAsideEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data)
|
|
|
|
{
|
|
|
|
effects->paintWindow(w, mask, region, data);
|
|
|
|
painted |= region;
|
|
|
|
}
|
|
|
|
|
2011-03-12 14:04:22 +00:00
|
|
|
void ThumbnailAsideEffect::slotWindowDamaged(EffectWindow* w, const QRect&)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
foreach (const Data & d, windows) {
|
|
|
|
if (d.window == w)
|
|
|
|
effects->addRepaint(d.rect);
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2020-02-11 17:04:08 +00:00
|
|
|
void ThumbnailAsideEffect::slotWindowFrameGeometryChanged(EffectWindow* w, const QRect& old)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
foreach (const Data & d, windows) {
|
|
|
|
if (d.window == w) {
|
|
|
|
if (w->size() == old.size())
|
|
|
|
effects->addRepaint(d.rect);
|
2008-01-22 11:32:27 +00:00
|
|
|
else
|
|
|
|
arrange();
|
|
|
|
return;
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-02-27 08:25:45 +00:00
|
|
|
void ThumbnailAsideEffect::slotWindowClosed(EffectWindow* w)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
removeThumbnail(w);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
void ThumbnailAsideEffect::toggleCurrentThumbnail()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
EffectWindow* active = effects->activeWindow();
|
Use nullptr everywhere
Summary:
Because KWin is a very old project, we use three kinds of null pointer
literals: 0, NULL, and nullptr. Since C++11, it's recommended to use
nullptr keyword.
This change converts all usages of 0 and NULL literal to nullptr. Even
though it breaks git history, we need to do it in order to have consistent
code as well to ease code reviews (it's very tempting for some people to
add unrelated changes to their patches, e.g. converting NULL to nullptr).
Test Plan: Compiles.
Reviewers: #kwin, davidedmundson, romangg
Reviewed By: #kwin, davidedmundson, romangg
Subscribers: romangg, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D23618
2019-09-19 14:46:54 +00:00
|
|
|
if (active == nullptr)
|
2007-04-29 17:35:43 +00:00
|
|
|
return;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (windows.contains(active))
|
|
|
|
removeThumbnail(active);
|
2007-04-29 17:35:43 +00:00
|
|
|
else
|
2011-01-30 14:34:42 +00:00
|
|
|
addThumbnail(active);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void ThumbnailAsideEffect::addThumbnail(EffectWindow* w)
|
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
repaintAll(); // repaint old areas
|
|
|
|
Data d;
|
|
|
|
d.window = w;
|
|
|
|
d.index = windows.count();
|
|
|
|
windows[ w ] = d;
|
|
|
|
arrange();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void ThumbnailAsideEffect::removeThumbnail(EffectWindow* w)
|
|
|
|
{
|
|
|
|
if (!windows.contains(w))
|
2007-04-29 17:35:43 +00:00
|
|
|
return;
|
|
|
|
repaintAll(); // repaint old areas
|
|
|
|
int index = windows[ w ].index;
|
2011-01-30 14:34:42 +00:00
|
|
|
windows.remove(w);
|
|
|
|
for (QHash< EffectWindow*, Data >::Iterator it = windows.begin();
|
|
|
|
it != windows.end();
|
|
|
|
++it) {
|
2007-04-29 17:35:43 +00:00
|
|
|
Data& d = *it;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (d.index > index)
|
2007-04-29 17:35:43 +00:00
|
|
|
--d.index;
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
arrange();
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
void ThumbnailAsideEffect::arrange()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
if (windows.size() == 0)
|
2008-01-22 11:32:27 +00:00
|
|
|
return;
|
2007-04-29 17:35:43 +00:00
|
|
|
int height = 0;
|
2011-01-30 14:34:42 +00:00
|
|
|
QVector< int > pos(windows.size());
|
2007-04-29 17:35:43 +00:00
|
|
|
int mwidth = 0;
|
2011-01-30 14:34:42 +00:00
|
|
|
foreach (const Data & d, windows) {
|
2007-04-29 17:35:43 +00:00
|
|
|
height += d.window->height();
|
2011-01-30 14:34:42 +00:00
|
|
|
mwidth = qMax(mwidth, d.window->width());
|
2007-04-29 17:35:43 +00:00
|
|
|
pos[ d.index ] = d.window->height();
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
QRect area = effects->clientArea(MaximizeArea, screen, effects->currentDesktop());
|
|
|
|
double scale = area.height() / double(height);
|
|
|
|
scale = qMin(scale, maxwidth / double(mwidth)); // don't be wider than maxwidth pixels
|
2007-04-29 17:35:43 +00:00
|
|
|
int add = 0;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 0;
|
|
|
|
i < windows.size();
|
|
|
|
++i) {
|
|
|
|
pos[ i ] = int(pos[ i ] * scale);
|
2007-04-29 17:35:43 +00:00
|
|
|
pos[ i ] += spacing + add; // compute offset of each item
|
|
|
|
add = pos[ i ];
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
for (QHash< EffectWindow*, Data >::Iterator it = windows.begin();
|
|
|
|
it != windows.end();
|
|
|
|
++it) {
|
2007-04-29 17:35:43 +00:00
|
|
|
Data& d = *it;
|
2011-01-30 14:34:42 +00:00
|
|
|
int width = int(d.window->width() * scale);
|
|
|
|
d.rect = QRect(area.right() - width, area.bottom() - pos[ d.index ], width, int(d.window->height() * scale));
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
repaintAll();
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
void ThumbnailAsideEffect::repaintAll()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
|
|
|
foreach (const Data & d, windows)
|
|
|
|
effects->addRepaint(d.rect);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-08-27 09:21:31 +00:00
|
|
|
bool ThumbnailAsideEffect::isActive() const
|
|
|
|
{
|
2013-01-30 12:07:59 +00:00
|
|
|
return !windows.isEmpty() && !effects->isScreenLocked();
|
2011-08-27 09:21:31 +00:00
|
|
|
}
|
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
} // namespace
|
|
|
|
|