#ifndef oxygenclient_h #define oxygenclient_h ////////////////////////////////////////////////////////////////////////////// // oxygenclient.h // ------------------- // // Copyright (c) 2009 Hugo Pereira Da Costa // Copyright (c) 2003, 2004 David Johnson // Copyright (c) 2006, 2007 Riccardo Iaconelli // // 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 "oxygenanimation.h" #include "oxygenclientgroupitemdata.h" #include "oxygenconfiguration.h" #include "oxygendecohelper.h" #include "oxygenfactory.h" #include "oxygenshadowcache.h" #include "oxygentitleanimationdata.h" #include #include #include #include #include namespace Oxygen { class SizeGrip; class Client : public KCommonDecorationUnstable { Q_OBJECT //! declare glow intensity property Q_PROPERTY( qreal glowIntensity READ glowIntensityUnbiased WRITE setGlowIntensity ) public: //! constructor Client(KDecorationBridge *b, Factory *f); //! destructor virtual ~Client(); //! decoration name virtual QString visibleName() const; //! buttons virtual KCommonDecorationButton *createButton(::ButtonType type); //!@name flags //@{ //! true if decoration has iquired behavior virtual bool decorationBehaviour(DecorationBehaviour behaviour) const; //! true if window is maximized virtual bool isMaximized( void ) const { return maximizeMode()==MaximizeFull && !options()->moveResizeMaximizedWindows(); } //! true if animations are used bool animationsEnabled( void ) const { return _configuration->animationsEnabled(); } //! true if glow is animated bool glowIsAnimated( void ) const { return _glowAnimation->isRunning(); } //! true when decoration is forced active bool isForcedActive( void ) const { return _forceActive && tabCount() > 1; } //! true when separator is to be drawn bool drawSeparator( void ) const { if( _configuration->drawTitleOutline() ) return false; switch( _configuration->separatorMode() ) { case Configuration::SeparatorAlways: return true; case Configuration::SeparatorActive: return ( glowIsAnimated() || isActive() ); default: case Configuration::SeparatorNever: return false; } } //! true if titlebar is hidden bool hideTitleBar( void ) const { return _configuration->hideTitleBar() && !isShade() && tabCount() == 1; } //@} //! window shape virtual void updateWindowShape(); //! initialization virtual void init(); // reset virtual void reset( unsigned long changed ); //! return associated configuration Factory::ConfigurationPtr configuration( void ) const { return _configuration; } //!@name glow animation //@{ void setGlowIntensity( qreal value ) { if( _glowIntensity == value ) return; _glowIntensity = value; widget()->update(); } //! unbiased glow intensity qreal glowIntensityUnbiased( void ) const { return _glowIntensity; } //! glow bias static qreal glowBias( void ) { return 0.2; } //! true (biased) intensity /*! this is needed to have glow go from either 0.2->1 or 0.8->0 depending on the animation direction */ qreal glowIntensity( void ) const { return _glowAnimation->direction() == Animation::Forward ? _glowIntensity : _glowIntensity-glowBias(); } //@} //! helper class DecoHelper& helper( void ) const { return _factory->helper(); } //! helper class ShadowCache& shadowCache( void ) const { return _factory->shadowCache(); } //!@name metrics and color definitions //@{ //! dimensions virtual int layoutMetric(LayoutMetric lm, bool respectWindowState = true, const KCommonDecorationButton * = 0) const; //! get title rect for untabbed window virtual QRect defaultTitleRect( bool active = true ) const; //! get title bounding rect virtual QRect titleBoundingRect( const QFont& font, const QString& caption ) const { return titleBoundingRect( font, titleRect(), caption ); } //! get title bounding rect virtual QRect titleBoundingRect( const QFont&, QRect, const QString& ) const; //! palette background QPalette backgroundPalette( const QWidget*, QPalette ) const; //! background QColor backgroundColor( const QWidget* widget, QPalette palette ) const { return backgroundColor( widget, palette, isActive() || isForcedActive() ); } //! background QColor backgroundColor( const QWidget*, QPalette, bool ) const; //@} //! default buttons located on the left virtual QString defaultButtonsLeft() const; //! default buttons located on the right virtual QString defaultButtonsRight() const; //! title alignment inline Qt::Alignment titleAlignment( void ) const; //! button size inline int buttonSize( void ) const; //! frame border inline int frameBorder( void ) const; //!@name status change methods (overloaded from KCommonDecorationUnstable) //@{ //! triggered when window activity is changed virtual void activeChange(); //! triggered when maximize state changed virtual void maximizeChange(); //! triggered when window shade is changed virtual void shadeChange(); //! triggered when window shade is changed virtual void captionChange(); //@} //! event filter virtual bool eventFilter( QObject*, QEvent* ); //! resize event virtual void resizeEvent( QResizeEvent* ); //! paint background to painter void paintBackground( QPainter& ) const; public slots: //! triggers widget update in titleRect only /*! one needs to add the title top margin to avoid some clipping glitches */ void updateTitleRect( void ) { widget()->update( titleRect().adjusted( 0, -layoutMetric( LM_TitleEdgeTop ), 0, 1 ) ); } //! return region for a given defines. This allows to implement extended borders QRegion region( KDecorationDefines::Region ); protected: //! return shadow cache key associated to this client ShadowCache::Key key( void ) const { ShadowCache::Key key; key.active = ( isActive() || isForcedActive() ) && shadowCache().isEnabled( QPalette::Active ); key.isShade = isShade(); key.hasBorder = ( _configuration->frameBorder() > Configuration::BorderNone ); return key; } //! true when decoration is forced active void setForceActive( bool value ) { _forceActive = value; } //!@name event filters //@{ //! paint virtual void paintEvent( QPaintEvent* ); //! render full decoration to provided painter virtual void paint( QPainter& ); //! mouse press event virtual bool mousePressEvent( QMouseEvent* ); //! mouse release event virtual bool mouseReleaseEvent( QMouseEvent* ); //! mouse move event virtual bool mouseMoveEvent( QMouseEvent* ); //! drag enter event virtual bool dragEnterEvent( QDragEnterEvent* ); //! drag move event virtual bool dragMoveEvent( QDragMoveEvent* ); //! drag leave event virtual bool dragLeaveEvent( QDragLeaveEvent* ); //! drop event virtual bool dropEvent( QDropEvent* ); //! timer event virtual void timerEvent( QTimerEvent* ); //@} //!@name rendering methods (called in paintEvent) //@{ //! window background virtual void renderWindowBackground( QPainter*, const QRect&, const QWidget*, const QPalette& ) const; //! window border // this draws a "blue" border around active window virtual void renderWindowBorder( QPainter*, const QRect&, const QWidget*, const QPalette& ) const; //! separator virtual void renderSeparator( QPainter*, const QRect&, const QWidget*, const QColor& ) const; //! title outline virtual void renderTitleOutline( QPainter*, const QRect&, const QPalette& ) const; //! title text /*! second color, if valid, is for contrast pixel */ virtual void renderTitleText( QPainter*, const QRect&, const QColor&, const QColor& = QColor() ) const; //! title text /*! second color, if valid, is for contrast pixel */ virtual void renderTitleText( QPainter*, const QRect&, const QString&, const QColor&, const QColor& = QColor(), bool elide = true ) const; //! title text virtual QPixmap renderTitleText( const QRect&, const QString&, const QColor&, bool elide = true ) const; //! GroupItem virtual void renderItem( QPainter*, int, const QPalette& ); //! tabbing target rect virtual void renderTargetRect( QPainter*, const QPalette& ); //! render corners virtual void renderCorners( QPainter*, const QRect&, const QPalette& ) const; //! render float frame virtual void renderFloatFrame( QPainter*, const QRect&, const QPalette& ) const; //! render dots virtual void renderDots( QPainter*, const QRect&, const QColor& ) const; //@} //! close tab matching give button virtual bool closeItem( const Button* ); //! index of item matching point int tabIndexAt( const QPoint& position, bool between = false ) const { return _itemData.itemAt( position , between ); } //! return pixmap corresponding to a given tab, for dragging QPixmap itemDragPixmap( int, QRect, bool = false ); //! return true when activity change are animated bool shadowAnimationsEnabled( void ) const { return ( animationsEnabled() && _configuration->shadowAnimationsEnabled() && !isPreview() ); } //! return true when activity change are animated bool titleAnimationsEnabled( void ) const { return animationsEnabled() && _configuration->titleAnimationsEnabled() && !_configuration->drawTitleOutline() && !hideTitleBar() && !isPreview(); } //! true if some title outline is rendered bool hasTitleOutline( void ) const { return tabCount() >= 2 || _itemData.isAnimated() || ( (isActive()||glowIsAnimated()) && _configuration->drawTitleOutline() ); } //! calculate mask QRegion calcMask( void ) const; //! text color QColor titlebarTextColor(const QPalette&) const; //! text color QColor titlebarTextColor(const QPalette& palette, bool active) const { return active ? palette.color(QPalette::Active, QPalette::WindowText): helper().inactiveTitleBarTextColor( palette ); } //! text color QColor titlebarContrastColor(const QPalette& palette ) const { return titlebarContrastColor( palette.color( widget()->window()->backgroundRole() ) ); } //! text color QColor titlebarContrastColor(const QColor& color ) const { return helper().calcLightColor( color ); } //!@name size grip //@{ //! create size grip void createSizeGrip( void ); //! delete size grip void deleteSizeGrip( void ); // size grip bool hasSizeGrip( void ) const { return (bool)_sizeGrip; } //! size grip SizeGrip& sizeGrip( void ) const { return *_sizeGrip; } //@} //! remove shadow hint void removeShadowHint( void ); protected slots: //! set target item to -1 void clearTargetItem( void ); //! clear force active flag void clearForceActive( void ) { if( isActive() ) setForceActive( false ); } //! title bounding rects /*! calculate and return title bounding rects in case of tabbed window */ void updateItemBoundingRects( bool alsoUpdate = true ); //! bound one rect to another void boundRectTo( QRect&, const QRect& ) const; private: //! factory Factory* _factory; //! backing store pixmap (when compositing is not active) QPixmap _pixmap; //! size grip widget SizeGrip* _sizeGrip; //! configuration Factory::ConfigurationPtr _configuration; //! glow animation Animation* _glowAnimation; //! title animation data TitleAnimationData* _titleAnimationData; //! glow intensity qreal _glowIntensity; //! true when initialized bool _initialized; //! true when decoration is forced active bool _forceActive; //! mouse button Qt::MouseButton _mouseButton; //! tab bounding rects ClientGroupItemDataList _itemData; //! index of tab being dragged if any, -1 otherwise int _sourceItem; //! drag start point QPoint _dragPoint; //! drag start timer. /*! it is needed to activate animations when this was not done via either dragMoveEvent or dragLeaveEvent */ QBasicTimer _dragStartTimer; //! shadow atom Atom _shadowAtom; }; } // namespace Oxygen //____________________________________________________ Qt::Alignment Oxygen::Client::titleAlignment( void ) const { switch( _configuration->titleAlignment() ) { case Configuration::AlignLeft: return Qt::AlignLeft; case Configuration::AlignRight: return Qt::AlignRight; default: case Configuration::AlignCenter: case Configuration::AlignCenterFullWidth: return Qt::AlignCenter; } } //____________________________________________________ int Oxygen::Client::buttonSize( void ) const { switch( _configuration->buttonSize() ) { case Configuration::ButtonSmall: return 18; default: case Configuration::ButtonDefault: return 20; case Configuration::ButtonLarge: return 24; case Configuration::ButtonVeryLarge: return 32; case Configuration::ButtonHuge: return 48; } } //____________________________________________________ int Oxygen::Client::frameBorder( void ) const { switch( _configuration->frameBorder() ) { case Configuration::BorderNone: return 0; case Configuration::BorderNoSide: return 1; default: case Configuration::BorderTiny: return 2; case Configuration::BorderDefault: return 4; case Configuration::BorderLarge: return 8; case Configuration::BorderVeryLarge: return 12; case Configuration::BorderHuge: return 18; case Configuration::BorderVeryHuge: return 27; case Configuration::BorderOversized: return 40; } } #endif