/* * * Copyright (c) 2003 Lubos Lunak * * 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 #include #include #include #include #include #include #include #include #include #include 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(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 ®ion, 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"