diff --git a/bridge.cpp b/bridge.cpp index 2888d3dc1..e5a59917b 100644 --- a/bridge.cpp +++ b/bridge.cpp @@ -1,181 +1,186 @@ /***************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2003 Lubos Lunak You can Freely distribute this program under the GNU General Public License. See the file "COPYING" for the exact licensing terms. ******************************************************************/ #include "bridge.h" #include "client.h" #include "options.h" namespace KWinInternal { Bridge::Bridge( Client* cl ) : c( cl ) { } #define BRIDGE_HELPER( rettype, prototype, args1, args2, cst ) \ rettype Bridge::prototype ( args1 ) cst \ { \ return c->prototype( args2 ); \ } BRIDGE_HELPER( bool, isActive,,, const ) BRIDGE_HELPER( bool, isCloseable,,, const ) BRIDGE_HELPER( bool, isMaximizable,,, const ) BRIDGE_HELPER( Bridge::MaximizeMode, maximizeMode,,, const ) BRIDGE_HELPER( bool, isMinimizable,,, const ) BRIDGE_HELPER( bool, providesContextHelp,,, const ) BRIDGE_HELPER( int, desktop,,, const ) BRIDGE_HELPER( bool, isModal,,, const ) BRIDGE_HELPER( bool, isShadeable,,, const ) BRIDGE_HELPER( bool, isShade,,, const ) BRIDGE_HELPER( bool, keepAbove,,, const ) BRIDGE_HELPER( bool, keepBelow,,, const ) BRIDGE_HELPER( bool, isMovable,,, const ) BRIDGE_HELPER( bool, isResizable,,, const ) BRIDGE_HELPER( QString, caption,,, const ) BRIDGE_HELPER( void, processMousePressEvent, QMouseEvent* e, e, ) BRIDGE_HELPER( QRect, geometry,,, const ) BRIDGE_HELPER( void, closeWindow,,, ) BRIDGE_HELPER( void, maximize, MaximizeMode m, m, ) BRIDGE_HELPER( void, minimize,,, ) BRIDGE_HELPER( void, showContextHelp,,, ) BRIDGE_HELPER( void, setDesktop, int desktop, desktop, ) BRIDGE_HELPER( void, setKeepAbove, bool set, set, ) BRIDGE_HELPER( void, setKeepBelow, bool set, set, ) NET::WindowType Bridge::windowType( unsigned long supported_types ) const { return c->windowType( false, supported_types ); } QIconSet Bridge::icon() const { return QIconSet( c->miniIcon(), c->icon()); } bool Bridge::isSetShade() const { return c->shadeMode() != Client::ShadeNone; } void Bridge::showWindowMenu( QPoint p ) { c->workspace()->showWindowMenu( p, c ); } +void Bridge::showWindowMenu( const QRect &p ) + { + c->workspace()->showWindowMenu( p, c ); + } + void Bridge::performWindowOperation( WindowOperation op ) { c->workspace()->performWindowOperation( c, op ); } void Bridge::setMask( const QRegion& r, int mode ) { c->setMask( r, mode ); } bool Bridge::isPreview() const { return false; } QRect Bridge::iconGeometry() const { NETRect r = c->info->iconGeometry(); return QRect( r.pos.x, r.pos.y, r.size.width, r.size.height ); } QWidget* Bridge::workspaceWidget() const { return c->workspace()->desktopWidget(); } void Bridge::titlebarDblClickOperation() { c->workspace()->performWindowOperation( c, options->operationTitlebarDblClick()); } void Bridge::setShade( bool set ) { c->setShade( set ? Client::ShadeNormal : Client::ShadeNone ); } int Bridge::currentDesktop() const { return c->workspace()->currentDesktop(); } QWidget* Bridge::initialParentWidget() const { return NULL; } Qt::WFlags Bridge::initialWFlags() const { return 0; } void Bridge::helperShowHide( bool show ) { if( show ) c->rawShow(); else c->rawHide(); } QRegion Bridge::unobscuredRegion( const QRegion& r ) const { QRegion reg( r ); const ClientList stacking_order = c->workspace()->stackingOrder(); ClientList::ConstIterator it = stacking_order.find( c ); ++it; for(; it != stacking_order.end(); ++it ) { if( !(*it)->isShown( true )) continue; // these don't obscure the window if( c->isOnAllDesktops()) { if( !(*it)->isOnCurrentDesktop()) continue; } else { if( !(*it)->isOnDesktop( c->desktop())) continue; } /* the clients all have their mask-regions in local coords so we have to translate them to a shared coord system we choose ours */ int dx = (*it)->x() - c->x(); int dy = (*it)->y() - c->y(); QRegion creg = (*it)->mask(); creg.translate(dx, dy); reg -= creg; if (reg.isEmpty()) { // early out, we are completely obscured break; } } return reg; } void Bridge::grabXServer( bool grab ) { if( grab ) KWinInternal::grabXServer(); else KWinInternal::ungrabXServer(); } } // namespace diff --git a/bridge.h b/bridge.h index eb6d7c102..a59811ab3 100644 --- a/bridge.h +++ b/bridge.h @@ -1,72 +1,73 @@ /***************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2003 Lubos Lunak You can Freely distribute this program under the GNU General Public License. See the file "COPYING" for the exact licensing terms. ******************************************************************/ #ifndef KWIN_BRIDGE_H #define KWIN_BRIDGE_H #include namespace KWinInternal { class Client; class Bridge : public KDecorationBridge { public: Bridge( Client* cl ); virtual bool isActive() const; virtual bool isCloseable() const; virtual bool isMaximizable() const; virtual MaximizeMode maximizeMode() const; virtual bool isMinimizable() const; virtual bool providesContextHelp() const; virtual int desktop() const; virtual bool isModal() const; virtual bool isShadeable() const; virtual bool isShade() const; virtual bool isSetShade() const; virtual bool keepAbove() const; virtual bool keepBelow() const; virtual bool isMovable() const; virtual bool isResizable() const; virtual NET::WindowType windowType( unsigned long supported_types ) const; virtual QIconSet icon() const; virtual QString caption() const; virtual void processMousePressEvent( QMouseEvent* ); virtual void showWindowMenu( QPoint ); + virtual void showWindowMenu( const QRect & ); virtual void performWindowOperation( WindowOperation ); virtual void setMask( const QRegion&, int ); virtual bool isPreview() const; virtual QRect geometry() const; virtual QRect iconGeometry() const; virtual QRegion unobscuredRegion( const QRegion& r ) const; virtual QWidget* workspaceWidget() const; virtual void closeWindow(); virtual void maximize( MaximizeMode mode ); virtual void minimize(); virtual void showContextHelp(); virtual void setDesktop( int desktop ); virtual void titlebarDblClickOperation(); virtual void setShade( bool set ); virtual void setKeepAbove( bool ); virtual void setKeepBelow( bool ); virtual int currentDesktop() const; virtual QWidget* initialParentWidget() const; virtual Qt::WFlags initialWFlags() const; virtual void helperShowHide( bool show ); virtual void grabXServer( bool grab ); private: Client* c; }; } // namespace #endif diff --git a/kcmkwin/kwindecoration/preview.cpp b/kcmkwin/kwindecoration/preview.cpp index ea24b8de2..d81c1aa4b 100644 --- a/kcmkwin/kwindecoration/preview.cpp +++ b/kcmkwin/kwindecoration/preview.cpp @@ -1,416 +1,420 @@ /* * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "preview.h" #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, const char* name ) : QWidget( parent, name ) { 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( 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(); 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::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 = kMin( int( titleBarHeight * .9 ), 30 ); xoffset = kMin( kMax( 10, QApplication::reverseLayout() ? leftBorder : rightBorder ), 30 ); // Resize the active window size = QSize( width() - xoffset, height() - titleBarHeight ) .expandedTo( deco[Active]->minimumSize() ); geometry = QRect( QPoint( 0, titleBarHeight ), size ); deco[Active]->widget()->setGeometry( QStyle::visualRect( geometry, this ) ); // Resize the inactive window size = QSize( width() - xoffset, height() - titleBarHeight ) .expandedTo( deco[Inactive]->minimumSize() ); geometry = QRect( QPoint( xoffset, 0 ), size ); deco[Inactive]->widget()->setGeometry( QStyle::visualRect( geometry, this ) ); } 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( qt_xdisplay(), widget->winId(), ShapeBounding, 0, 0, reg.handle(), ShapeSet ); } else { QMemArray< QRect > rects = reg.rects(); XRectangle* xrects = new XRectangle[ rects.count() ]; for( unsigned 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( qt_xdisplay(), 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(); } 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; } QIconSet KDecorationPreviewBridge::icon() const { return SmallIconSet( "xapp" ); } QString KDecorationPreviewBridge::caption() const { return active ? i18n( "Active window" ) : i18n( "Inactive window" ); } void KDecorationPreviewBridge::processMousePressEvent( QMouseEvent* ) { } +void KDecorationPreviewBridge::showWindowMenu( const QRect &) + { + } + void KDecorationPreviewBridge::showWindowMenu( 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 ); } QWidget* KDecorationPreviewBridge::workspaceWidget() const { return preview; } void KDecorationPreviewBridge::closeWindow() { } void KDecorationPreviewBridge::maximize( MaximizeMode ) { } void KDecorationPreviewBridge::minimize() { } void KDecorationPreviewBridge::showContextHelp() { } void KDecorationPreviewBridge::setDesktop( int ) { } void KDecorationPreviewBridge::titlebarDblClickOperation() { } void KDecorationPreviewBridge::setShade( bool ) { } void KDecorationPreviewBridge::setKeepAbove( bool ) { } void KDecorationPreviewBridge::setKeepBelow( bool ) { } int KDecorationPreviewBridge::currentDesktop() const { return 1; } void KDecorationPreviewBridge::helperShowHide( bool ) { } void KDecorationPreviewBridge::grabXServer( bool ) { } KDecorationPreviewOptions::KDecorationPreviewOptions() { d = new KDecorationOptionsPrivate; d->defaultKWinSettings(); updateSettings(); } KDecorationPreviewOptions::~KDecorationPreviewOptions() { delete d; } unsigned long KDecorationPreviewOptions::updateSettings() { KConfig cfg( "kwinrc", true ); unsigned long changed = 0; changed |= d->updateKWinSettings( &cfg ); return changed; } bool KDecorationPreviewPlugins::provides( Requirement ) { return false; } #include "preview.moc" diff --git a/kcmkwin/kwindecoration/preview.h b/kcmkwin/kwindecoration/preview.h index d469f71f9..eabe7dc9a 100644 --- a/kcmkwin/kwindecoration/preview.h +++ b/kcmkwin/kwindecoration/preview.h @@ -1,134 +1,135 @@ /* * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef KWINDECORATION_PREVIEW_H #define KWINDECORATION_PREVIEW_H #include #include #include class QLabel; class KDecorationPreviewBridge; class KDecorationOptions; class KDecorationPreview : public QWidget { Q_OBJECT public: // Note: Windows can't be added or removed without making changes to // the code, since parts of it assume there's just an active // and an inactive window. enum Windows { Inactive = 0, Active, NumWindows }; KDecorationPreview( QWidget* parent = NULL, const char* name = NULL ); virtual ~KDecorationPreview(); bool recreateDecoration( KDecorationPlugins* plugin ); void enablePreview(); void disablePreview(); void setPreviewMask( const QRegion&, int, bool ); QRegion unobscuredRegion( bool, const QRegion& ) const; QRect windowGeometry( bool ) const; protected: virtual void resizeEvent( QResizeEvent* ); private: void positionPreviews(); KDecorationOptions* options; KDecorationPreviewBridge* bridge[NumWindows]; KDecoration* deco[NumWindows]; QLabel* no_preview; QRegion mask; }; class KDecorationPreviewBridge : public KDecorationBridge { public: KDecorationPreviewBridge( KDecorationPreview* preview, bool active ); virtual bool isActive() const; virtual bool isCloseable() const; virtual bool isMaximizable() const; virtual MaximizeMode maximizeMode() const; virtual bool isMinimizable() const; virtual bool providesContextHelp() const; virtual int desktop() const; virtual bool isModal() const; virtual bool isShadeable() const; virtual bool isShade() const; virtual bool isSetShade() const; virtual bool keepAbove() const; virtual bool keepBelow() const; virtual bool isMovable() const; virtual bool isResizable() const; virtual NET::WindowType windowType( unsigned long supported_types ) const; virtual QIconSet icon() const; virtual QString caption() const; virtual void processMousePressEvent( QMouseEvent* ); + virtual void showWindowMenu( const QRect &); virtual void showWindowMenu( QPoint ); virtual void performWindowOperation( WindowOperation ); virtual void setMask( const QRegion&, int ); virtual bool isPreview() const; virtual QRect geometry() const; virtual QRect iconGeometry() const; virtual QRegion unobscuredRegion( const QRegion& r ) const; virtual QWidget* workspaceWidget() const; virtual void closeWindow(); virtual void maximize( MaximizeMode mode ); virtual void minimize(); virtual void showContextHelp(); virtual void setDesktop( int desktop ); virtual void titlebarDblClickOperation(); virtual void setShade( bool set ); virtual void setKeepAbove( bool ); virtual void setKeepBelow( bool ); virtual int currentDesktop() const; virtual QWidget* initialParentWidget() const; virtual Qt::WFlags initialWFlags() const; virtual void helperShowHide( bool show ); virtual void grabXServer( bool grab ); private: KDecorationPreview* preview; bool active; }; class KDecorationPreviewOptions : public KDecorationOptions { public: KDecorationPreviewOptions(); virtual ~KDecorationPreviewOptions(); virtual unsigned long updateSettings(); }; class KDecorationPreviewPlugins : public KDecorationPlugins { public: KDecorationPreviewPlugins( KConfig* cfg ); virtual bool provides( Requirement ); }; inline KDecorationPreviewPlugins::KDecorationPreviewPlugins( KConfig* cfg ) : KDecorationPlugins( cfg ) { } #endif diff --git a/lib/kdecoration.cpp b/lib/kdecoration.cpp index b013d4e41..5c07771a6 100644 --- a/lib/kdecoration.cpp +++ b/lib/kdecoration.cpp @@ -1,417 +1,422 @@ /***************************************************************** This file is part of the KDE project. Copyright (C) 2003 Lubos Lunak Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************/ #include "kdecoration.h" #include #include #include #include #if defined Q_WS_X11 && ! defined K_WS_QTONLY #include #include #endif #include "kdecoration_p.h" #include "kdecorationfactory.h" KDecorationOptions* KDecoration::options_; KDecoration::KDecoration( KDecorationBridge* bridge, KDecorationFactory* factory ) : bridge_( bridge ), w_( NULL ), factory_( factory ) { factory->addDecoration( this ); } KDecoration::~KDecoration() { factory()->removeDecoration( this ); delete w_; } const KDecorationOptions* KDecoration::options() { return options_; } void KDecoration::createMainWidget( WFlags flags ) { // FRAME check flags? setMainWidget( new QWidget( initialParentWidget(), "decoration widget", initialWFlags() | flags )); } void KDecoration::setMainWidget( QWidget* w ) { assert( w_ == NULL ); w_ = w; w->setMouseTracking( true ); widget()->resize( geometry().size()); } QWidget* KDecoration::initialParentWidget() const { return bridge_->initialParentWidget(); } Qt::WFlags KDecoration::initialWFlags() const { return bridge_->initialWFlags(); } bool KDecoration::isActive() const { return bridge_->isActive(); } bool KDecoration::isCloseable() const { return bridge_->isCloseable(); } bool KDecoration::isMaximizable() const { return bridge_->isMaximizable(); } KDecoration::MaximizeMode KDecoration::maximizeMode() const { return bridge_->maximizeMode(); } bool KDecoration::isMinimizable() const { return bridge_->isMinimizable(); } bool KDecoration::providesContextHelp() const { return bridge_->providesContextHelp(); } int KDecoration::desktop() const { return bridge_->desktop(); } bool KDecoration::isModal() const { return bridge_->isModal(); } bool KDecoration::isShadeable() const { return bridge_->isShadeable(); } bool KDecoration::isShade() const { return bridge_->isShade(); } bool KDecoration::isSetShade() const { return bridge_->isSetShade(); } bool KDecoration::keepAbove() const { return bridge_->keepAbove(); } bool KDecoration::keepBelow() const { return bridge_->keepBelow(); } bool KDecoration::isMovable() const { return bridge_->isMovable(); } bool KDecoration::isResizable() const { return bridge_->isResizable(); } NET::WindowType KDecoration::windowType( unsigned long supported_types ) const { // this one is also duplicated in KDecorationFactory return bridge_->windowType( supported_types ); } QIconSet KDecoration::icon() const { return bridge_->icon(); } QString KDecoration::caption() const { return bridge_->caption(); } void KDecoration::processMousePressEvent( QMouseEvent* e ) { return bridge_->processMousePressEvent( e ); } -void KDecoration::showWindowMenu( QPoint pos ) +void KDecoration::showWindowMenu( const QRect &pos ) { bridge_->showWindowMenu( pos ); } +void KDecoration::showWindowMenu( QPoint pos ) + { + bridge_->showWindowMenu( pos ); + } + void KDecoration::performWindowOperation( WindowOperation op ) { bridge_->performWindowOperation( op ); } void KDecoration::setMask( const QRegion& reg, int mode ) { bridge_->setMask( reg, mode ); } void KDecoration::clearMask() { bridge_->setMask( QRegion(), 0 ); } bool KDecoration::isPreview() const { return bridge_->isPreview(); } QRect KDecoration::geometry() const { return bridge_->geometry(); } QRect KDecoration::iconGeometry() const { return bridge_->iconGeometry(); } QRegion KDecoration::unobscuredRegion( const QRegion& r ) const { return bridge_->unobscuredRegion( r ); } QWidget* KDecoration::workspaceWidget() const { return bridge_->workspaceWidget(); } void KDecoration::closeWindow() { bridge_->closeWindow(); } void KDecoration::maximize( MaximizeMode mode ) { bridge_->maximize( mode ); } void KDecoration::minimize() { bridge_->minimize(); } void KDecoration::showContextHelp() { bridge_->showContextHelp(); } void KDecoration::setDesktop( int desktop ) { bridge_->setDesktop( desktop ); } void KDecoration::toggleOnAllDesktops() { if( isOnAllDesktops()) setDesktop( bridge_->currentDesktop()); else setDesktop( NET::OnAllDesktops ); } void KDecoration::titlebarDblClickOperation() { bridge_->titlebarDblClickOperation(); } void KDecoration::setShade( bool set ) { bridge_->setShade( set ); } void KDecoration::setKeepAbove( bool set ) { bridge_->setKeepAbove( set ); } void KDecoration::setKeepBelow( bool set ) { bridge_->setKeepBelow( set ); } bool KDecoration::drawbound( const QRect&, bool ) { return false; } bool KDecoration::animateMinimize( bool ) { return false; } bool KDecoration::windowDocked( Position ) { return false; } void KDecoration::helperShowHide( bool show ) { bridge_->helperShowHide( show ); } void KDecoration::reset( unsigned long ) { } void KDecoration::grabXServer() { bridge_->grabXServer( true ); } void KDecoration::ungrabXServer() { bridge_->grabXServer( false ); } KDecoration::Position KDecoration::mousePosition( const QPoint& p ) const { const int range = 16; int bleft, bright, btop, bbottom; borders( bleft, bright, btop, bbottom ); btop = KMIN( btop, 4 ); // otherwise whole titlebar would have resize cursor Position m = PositionCenter; if ( ( p.x() > bleft && p.x() < widget()->width() - bright ) && ( p.y() > btop && p.y() < widget()->height() - bbottom ) ) return PositionCenter; if ( p.y() <= KMAX( range, btop ) && p.x() <= KMAX( range, bleft )) m = PositionTopLeft; else if ( p.y() >= widget()->height()- KMAX( range, bbottom ) && p.x() >= widget()->width()- KMAX( range, bright )) m = PositionBottomRight; else if ( p.y() >= widget()->height()- KMAX( range, bbottom ) && p.x() <= KMAX( range, bleft )) m = PositionBottomLeft; else if ( p.y() <= KMAX( range, btop ) && p.x() >= widget()->width()- KMAX( range, bright )) m = PositionTopRight; else if ( p.y() <= btop ) m = PositionTop; else if ( p.y() >= widget()->height()-bbottom ) m = PositionBottom; else if ( p.x() <= bleft ) m = PositionLeft; else if ( p.x() >= widget()->width()-bright ) m = PositionRight; else m = PositionCenter; return m; } KDecorationOptions::KDecorationOptions() { assert( KDecoration::options_ == NULL ); KDecoration::options_ = this; } KDecorationOptions::~KDecorationOptions() { assert( KDecoration::options_ == this ); KDecoration::options_ = NULL; } const QColor& KDecorationOptions::color(ColorType type, bool active) const { return(d->colors[type + (active ? 0 : NUM_COLORS)]); } const QFont& KDecorationOptions::font(bool active, bool small) const { if ( small ) return(active ? d->activeFontSmall : d->inactiveFontSmall); else return(active ? d->activeFont : d->inactiveFont); } const QColorGroup& KDecorationOptions::colorGroup(ColorType type, bool active) const { int idx = type + (active ? 0 : NUM_COLORS); if(d->cg[idx]) return(*d->cg[idx]); d->cg[idx] = new QColorGroup(Qt::black, d->colors[idx], d->colors[idx].light(150), d->colors[idx].dark(), d->colors[idx].dark(120), Qt::black, QApplication::palette().active(). base()); return(*d->cg[idx]); } bool KDecorationOptions::customButtonPositions() const { return d->custom_button_positions; } QString KDecorationOptions::titleButtonsLeft() const { return d->title_buttons_left; } QString KDecorationOptions::titleButtonsRight() const { return d->title_buttons_right; } bool KDecorationOptions::showTooltips() const { return d->show_tooltips; } KDecorationOptions::BorderSize KDecorationOptions::preferredBorderSize( KDecorationFactory* factory ) const { assert( factory != NULL ); if( d->cached_border_size == BordersCount ) // invalid d->cached_border_size = d->findPreferredBorderSize( d->border_size, factory->borderSizes()); return d->cached_border_size; } bool KDecorationOptions::moveResizeMaximizedWindows() const { return d->move_resize_maximized_windows; } #include "kdecoration.moc" diff --git a/lib/kdecoration.h b/lib/kdecoration.h index a57e3f651..113d21e69 100644 --- a/lib/kdecoration.h +++ b/lib/kdecoration.h @@ -1,760 +1,775 @@ /***************************************************************** This file is part of the KDE project. Copyright (C) 2003 Lubos Lunak Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************/ #ifndef KDECORATION_H #define KDECORATION_H #include #include #include #include #include class KDecorationOptionsPrivate; class KDecorationBridge; class KDecorationPrivate; class KDecorationFactory; /** * This class provides a namespace for all decoration related classes. * All shared types are defined here. */ class KDecorationDefines { public: /** * These values represent positions inside an area */ enum Position { // without prefix, they'd conflict with Qt::TopLeft etc. :( PositionCenter = 0x00, PositionLeft = 0x01, PositionRight = 0x02, PositionTop = 0x04, PositionBottom = 0x08, PositionTopLeft = PositionLeft | PositionTop, PositionTopRight = PositionRight | PositionTop, PositionBottomLeft = PositionLeft | PositionBottom, PositionBottomRight = PositionRight | PositionBottom }; /** * Maximize mode. These values specify how a window is maximized. */ // these values are written to session files, don't change the order enum MaximizeMode { MaximizeRestore = 0, ///< The window is not maximized in any direction. MaximizeVertical = 1, ///< The window is maximized vertically. MaximizeHorizontal = 2, ///< The window is maximized horizontally. /// Equal to @p MaximizeVertical | @p MaximizeHorizontal MaximizeFull = MaximizeVertical | MaximizeHorizontal }; enum WindowOperation { MaximizeOp = 5000, RestoreOp, MinimizeOp, MoveOp, UnrestrictedMoveOp, ResizeOp, UnrestrictedResizeOp, CloseOp, OnAllDesktopsOp, ShadeOp, KeepAboveOp, KeepBelowOp, OperationsOp, WindowRulesOp, ToggleStoreSettingsOp = WindowRulesOp, ///< @obsolete HMaximizeOp, VMaximizeOp, LowerOp, FullScreenOp, NoBorderOp, NoOp }; /** * Basic color types that should be recognized by all decoration styles. * Decorations are not required to implement all the colors, but for the ones that * are implemented the color setting for them should be obeyed. */ enum ColorType { ColorTitleBar, ///< The color for the titlebar ColorTitleBlend, ///< The blend color for the titlebar ColorFont, ///< The titlebar text color ColorButtonBg, ///< The color to use for the titlebar buttons ColorFrame, ///< The color for the window frame (border) ColorHandle, ///< The color for the resize handle NUM_COLORS }; /** * These flags specify which settings changed when rereading settings. * Each setting in class KDecorationOptions specifies its matching flag. */ enum { SettingDecoration = 1 << 0, ///< The decoration was changed SettingColors = 1 << 1, ///< The color palette was changed SettingFont = 1 << 2, ///< The titlebar font was changed SettingButtons = 1 << 3, ///< The button layout was changed SettingTooltips = 1 << 4, ///< The tooltip setting was changed SettingBorder = 1 << 5 ///< The border size setting was changed }; /** * Border size. KDecorationOptions::preferredBorderSize() returns * one of these values. */ enum BorderSize { BorderTiny, ///< Minimal borders BorderNormal, ///< Standard size borders, the default setting BorderLarge, ///< Larger borders BorderVeryLarge, ///< Very large borders BorderHuge, ///< Huge borders BorderVeryHuge, ///< Very huge borders BorderOversized, ///< Oversized borders BordersCount ///< @internal }; enum Ability { ABILITY_DUMMY = 10000000 }; enum Requirement { REQUIREMENT_DUMMY = 1000000 }; }; class KDecorationProvides : public KDecorationDefines { public: virtual bool provides( Requirement req ) = 0; }; /** * This class holds various configuration settings for the decoration. * It is accessible from the decorations either as KDecoration::options() * or KDecorationFactory::options(). */ class KDecorationOptions : public KDecorationDefines { public: KDecorationOptions(); virtual ~KDecorationOptions(); /** * Returns the color that should be used for the given part of the decoration. * The changed flags for this setting is SettingColors. * * @param type The requested color type. * @param active Whether the color should be for active or inactive windows. */ const QColor& color(ColorType type, bool active=true) const; /** * Returns a colorgroup using the given decoration color as the background. * The changed flags for this setting is SettingColors. * * @param type The requested color type. * @param active Whether to return the color for active or inactive windows. */ const QColorGroup& colorGroup(ColorType type, bool active=true) const; /** * Returns the active or inactive decoration font. * The changed flags for this setting is SettingFont. * * @param active Whether to return the color for active or inactive windows. * @param small If @a true, returns a font that's suitable for tool windows. */ const QFont& font(bool active=true, bool small = false) const; /** * Returns @a true if the style should use custom button positions * The changed flags for this setting is SettingButtons. * * @see titleButtonsLeft * @see titleButtonsRight */ bool customButtonPositions() const; /** * If customButtonPositions() returns true, titleButtonsLeft * returns which buttons should be on the left side of the titlebar from left * to right. Characters in the returned string have this meaning : * @li 'M' menu button * @li 'S' on_all_desktops button * @li 'H' quickhelp button * @li 'I' minimize ( iconify ) button * @li 'A' maximize button * @li 'X' close button * @li 'F' keep_above_others button * @li 'B' keep_below_others button * @li 'L' shade button * @li '_' spacer * * The default ( which is also returned if customButtonPositions returns false ) * is "MS". * The changed flags for this setting is SettingButtons. */ // FRAME vice druhu tlacitek QString titleButtonsLeft() const; /** * If customButtonPositions() returns true, titleButtonsRight * returns which buttons should be on the right side of the titlebar from left * to right. Characters in the return string have the same meaning like * in titleButtonsLeft(). * * The default ( which is also returned if customButtonPositions returns false ) * is "HIAX". * The changed flags for this setting is SettingButtons. */ QString titleButtonsRight() const; /** * @returns true if the style should use tooltips for window buttons * The changed flags for this setting is SettingTooltips. */ bool showTooltips() const; /** * The preferred border size selected by the user, e.g. for accessibility * reasons, or when using high resolution displays. It's up to the decoration * to decide which borders or if any borders at all will obey this setting. * It is guaranteed that the returned value will be one of those * returned by KDecorationFactory::borderSizes(), so if that one hasn't been * reimplemented, BorderNormal is always returned. * The changed flags for this setting is SettingBorder. * @param factory the decoration factory used */ BorderSize preferredBorderSize( KDecorationFactory* factory ) const; /* * When this functions returns false, moving and resizing of maximized windows * is not allowed, and therefore the decoration is allowed to turn off (some of) * its borders. * The changed flags for this setting is SettingButtons. */ bool moveResizeMaximizedWindows() const; /** * @internal */ virtual unsigned long updateSettings() = 0; // returns SettingXYZ mask protected: /** * @internal */ KDecorationOptionsPrivate* d; }; /** * This is the base class for a decoration object. It provides functions * that give various information about the decorated window, and also * provides pure virtual functions for controlling the decoration that * every decoration should implement. */ class KDecoration : public QObject, public KDecorationDefines { Q_OBJECT public: /** * Constructs a KDecoration object. Both the arguments are passed from * KDecorationFactory. Note that the initialization code of the decoration * should be done in the init() method. */ KDecoration( KDecorationBridge* bridge, KDecorationFactory* factory ); /** * Destroys the KDecoration. */ virtual ~KDecoration(); // requests from decoration /** * Returns the KDecorationOptions object, which is used to access * configuration settings for the decoration. */ static const KDecorationOptions* options(); /** * Returns @a true if the decorated window is currently active. */ bool isActive() const; /** * Returns @a true if the decoration window can be closed by the user. */ bool isCloseable() const; /** * Returns @a true if the decorated window can be maximized. */ bool isMaximizable() const; /** * Returns the current maximization mode of the decorated window. * Note that only fully maximized windows should be treated * as "maximized" (e.g. if the maximize button has only two states). */ MaximizeMode maximizeMode() const; /** * Returns @a true if the decorated window can be minimized by the user. */ bool isMinimizable() const; /** * Return @a true if the decorated window can show context help * (i.e. the decoration should provide the context help button). */ bool providesContextHelp() const; /** * Returns the number of the virtual desktop the decorated window * is currently on (including NET::OnAllDesktops for being on all * desktops). */ int desktop() const; /** * Convenience function that returns @a true if the window is on all * virtual desktops. */ bool isOnAllDesktops() const; // convenience /** * Returns @a true if the decoration window is modal (usually a modal dialog). */ bool isModal() const; /** * Returns @a true if the decorated window can be shaded. */ bool isShadeable() const; /** * Returns @a true if the decorated window is currently shaded. * If the window is e.g. hover unshaded, it's not considered to be shaded. * * @see isSetShade */ bool isShade() const; /** * Returns @a true if the decorated window was set to be shaded. This function * returns also true if the window is e.g. hover unshaded, so it doesn't * always correspond to the actual window state. * * @see isShade */ bool isSetShade() const; /** * Returns @a true if the decorated window should be kept above other windows. */ bool keepAbove() const; /** * Returns @a true if the decorated window should be kept below other windows. */ bool keepBelow() const; /** * Returns @a true if the decorated window can be moved by the user. */ bool isMovable() const; /** * Returns @a true if the decorated window can be resized by the user. */ bool isResizable() const; /** * This function returns the window type of the decorated window. * The argument to this function is a mask of all window types * the decoration knows about (as the list of valid window types * is extended over time, and fallback types are specified in order * to support older code). For a description of all window types, * see the definition of the NET::WindowType type. Note that * some window types never have decorated windows. * * An example of usage: * @code * const unsigned long supported_types = NET::NormalMask | NET::DesktopMask * | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask * | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask; * * NET::WindowType type = windowType( supported_types ); * * if( type == NET::Utility || type == NET::Menu || type == NET::Toolbar ) * // ... use smaller decorations for tool window types * else * // ... use normal decorations * @endcode */ NET::WindowType windowType( unsigned long supported_types ) const; /** * Returns an icon set with the decorated window's icon. */ QIconSet icon() const; /** * Returns the decorated window's caption that should be shown in the titlebar. */ QString caption() const; /** - * This function invokes the window operations menu. IMPORTANT: As a result - * of this function, the decoration object that called it may be destroyed - * after the function returns. This means that the decoration object must - * either return immediately after calling showWindowMenu(), or it must - * use KDecorationFactory::exists() to check it's still valid. For example, - * the code handling clicks on the menu button should look similarly like this: + * This function invokes the window operations menu. + * \param pos specifies the place on the screen where the menu should + * show up. The menu pops up at the bottom-left corner of the specified + * rectangle, unless there is no space, in which case the menu is + * displayed above the rectangle. + * + * \note Decorations that enable a double-click operation for the menu + * button must ensure to call \a showWindowMenu() with the \a pos + * rectangle set to the menu button geometry. + * IMPORTANT: As a result of this function, the decoration object that + * called it may be destroyed after the function returns. This means + * that the decoration object must either return immediately after + * calling showWindowMenu(), or it must use + * KDecorationFactory::exists() to check it's still valid. For example, + * the code handling clicks on the menu button should look similarly + * like this: * * \code * KDecorationFactory* f = factory(); // needs to be saved before * showWindowMenu( button[MenuButton]->mapToGlobal( menuPoint )); * if( !f->exists( this )) // destroyed, return immediately * return; * button[MenuButton]->setDown(false); * \endcode */ + void showWindowMenu( const QRect &pos ); + + /** + * Overloaded version of the above. + */ void showWindowMenu( QPoint pos ); /** * This function performs the given window operation. This function may destroy * the current decoration object, just like showWindowMenu(). */ void performWindowOperation( WindowOperation op ); /** * If the decoration is non-rectangular, this function needs to be called * to set the shape of the decoration. * * @param reg The shape of the decoration. * @param mode The X11 values Unsorted, YSorted, YXSorted and YXBanded that specify * the sorting of the rectangles, default value is Unsorted. */ void setMask( const QRegion& reg, int mode = 0 ); /** * This convenience function resets the shape mask. */ void clearMask(); // convenience /** * If this function returns @a true, the decorated window is used as a preview * e.g. in the configuration module. In such case, the decoration can e.g. * show some information in the window area. */ bool isPreview() const; /** * Returns the geometry of the decoration. */ QRect geometry() const; /** * Returns the icon geometry for the window, i.e. the geometry of the taskbar * entry. This is used mainly for window minimize animations. Note that * the geometry may be null. */ QRect iconGeometry() const; /** * Returns the intersection of the given region with the region left * unobscured by the windows stacked above the current one. You can use * this function to, for example, try to keep the titlebar visible if - * there is an hole available. The region returned is in the coordinate + * there is a hole available. The region returned is in the coordinate * space of the decoration. * @param r The region you want to check for holes */ QRegion unobscuredRegion( const QRegion& r ) const; /** * Returns the main workspace widget. The main purpose of this function is to * allow painting the minimize animation or the transparent move bound on it. */ QWidget* workspaceWidget() const; /** * Convenience function that returns the width of the decoration. */ int width() const; // convenience /** * Convenience function that returns the height of the decoration. */ int height() const; // convenience /** * This function is the default handler for mouse events. All mouse events * that are not handled by the decoration itself should be passed to it * in order to make work operations like window resizing by dragging borders etc. */ void processMousePressEvent( QMouseEvent* e ); // requests to decoration /** * This function is called immediately after the decoration object is created. * Due to some technical reasons, initialization should be done here * instead of in the constructor. */ virtual void init() = 0; // called once right after created /** * This function should return mouse cursor position in the decoration. * Positions at the edge will result in window resizing with mouse button * pressed, center position will result in moving. */ virtual Position mousePosition( const QPoint& p ) const = 0; /** * This function should return the distance from each window side to the inner * window. The sizes may depend on the state of the decorated window, such as * whether it's shaded. Decorations often turn off their bottom border when the * window is shaded, and turn off their left/right/bottom borders when * the window is maximized and moving and resizing of maximized windows is disabled. * This function mustn't do any repaints or resizes. Also, if the sizes returned * by this function don't match the real values, this may result in drawing errors * or other problems. * * @see KDecorationOptions::moveResizeMaximizedWindows() */ // mustn't do any repaints, resizes or anything like that virtual void borders( int& left, int& right, int& top, int& bottom ) const = 0; /** * This method is called by kwin when the style should resize the decoration window. * The usual implementation is to resize the main widget of the decoration to the * given size. * * @param s Specifies the new size of the decoration window. */ virtual void resize( const QSize& s ) = 0; /** * This function should return the minimum required size for the decoration. * Note that the returned size shouldn't be too large, because it will be * used to keep the decorated window at least as large. */ virtual QSize minimumSize() const = 0; /** * This function is called whenever the window either becomes or stops being active. * Use isActive() to find out the current state. */ virtual void activeChange() = 0; /** * This function is called whenever the caption changes. Use caption() to get it. */ virtual void captionChange() = 0; /** * This function is called whenever the window icon changes. Use icon() to get it. */ virtual void iconChange() = 0; /** * This function is called whenever the maximalization state of the window changes. * Use maximizeMode() to get the current state. */ virtual void maximizeChange() = 0; /** * This function is called whenever the desktop for the window changes. Use * desktop() or isOnAllDesktops() to find out the current desktop * on which the window is. */ virtual void desktopChange() = 0; /** * This function is called whenever the window is shaded or unshaded. Use * isShade() to get the current state. */ virtual void shadeChange() = 0; /** * This function may be reimplemented to provide custom bound drawing * for transparent moving or resizing of the window. * @a False should be returned if the default implementation should be used. * * @param geom The geometry at this the bound should be drawn * @param clear @a true if the bound should be cleared * * @see workspaceWidget() and geometry(). */ virtual bool drawbound( const QRect& geom, bool clear ); /** * This function may be reimplemented to provide custom minimize/restore animations * The reimplementation is allowed to perform X server grabs if necessary * (only using the functions provided by this API, no direct Xlib calls), but no * futher event processing is allowed (i.e. no kapp->processEvents()). * @a False should be returned if the default implementation should be used. * Note that you should not use this function to force disabling of the animation. * * @see workspaceWidget(), geometry() and helperShowHide(). */ virtual bool animateMinimize( bool minimize ); /** * @internal Reserved. */ // TODO position will need also values for top+left+bottom etc. docking ? virtual bool windowDocked( Position side ); /** * This function is called to reset the decoration on settings changes. * It is usually invoked by calling KDecorationFactory::resetDecorations(). * * @param changed Specifies which settings were changed, given by the SettingXXX masks */ virtual void reset( unsigned long changed ); // special /** * This should be the first function called in init() to specify * the main widget of the decoration. The widget should be created * with parent specified by initialParentWidget() and flags * specified by initialWFlags(). */ void setMainWidget( QWidget* ); /** * Convenience functions that creates and sets a main widget as necessary. * In such case, it's usually needed to install an event filter * on the main widget to receive important events on it. * * @param flags Additional widget flags for the main widget. Note that only * flags that affect widget drawing are allowed. Window type flags * like WX11BypassWM or WStyle_NoBorder are forbidden. */ void createMainWidget( WFlags flags = 0 ); /** * The parent widget that should be used for the main widget. */ QWidget* initialParentWidget() const; /** * The flags that should be used when creating the main widget. * It is possible to add more flags when creating the main widget, but only flags * that affect widget drawing are allowed. Window type flags like WX11BypassWM * or WStyle_NoBorder are forbidden. */ WFlags initialWFlags() const; /** * This function is only allowed to be called once from animateMinimize(). * It can be used if the window should be shown or hidden at a specific * time during the animation. It is forbidden to use this function * for other purposes. */ void helperShowHide( bool show ); /** * Returns the main widget for the decoration. */ QWidget* widget(); /** * Returns the main widget for the decoration. */ const QWidget* widget() const; /** * Returns the factory that created this decoration. */ KDecorationFactory* factory() const; /** * Performs X server grab. It is safe to call it several times in a row. */ void grabXServer(); /** * Ungrabs X server (if the number of ungrab attempts matches the number of grab attempts). */ void ungrabXServer(); public slots: // requests from decoration /** * This function can be called by the decoration to request * closing of the decorated window. Note that closing the window * also involves destroying the decoration. * IMPORTANT: This function may destroy the current decoration object, * just like showWindowMenu(). */ void closeWindow(); /** * Set the maximize mode of the decorated window. * @param mode The maximization mode to be set. */ void maximize( MaximizeMode mode ); /** * Minimize the decorated window. */ void minimize(); /** * Start showing context help in the window (i.e. the mouse will enter * the what's this mode). */ void showContextHelp(); void setDesktop( int desktop ); /** * This function toggles the on-all-desktops state of the decorated window. */ void toggleOnAllDesktops(); // convenience /** * This function performs the operation configured as titlebar double click * operation. */ void titlebarDblClickOperation(); /** * Shades or unshades the decorated window. * @param set Whether the window should be shaded */ void setShade( bool set ); /** * Sets or reset keeping this window above others. * @param set Whether to keep the window above others */ void setKeepAbove( bool set ); /** * Sets or reset keeping this window below others. * @param set Whether to keep the window below others */ void setKeepBelow( bool set ); private: KDecorationBridge* bridge_; QWidget* w_; KDecorationFactory* factory_; friend class KDecorationOptions; // for options_ static KDecorationOptions* options_; KDecorationPrivate* d; }; inline KDecorationDefines::MaximizeMode operator^( KDecorationDefines::MaximizeMode m1, KDecorationDefines::MaximizeMode m2 ) { return KDecorationDefines::MaximizeMode( int(m1) ^ int(m2) ); } inline KDecorationDefines::MaximizeMode operator&( KDecorationDefines::MaximizeMode m1, KDecorationDefines::MaximizeMode m2 ) { return KDecorationDefines::MaximizeMode( int(m1) & int(m2) ); } inline KDecorationDefines::MaximizeMode operator|( KDecorationDefines::MaximizeMode m1, KDecorationDefines::MaximizeMode m2 ) { return KDecorationDefines::MaximizeMode( int(m1) | int(m2) ); } inline QWidget* KDecoration::widget() { return w_; } inline const QWidget* KDecoration::widget() const { return w_; } inline KDecorationFactory* KDecoration::factory() const { return factory_; } inline bool KDecoration::isOnAllDesktops() const { return desktop() == NET::OnAllDesktops; } inline int KDecoration::width() const { return geometry().width(); } inline int KDecoration::height() const { return geometry().height(); } #endif diff --git a/lib/kdecoration_p.h b/lib/kdecoration_p.h index 7d52ae164..ba59e3d5e 100644 --- a/lib/kdecoration_p.h +++ b/lib/kdecoration_p.h @@ -1,105 +1,106 @@ /***************************************************************** This file is part of the KDE project. Copyright (C) 2003 Lubos Lunak Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************/ #ifndef KDECORATION_P_H #define KDECORATION_P_H // // This header file is internal. I mean it. // #include "kdecoration.h" #include #include class KConfig; class KDecorationOptionsPrivate : public KDecorationDefines { public: KDecorationOptionsPrivate(); virtual ~KDecorationOptionsPrivate(); void defaultKWinSettings(); // shared implementation unsigned long updateKWinSettings( KConfig* ); // shared implementation BorderSize findPreferredBorderSize( BorderSize size, QValueList< BorderSize > ) const; // shared implementation QColor colors[NUM_COLORS*2]; QColorGroup *cg[NUM_COLORS*2]; QFont activeFont, inactiveFont, activeFontSmall, inactiveFontSmall; QString title_buttons_left; QString title_buttons_right; bool custom_button_positions; bool show_tooltips; BorderSize border_size, cached_border_size; bool move_resize_maximized_windows; }; class KDecorationBridge : public KDecorationDefines { public: virtual bool isActive() const = 0; virtual bool isCloseable() const = 0; virtual bool isMaximizable() const = 0; virtual MaximizeMode maximizeMode() const = 0; virtual bool isMinimizable() const = 0; virtual bool providesContextHelp() const = 0; virtual int desktop() const = 0; virtual bool isModal() const = 0; virtual bool isShadeable() const = 0; virtual bool isShade() const = 0; virtual bool isSetShade() const = 0; virtual bool keepAbove() const = 0; virtual bool keepBelow() const = 0; virtual bool isMovable() const = 0; virtual bool isResizable() const = 0; virtual NET::WindowType windowType( unsigned long supported_types ) const = 0; virtual QIconSet icon() const = 0; virtual QString caption() const = 0; virtual void processMousePressEvent( QMouseEvent* ) = 0; + virtual void showWindowMenu( const QRect &) = 0; virtual void showWindowMenu( QPoint ) = 0; virtual void performWindowOperation( WindowOperation ) = 0; virtual void setMask( const QRegion&, int ) = 0; virtual bool isPreview() const = 0; virtual QRect geometry() const = 0; virtual QRect iconGeometry() const = 0; virtual QRegion unobscuredRegion( const QRegion& r ) const = 0; virtual QWidget* workspaceWidget() const = 0; virtual void closeWindow() = 0; virtual void maximize( MaximizeMode mode ) = 0; virtual void minimize() = 0; virtual void showContextHelp() = 0; virtual void setDesktop( int desktop ) = 0; virtual void titlebarDblClickOperation() = 0; virtual void setShade( bool set ) = 0; virtual void setKeepAbove( bool ) = 0; virtual void setKeepBelow( bool ) = 0; // not part of public API virtual int currentDesktop() const = 0; virtual QWidget* initialParentWidget() const = 0; virtual Qt::WFlags initialWFlags() const = 0; virtual void helperShowHide( bool ) = 0; virtual void grabXServer( bool grab ) = 0; }; #endif diff --git a/useractions.cpp b/useractions.cpp index 397793933..0fd2ae898 100644 --- a/useractions.cpp +++ b/useractions.cpp @@ -1,809 +1,821 @@ /***************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 1999, 2000 Matthias Ettrich Copyright (C) 2003 Lubos Lunak You can Freely distribute this program under the GNU General Public License. See the file "COPYING" for the exact licensing terms. ******************************************************************/ /* This file contains things relevant to direct user actions, such as responses to global keyboard shortcuts, or selecting actions from the window operations menu. */ #include "client.h" #include "workspace.h" #include #include #include #include #include #include #include #include "popupinfo.h" #include "killwindow.h" #include "tabbox.h" namespace KWinInternal { //**************************************** // Workspace //**************************************** QPopupMenu* Workspace::clientPopup() { if ( !popup ) { popup = new QPopupMenu; popup->setCheckable( TRUE ); popup->setFont(KGlobalSettings::menuFont()); connect( popup, SIGNAL( aboutToShow() ), this, SLOT( clientPopupAboutToShow() ) ); connect( popup, SIGNAL( activated(int) ), this, SLOT( clientPopupActivated(int) ) ); advanced_popup = new QPopupMenu( popup ); advanced_popup->setCheckable( TRUE ); advanced_popup->setFont(KGlobalSettings::menuFont()); connect( advanced_popup, SIGNAL( activated(int) ), this, SLOT( clientPopupActivated(int) ) ); advanced_popup->insertItem( SmallIconSet( "up" ), i18n("Keep &Above Others"), Options::KeepAboveOp ); advanced_popup->insertItem( SmallIconSet( "down" ), i18n("Keep &Below Others"), Options::KeepBelowOp ); advanced_popup->insertItem( SmallIconSet( "window_fullscreen" ), i18n("&Fullscreen"), Options::FullScreenOp ); advanced_popup->insertItem( i18n("&No Border"), Options::NoBorderOp ); advanced_popup->insertItem( SmallIconSet( "filesave" ), i18n("&Special Window Rules"), Options::WindowRulesOp ); popup->insertItem(i18n("Ad&vanced"), advanced_popup ); desk_popup_index = popup->count(); popup->insertItem( SmallIconSet( "move" ), i18n("&Move")+'\t'+keys->shortcut("Window Move").seq(0).toString(), Options::MoveOp ); popup->insertItem( i18n("Re&size")+'\t'+keys->shortcut("Window Resize").seq(0).toString(), Options::ResizeOp ); popup->insertItem( i18n("Mi&nimize")+'\t'+keys->shortcut("Window Minimize").seq(0).toString(), Options::MinimizeOp ); popup->insertItem( i18n("Ma&ximize")+'\t'+keys->shortcut("Window Maximize").seq(0).toString(), Options::MaximizeOp ); popup->insertItem( i18n("Sh&ade")+'\t'+keys->shortcut("Window Shade").seq(0).toString(), Options::ShadeOp ); popup->insertSeparator(); if (!KGlobal::config()->isImmutable() && !kapp->authorizeControlModules(Workspace::configModules(true)).isEmpty()) { popup->insertItem(SmallIconSet( "configure" ), i18n("Configur&e Window Behavior..."), this, SLOT( configureWM() )); popup->insertSeparator(); } popup->insertItem( SmallIconSet( "fileclose" ), i18n("&Close")+'\t'+keys->shortcut("Window Close").seq(0).toString(), Options::CloseOp ); } return popup; } /*! The client popup menu will become visible soon. Adjust the items according to the respective popup client. */ void Workspace::clientPopupAboutToShow() { if ( !popup_client || !popup ) return; if ( numberOfDesktops() == 1 ) { delete desk_popup; desk_popup = 0; } else { initDesktopPopup(); } popup->setItemEnabled( Options::ResizeOp, popup_client->isResizable() ); popup->setItemEnabled( Options::MoveOp, popup_client->isMovable() ); popup->setItemEnabled( Options::MaximizeOp, popup_client->isMaximizable() ); popup->setItemChecked( Options::MaximizeOp, popup_client->maximizeMode() == Client::MaximizeFull ); // This should be checked also when hover unshaded popup->setItemChecked( Options::ShadeOp, popup_client->shadeMode() != Client::ShadeNone ); popup->setItemEnabled( Options::ShadeOp, popup_client->isShadeable()); advanced_popup->setItemChecked( Options::KeepAboveOp, popup_client->keepAbove() ); advanced_popup->setItemChecked( Options::KeepBelowOp, popup_client->keepBelow() ); advanced_popup->setItemChecked( Options::FullScreenOp, popup_client->isFullScreen() ); advanced_popup->setItemEnabled( Options::FullScreenOp, popup_client->userCanSetFullScreen() ); advanced_popup->setItemChecked( Options::NoBorderOp, popup_client->noBorder() ); advanced_popup->setItemEnabled( Options::NoBorderOp, popup_client->userCanSetNoBorder() ); popup->setItemEnabled( Options::MinimizeOp, popup_client->isMinimizable() ); popup->setItemEnabled( Options::CloseOp, popup_client->isCloseable() ); } void Workspace::initDesktopPopup() { if (desk_popup) return; desk_popup = new QPopupMenu( popup ); desk_popup->setCheckable( TRUE ); desk_popup->setFont(KGlobalSettings::menuFont()); connect( desk_popup, SIGNAL( activated(int) ), this, SLOT( slotSendToDesktop(int) ) ); connect( desk_popup, SIGNAL( aboutToShow() ), this, SLOT( desktopPopupAboutToShow() ) ); popup->insertItem(i18n("To &Desktop"), desk_popup, -1, desk_popup_index ); } /*! Adjusts the desktop popup to the current values and the location of the popup client. */ void Workspace::desktopPopupAboutToShow() { if ( !desk_popup ) return; desk_popup->clear(); desk_popup->insertItem( i18n("&All Desktops"), 0 ); if ( active_client && active_client->isOnAllDesktops() ) desk_popup->setItemChecked( 0, TRUE ); desk_popup->insertSeparator( -1 ); int id; const int BASE = 10; for ( int i = 1; i <= numberOfDesktops(); i++ ) { QString basic_name("%1 %2"); if (iinsertItem( basic_name .arg(i) .arg( desktopName(i).replace( '&', "&&" )), i ); if ( active_client && !active_client->isOnAllDesktops() && active_client->desktop() == i ) desk_popup->setItemChecked( id, TRUE ); } } /*! Create the global accel object \c keys. */ void Workspace::initShortcuts() { keys = new KGlobalAccel( this ); #include "kwinbindings.cpp" readShortcuts(); } void Workspace::readShortcuts() { keys->readSettings(); cutWalkThroughDesktops = keys->shortcut("Walk Through Desktops"); cutWalkThroughDesktopsReverse = keys->shortcut("Walk Through Desktops (Reverse)"); cutWalkThroughDesktopList = keys->shortcut("Walk Through Desktop List"); cutWalkThroughDesktopListReverse = keys->shortcut("Walk Through Desktop List (Reverse)"); cutWalkThroughWindows = keys->shortcut("Walk Through Windows"); cutWalkThroughWindowsReverse = keys->shortcut("Walk Through Windows (Reverse)"); keys->updateConnections(); } void Workspace::clientPopupActivated( int id ) { WindowOperation op = static_cast< WindowOperation >( id ); Client* c = popup_client ? popup_client : active_client; QString type; switch( op ) { case FullScreenOp: if( !c->isFullScreen() && c->userCanSetFullScreen()) type = "fullscreenaltf3"; break; case NoBorderOp: if( !c->noBorder() && c->userCanSetNoBorder()) type = "noborderaltf3"; break; default: break; }; if( !type.isEmpty()) helperDialog( type, c ); performWindowOperation( c, op ); } void Workspace::performWindowOperation( Client* c, Options::WindowOperation op ) { if ( !c ) return; if (op == Options::MoveOp || op == Options::UnrestrictedMoveOp ) QCursor::setPos( c->geometry().center() ); if (op == Options::ResizeOp || op == Options::UnrestrictedResizeOp ) QCursor::setPos( c->geometry().bottomRight()); switch ( op ) { case Options::MoveOp: c->performMouseCommand( Options::MouseMove, QCursor::pos() ); break; case Options::UnrestrictedMoveOp: c->performMouseCommand( Options::MouseUnrestrictedMove, QCursor::pos() ); break; case Options::ResizeOp: c->performMouseCommand( Options::MouseResize, QCursor::pos() ); break; case Options::UnrestrictedResizeOp: c->performMouseCommand( Options::MouseUnrestrictedResize, QCursor::pos() ); break; case Options::CloseOp: c->closeWindow(); break; case Options::MaximizeOp: c->maximize( c->maximizeMode() == Client::MaximizeFull ? Client::MaximizeRestore : Client::MaximizeFull ); break; case Options::HMaximizeOp: c->maximize( c->maximizeMode() ^ Client::MaximizeHorizontal ); break; case Options::VMaximizeOp: c->maximize( c->maximizeMode() ^ Client::MaximizeVertical ); break; case Options::MinimizeOp: c->minimize(); break; case Options::ShadeOp: c->toggleShade(); break; case Options::OnAllDesktopsOp: c->setOnAllDesktops( !c->isOnAllDesktops() ); break; case Options::FullScreenOp: c->setFullScreen( !c->isFullScreen(), true ); break; case Options::NoBorderOp: c->setUserNoBorder( !c->isUserNoBorder()); break; case Options::KeepAboveOp: c->setKeepAbove( !c->keepAbove() ); break; case Options::KeepBelowOp: c->setKeepBelow( !c->keepBelow() ); break; case Options::WindowRulesOp: editWindowRules( c ); break; case Options::LowerOp: lowerClient(c); break; default: break; } } /*! Performs a mouse command on this client (see options.h) */ bool Client::performMouseCommand( Options::MouseCommand command, QPoint globalPos, bool handled ) { bool replay = FALSE; switch (command) { case Options::MouseRaise: workspace()->raiseClient( this ); break; case Options::MouseLower: workspace()->lowerClient( this ); break; case Options::MouseShade : toggleShade(); break; case Options::MouseOperationsMenu: if ( isActive() & options->clickRaise ) autoRaise(); workspace()->showWindowMenu( globalPos, this ); break; case Options::MouseToggleRaiseAndLower: workspace()->raiseOrLowerClient( this ); break; case Options::MouseActivateAndRaise: replay = isActive(); // for clickraise mode workspace()->takeActivity( this, ActivityFocus | ActivityRaise, handled && replay ); break; case Options::MouseActivateAndLower: workspace()->requestFocus( this ); workspace()->lowerClient( this ); break; case Options::MouseActivate: replay = isActive(); // for clickraise mode workspace()->takeActivity( this, ActivityFocus, handled && replay ); break; case Options::MouseActivateRaiseAndPassClick: workspace()->takeActivity( this, ActivityFocus | ActivityRaise, handled ); replay = TRUE; break; case Options::MouseActivateAndPassClick: workspace()->takeActivity( this, ActivityFocus, handled ); replay = TRUE; break; case Options::MouseActivateRaiseAndMove: case Options::MouseActivateRaiseAndUnrestrictedMove: workspace()->raiseClient( this ); workspace()->requestFocus( this ); if( options->moveMode == Options::Transparent && isMovable()) move_faked_activity = workspace()->fakeRequestedActivity( this ); // fallthrough case Options::MouseMove: case Options::MouseUnrestrictedMove: { if (!isMovable()) break; if( moveResizeMode ) finishMoveResize( false ); mode = PositionCenter; buttonDown = TRUE; moveOffset = QPoint( globalPos.x() - x(), globalPos.y() - y()); // map from global invertedMoveOffset = rect().bottomRight() - moveOffset; unrestrictedMoveResize = ( command == Options::MouseActivateRaiseAndUnrestrictedMove || command == Options::MouseUnrestrictedMove ); setCursor( mode ); if( !startMoveResize()) { buttonDown = false; setCursor( mode ); } break; } case Options::MouseResize: case Options::MouseUnrestrictedResize: { if (!isResizable() || isShade()) // SHADE break; if( moveResizeMode ) finishMoveResize( false ); buttonDown = TRUE; moveOffset = QPoint( globalPos.x() - x(), globalPos.y() - y()); // map from global int x = moveOffset.x(), y = moveOffset.y(); bool left = x < width() / 3; bool right = x >= 2 * width() / 3; bool top = y < height() / 3; bool bot = y >= 2 * height() / 3; if (top) mode = left ? PositionTopLeft : (right ? PositionTopRight : PositionTop); else if (bot) mode = left ? PositionBottomLeft : (right ? PositionBottomRight : PositionBottom); else mode = (x < width() / 2) ? PositionLeft : PositionRight; invertedMoveOffset = rect().bottomRight() - moveOffset; unrestrictedMoveResize = ( command == Options::MouseUnrestrictedResize ); setCursor( mode ); if( !startMoveResize()) { buttonDown = false; setCursor( mode ); } break; } case Options::MouseMinimize: minimize(); break; case Options::MouseNothing: // fall through default: replay = TRUE; break; } return replay; } // KDE4 remove me void Workspace::showWindowMenuAt( unsigned long, int, int ) { slotWindowOperations(); } void Workspace::slotActivateAttentionWindow() { if( attention_chain.count() > 0 ) activateClient( attention_chain.first()); } void Workspace::slotSwitchDesktopNext() { int d = currentDesktop() + 1; if ( d > numberOfDesktops() ) { if ( options->rollOverDesktops ) { d = 1; } else { return; } } setCurrentDesktop(d); popupinfo->showInfo( desktopName(currentDesktop()) ); } void Workspace::slotSwitchDesktopPrevious() { int d = currentDesktop() - 1; if ( d <= 0 ) { if ( options->rollOverDesktops ) d = numberOfDesktops(); else return; } setCurrentDesktop(d); popupinfo->showInfo( desktopName(currentDesktop()) ); } void Workspace::slotSwitchDesktopRight() { int x,y; calcDesktopLayout(x,y); int dt = currentDesktop()-1; if (layoutOrientation == Qt::Vertical) { dt += y; if ( dt >= numberOfDesktops() ) { if ( options->rollOverDesktops ) dt -= numberOfDesktops(); else return; } } else { int d = (dt % x) + 1; if ( d >= x ) { if ( options->rollOverDesktops ) d -= x; else return; } dt = dt - (dt % x) + d; } setCurrentDesktop(dt+1); popupinfo->showInfo( desktopName(currentDesktop()) ); } void Workspace::slotSwitchDesktopLeft() { int x,y; calcDesktopLayout(x,y); int dt = currentDesktop()-1; if (layoutOrientation == Qt::Vertical) { dt -= y; if ( dt < 0 ) { if ( options->rollOverDesktops ) dt += numberOfDesktops(); else return; } } else { int d = (dt % x) - 1; if ( d < 0 ) { if ( options->rollOverDesktops ) d += x; else return; } dt = dt - (dt % x) + d; } setCurrentDesktop(dt+1); popupinfo->showInfo( desktopName(currentDesktop()) ); } void Workspace::slotSwitchDesktopUp() { int x,y; calcDesktopLayout(x,y); int dt = currentDesktop()-1; if (layoutOrientation == Qt::Horizontal) { dt -= x; if ( dt < 0 ) { if ( options->rollOverDesktops ) dt += numberOfDesktops(); else return; } } else { int d = (dt % y) - 1; if ( d < 0 ) { if ( options->rollOverDesktops ) d += y; else return; } dt = dt - (dt % y) + d; } setCurrentDesktop(dt+1); popupinfo->showInfo( desktopName(currentDesktop()) ); } void Workspace::slotSwitchDesktopDown() { int x,y; calcDesktopLayout(x,y); int dt = currentDesktop()-1; if (layoutOrientation == Qt::Horizontal) { dt += x; if ( dt >= numberOfDesktops() ) { if ( options->rollOverDesktops ) dt -= numberOfDesktops(); else return; } } else { int d = (dt % y) + 1; if ( d >= y ) { if ( options->rollOverDesktops ) d -= y; else return; } dt = dt - (dt % y) + d; } setCurrentDesktop(dt+1); popupinfo->showInfo( desktopName(currentDesktop()) ); } void Workspace::slotSwitchToDesktop( int i ) { setCurrentDesktop( i ); popupinfo->showInfo( desktopName(currentDesktop()) ); } void Workspace::slotWindowToDesktop( int i ) { if( i >= 1 && i <= numberOfDesktops() && active_client && !active_client->isDesktop() && !active_client->isDock() && !active_client->isTopMenu()) sendClientToDesktop( active_client, i, true ); } /*! Maximizes the popup client */ void Workspace::slotWindowMaximize() { if ( active_client ) performWindowOperation( active_client, Options::MaximizeOp ); } /*! Maximizes the popup client vertically */ void Workspace::slotWindowMaximizeVertical() { if ( active_client ) performWindowOperation( active_client, Options::VMaximizeOp ); } /*! Maximizes the popup client horiozontally */ void Workspace::slotWindowMaximizeHorizontal() { if ( active_client ) performWindowOperation( active_client, Options::HMaximizeOp ); } /*! Minimizes the popup client */ void Workspace::slotWindowMinimize() { performWindowOperation( active_client, Options::MinimizeOp ); } /*! Shades/unshades the popup client respectively */ void Workspace::slotWindowShade() { performWindowOperation( active_client, Options::ShadeOp ); } /*! Raises the popup client */ void Workspace::slotWindowRaise() { if ( active_client ) raiseClient( active_client ); } /*! Lowers the popup client */ void Workspace::slotWindowLower() { if ( active_client ) lowerClient( active_client ); } /*! Does a toggle-raise-and-lower on the popup client; */ void Workspace::slotWindowRaiseOrLower() { if ( active_client ) raiseOrLowerClient( active_client ); } void Workspace::slotWindowOnAllDesktops() { if( active_client ) active_client->setOnAllDesktops( !active_client->isOnAllDesktops()); } void Workspace::slotWindowFullScreen() { if( active_client ) performWindowOperation( active_client, Options::FullScreenOp ); } void Workspace::slotWindowNoBorder() { if( active_client ) performWindowOperation( active_client, Options::NoBorderOp ); } void Workspace::slotWindowAbove() { if( active_client ) performWindowOperation( active_client, Options::KeepAboveOp ); } void Workspace::slotWindowBelow() { if( active_client ) performWindowOperation( active_client, Options::KeepBelowOp ); } /*! Move window to next desktop */ void Workspace::slotWindowToNextDesktop() { int d = currentDesktop() + 1; if ( d > numberOfDesktops() ) d = 1; if (active_client && !active_client->isDesktop() && !active_client->isDock() && !active_client->isTopMenu()) sendClientToDesktop(active_client,d,true); setCurrentDesktop(d); popupinfo->showInfo( desktopName(currentDesktop()) ); } /*! Move window to previous desktop */ void Workspace::slotWindowToPreviousDesktop() { int d = currentDesktop() - 1; if ( d <= 0 ) d = numberOfDesktops(); if (active_client && !active_client->isDesktop() && !active_client->isDock() && !active_client->isTopMenu()) sendClientToDesktop(active_client,d,true); setCurrentDesktop(d); popupinfo->showInfo( desktopName(currentDesktop()) ); } /*! Kill Window feature, similar to xkill */ void Workspace::slotKillWindow() { KillWindow kill( this ); kill.start(); } /*! Sends the popup client to desktop \a desk Internal slot for the window operation menu */ void Workspace::slotSendToDesktop( int desk ) { if ( !popup_client ) return; if ( desk == 0 ) { // the 'on_all_desktops' menu entry popup_client->setOnAllDesktops( !popup_client->isOnAllDesktops()); return; } sendClientToDesktop( popup_client, desk, false ); } /*! Shows the window operations popup menu for the activeClient() */ void Workspace::slotWindowOperations() { if ( !active_client ) return; QPoint pos = active_client->pos() + active_client->clientPos(); showWindowMenu( pos.x(), pos.y(), active_client ); } -void Workspace::showWindowMenu( int x, int y, Client* cl ) +void Workspace::showWindowMenu( const QRect &pos, Client* cl ) { if (!kapp->authorizeKAction("kwin_rmb")) return; if( !cl ) return; if( popup_client != NULL ) // recursion return; if ( cl->isDesktop() || cl->isDock() || cl->isTopMenu()) return; popup_client = cl; QPopupMenu* p = clientPopup(); - p->exec( QPoint( x, y ) ); + int x = pos.left(); + int y = pos.bottom(); + if (y == pos.top()) { + p->exec( QPoint( x, y ) ); + } else { + QRect area = clientArea(ScreenArea, QPoint(x, y), currentDesktop()); + int popupHeight = p->sizeHint().height(); + if (y + popupHeight < area.height()) { + p->exec( QPoint( x, y ) ); + } else { + p->exec( QPoint( x, pos.top() - popupHeight ) ); + } + } popup_client = 0; } /*! Closes the popup client */ void Workspace::slotWindowClose() { if ( tab_box->isVisible() || popupinfo->isVisible() ) return; performWindowOperation( active_client, Options::CloseOp ); } /*! Starts keyboard move mode for the popup client */ void Workspace::slotWindowMove() { performWindowOperation( active_client, Options::UnrestrictedMoveOp ); } /*! Starts keyboard resize mode for the popup client */ void Workspace::slotWindowResize() { performWindowOperation( active_client, Options::UnrestrictedResizeOp ); } } // namespace diff --git a/workspace.h b/workspace.h index fd176fea7..8c9c92131 100644 --- a/workspace.h +++ b/workspace.h @@ -1,697 +1,706 @@ /***************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 1999, 2000 Matthias Ettrich Copyright (C) 2003 Lubos Lunak You can Freely distribute this program under the GNU General Public License. See the file "COPYING" for the exact licensing terms. ******************************************************************/ #ifndef KWIN_WORKSPACE_H #define KWIN_WORKSPACE_H #include #include #include #include #include "KWinInterface.h" #include "utils.h" #include "kdecoration.h" #include "sm.h" #include class QPopupMenu; class KConfig; class KGlobalAccel; class KStartupInfo; class KStartupInfoId; class KStartupInfoData; namespace KWinInternal { class Client; class TabBox; class PopupInfo; class RootInfo; class PluginMgr; class Placement; class WindowRules; class SystemTrayWindow { public: SystemTrayWindow() : win(0),winFor(0) {} SystemTrayWindow( WId w ) : win(w),winFor(0) {} SystemTrayWindow( WId w, WId wf ) : win(w),winFor(wf) {} bool operator==( const SystemTrayWindow& other ) { return win == other.win; } WId win; WId winFor; }; typedef QValueList SystemTrayWindowList; class Workspace : public QObject, public KWinInterface, public KDecorationDefines { Q_OBJECT public: Workspace( bool restore = FALSE ); virtual ~Workspace(); static Workspace * self() { return _self; } bool workspaceEvent( XEvent * ); KDecoration* createDecoration( KDecorationBridge* bridge ); bool hasClient( const Client * ); template< typename T > Client* findClient( T predicate ); template< typename T1, typename T2 > void forEachClient( T1 procedure, T2 predicate ); template< typename T > void forEachClient( T procedure ); QRect clientArea( clientAreaOption, const QPoint& p, int desktop ) const; QRect clientArea( clientAreaOption, const Client* c ) const; /** * @internal */ void killWindowId( Window window); void killWindow() { slotKillWindow(); } WId rootWin() const; bool initializing() const; /** * Returns the active client, i.e. the client that has the focus (or None * if no client has the focus) */ Client* activeClient() const; // Client that was activated, but it's not yet really activeClient(), because // we didn't process yet the matching FocusIn event. Used mostly in focus // stealing prevention code. Client* mostRecentlyActivatedClient() const; void activateClient( Client*, bool force = FALSE ); void requestFocus( Client* c, bool force = FALSE ); void takeActivity( Client* c, int flags, bool handled ); // flags are ActivityFlags void handleTakeActivity( Client* c, Time timestamp, int flags ); // flags are ActivityFlags bool allowClientActivation( const Client* c, Time time = -1U, bool focus_in = false, bool session_active = false ); void restoreFocus(); void gotFocusIn( const Client* ); void setShouldGetFocus( Client* ); bool fakeRequestedActivity( Client* c ); void unfakeActivity( Client* c ); void activateNextClient( Client* c ); bool focusChangeEnabled() { return block_focus == 0; } void updateColormap(); /** * Indicates that the client c is being moved around by the user. */ void setClientIsMoving( Client *c ); void place( Client *c, QRect& area ); void placeSmart( Client* c, const QRect& area ); QPoint adjustClientPosition( Client* c, QPoint pos ); void raiseClient( Client* c ); void lowerClient( Client* c ); void raiseClientRequest( Client* c, NET::RequestSource src, Time timestamp ); void lowerClientRequest( Client* c, NET::RequestSource src, Time timestamp ); void restackClientUnderActive( Client* ); void updateClientLayer( Client* c ); void raiseOrLowerClient( Client * ); void reconfigure(); void clientHidden( Client* ); void clientAttentionChanged( Client* c, bool set ); void clientMoved(const QPoint &pos, Time time); /** * Returns the current virtual desktop of this workspace */ int currentDesktop() const; /** * Returns the number of virtual desktops of this workspace */ int numberOfDesktops() const; void setNumberOfDesktops( int n ); QWidget* desktopWidget(); // for TabBox Client* nextFocusChainClient(Client*) const; Client* previousFocusChainClient(Client*) const; Client* nextStaticClient(Client*) const; Client* previousStaticClient(Client*) const; int nextDesktopFocusChain( int iDesktop ) const; int previousDesktopFocusChain( int iDesktop ) const; void closeTabBox(); /** * Returns the list of clients sorted in stacking order, with topmost client * at the last position */ const ClientList& stackingOrder() const; ClientList ensureStackingOrder( const ClientList& clients ) const; Client* topClientOnDesktop( int desktop, bool unconstrained = false ) const; Client* findDesktop( bool topmost, int desktop ) const; void sendClientToDesktop( Client* c, int desktop, bool dont_activate ); // KDE4 remove me - and it's also in the DCOP interface :( void showWindowMenuAt( unsigned long id, int x, int y ); /** - * Shows the menu operations menu for the client - * and makes it active if it's not already. + * Shows the menu operations menu for the client and makes it active if + * it's not already. */ + void showWindowMenu( const QRect &pos, Client* cl ); + /** + * Backwards compatibility. + */ void showWindowMenu( int x, int y, Client* cl ); void showWindowMenu( QPoint pos, Client* cl ); void updateMinimizedOfTransients( Client* ); void updateOnAllDesktopsOfTransients( Client* ); void checkTransients( Window w ); void performWindowOperation( Client* c, WindowOperation op ); void storeSession( KConfig* config, SMSavePhase phase ); SessionInfo* takeSessionInfo( Client* ); WindowRules* findWindowRules( const Client* ) const; // dcop interface void cascadeDesktop(); void unclutterDesktop(); void doNotManage(QString); bool setCurrentDesktop( int new_desktop ); void nextDesktop(); void previousDesktop(); void circulateDesktopApplications(); QString desktopName( int desk ) const; void setDesktopLayout(int o, int x, int y); bool isNotManaged( const QString& title ); // ### setter or getter ? void sendPingToWindow( Window w, Time timestamp ); // called from Client::pingWindow() void sendTakeActivity( Client* c, Time timestamp, long flags ); // called from Client::takeActivity() // only called from Client::destroyClient() or Client::releaseWindow() void removeClient( Client*, allowed_t ); void setActiveClient( Client*, allowed_t ); Group* findGroup( Window leader ) const; void addGroup( Group* group, allowed_t ); void removeGroup( Group* group, allowed_t ); Group* findClientLeaderGroup( const Client* c ) const; bool checkStartupNotification( Window w, KStartupInfoId& id, KStartupInfoData& data ); void focusToNull(); // SELI public? bool forcedGlobalMouseGrab() const; void sessionSaveStarted(); void sessionSaveDone(); void setWasUserInteraction(); bool sessionSaving() const; bool managingTopMenus() const; int topMenuHeight() const; int packPositionLeft( const Client* cl, int oldx, bool left_edge ) const; int packPositionRight( const Client* cl, int oldx, bool right_edge ) const; int packPositionUp( const Client* cl, int oldy, bool top_edge ) const; int packPositionDown( const Client* cl, int oldy, bool bottom_edge ) const; static QStringList configModules(bool controlCenter); void cancelDelayFocus(); void requestDelayFocus( Client* ); public slots: void refresh(); // keybindings void slotSwitchDesktopNext(); void slotSwitchDesktopPrevious(); void slotSwitchDesktopRight(); void slotSwitchDesktopLeft(); void slotSwitchDesktopUp(); void slotSwitchDesktopDown(); void slotSwitchToDesktop( int ); //void slotSwitchToWindow( int ); void slotWindowToDesktop( int ); //void slotWindowToListPosition( int ); void slotWindowMaximize(); void slotWindowMaximizeVertical(); void slotWindowMaximizeHorizontal(); void slotWindowMinimize(); void slotWindowShade(); void slotWindowRaise(); void slotWindowLower(); void slotWindowRaiseOrLower(); void slotActivateAttentionWindow(); void slotWindowPackLeft(); void slotWindowPackRight(); void slotWindowPackUp(); void slotWindowPackDown(); void slotWindowGrowHorizontal(); void slotWindowGrowVertical(); void slotWindowShrinkHorizontal(); void slotWindowShrinkVertical(); void slotWalkThroughDesktops(); void slotWalkBackThroughDesktops(); void slotWalkThroughDesktopList(); void slotWalkBackThroughDesktopList(); void slotWalkThroughWindows(); void slotWalkBackThroughWindows(); void slotWindowOperations(); void slotWindowClose(); void slotWindowMove(); void slotWindowResize(); void slotWindowAbove(); void slotWindowBelow(); void slotWindowOnAllDesktops(); void slotWindowFullScreen(); void slotWindowNoBorder(); void slotWindowToNextDesktop(); void slotWindowToPreviousDesktop(); void slotMouseEmulation(); void slotSettingsChanged( int category ); void slotReconfigure(); void slotKillWindow(); void slotGrabWindow(); void slotGrabDesktop(); void updateClientArea(); private slots: void desktopPopupAboutToShow(); void clientPopupAboutToShow(); void slotSendToDesktop( int ); void clientPopupActivated( int ); void configureWM(); void desktopResized(); void slotUpdateToolWindows(); void lostTopMenuSelection(); void lostTopMenuOwner(); void delayFocus(); protected: bool keyPressMouseEmulation( XKeyEvent& ev ); bool netCheck( XEvent* e ); private: void init(); void initShortcuts(); void readShortcuts(); void initDesktopPopup(); bool startKDEWalkThroughWindows(); bool startWalkThroughDesktops( int mode ); // TabBox::Mode::DesktopMode | DesktopListMode bool startWalkThroughDesktops(); bool startWalkThroughDesktopList(); void KDEWalkThroughWindows( bool forward ); void CDEWalkThroughWindows( bool forward ); void walkThroughDesktops( bool forward ); void KDEOneStepThroughWindows( bool forward ); void oneStepThroughDesktops( bool forward, int mode ); // TabBox::Mode::DesktopMode | DesktopListMode void oneStepThroughDesktops( bool forward ); void oneStepThroughDesktopList( bool forward ); bool establishTabBoxGrab(); void removeTabBoxGrab(); void updateStackingOrder( bool propagate_new_clients = false ); void propagateClients( bool propagate_new_clients ); // called only from updateStackingOrder ClientList constrainedStackingOrder(); void raiseClientWithinApplication( Client* c ); void lowerClientWithinApplication( Client* c ); bool allowFullClientRaising( const Client* c, Time timestamp ); bool keepTransientAbove( const Client* mainwindow, const Client* transient ); void blockStackingUpdates( bool block ); void updateCurrentTopMenu(); void addTopMenu( Client* c ); void removeTopMenu( Client* c ); void setupTopMenuHandling(); void updateTopMenuGeometry( Client* c = NULL ); void updateToolWindows( bool also_hide ); // this is the right way to create a new client Client* createClient( Window w, bool is_mapped ); void addClient( Client* c, allowed_t ); Window findSpecialEventWindow( XEvent* e ); void randomPlacement(Client* c); void smartPlacement(Client* c); void cascadePlacement(Client* c, bool re_init = false); bool addSystemTrayWin( WId w ); bool removeSystemTrayWin( WId w, bool check ); void propagateSystemTrayWins(); SystemTrayWindow findSystemTrayWin( WId w ); // desktop names and number of desktops void loadDesktopSettings(); void saveDesktopSettings(); // mouse emulation WId getMouseEmulationWindow(); enum MouseEmulation { EmuPress, EmuRelease, EmuMove }; unsigned int sendFakedMouseEvent( QPoint pos, WId win, MouseEmulation type, int button, unsigned int state ); // returns the new state void tabBoxKeyPress( const KKeyNative& keyX ); void tabBoxKeyRelease( const XKeyEvent& ev ); // electric borders void checkElectricBorders(); void createBorderWindows(); void destroyBorderWindows(); void electricBorder(XEvent * e); void raiseElectricBorders(); // ------------------ void helperDialog( const QString& message, const Client* c ); void calcDesktopLayout(int &x, int &y); QPopupMenu* clientPopup(); void updateClientArea( bool force ); SystemTrayWindowList systemTrayWins; int current_desktop; int number_of_desktops; QMemArray desktop_focus_chain; Client* popup_client; QWidget* desktop_widget; void loadSessionInfo(); void loadWindowRules(); void writeWindowRules(); void editWindowRules( Client* ); QPtrList session; QValueList windowRules; static const char* windowTypeToTxt( NET::WindowType type ); static NET::WindowType txtToWindowType( const char* txt ); static bool sessionInfoWindowTypeMatch( Client* c, SessionInfo* info ); Client* active_client; Client* last_active_client; Client* most_recently_raised; // used _only_ by raiseOrLowerClient() Client* movingClient; Client* pending_take_activity; // delay(ed) window focus timer and client QTimer* delayFocusTimer; Client* delayfocus_client; ClientList clients; ClientList desktops; ClientList unconstrained_stacking_order; ClientList stacking_order; ClientList focus_chain; ClientList should_get_focus; // last is most recent ClientList attention_chain; GroupList groups; bool was_user_interaction; bool session_saving; int session_active_client; int session_desktop; bool control_grab; bool tab_grab; //KKeyNative walkThroughDesktopsKeycode, walkBackThroughDesktopsKeycode; //KKeyNative walkThroughDesktopListKeycode, walkBackThroughDesktopListKeycode; //KKeyNative walkThroughWindowsKeycode, walkBackThroughWindowsKeycode; KShortcut cutWalkThroughDesktops, cutWalkThroughDesktopsReverse; KShortcut cutWalkThroughDesktopList, cutWalkThroughDesktopListReverse; KShortcut cutWalkThroughWindows, cutWalkThroughWindowsReverse; bool mouse_emulation; unsigned int mouse_emulation_state; WId mouse_emulation_window; int block_focus; TabBox* tab_box; PopupInfo* popupinfo; QPopupMenu *popup; QPopupMenu *advanced_popup; QPopupMenu *desk_popup; int desk_popup_index; KGlobalAccel *keys; WId root; PluginMgr *mgr; RootInfo *rootInfo; QWidget* supportWindow; // swallowing QStringList doNotManageList; // colormap handling Colormap default_colormap; Colormap installed_colormap; // Timer to collect requests for 'reconfigure' QTimer reconfigureTimer; QTimer updateToolWindowsTimer; static Workspace *_self; bool workspaceInit; KStartupInfo* startup; bool electric_have_borders; int electric_current_border; WId electric_top_border; WId electric_bottom_border; WId electric_left_border; WId electric_right_border; int electricLeft; int electricRight; int electricTop; int electricBottom; Time electric_time_first; Time electric_time_last; QPoint electric_push_point; Qt::Orientation layoutOrientation; int layoutX; int layoutY; Placement *initPositioning; QRect* workarea; // array of workareas for virtual desktops QRect** screenarea; // array of workareas per xinerama screen for all virtual desktops bool managing_topmenus; KSelectionOwner* topmenu_selection; KSelectionWatcher* topmenu_watcher; ClientList topmenus; // doesn't own them mutable int topmenu_height; QWidget* topmenu_space; int set_active_client_recursion; int block_stacking_updates; // when >0, stacking updates are temporarily disabled bool blocked_propagating_new_clients; // propagate also new clients after enabling stacking updates? Window null_focus_window; bool forced_global_mouse_grab; friend class StackingUpdatesBlocker; }; // helper for Workspace::blockStackingUpdates() being called in pairs (true/false) class StackingUpdatesBlocker { public: StackingUpdatesBlocker( Workspace* w ) : ws( w ) { ws->blockStackingUpdates( true ); } ~StackingUpdatesBlocker() { ws->blockStackingUpdates( false ); } private: Workspace* ws; }; // NET WM Protocol handler class class RootInfo : public NETRootInfo3 { private: typedef KWinInternal::Client Client; // because of NET::Client public: RootInfo( Workspace* ws, Display *dpy, Window w, const char *name, unsigned long pr[], int pr_num, int scr= -1); protected: virtual void changeNumberOfDesktops(int n); virtual void changeCurrentDesktop(int d); // virtual void changeActiveWindow(Window w); the extended version is used virtual void changeActiveWindow(Window w,NET::RequestSource src, Time timestamp, Window active_window); virtual void closeWindow(Window w); virtual void moveResize(Window w, int x_root, int y_root, unsigned long direction); virtual void moveResizeWindow(Window w, int flags, int x, int y, int width, int height ); virtual void gotPing(Window w, Time timestamp); virtual void restackWindow(Window w, RequestSource source, Window above, int detail, Time timestamp); virtual void gotTakeActivity(Window w, Time timestamp, long flags ); private: Workspace* workspace; }; inline WId Workspace::rootWin() const { return root; } inline bool Workspace::initializing() const { return workspaceInit; } inline Client* Workspace::activeClient() const { return active_client; } inline Client* Workspace::mostRecentlyActivatedClient() const { return should_get_focus.count() > 0 ? should_get_focus.last() : active_client; } inline int Workspace::currentDesktop() const { return current_desktop; } inline int Workspace::numberOfDesktops() const { return number_of_desktops; } inline void Workspace::addGroup( Group* group, allowed_t ) { groups.append( group ); } inline void Workspace::removeGroup( Group* group, allowed_t ) { groups.remove( group ); } inline const ClientList& Workspace::stackingOrder() const { // TODO Q_ASSERT( block_stacking_updates == 0 ); return stacking_order; } inline void Workspace::showWindowMenu(QPoint pos, Client* cl) { - showWindowMenu(pos.x(), pos.y(), cl); + showWindowMenu(QRect(pos, pos), cl); + } + +inline void Workspace::showWindowMenu(int x, int y, Client* cl) + { + showWindowMenu(QRect(QPoint(x, y), QPoint(x, y)), cl); } inline void Workspace::setWasUserInteraction() { was_user_interaction = true; } inline bool Workspace::managingTopMenus() const { return managing_topmenus; } inline void Workspace::sessionSaveStarted() { session_saving = true; } inline void Workspace::sessionSaveDone() { session_saving = false; } inline bool Workspace::sessionSaving() const { return session_saving; } inline bool Workspace::forcedGlobalMouseGrab() const { return forced_global_mouse_grab; } template< typename T > inline Client* Workspace::findClient( T predicate ) { if( Client* ret = findClientInList( clients, predicate )) return ret; if( Client* ret = findClientInList( desktops, predicate )) return ret; return NULL; } template< typename T1, typename T2 > inline void Workspace::forEachClient( T1 procedure, T2 predicate ) { for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) if ( predicate( const_cast< const Client* >( *it))) procedure( *it ); for ( ClientList::ConstIterator it = desktops.begin(); it != desktops.end(); ++it) if ( predicate( const_cast< const Client* >( *it))) procedure( *it ); } template< typename T > inline void Workspace::forEachClient( T procedure ) { return forEachClient( procedure, TruePredicate()); } KWIN_COMPARE_PREDICATE( ClientMatchPredicate, const Client*, cl == value ); inline bool Workspace::hasClient( const Client* c ) { return findClient( ClientMatchPredicate( c )); } } // namespace #endif