kwin/kcmkwin/kwindecoration/preview.cpp
Martin Gräßlin 2aed7b13d1 Cleanup the Preview rendering of Window Decorations
The preview code still contained all the old logic for embedding the
preview into another widget. Most of the code had been dead for quite
some time.

The only preview rendering code now is the one to render into a pixmap.
This is actually changed to render the widget directly at the right
position obsoleting the previous widget positioning code.

The no preview available label is dropped as it did not get rendered into
the pixmap at all.

Last but not least we fake that compositing is on. This has always been
the case for Aurorae themes and just looks better. Especially on Oxygen I
had always had some corruption when rendering this preview with
compositing disabled.

REVIEW: 108777
2013-02-12 11:51:17 +01:00

529 lines
12 KiB
C++

/*
*
* Copyright (c) 2003 Lubos Lunak <l.lunak@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "preview.h"
#include <kapplication.h>
#include <klocale.h>
#include <kconfig.h>
#include <kglobal.h>
#include <QLabel>
#include <QStyle>
#include <QPainter>
#include <QMouseEvent>
#include <QVector>
#include <kicon.h>
#include <kdecorationfactory.h>
KDecorationPreview::KDecorationPreview(QWidget* parent)
: QWidget(parent)
{
options = new KDecorationPreviewOptions;
bridge[Active] = new KDecorationPreviewBridge(this, true);
bridge[Inactive] = new KDecorationPreviewBridge(this, false);
deco[Active] = deco[Inactive] = NULL;
setMinimumSize(100, 100);
}
KDecorationPreview::~KDecorationPreview()
{
for (int i = 0; i < NumWindows; i++) {
delete deco[i];
delete bridge[i];
}
delete options;
}
bool KDecorationPreview::recreateDecoration(KDecorationPlugins* plugins)
{
for (int i = 0; i < NumWindows; i++) {
delete deco[i]; // deletes also window
deco[i] = plugins->createDecoration(bridge[i]);
deco[i]->init();
}
m_activeMask = QRegion();
m_inactiveMask = QRegion();
if (deco[Active] == NULL || deco[Inactive] == NULL) {
return false;
}
return true;
}
void KDecorationPreview::disablePreview()
{
delete deco[Active];
delete deco[Inactive];
deco[Active] = deco[Inactive] = NULL;
}
KDecorationFactory *KDecorationPreview::factory() const
{
return deco[Active] ? deco[Active]->factory() : 0;
}
QPixmap KDecorationPreview::preview()
{
QPixmap pixmap(size());
pixmap.fill(Qt::transparent);
if (!deco[Active] || !deco[Inactive])
return pixmap;
int titleBarHeight, leftBorder, rightBorder, xoffset,
dummy1, dummy2, dummy3;
// don't have more than one reference to the same dummy variable in one borders() call.
deco[Active]->borders(dummy1, dummy2, titleBarHeight, dummy3);
deco[Inactive]->borders(leftBorder, rightBorder, dummy1, dummy2);
titleBarHeight = qMin(int(titleBarHeight * .9), 30);
xoffset = qMin(qMax(10, QApplication::isRightToLeft()
? leftBorder : rightBorder), 30);
QPainter p;
p.begin(&pixmap);
const QSize size(width() - xoffset - 20, height() - titleBarHeight - 20);
render(&p, deco[Inactive], size, QPoint(10 + xoffset, 10), m_inactiveMask);
render(&p, deco[Active], size, QPoint(10, 10 + titleBarHeight), m_activeMask);
p.end();
return pixmap;
}
void KDecorationPreview::render(QPainter *painter, KDecoration *decoration, const QSize &recommendedSize, const QPoint &offset, const QRegion &mask) const
{
QWidget *w = decoration->widget();
QSize size = QSize(recommendedSize)
.expandedTo(decoration->minimumSize());
int padLeft, padRight, padTop, padBottom;
padLeft = padRight = padTop = padBottom = 0;
bool useMask = true;
if (KDecorationUnstable *unstable = qobject_cast<KDecorationUnstable *>(decoration)) {
unstable->padding(padLeft, padRight, padTop, padBottom);
size.setWidth(size.width() + padLeft + padRight);
size.setHeight(size.height() + padTop + padBottom);
if (padLeft || padRight || padTop || padBottom) {
useMask = false;
}
}
decoration->resize(size);
// why an if-else block instead of (useMask ? mask : QRegion())?
// For what reason ever it completely breaks if the mask is copied.
if (useMask) {
w->render(painter, offset + QPoint(-padLeft, - padTop), mask,
QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask);
} else {
w->render(painter, offset + QPoint(-padLeft, - padTop), QRegion(),
QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask);
}
}
QRect KDecorationPreview::windowGeometry(bool active) const
{
QWidget *widget = active ? deco[Active]->widget() : deco[Inactive]->widget();
return widget->geometry();
}
void KDecorationPreview::setTempBorderSize(KDecorationPlugins* plugin, KDecorationDefines::BorderSize size)
{
options->setCustomBorderSize(size);
if (plugin->factory()->reset(KDecorationDefines::SettingBorder)) {
// can't handle the change, recreate decorations then
recreateDecoration(plugin);
}
}
void KDecorationPreview::setTempButtons(KDecorationPlugins* plugin, bool customEnabled, const QString &left, const QString &right)
{
options->setCustomTitleButtonsEnabled(customEnabled);
options->setCustomTitleButtons(left, right);
if (plugin->factory()->reset(KDecorationDefines::SettingButtons)) {
// can't handle the change, recreate decorations then
recreateDecoration(plugin);
}
}
QRegion KDecorationPreview::unobscuredRegion(bool active, const QRegion& r) const
{
Q_UNUSED(active)
return r;
}
void KDecorationPreview::setMask(const QRegion &region, bool active)
{
if (active) {
m_activeMask = region;
} else {
m_inactiveMask = region;
}
}
KDecorationPreviewBridge::KDecorationPreviewBridge(KDecorationPreview* p, bool a)
: preview(p), active(a)
{
}
QWidget* KDecorationPreviewBridge::initialParentWidget() const
{
return preview;
}
Qt::WFlags KDecorationPreviewBridge::initialWFlags() const
{
return 0;
}
bool KDecorationPreviewBridge::isActive() const
{
return active;
}
bool KDecorationPreviewBridge::isCloseable() const
{
return true;
}
bool KDecorationPreviewBridge::isMaximizable() const
{
return true;
}
KDecoration::MaximizeMode KDecorationPreviewBridge::maximizeMode() const
{
return KDecoration::MaximizeRestore;
}
bool KDecorationPreviewBridge::isMinimizable() const
{
return true;
}
bool KDecorationPreviewBridge::providesContextHelp() const
{
return true;
}
int KDecorationPreviewBridge::desktop() const
{
return 1;
}
bool KDecorationPreviewBridge::isModal() const
{
return false;
}
bool KDecorationPreviewBridge::isShadeable() const
{
return true;
}
bool KDecorationPreviewBridge::isShade() const
{
return false;
}
bool KDecorationPreviewBridge::isSetShade() const
{
return false;
}
bool KDecorationPreviewBridge::keepAbove() const
{
return false;
}
bool KDecorationPreviewBridge::keepBelow() const
{
return false;
}
bool KDecorationPreviewBridge::isMovable() const
{
return true;
}
bool KDecorationPreviewBridge::isResizable() const
{
return true;
}
NET::WindowType KDecorationPreviewBridge::windowType(unsigned long) const
{
return NET::Normal;
}
QIcon KDecorationPreviewBridge::icon() const
{
return KIcon("xorg");
}
QString KDecorationPreviewBridge::caption() const
{
return active ? i18n("Active Window") : i18n("Inactive Window");
}
void KDecorationPreviewBridge::processMousePressEvent(QMouseEvent*)
{
}
void KDecorationPreviewBridge::showWindowMenu(const QRect &)
{
}
void KDecorationPreviewBridge::showWindowMenu(const QPoint &)
{
}
void KDecorationPreviewBridge::showApplicationMenu(const QPoint &)
{
}
bool KDecorationPreviewBridge::menuAvailable() const
{
return false;
}
void KDecorationPreviewBridge::performWindowOperation(WindowOperation)
{
}
void KDecorationPreviewBridge::setMask(const QRegion& reg, int mode)
{
Q_UNUSED(mode)
preview->setMask(reg, active);
}
bool KDecorationPreviewBridge::isPreview() const
{
return true;
}
QRect KDecorationPreviewBridge::geometry() const
{
return preview->windowGeometry(active);
}
QRect KDecorationPreviewBridge::iconGeometry() const
{
return QRect();
}
QRegion KDecorationPreviewBridge::unobscuredRegion(const QRegion& r) const
{
return preview->unobscuredRegion(active, r);
}
WId KDecorationPreviewBridge::windowId() const
{
return 0; // no decorated window
}
void KDecorationPreviewBridge::closeWindow()
{
}
void KDecorationPreviewBridge::maximize(MaximizeMode)
{
}
void KDecorationPreviewBridge::minimize()
{
}
void KDecorationPreviewBridge::showContextHelp()
{
}
void KDecorationPreviewBridge::setDesktop(int)
{
}
void KDecorationPreviewBridge::titlebarDblClickOperation()
{
}
void KDecorationPreviewBridge::titlebarMouseWheelOperation(int)
{
}
void KDecorationPreviewBridge::setShade(bool)
{
}
void KDecorationPreviewBridge::setKeepAbove(bool)
{
}
void KDecorationPreviewBridge::setKeepBelow(bool)
{
}
int KDecorationPreviewBridge::currentDesktop() const
{
return 1;
}
void KDecorationPreviewBridge::grabXServer(bool)
{
}
bool KDecorationPreviewBridge::compositingActive() const
{
return true;
}
QRect KDecorationPreviewBridge::transparentRect() const
{
return QRect();
}
// Window tabbing
int KDecorationPreviewBridge::tabCount() const
{
return 1;
}
QString KDecorationPreviewBridge::caption(int) const
{
return active ? "Active Window" : "Inactive Window";
}
QIcon KDecorationPreviewBridge::icon(int) const
{
return icon();
}
long KDecorationPreviewBridge::tabId(int) const
{
return 0;
}
long KDecorationPreviewBridge::currentTabId() const
{
return 0;
}
void KDecorationPreviewBridge::setCurrentTab(long)
{
}
void KDecorationPreviewBridge::tab_A_before_B(long, long)
{
}
void KDecorationPreviewBridge::tab_A_behind_B(long, long)
{
}
void KDecorationPreviewBridge::untab(long, const QRect&)
{
}
void KDecorationPreviewBridge::closeTab(long)
{
}
void KDecorationPreviewBridge::closeTabGroup()
{
}
void KDecorationPreviewBridge::showWindowMenu(const QPoint &, long)
{
}
KDecoration::WindowOperation KDecorationPreviewBridge::buttonToWindowOperation(Qt::MouseButtons)
{
return KDecoration::NoOp;
}
KDecorationPreviewOptions::KDecorationPreviewOptions()
{
customBorderSize = BordersCount; // invalid
customButtonsChanged = false; // invalid
customButtons = true;
customTitleButtonsLeft.clear(); // invalid
customTitleButtonsRight.clear(); // invalid
updateSettings();
}
KDecorationPreviewOptions::~KDecorationPreviewOptions()
{
}
unsigned long KDecorationPreviewOptions::updateSettings()
{
KConfig cfg("kwinrc");
unsigned long changed = 0;
changed |= KDecorationOptions::updateSettings(&cfg);
// set custom border size/buttons
if (customBorderSize != BordersCount)
setBorderSize(customBorderSize);
if (customButtonsChanged)
setCustomButtonPositions(customButtons);
if (customButtons) {
if (!customTitleButtonsLeft.isNull())
setTitleButtonsLeft(customTitleButtonsLeft);
if (!customTitleButtonsRight.isNull())
setTitleButtonsRight(customTitleButtonsRight);
} else {
setTitleButtonsLeft(KDecorationOptions::defaultTitleButtonsLeft());
setTitleButtonsRight(KDecorationOptions::defaultTitleButtonsRight());
}
return changed;
}
void KDecorationPreviewOptions::setCustomBorderSize(BorderSize size)
{
customBorderSize = size;
updateSettings();
}
void KDecorationPreviewOptions::setCustomTitleButtonsEnabled(bool enabled)
{
customButtonsChanged = true;
customButtons = enabled;
updateSettings();
}
void KDecorationPreviewOptions::setCustomTitleButtons(const QString &left, const QString &right)
{
customTitleButtonsLeft = left;
customTitleButtonsRight = right;
updateSettings();
}
bool KDecorationPreviewPlugins::provides(Requirement)
{
return false;
}
#include "preview.moc"