From 2aed7b13d16fe037b4c6cd1b145e5f669d829b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Mon, 4 Feb 2013 17:30:24 +0100 Subject: [PATCH] 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 --- kcmkwin/kwindecoration/decorationmodel.cpp | 23 +-- kcmkwin/kwindecoration/decorationmodel.h | 1 - kcmkwin/kwindecoration/preview.cpp | 188 ++++++--------------- kcmkwin/kwindecoration/preview.h | 22 +-- 4 files changed, 57 insertions(+), 177 deletions(-) diff --git a/kcmkwin/kwindecoration/decorationmodel.cpp b/kcmkwin/kwindecoration/decorationmodel.cpp index 022c80ad0c..0414874cdf 100644 --- a/kcmkwin/kwindecoration/decorationmodel.cpp +++ b/kcmkwin/kwindecoration/decorationmodel.cpp @@ -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 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("%1").arg(data.name); - - if (!data.author.isEmpty()) { - QString authorCaption = i18nc("Caption to decoration preview, %1 author name", - "by %1", data.author); - - html += QString("
%2") - .arg(KGlobalSettings::smallestReadableFont().pointSize()) - .arg(authorCaption); - } - - QColor color = QApplication::palette().brush(QPalette::Text).color(); - html = QString("
%2
").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()); } diff --git a/kcmkwin/kwindecoration/decorationmodel.h b/kcmkwin/kwindecoration/decorationmodel.h index de324c4ba5..d191c35a66 100644 --- a/kcmkwin/kwindecoration/decorationmodel.h +++ b/kcmkwin/kwindecoration/decorationmodel.h @@ -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; diff --git a/kcmkwin/kwindecoration/preview.cpp b/kcmkwin/kwindecoration/preview.cpp index 0b19986419..94aacbaf1a 100644 --- a/kcmkwin/kwindecoration/preview.cpp +++ b/kcmkwin/kwindecoration/preview.cpp @@ -27,18 +27,10 @@ #include #include #include -#include #include #include -#include -#include - #include -#include -#include -#include -#include 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(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(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(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 ®ion, 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 diff --git a/kcmkwin/kwindecoration/preview.h b/kcmkwin/kwindecoration/preview.h index ce75088823..420e302b64 100644 --- a/kcmkwin/kwindecoration/preview.h +++ b/kcmkwin/kwindecoration/preview.h @@ -21,19 +21,13 @@ #define KWINDECORATION_PREVIEW_H #include -//Added by qt3to4: -#include -#include -#include #include #include #include -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 ®ion, 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