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
This commit is contained in:
Martin Gräßlin 2013-02-04 17:30:24 +01:00
parent f63f41de83
commit 2aed7b13d1
4 changed files with 57 additions and 177 deletions

View file

@ -61,7 +61,6 @@ DecorationModel::DecorationModel(KSharedConfigPtr config, QObject* parent)
, m_customButtons(false)
, m_leftButtons(QString())
, m_rightButtons(QString())
, m_renderWidget(new QWidget(0))
{
QHash<int, QByteArray> roleNames;
roleNames[Qt::DisplayRole] = "display";
@ -80,7 +79,6 @@ DecorationModel::~DecorationModel()
{
delete m_preview;
delete m_plugins;
delete m_renderWidget;
}
void DecorationModel::reload()
@ -360,24 +358,6 @@ void DecorationModel::regeneratePreview(const QModelIndex& index, const QSize& s
switch(data.type) {
case DecorationModelData::NativeDecoration: {
//Use a QTextDocument to layout the text
QTextDocument document;
QString html = QString("<strong>%1</strong>").arg(data.name);
if (!data.author.isEmpty()) {
QString authorCaption = i18nc("Caption to decoration preview, %1 author name",
"by %1", data.author);
html += QString("<br /><span style=\"font-size: %1pt;\">%2</span>")
.arg(KGlobalSettings::smallestReadableFont().pointSize())
.arg(authorCaption);
}
QColor color = QApplication::palette().brush(QPalette::Text).color();
html = QString("<div style=\"color: %1\" align=\"center\">%2</div>").arg(color.name()).arg(html);
document.setHtml(html);
bool enabled = false;
bool loaded;
// m_preview->deco management is not required
@ -385,7 +365,6 @@ void DecorationModel::regeneratePreview(const QModelIndex& index, const QSize& s
// or the deco does not load and destroyPreviousPlugin() is not called
if ((loaded = m_plugins->loadPlugin(data.libraryName)) && m_preview->recreateDecoration(m_plugins)) {
enabled = true;
m_preview->enablePreview();
} else {
m_preview->disablePreview();
}
@ -395,7 +374,7 @@ void DecorationModel::regeneratePreview(const QModelIndex& index, const QSize& s
m_preview->resize(size);
m_preview->setTempButtons(m_plugins, m_customButtons, m_leftButtons, m_rightButtons);
m_preview->setTempBorderSize(m_plugins, data.borderSize);
data.preview = m_preview->preview(&document, m_renderWidget);
data.preview = m_preview->preview();
} else {
m_decorations.removeAt(index.row());
}

View file

@ -140,7 +140,6 @@ private:
QString m_leftButtons;
QString m_rightButtons;
KSharedConfigPtr m_config;
QWidget* m_renderWidget;
int m_nextPreviewIndex;
int m_firstUpdateIndex;
int m_lastUpdateIndex;

View file

@ -27,18 +27,10 @@
#include <QStyle>
#include <QPainter>
#include <QMouseEvent>
#include <QResizeEvent>
#include <QVector>
#include <kicon.h>
#include <X11/Xlib.h>
#include <X11/extensions/shape.h>
#include <kdecorationfactory.h>
#include <kdecoration_plugins_p.h>
#include <QX11Info>
#include <kwindowsystem.h>
#include <QTextDocument>
KDecorationPreview::KDecorationPreview(QWidget* parent)
: QWidget(parent)
@ -50,14 +42,7 @@ KDecorationPreview::KDecorationPreview(QWidget* parent)
deco[Active] = deco[Inactive] = NULL;
no_preview = new QLabel(i18n("No preview available.\n"
"Most probably there\n"
"was a problem loading the plugin."), this);
no_preview->setAlignment(Qt::AlignCenter);
setMinimumSize(100, 100);
no_preview->resize(size());
}
KDecorationPreview::~KDecorationPreview()
@ -77,30 +62,21 @@ bool KDecorationPreview::recreateDecoration(KDecorationPlugins* plugins)
deco[i]->init();
}
m_activeMask = QRegion();
m_inactiveMask = QRegion();
if (deco[Active] == NULL || deco[Inactive] == NULL) {
return false;
}
positionPreviews();
//deco[Inactive]->widget()->show();
//deco[Active]->widget()->show();
//deco[Inactive]->widget()->render( this, deco[Inactive]->widget()->mapToParent( QPoint(0,0) ) );
return true;
}
void KDecorationPreview::enablePreview()
{
no_preview->hide();
}
void KDecorationPreview::disablePreview()
{
delete deco[Active];
delete deco[Inactive];
deco[Active] = deco[Inactive] = NULL;
no_preview->show();
}
KDecorationFactory *KDecorationPreview::factory() const
@ -108,58 +84,15 @@ KDecorationFactory *KDecorationPreview::factory() const
return deco[Active] ? deco[Active]->factory() : 0;
}
void KDecorationPreview::paintEvent(QPaintEvent* e)
QPixmap KDecorationPreview::preview()
{
Q_UNUSED(e);
QPainter painter(this);
QPoint delta = mapTo(window(), QPoint(0, 0));
if (deco[Inactive]) {
QWidget *w = deco[Inactive]->widget();
w->render(&painter, delta + w->mapToParent(QPoint(0, 0)));
}
if (deco[Active]) {
QWidget *w = deco[Active]->widget();
w->render(&painter, delta + w->mapToParent(QPoint(0, 0)));
}
}
QPixmap KDecorationPreview::preview(QTextDocument* document, QWidget* widget)
{
Q_UNUSED(document);
Q_UNUSED(widget);
QPixmap pixmap(size());
pixmap.fill(Qt::transparent);
if (!deco[Active] || !deco[Inactive])
return pixmap;
if (deco[Inactive]) {
QWidget *w = deco[Inactive]->widget();
w->render(&pixmap, w->mapToParent(QPoint(0, 0)));
}
if (deco[Active]) {
QWidget *w = deco[Active]->widget();
w->render(&pixmap, w->mapToParent(QPoint(0, 0)));
}
return pixmap;
}
void KDecorationPreview::resizeEvent(QResizeEvent* e)
{
QWidget::resizeEvent(e);
positionPreviews();
}
void KDecorationPreview::positionPreviews()
{
int titleBarHeight, leftBorder, rightBorder, xoffset,
dummy1, dummy2, dummy3;
QRect geometry;
QSize size;
no_preview->resize(this->size());
if (!deco[Active] || !deco[Inactive])
return;
// 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);
@ -167,57 +100,43 @@ void KDecorationPreview::positionPreviews()
titleBarHeight = qMin(int(titleBarHeight * .9), 30);
xoffset = qMin(qMax(10, QApplication::isRightToLeft()
? leftBorder : rightBorder), 30);
QPainter p;
p.begin(&pixmap);
// Resize the active window
size = QSize(width() - xoffset, height() - titleBarHeight)
.expandedTo(deco[Active]->minimumSize());
geometry = QRect(QPoint(0, titleBarHeight), size);
if (KDecorationUnstable *unstable = qobject_cast<KDecorationUnstable *>(deco[Active])) {
int padLeft, padRight, padTop, padBottom;
unstable->padding(padLeft, padRight, padTop, padBottom);
geometry.adjust(-padLeft, -padTop, padRight, padBottom);
}
geometry.adjust(10, 10, -10, -10);
deco[Active]->widget()->setGeometry(QStyle::visualRect(this->layoutDirection(), this->rect(), geometry));
// Resize the inactive window
size = QSize(width() - xoffset, height() - titleBarHeight)
.expandedTo(deco[Inactive]->minimumSize());
geometry = QRect(QPoint(xoffset, 0), size);
if (KDecorationUnstable *unstable = qobject_cast<KDecorationUnstable *>(deco[Inactive])) {
int padLeft, padRight, padTop, padBottom;
unstable->padding(padLeft, padRight, padTop, padBottom);
geometry.adjust(-padLeft, -padTop, padRight, padBottom);
}
geometry.adjust(10, 10, -10, -10);
deco[Inactive]->widget()->setGeometry(QStyle::visualRect(this->layoutDirection(), this->rect(), geometry));
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::setPreviewMask(const QRegion& reg, int mode, bool active)
void KDecorationPreview::render(QPainter *painter, KDecoration *decoration, const QSize &recommendedSize, const QPoint &offset, const QRegion &mask) const
{
QWidget *widget = active ? deco[Active]->widget() : deco[Inactive]->widget();
// FRAME duped from client.cpp
if (mode == Unsorted) {
XShapeCombineRegion(QX11Info::display(), widget->winId(), ShapeBounding, 0, 0,
reg.handle(), ShapeSet);
} else {
QVector< QRect > rects = reg.rects();
XRectangle* xrects = new XRectangle[ rects.count()];
for (int i = 0;
i < rects.count();
++i) {
xrects[ i ].x = rects[ i ].x();
xrects[ i ].y = rects[ i ].y();
xrects[ i ].width = rects[ i ].width();
xrects[ i ].height = rects[ i ].height();
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;
}
XShapeCombineRectangles(QX11Info::display(), widget->winId(), ShapeBounding, 0, 0,
xrects, rects.count(), ShapeSet, mode);
delete[] xrects;
}
if (active)
mask = reg; // keep shape of the active window for unobscuredRegion()
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
@ -232,9 +151,6 @@ void KDecorationPreview::setTempBorderSize(KDecorationPlugins* plugin, KDecorati
if (plugin->factory()->reset(KDecorationDefines::SettingBorder)) {
// can't handle the change, recreate decorations then
recreateDecoration(plugin);
} else {
// handles the update, only update position...
positionPreviews();
}
}
@ -245,26 +161,21 @@ void KDecorationPreview::setTempButtons(KDecorationPlugins* plugin, bool customE
if (plugin->factory()->reset(KDecorationDefines::SettingButtons)) {
// can't handle the change, recreate decorations then
recreateDecoration(plugin);
} else {
// handles the update, only update position...
positionPreviews();
}
}
QRegion KDecorationPreview::unobscuredRegion(bool active, const QRegion& r) const
{
if (active) // this one is not obscured
return r;
else {
// copied from KWin core's code
QRegion ret = r;
QRegion r2 = mask;
if (r2.isEmpty())
r2 = QRegion(windowGeometry(true));
r2.translate(windowGeometry(true).x() - windowGeometry(false).x(),
windowGeometry(true).y() - windowGeometry(false).y());
ret -= r2;
return ret;
Q_UNUSED(active)
return r;
}
void KDecorationPreview::setMask(const QRegion &region, bool active)
{
if (active) {
m_activeMask = region;
} else {
m_inactiveMask = region;
}
}
@ -400,7 +311,8 @@ void KDecorationPreviewBridge::performWindowOperation(WindowOperation)
void KDecorationPreviewBridge::setMask(const QRegion& reg, int mode)
{
preview->setPreviewMask(reg, mode, active);
Q_UNUSED(mode)
preview->setMask(reg, active);
}
bool KDecorationPreviewBridge::isPreview() const
@ -479,7 +391,7 @@ void KDecorationPreviewBridge::grabXServer(bool)
bool KDecorationPreviewBridge::compositingActive() const
{
return KWindowSystem::compositingActive();
return true;
}
QRect KDecorationPreviewBridge::transparentRect() const

View file

@ -21,19 +21,13 @@
#define KWINDECORATION_PREVIEW_H
#include <QWidget>
//Added by qt3to4:
#include <QMouseEvent>
#include <QLabel>
#include <QResizeEvent>
#include <kdecoration.h>
#include <kdecorationbridge.h>
#include <kdecoration_plugins_p.h>
class QLabel;
class QTextDocument;
class KDecorationPreviewBridge;
class KDecorationPreviewOptions;
class QMouseEvent;
class KDecorationPreview
: public QWidget
@ -48,25 +42,21 @@ public:
explicit KDecorationPreview(QWidget* parent = NULL);
virtual ~KDecorationPreview();
bool recreateDecoration(KDecorationPlugins* plugin);
void enablePreview();
void disablePreview();
KDecorationFactory *factory() const;
void setPreviewMask(const QRegion&, int, bool);
QRegion unobscuredRegion(bool, const QRegion&) const;
QRect windowGeometry(bool) const;
void setTempBorderSize(KDecorationPlugins* plugin, KDecorationDefines::BorderSize size);
void setTempButtons(KDecorationPlugins* plugin, bool customEnabled, const QString &left, const QString &right);
QPixmap preview(QTextDocument* document, QWidget* widget);
protected:
virtual void paintEvent(QPaintEvent*);
virtual void resizeEvent(QResizeEvent*);
QPixmap preview();
void setMask(const QRegion &region, bool active);
private:
void positionPreviews();
void render(QPainter *painter, KDecoration *decoration, const QSize &recommendedSize, const QPoint &offset, const QRegion &mask) const;
KDecorationPreviewOptions* options;
KDecorationPreviewBridge* bridge[NumWindows];
KDecoration* deco[NumWindows];
QLabel* no_preview;
QRegion mask;
QRegion m_activeMask;
QRegion m_inactiveMask;
};
class KDecorationPreviewBridge