/* * * 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 #include #include #include #include #include #include // FRAME the preview doesn't update to reflect the changes done in the kcm 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; 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() { 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(); } 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(); } void KDecorationPreview::paintEvent( QPaintEvent* 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) ) ); } } 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 ); titleBarHeight = qMin( int( titleBarHeight * .9 ), 30 ); xoffset = qMin( qMax( 10, QApplication::isRightToLeft() ? leftBorder : rightBorder ), 30 ); // 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 ) ); } void KDecorationPreview::setPreviewMask( const QRegion& reg, int mode, bool active ) { 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(); } 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() } 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); } else { // handles the update, only update position... positionPreviews(); } } 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); } 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; } } 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::performWindowOperation( WindowOperation ) { } void KDecorationPreviewBridge::setMask( const QRegion& reg, int mode ) { preview->setPreviewMask( reg, mode, 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 KWindowSystem::compositingActive(); } 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"