kwin/clients/oxygen/oxygenclient.h

541 lines
16 KiB
C
Raw Normal View History

#ifndef oxygenclient_h
#define oxygenclient_h
//////////////////////////////////////////////////////////////////////////////
// oxygenclient.h
// -------------------
//
// Copyright (c) 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
// Copyright (c) 2003, 2004 David Johnson <david@usermode.org>
// Copyright (c) 2006, 2007 Riccardo Iaconelli <ruphy@fsfe.org>
//
// 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 <kcommondecoration.h>
#include <QBasicTimer>
#include <QTextStream>
#include <QTimerEvent>
#include <xcb/xcb.h>
namespace Oxygen
{
class SizeGrip;
class Client : public KCommonDecoration
{
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 && !configuration()->drawBorderOnMaximizedWindows(); }
//! true if animations are used
bool animationsEnabled( void ) const
{ return _configuration->animationsEnabled(); }
//! true if glow is animated
bool glowIsAnimated( void ) const
2011-02-24 16:37:04 +00:00
{ 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();
//! return associated configuration
Factory::ConfigurationPtr configuration( void ) const
2011-02-24 16:37:04 +00:00
{ return _configuration; }
//!@name glow animation
//@{
void setGlowIntensity( qreal value )
{
2011-02-24 16:37:04 +00:00
if( _glowIntensity == value ) return;
_glowIntensity = value;
widget()->update();
}
//! unbiased glow intensity
qreal glowIntensityUnbiased( void ) const
2011-02-24 16:37:04 +00:00
{ 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
2011-02-24 16:37:04 +00:00
{ return _glowAnimation->direction() == Animation::Forward ? _glowIntensity : _glowIntensity-glowBias(); }
//@}
//! helper class
DecoHelper& helper( void ) const
2011-02-24 16:37:04 +00:00
{ return _factory->helper(); }
//! helper class
ShadowCache& shadowCache( void ) const
2011-02-24 16:37:04 +00:00
{ 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;
//@}
//! 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;
2013-07-30 04:47:50 +00:00
public Q_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 )
2011-02-24 16:37:04 +00:00
{ _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
2011-02-24 16:37:04 +00:00
{ 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 ||
2011-02-24 16:37:04 +00:00
_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
2011-02-24 16:37:04 +00:00
{ return (bool)_sizeGrip; }
//! size grip
SizeGrip& sizeGrip( void ) const
2011-02-24 16:37:04 +00:00
{ return *_sizeGrip; }
//@}
//! remove shadow hint
void removeShadowHint( void );
2013-07-30 04:47:50 +00:00
protected Q_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 Q_SLOTS:
void updateCompositing();
void updateConfig();
private:
//! factory
2011-02-24 16:37:04 +00:00
Factory* _factory;
//! backing store pixmap (when compositing is not active)
QPixmap _pixmap;
//! size grip widget
2011-02-24 16:37:04 +00:00
SizeGrip* _sizeGrip;
//! configuration
Factory::ConfigurationPtr _configuration;
//! glow animation
2011-02-24 16:37:04 +00:00
Animation* _glowAnimation;
//! title animation data
2011-02-24 16:37:04 +00:00
TitleAnimationData* _titleAnimationData;
//! glow intensity
2011-02-24 16:37:04 +00:00
qreal _glowIntensity;
//! true when initialized
2011-02-24 16:37:04 +00:00
bool _initialized;
//! true when decoration is forced active
2011-02-24 16:37:04 +00:00
bool _forceActive;
//! mouse button
2011-02-24 16:37:04 +00:00
Qt::MouseButton _mouseButton;
//! tab bounding rects
2011-02-24 16:37:04 +00:00
ClientGroupItemDataList _itemData;
//! index of tab being dragged if any, -1 otherwise
2011-02-24 16:37:04 +00:00
int _sourceItem;
//! drag start point
2011-02-24 16:37:04 +00:00
QPoint _dragPoint;
//! drag start timer.
/*!
it is needed to activate animations when this was not done via either
dragMoveEvent or dragLeaveEvent
*/
2011-02-24 16:37:04 +00:00
QBasicTimer _dragStartTimer;
//! shadow atom
xcb_atom_t _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