/*
	Copyright (C) 2006 Michael Lentner <michaell@gmx.net>
	
	based on KDE2 Default KWin client:
	Copyright (C) 1999, 2001 Daniel Duley <mosfet@kde.org>
	Matthias Ettrich <ettrich@kde.org>
	Karol Szwed <gallium@kde.org>
	
	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Library General Public
	License version 2 as published by the Free Software Foundation.
	
	This library 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
	Library General Public License for more details.
	
	You should have received a copy of the GNU General Public License
	along with this library; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/

#include "dominoclient.h"
#include "clientData.h"

#include <tdeconfig.h>
#include <tdeglobal.h>
#include <tqlayout.h>
#include <tqbitmap.h>
#include <tqimage.h>
#include <tqapplication.h>
#include <tqlabel.h>
#include <tqpixmap.h>
#include <X11/extensions/shape.h>
#include <tqwmatrix.h>
#include <tqpainter.h>
#include <tqsettings.h>


namespace Domino
{

static DominoHandler* clientHandler;
static bool Domino_initialized = false;
const int titleEdgeTop = 3;
const int titleEdgeBottom = 1;
static int titleHeight;

static TQPixmap* buttonPix;
static TQPixmap* buttonHidePix;
static TQPixmap* titleBarPix;
static TQPixmap* borderTopLeftPix;
static TQPixmap* borderTopRightPix;
static TQPixmap* borderBottomPix;
static TQPixmap* borderBottomLeftPix;
static TQPixmap* borderBottomRightPix;
static TQPixmap* borderLeftPix;
static TQPixmap* borderRightPix;


static TQPixmap* closeButtonIcon;
static TQPixmap* minButtonIcon;
static TQPixmap* maxButtonIcon;
static TQPixmap* helpButtonIcon;
static TQPixmap* onAllDesktopsButtonIcon;
static TQPixmap* shadeButtonIcon;
static TQPixmap* aboveButtonIcon;
static TQPixmap* belowButtonIcon;

static TQPixmap* pressedCloseButtonIcon;
static TQPixmap* pressedMinButtonIcon;
static TQPixmap* pressedMaxButtonIcon;
static TQPixmap* pressedHelpButtonIcon;
static TQPixmap* pressedOnAllDesktopsButtonIcon;
static TQPixmap* pressedShadeButtonIcon;
static TQPixmap* pressedAboveButtonIcon;
static TQPixmap* pressedBelowButtonIcon;

static TQPixmap* mouseOverCloseButtonIcon;
static TQPixmap* mouseOverMinButtonIcon;
static TQPixmap* mouseOverMaxButtonIcon;
static TQPixmap* mouseOverHelpButtonIcon;
static TQPixmap* mouseOverOnAllDesktopsButtonIcon;
static TQPixmap* mouseOverShadeButtonIcon;
static TQPixmap* mouseOverAboveButtonIcon;
static TQPixmap* mouseOverBelowButtonIcon;

static bool buttonInputShape;
static TQBitmap* buttonShapeBitmap;

static TQColor background;
static TQColor topGradientColor;
static TQColor bottomGradientColor;
static TQColor topBorderGradientColor;
static TQColor bottomBorderGradientColor;
static bool showButtonIcons;
static bool showInactiveButtons;

const int titleGradientHeight = 10;
const int bottomBorderHeight = 8;
const int borderWidth = 5;

// ===========================================================================

DominoHandler::DominoHandler()
{
	int ignore, maj, min;
	
	if(XShapeQueryExtension(tqt_xdisplay(), &ignore, &ignore) &&
		  XShapeQueryVersion(tqt_xdisplay(), &maj, &min) &&
		  maj >= 1 && min >= 1) {
		
		buttonInputShape = true;
	}
	else
		buttonInputShape = false;
	
	clientHandler = this;
	readConfig( false );
	createPixmaps();
	Domino_initialized = true;
}


DominoHandler::~DominoHandler()
{
	Domino_initialized = false;
	freePixmaps();
	clientHandler = NULL;
}

KDecoration* DominoHandler::createDecoration( KDecorationBridge* b )
{
		return new DominoClient( b, this );
}

bool DominoHandler::reset( unsigned long changed )
{
	Domino_initialized = false;
	changed |= readConfig( true );
	if( changed & SettingColors )
	{ // pixmaps need to be recreated
		freePixmaps();
		createPixmaps();
	}
	Domino_initialized = true;
	// SettingButtons is handled by KCommonDecoration
	bool need_recreate = ( changed & ( SettingDecoration | SettingFont | SettingBorder )) != 0;
	if( need_recreate )  // something else than colors changed
		return true;
	resetDecorations( changed );
	return false;
}


unsigned long DominoHandler::readConfig( bool update )
{
	unsigned long changed = 0;
	TDEConfig conf("twindominorc");
	conf.setGroup("General");
	
	titleHeight = TQMAX(TQFontMetrics(options()->font(true)).height(), 16);
	background = tqApp->palette().active().background();
	
	customBorderColor = conf.readBoolEntry("customBorderColor", true);
	borderColor = customBorderColor ? conf.readEntry("borderColor", "#777B7F") : background;
	
	customButtonColor = conf.readBoolEntry("customButtonColor", false);
	buttonColor = customButtonColor ? conf.readEntry("buttonColor", "#212121") : background;
	customButtonIconColor = conf.readBoolEntry("customButtonIconColor", false);
	buttonIconColor = customButtonIconColor ? conf.readEntry("buttonIconColor", "#000000") : "#000000";
	showInactiveButtons = conf.readBoolEntry("showInactiveButtons", false);
	showButtonIcons = conf.readBoolEntry("showButtonIcons", false);
	darkLines = conf.readBoolEntry("darkFrame", false);
	
	if(!conf.readBoolEntry( "customGradientColors", false)) {
		topGradientColor = alphaBlendColors(background, TQt::white, 180);
		bottomGradientColor = alphaBlendColors(background, TQt::black, 230);
		topBorderGradientColor = alphaBlendColors(borderColor, TQt::white, 180);
		bottomBorderGradientColor = alphaBlendColors(borderColor, TQt::black, 230);
	}
	else {
		topGradientColor = conf.readEntry("topGradientColor", "#ffffff");
		bottomGradientColor = conf.readEntry("bottomGradientColor", "#000000");
		topBorderGradientColor = topGradientColor;
		bottomBorderGradientColor = bottomGradientColor;
	}

	if( update ) {
		changed |= SettingColors; // just recreate the pixmaps and repaint
	}
	
	if(conf.readBoolEntry("useDominoStyleContourColors", true)) {
		TQSettings s;
		buttonContourColor = s.readEntry("/domino/Settings/buttonContourColor", background.dark(250).name());
		buttonMouseOverContourColor = s.readEntry("/domino/Settings/buttonMouseOverContourColor", background.dark(250).name());
		buttonPressedContourColor = s.readEntry("/domino/Settings/buttonPressedContourColor", background.dark(250).name());
	}
	else {
		buttonContourColor = conf.readEntry("buttonContourColor", background.dark(250).name());
		buttonMouseOverContourColor = conf.readEntry("buttonMouseOverContourColor", background.dark(250).name());
		buttonPressedContourColor= conf.readEntry("buttonPressedContourColor", background.dark(250).name());
	}
	
	return changed;
}


// This paints the button pixmaps upon loading the style.
void DominoHandler::createPixmaps()
{
	
	TQImage edges;
	TQImage topLines;
	TQImage rightLines;
	TQImage bottomLines;
	
	if(darkLines) {
		edges = qembed_findImage("client_edges_dark");
		topLines = qembed_findImage("client_topLines_dark");
		rightLines = qembed_findImage("client_rightLines_dark");
		bottomLines = qembed_findImage("client_bottomLines_dark");
	}
	else {
		edges = qembed_findImage("client_edges");
		topLines = qembed_findImage("client_topLines");
		rightLines = qembed_findImage("client_rightLines");
		bottomLines = qembed_findImage("client_bottomLines");
	}
	
	
	
	
	int titleBarHeight = titleHeight+titleEdgeTop+titleEdgeBottom;
	TQWMatrix m;
	m.rotate(180);
	
	titleBarPix = new TQPixmap(TQSize(10, titleBarHeight));
	titleBarPix->fill(background);
	TQRect r(titleBarPix->rect());
	TQPainter p(titleBarPix);
	TQRect rect(r.x(), r.y(), r.width(), titleGradientHeight);
	renderGradient(&p, rect, topGradientColor, background, "titleBar");
	p.drawPixmap(0, 0, topLines);
	p.end();
	
	
	
	///////// borders
	// sides
	TQPixmap sideLinesRight =  rightLines;
	
	borderRightPix = new TQPixmap(5, 10);
	borderRightPix->fill(borderColor);
	p.begin(borderRightPix);
	p.drawPixmap(3, 0, sideLinesRight);
	p.end();
	
	borderLeftPix = new TQPixmap(borderRightPix->xForm(m));
	// edges
	borderTopLeftPix = new TQPixmap(TQSize(5, titleBarHeight));
	borderTopLeftPix->fill(borderColor);
	p.begin(borderTopLeftPix);
	r = TQRect(0, 0, 5, titleGradientHeight);
	// if the gradient color is equal to the background color, we make the border also flat.
	renderGradient(&p, r, topGradientColor == background ? borderColor : topBorderGradientColor, borderColor, "borderTopLeftPix");
	borderTopRightPix = new TQPixmap(*borderTopLeftPix);
	p.drawPixmap(0, 1, edges, 0, 0, 5, 6);
	p.drawTiledPixmap(0, 7, 2, titleBarHeight, sideLinesRight.xForm(m));
	p.end();
	p.begin(borderTopRightPix);
	p.drawPixmap(0, 1, edges, 5, 0, 5, 6);
	p.drawTiledPixmap(3, 7, 2, titleBarHeight, sideLinesRight);
	p.end();
	
	
	borderBottomRightPix = new TQPixmap(TQSize(5, bottomBorderHeight));
	borderBottomRightPix->fill(borderColor);
	p.begin(borderBottomRightPix);
	r = TQRect(0, bottomBorderHeight-6, 5, 6);
	renderGradient(&p, r, borderColor, bottomGradientColor == background ? borderColor : bottomBorderGradientColor, "borderBottomRightPix");
	borderBottomLeftPix = new TQPixmap(*borderBottomRightPix);
	p.drawPixmap(0, bottomBorderHeight-7, edges, 5, 6, 5, 6);
	p.drawPixmap(3, 0, sideLinesRight, 0, 0, 2, borderBottomLeftPix->height()-7);
	p.end();
	
	
	p.begin(borderBottomLeftPix);
	p.drawPixmap(0, bottomBorderHeight-7, edges, 0, 6, 5 ,6);
	p.drawPixmap(0, 0, sideLinesRight.xForm(m),  0, 0, 2, borderBottomLeftPix->height()-7);
	p.end();
	
	borderBottomPix = new TQPixmap(TQSize(10, bottomBorderHeight));
	borderBottomPix->fill(background);
	p.begin(borderBottomPix);
	r = TQRect(0, bottomBorderHeight-6, 10, 6);
	renderGradient(&p, r, background, bottomGradientColor, "borderBottom");
	p.drawPixmap(0, bottomBorderHeight-2, bottomLines);
	p.end();
	
	
	
	///////// buttons
	////////////////////////////////////////////////////////////////////////
	
	if(buttonInputShape) {
		TQRegion buttonClip(6,2,6,1);
		buttonClip += TQRegion(5,3,8,1);
		buttonClip += TQRegion(4,4,10,1);
		buttonClip += TQRegion(3,5,12,1);
		buttonClip += TQRegion(2,6,14,6);
		buttonClip += TQRegion(3,12,12,1);
		buttonClip += TQRegion(4,13,10,1);
		buttonClip += TQRegion(5,14,8,1);
		buttonClip += TQRegion(6,15,6,1);
		
		buttonShapeBitmap = new TQBitmap(16, titleBarHeight, true);
		TQPainter p(buttonShapeBitmap);
		p.setClipRegion(buttonClip);
		p.fillRect(TQRect(0, 0, 16, titleBarHeight), TQt::color1);
	}
	
	TQPixmap* buttonShadow = new TQPixmap(qembed_findImage("clientButtonShadow"));
	TQPixmap* buttonPressed = new TQPixmap(qembed_findImage("clientButtonPressed"));
	
	buttonPix = new TQPixmap(TQSize(16, titleBarHeight));
	p.begin(buttonPix);
	p.drawTiledPixmap(0, 0, titleBarHeight, titleBarHeight, *titleBarPix, 0, titleEdgeTop);
	
	//////////// custom color
	r = TQRect(buttonPix->rect());
	TQRegion buttonClip(5,2,6,1);
	buttonClip += TQRegion(4,3,8,1);
	buttonClip += TQRegion(3,4,10,1);
	buttonClip += TQRegion(2,5,12,6);
	buttonClip += TQRegion(3,11,10,1);
	buttonClip += TQRegion(4,12,8,1);
	buttonClip += TQRegion(5,13,6,1);
	
	p.setClipRegion(buttonClip);
	p.fillRect(TQRect(0, 0, r.width(), r.height()), buttonColor);
	TQRect gr(0, -3, r.width(), titleGradientHeight);
	renderGradient(&p, gr, topGradientColor, buttonColor, "titleBar");
	p.setClipping(false);
	///////////
	p.drawPixmap(0, 0, *buttonShadow);
	p.end();
	
	
	TQPixmap* pressedButtonPix = new TQPixmap(*buttonPix);
	p.begin(pressedButtonPix);
	p.drawPixmap(0, 0, tintImage(qembed_findImage("clientButtonContour"), buttonPressedContourColor));
	p.drawPixmap(0, 0, *buttonPressed);
	p.end();
	
	
	TQPixmap* mouseOverButtonPix = new TQPixmap(*buttonPix);
	p.begin(mouseOverButtonPix);
	p.drawPixmap(0, 0, tintImage(qembed_findImage("clientButtonContour"), buttonMouseOverContourColor));
	p.end();
	
	
	p.begin(buttonPix);
	p.drawPixmap(0, 0, tintImage(qembed_findImage("clientButtonContour"), buttonContourColor));
	p.end();
	
	
	buttonHidePix = new TQPixmap(TQSize(buttonPix->width(), titleBarHeight));
	p.begin(buttonHidePix);
	p.drawTiledPixmap(0, 0, buttonHidePix->width(), buttonHidePix->height(), *titleBarPix, 0, titleEdgeTop);
	p.end();
	
	
	
	
	///////// icons
	///////////////////////////////////////////////////////////////////////
	
	TQPixmap* icon = new TQPixmap(customButtonIconColor ? tintImage(qembed_findImage("closeButtonIcon"), buttonIconColor) : qembed_findImage("closeButtonIcon"));
	closeButtonIcon = new TQPixmap(*buttonPix);
	bitBlt(closeButtonIcon, 5, 5, icon);
	pressedCloseButtonIcon = new TQPixmap(*pressedButtonPix);
	bitBlt(pressedCloseButtonIcon, 5, 5, icon);
	mouseOverCloseButtonIcon = new TQPixmap(*mouseOverButtonPix);
	bitBlt(mouseOverCloseButtonIcon, 5, 5, icon);
	delete icon;
	
	icon = new TQPixmap(customButtonIconColor ? tintImage(qembed_findImage("maxButtonIcon"), buttonIconColor) : qembed_findImage("maxButtonIcon"));
	maxButtonIcon = new TQPixmap(*buttonPix);
	bitBlt(maxButtonIcon, 4, 4, icon);
	pressedMaxButtonIcon = new TQPixmap(*pressedButtonPix);
	bitBlt(pressedMaxButtonIcon, 4, 4, icon);
	mouseOverMaxButtonIcon = new TQPixmap(*mouseOverButtonPix);
	bitBlt(mouseOverMaxButtonIcon, 4, 4, icon);
	delete icon;
	
	icon = new TQPixmap(customButtonIconColor ? tintImage(qembed_findImage("minButtonIcon"), buttonIconColor) : qembed_findImage("minButtonIcon"));
	minButtonIcon = new TQPixmap(*buttonPix);
	bitBlt(minButtonIcon, 5, 9, icon);
	pressedMinButtonIcon = new TQPixmap(*pressedButtonPix);
	bitBlt(pressedMinButtonIcon, 5, 9, icon);
	mouseOverMinButtonIcon = new TQPixmap(*mouseOverButtonPix);
	bitBlt(mouseOverMinButtonIcon, 5, 9, icon);
	delete icon;
	
	icon = new TQPixmap(customButtonIconColor ? tintImage(qembed_findImage("helpButtonIcon"), buttonIconColor) : qembed_findImage("helpButtonIcon"));
	helpButtonIcon = new TQPixmap(*buttonPix);
	bitBlt(helpButtonIcon, 5, 4, icon);
	pressedHelpButtonIcon = new TQPixmap(*pressedButtonPix);
	bitBlt(pressedHelpButtonIcon, 5, 4, icon);
	mouseOverHelpButtonIcon = new TQPixmap(*mouseOverButtonPix);
	bitBlt(mouseOverHelpButtonIcon, 5, 4, icon);
	delete icon;
	
	icon = new TQPixmap(customButtonIconColor ? tintImage(qembed_findImage("onAllDesktopsButtonIcon"), buttonIconColor) : qembed_findImage("onAllDesktopsButtonIcon"));
	onAllDesktopsButtonIcon = new TQPixmap(*buttonPix);
	bitBlt(onAllDesktopsButtonIcon, 6, 6, icon);
	pressedOnAllDesktopsButtonIcon = new TQPixmap(*pressedButtonPix);
	bitBlt(pressedOnAllDesktopsButtonIcon, 6, 6, icon);
	mouseOverOnAllDesktopsButtonIcon = new TQPixmap(*mouseOverButtonPix);
	bitBlt(mouseOverOnAllDesktopsButtonIcon, 6, 6, icon);
	delete icon;
	
	icon = new TQPixmap(customButtonIconColor ? tintImage(qembed_findImage("aboveButtonIcon"), buttonIconColor) : qembed_findImage("aboveButtonIcon"));
	aboveButtonIcon = new TQPixmap(*buttonPix);
	bitBlt(aboveButtonIcon, 5, 4, icon);
	pressedAboveButtonIcon = new TQPixmap(*pressedButtonPix);
	bitBlt(pressedAboveButtonIcon, 5, 4, icon);
	mouseOverAboveButtonIcon = new TQPixmap(*mouseOverButtonPix);
	bitBlt(mouseOverAboveButtonIcon, 5, 4, icon);
	delete icon;
	
	icon = new TQPixmap(customButtonIconColor ? tintImage(qembed_findImage("aboveButtonIcon").xForm(m), buttonIconColor) : qembed_findImage("aboveButtonIcon").xForm(m));
	belowButtonIcon = new TQPixmap(*buttonPix);
	bitBlt(belowButtonIcon, 5, 4, icon);
	pressedBelowButtonIcon = new TQPixmap(*pressedButtonPix);
	bitBlt(pressedBelowButtonIcon, 5, 4, icon);
	mouseOverBelowButtonIcon = new TQPixmap(*mouseOverButtonPix);
	bitBlt(mouseOverBelowButtonIcon, 5, 4, icon);
	delete icon;
	
	icon = new TQPixmap(customButtonIconColor ? tintImage(qembed_findImage("minButtonIcon"), buttonIconColor) : qembed_findImage("minButtonIcon"));
	shadeButtonIcon = new TQPixmap(*buttonPix);
	bitBlt(shadeButtonIcon, 5, 5, icon);
	pressedShadeButtonIcon = new TQPixmap(*pressedButtonPix);
	bitBlt(pressedShadeButtonIcon, 5, 5, icon);
	mouseOverShadeButtonIcon = new TQPixmap(*mouseOverButtonPix);
	bitBlt(mouseOverShadeButtonIcon, 5, 5, icon);
	delete icon;
	
	delete mouseOverButtonPix;
	delete pressedButtonPix;
}

void DominoHandler::freePixmaps()
{
	
	delete buttonPix;
	delete buttonHidePix;
	buttonPix = 0;
	delete titleBarPix;
	delete borderTopRightPix;
	delete borderTopLeftPix;
	delete borderBottomRightPix;
	delete borderBottomLeftPix;
	delete borderLeftPix;
	delete borderRightPix;
	delete borderBottomPix;
	
	delete closeButtonIcon;
	delete maxButtonIcon;
	delete minButtonIcon;
	delete helpButtonIcon;
	delete onAllDesktopsButtonIcon;
	delete aboveButtonIcon;
	delete belowButtonIcon;
	delete shadeButtonIcon;
	
	delete pressedCloseButtonIcon;
	delete pressedMaxButtonIcon;
	delete pressedMinButtonIcon;
	delete pressedHelpButtonIcon;
	delete pressedOnAllDesktopsButtonIcon;
	delete pressedAboveButtonIcon;
	delete pressedBelowButtonIcon;
	delete pressedShadeButtonIcon;
	
	delete mouseOverCloseButtonIcon;
	delete mouseOverMinButtonIcon;
	delete mouseOverMaxButtonIcon;
	delete mouseOverHelpButtonIcon;
	delete mouseOverOnAllDesktopsButtonIcon;
	delete mouseOverShadeButtonIcon;
	delete mouseOverAboveButtonIcon;
	delete mouseOverBelowButtonIcon;
	
	
	
	if(buttonInputShape)
		delete buttonShapeBitmap;
	
}

bool DominoHandler::supports( Ability ability )
{
	switch( ability )
		{
		case AbilityAnnounceButtons:
		case AbilityButtonMenu:
		case AbilityButtonOnAllDesktops:
		case AbilityButtonSpacer:
		case AbilityButtonHelp:
		case AbilityButtonMinimize:
		case AbilityButtonMaximize:
		case AbilityButtonClose:
		case AbilityButtonAboveOthers:
		case AbilityButtonBelowOthers:
		case AbilityButtonShade:
			return true;
		default:
			return false;
		};
}

// ===========================================================================

DominoButton::DominoButton(ButtonType type, DominoClient *parent, const char *name)
	: KCommonDecorationButton(type, parent, name)
{
	isMouseOver = false;
	client = parent;
#ifdef ShapeInput
	if(buttonInputShape && buttonShapeBitmap ) {
		XShapeCombineMask (tqt_xdisplay(),
				   winId(),
				   ShapeInput,
				   0,
				   0,
				   buttonShapeBitmap->handle(),
				   ShapeSet);
	}
#endif
}


DominoButton::~DominoButton()
{
}


void DominoButton::reset(unsigned long changed)
{
	if (changed&SizeChange || changed&ManualReset) {
		setBackgroundOrigin(TQWidget::WidgetOrigin);
		setErasePixmap(showInactiveButtons ? *buttonPix : *buttonHidePix);
	}
	
	
	if (changed&DecorationReset || changed&ManualReset || changed&SizeChange || changed&StateChange) {
		this->update();
	}

	
}


void DominoButton::drawButton(TQPainter *p)
{
	if (!Domino_initialized)
		return;
	
	bool down = isDown() || isOn();
	if(down || (( isMouseOver || showButtonIcons) && (showInactiveButtons || decoration()->isActive() || client->titleBarMouseOver)) ) {
		switch (type()) {
			case CloseButton:
				p->drawPixmap(0, 0, down ? *pressedCloseButtonIcon : isMouseOver ? *mouseOverCloseButtonIcon : *closeButtonIcon);
				break;
			case HelpButton:
				p->drawPixmap(0, 0, down ? *pressedHelpButtonIcon : isMouseOver ? *mouseOverHelpButtonIcon : *helpButtonIcon);
				break;
			case MinButton:
				p->drawPixmap(0, 0, down ? *pressedMinButtonIcon : isMouseOver ? *mouseOverMinButtonIcon : *minButtonIcon);
				break;
			case MaxButton:
				p->drawPixmap(0, 0, down ? *pressedMaxButtonIcon : isMouseOver ? *mouseOverMaxButtonIcon : *maxButtonIcon);
				break;
			case OnAllDesktopsButton:
				p->drawPixmap(0, 0, down ? *pressedOnAllDesktopsButtonIcon : isMouseOver ? *mouseOverOnAllDesktopsButtonIcon : *onAllDesktopsButtonIcon);
				break;
			case ShadeButton:
				p->drawPixmap(0, 0, down ? *pressedShadeButtonIcon : isMouseOver ? *mouseOverShadeButtonIcon : *shadeButtonIcon);
				break;
			case AboveButton:
				p->drawPixmap(0, 0, down ? *pressedAboveButtonIcon : isMouseOver ? *mouseOverAboveButtonIcon : *aboveButtonIcon);
				break;
			case BelowButton:
				p->drawPixmap(0, 0, down ? *pressedBelowButtonIcon : isMouseOver ? *mouseOverBelowButtonIcon : *belowButtonIcon);
				break;
			case MenuButton:
			default:
				break;
		}
	}
	else {
		if((client->titleBarMouseOver && type() != MenuButton) || (decoration()->isActive() && !showInactiveButtons && type() != MenuButton)) {
			p->drawPixmap(0, 0, *buttonPix);
		}
	}
}



void DominoButton::enterEvent(TQEvent */*e*/)
{
	
	if(!client->isActive() && !showInactiveButtons)
		client->titleBarMouseOver = true;
	
	isMouseOver=true;
	repaint(false);
}


void DominoButton::leaveEvent(TQEvent */*e*/)
{
	isMouseOver=false;
	repaint(false);
	client->titleBarMouseOver = false;
}


// ===========================================================================

DominoClient::DominoClient( KDecorationBridge* b, KDecorationFactory* f )
	: KCommonDecoration( b, f )
{
}

DominoClient::~DominoClient()
{
	
	delete titleBar;
	delete borderTopLeft;
	delete borderTopRight;
	delete borderBottomLeft;
	delete borderBottomRight;
	delete borderLeft;
	delete borderRight;
	delete borderBottom;
}

TQString DominoClient::visibleName() const
{
	return "Domino";
}

TQString DominoClient::defaultButtonsLeft() const
{
	return "MF";
}

TQString DominoClient::defaultButtonsRight() const
{
	return "HIAX";
}

bool DominoClient::decorationBehaviour(DecorationBehaviour behaviour) const
{
	switch (behaviour) {
		case DB_MenuClose:
			return true;
		case DB_WindowMask:
			return true;
		case DB_ButtonHide:
			return true;
		default:
			return KCommonDecoration::decorationBehaviour(behaviour);
	}
}

int DominoClient::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *btn) const
{
	bool maximized = maximizeMode() == MaximizeFull && !options()->moveResizeMaximizedWindows();
	
	switch (lm) {
		case LM_BorderLeft:
		case LM_BorderRight:
			if(respectWindowState && maximized)
				return 0;
			return borderWidth;

		case LM_BorderBottom: {
			if(respectWindowState && maximized)
				return 0;
			return bottomBorderHeight; // = 8
		}
			
		case LM_TitleEdgeLeft:
		case LM_TitleEdgeRight:
			return borderWidth + 3;

		case LM_TitleEdgeTop:
			return titleEdgeTop; // = 3

		case LM_TitleEdgeBottom:
			return titleEdgeBottom; // = 1

		case LM_TitleBorderLeft:
		case LM_TitleBorderRight:
			return 1;

		case LM_TitleHeight: {
			return titleHeight;
		}

		case LM_ButtonWidth:
			return 16; // pixmap width
			
		case LM_ButtonHeight:
			return titleHeight;

		case LM_ButtonSpacing:
			return 3;

		case LM_ExplicitButtonSpacer:
			return 2;

		default:
			return KCommonDecoration::layoutMetric(lm, respectWindowState, btn);
	}
}

KCommonDecorationButton *DominoClient::createButton(ButtonType type)
{
	switch (type) {
		case MenuButton: {
			DominoButton* menu = new DominoButton(MenuButton, this, "menu");
			menuButton = menu;
			connect(menu, SIGNAL(destroyed()), this, SLOT(menuButtonDestroyed()));
			return menu;
			break;
		}
		case OnAllDesktopsButton: {
			return new DominoButton(OnAllDesktopsButton, this, "on_all_desktops");
		}
		case HelpButton: {
			return new DominoButton(HelpButton, this, "help");
		}
		case MinButton: {
			return new DominoButton(MinButton, this, "minimize");
		}
		case MaxButton: {
			return new DominoButton(MaxButton, this, "maximize");
		}
		case CloseButton: {
			return new DominoButton(CloseButton, this, "close");
		}
		case AboveButton: {
			return new DominoButton(AboveButton, this, "above");
		}
		case BelowButton: {
			return new DominoButton(BelowButton, this, "below");
		}
		case ShadeButton: {
			return new DominoButton(ShadeButton, this, "shade");
		}
		default:
			return 0;
	}
}


void DominoClient::init()
{
	
	menuButton = 0;
	globalMouseTracking = false;
	titleBarMouseOver = false;
	TQWidget* w = new TQWidget(KDecoration::initialParentWidget(), "clientMainWidget", WNoAutoErase|WStaticContents);
	setMainWidget(w);
	
	widget()->setBackgroundMode(NoBackground);
	widget()->installEventFilter(this);
	createLayout();

	KCommonDecoration::reset(SettingButtons);
	iconChange();
	connect(this, SIGNAL(keepAboveChanged(bool) ), SLOT(keepAboveChange(bool) ) );
	connect(this, SIGNAL(keepBelowChanged(bool) ), SLOT(keepBelowChange(bool) ) );
}

void DominoClient::createLayout()
{
	
	int titleBarHeight = titleHeight+titleEdgeTop+titleEdgeBottom;
	
	mainlayout = new TQGridLayout(widget(), 3, 3, 0);
	titleBar = new TitleBar(widget(), "titlebar");
	titleBar->client = this;
	titleBar->setMouseTracking(true);
	
	borderTopLeft = new TQWidget(widget(), "borderTopLeft", TQt::WNoAutoErase);
	borderTopLeft->setMouseTracking(true);
	borderTopRight = new TQWidget(widget(), "borderTopRight", TQt::WNoAutoErase);
	borderTopRight->setMouseTracking(true);
	borderBottomLeft = new TQWidget(widget(), "borderBottomLeft", TQt::WNoAutoErase);
	borderBottomLeft->setMouseTracking(true);
	borderBottomRight = new TQWidget(widget(), "borderBottomRight", TQt::WNoAutoErase);
	borderBottomRight->setMouseTracking(true);
	borderLeft = new TQWidget(widget(), "borderLeft", TQt::WNoAutoErase);
	borderLeft->setMouseTracking(true);
	borderRight = new TQWidget(widget(), "borderRight", TQt::WNoAutoErase);
	borderRight->setMouseTracking(true);
	borderBottom = new TQWidget(widget(), "borderBottom", TQt::WNoAutoErase);
	borderBottom->setMouseTracking(true);
	
	
	titleBar->setFixedHeight(titleBarHeight);
	titleBar->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Fixed);
	borderTopLeft->setFixedSize(borderWidth, titleBarHeight);
	borderTopRight->setFixedSize(borderWidth, titleBarHeight);
	
	borderLeft->setFixedWidth(borderWidth);
	borderLeft->setSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Expanding);
	borderRight->setFixedWidth(borderWidth);
	borderRight->setSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Expanding);
	
	borderBottomLeft->setFixedSize(borderWidth, bottomBorderHeight);
	borderBottomRight->setFixedSize(borderWidth, bottomBorderHeight);
	borderBottom->setFixedHeight(bottomBorderHeight);
	borderBottom->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Fixed);
	
	mainlayout->addWidget(titleBar, 0,1);
	mainlayout->addWidget(borderTopLeft, 0,0);
	mainlayout->addWidget(borderTopRight, 0,2);
	
	mainlayout->addWidget(borderLeft, 1,0);
	mainlayout->addItem(new TQSpacerItem(1, 1, TQSizePolicy::Expanding, TQSizePolicy::Expanding));
	mainlayout->addWidget(borderRight, 1,2);
	
	mainlayout->addWidget(borderBottomLeft, 2,0);
	mainlayout->addWidget(borderBottom, 2,1);
	mainlayout->addWidget(borderBottomRight, 2,2);
	
	setPixmaps();
	
}

void DominoClient::setPixmaps()
{
	borderTopLeft->setErasePixmap(*borderTopLeftPix);
	borderTopRight->setErasePixmap(*borderTopRightPix);
	borderBottomLeft->setErasePixmap(*borderBottomLeftPix);
	borderBottomRight->setErasePixmap(*borderBottomRightPix);
	borderLeft->setErasePixmap(*borderLeftPix);
	borderRight->setErasePixmap(*borderRightPix);
	borderBottom->setErasePixmap(*borderBottomPix);
	
	borderTopLeft->erase();
	borderTopRight->erase();
	borderBottomLeft->erase();
	borderBottomRight->erase();
	borderLeft->erase();
	borderRight->erase();
	borderBottom->erase();
}

void DominoClient::reset( unsigned long changed)
{
	
	widget()->repaint();
	KCommonDecoration::reset(changed);
	KCommonDecoration::resetButtons();
	updateCaption();
	setPixmaps();
	iconChange();
}


void DominoClient::updateMask()
{
	if(maximizeMode() == MaximizeFull && !options()->moveResizeMaximizedWindows()) {
		clearMask();
		return;
	}
	TQRect r(widget()->rect());
	
	TQRegion mask(r.x()+5, r.y(), r.width()-10, r.height());
	mask += TQRect(r.x()+3, r.y()+1, r.width()-6, r.height()-2);
	mask += TQRect(r.x()+2, r.y()+2, r.width()-4, r.height()-4);
	mask += TQRect(r.x()+1, r.y()+3, r.width()-2, r.height()-6);
	mask += TQRect(r.x(), r.y()+5, r.width(), r.height()-10);
	setMask(mask);
	
}

void DominoClient::updateCaption()
{
	TQRect r(titleBar->rect());
	
	TQPixmap* titleBar_pix = new TQPixmap(r.size());
	TQPainter painter(titleBar_pix);
	painter.drawTiledPixmap(0, 0, r.width(), r.height(), *titleBarPix);
	
	int lw = buttonsLeftWidth()+3;
	int rw = buttonsRightWidth();

	painter.setFont(options()->font(true,false));
	TQFontMetrics fm = painter.fontMetrics();
	int captionWidth = fm.width(caption());
	int titleWidth = titleBar->width()-(lw+rw);
	
	
	TQRect re(titleWidth > captionWidth ? (titleWidth-captionWidth)/2+lw : lw, 0, titleWidth, r.height());
	painter.setClipRect(re);
	painter.setPen(options()->color(KDecorationDefines::ColorFont, isActive()));
	painter.drawText(TQRect(lw, r.y(), r.width()-(rw+lw), r.height()), titleWidth > captionWidth ? TQt::AlignCenter : TQt::AlignLeft|TQt::AlignVCenter, caption());
	painter.end();
	
	titleBar->setErasePixmap(*titleBar_pix);
	titleBar->erase();
	delete titleBar_pix;
}

void DominoClient::activeChange()
{
	updateButtons();
	updateCaption();
}

void DominoClient::iconChange()
{
	if(menuButton) {
		TQPixmap pix(*buttonHidePix);
		TQPixmap icon = KDecoration::icon().pixmap(TQIconSet::Small, TQIconSet::Normal);
		if(!icon.isNull())
			bitBlt(&pix, 0, 0, &icon, 0, 0, -1, -1, TQt::CopyROP);
		menuButton->setErasePixmap(pix);
	}
	
}

void DominoClient::menuButtonDestroyed()
{
	menuButton = 0;
}

void DominoClient::slotShade()
{
	setShade( !isSetShade() );
}


void DominoClient::borders( int& left, int& right, int& top, int& bottom ) const
{
	
	left = layoutMetric(LM_BorderLeft);
	right = layoutMetric(LM_BorderRight);
	bottom = layoutMetric(LM_BorderBottom);
	top = layoutMetric(LM_TitleHeight) +
			layoutMetric(LM_TitleEdgeTop) +
			layoutMetric(LM_TitleEdgeBottom);
	
	widget()->layout()->activate();
	
}

void DominoClient::shadeChange()
{
	if(isSetShade()) {
		mainlayout->remove(borderLeft);
		mainlayout->remove(borderRight);
		borderLeft->resize(borderLeft->width(), 0);
		borderRight->resize(borderLeft->width(), 0);
	}
	else {
		mainlayout->addWidget(borderLeft,1,0);
		mainlayout->addWidget(borderRight,1,2);
	}
	
	widget()->layout()->activate();
	
}

void DominoClient::resize( const TQSize& s )
{
	widget()->resize( s );
	if(maximizeMode() == MaximizeFull && !options()->moveResizeMaximizedWindows()) {
		borderLeft->hide();
		borderRight->hide();
		borderTopLeft->hide();
		borderTopRight->hide();
		borderBottomLeft->hide();
		borderBottomRight->hide();
	}
	else if(borderLeft->isHidden()) {
		borderLeft->show();
		borderRight->show();
		borderTopLeft->show();
		borderTopRight->show();
		borderBottomLeft->show();
		borderBottomRight->show();
	}
}


void DominoClient::resizeEvent( TQResizeEvent* ev )
{
	
	if (!Domino_initialized || ev->size() == ev->oldSize())
		return;
	KCommonDecoration::resizeEvent(ev); // which calls calcHiddenButtons()
	
	updateMask();
	updateCaption();
}
void DominoClient::updateWindowShape()
{
}

void DominoClient::showEvent(TQShowEvent *)
{
}

void DominoClient::paintEvent( TQPaintEvent* )
{
}

bool DominoClient::eventFilter(TQObject*, TQEvent* e)
{
	switch(e->type()) {
		case TQEvent::Resize:
			resizeEvent(static_cast<TQResizeEvent*>(e));
			return true;
		case TQEvent::ApplicationPaletteChange:
			return false;
		case TQEvent::Paint:
			paintEvent(static_cast<TQPaintEvent*>(e));
			return true;
		case TQEvent::MouseButtonDblClick:
			mouseDoubleClickEvent(static_cast<TQMouseEvent*>(e));
			return true;
		case TQEvent::Wheel:
			if(titleBar->hasMouse() || isSetShade())
				wheelEvent(static_cast<TQWheelEvent*>(e));
			return true;
		case TQEvent::MouseButtonPress:
			processMousePressEvent(static_cast<TQMouseEvent*>(e));
			return true;
		case TQEvent::Show:
			return true;
		case TQEvent::Enter:
			updateButtons();
			return true;
		case TQEvent::Leave:
			if(globalMouseTracking && !showInactiveButtons) {
				globalMouseTracking = false;
				tqApp->setGlobalMouseTracking( false );
				tqApp->removeEventFilter(titleBar);
				titleBarMouseOver = false;
			}
			updateButtons();
			return true;
		default:
			return false;
	}
	return false;
}


void TitleBar::enterEvent(TQEvent*)
{
	if(!client->isActive() && !showInactiveButtons) {
		if(!client->globalMouseTracking) {
			client->globalMouseTracking = true;
			tqApp->setGlobalMouseTracking( true );
			tqApp->installEventFilter(this);
			client->titleBarMouseOver = true;
			client->updateButtons();
		}
	}
}


bool TitleBar::eventFilter(TQObject*o, TQEvent* e) {
	
	if(e->type() == TQEvent::MouseMove && !showInactiveButtons && !client->isActive()) {
		TQPoint pos = ((TQMouseEvent*)e)->pos();
		if((dynamic_cast<TQWidget*>(o) && geometry().contains(pos)) || dynamic_cast<TQButton*>(o)) {
			client->titleBarMouseOver = true;
		}
		else {
			client->titleBarMouseOver = false;
			client->updateButtons();
		}
	}
	return false;
}



/////////////

void renderGradient(TQPainter *painter, TQRect &rect,
		    TQColor &c1, TQColor &c2, const char* /*name*/)
{
	if((rect.width() <= 0)||(rect.height() <= 0))
		return;
	
	TQPixmap *result;
	
	result = new TQPixmap(10, rect.height());
	TQPainter p(result);
	
	int r_h = result->rect().height();
	int r_x, r_y, r_x2, r_y2;
	result->rect().coords(&r_x, &r_y, &r_x2, &r_y2);

	int rDiff, gDiff, bDiff;
	int rc, gc, bc;

	int y;

	rDiff = ( c2.red())	  - (rc = c1.red());
	gDiff = ( c2.green()) - (gc = c1.green());
	bDiff = ( c2.blue())  - (bc = c1.blue());

	int rl = rc << 16;
	int gl = gc << 16;
	int bl = bc << 16;

	int rdelta = ((1<<16) / r_h) * rDiff;
	int gdelta = ((1<<16) / r_h ) * gDiff;
	int bdelta = ((1<<16) / r_h ) * bDiff;

	
	for ( y = 0; y < r_h; y++ ) {
		rl += rdelta;
		gl += gdelta;
		bl += bdelta;
		p.setPen(TQColor(rl>>16, gl>>16, bl>>16));
		p.drawLine(r_x, r_y+y, r_x2, r_y+y);
	}
	p.end();

	// draw the result...
	painter->drawTiledPixmap(rect, *result);
	
}


TQColor alphaBlendColors(const TQColor &bgColor, const TQColor &fgColor, const int a)
{

	TQRgb rgb = bgColor.rgb();
	TQRgb rgb_b = fgColor.rgb();
	int alpha = a;
	if(alpha>255) alpha = 255;
	if(alpha<0) alpha = 0;
	int inv_alpha = 255 - alpha;

	TQColor result  = TQColor( tqRgb(tqRed(rgb_b)*inv_alpha/255 + tqRed(rgb)*alpha/255,
				 tqGreen(rgb_b)*inv_alpha/255 + tqGreen(rgb)*alpha/255,
				 tqBlue(rgb_b)*inv_alpha/255 + tqBlue(rgb)*alpha/255) );

	return result;
}

TQImage tintImage(const TQImage &img, const TQColor &tintColor) {
	
	TQImage *result = new TQImage(img.width(), img.height(), 32, 0, TQImage::IgnoreEndian);
	unsigned int *data = (unsigned int*) img.bits();
	unsigned int *resultData = (unsigned int*) result->bits();
	result->setAlphaBuffer( true );
	int alpha;
	int total = img.width()*img.height();
	for ( int current = 0 ; current < total ; ++current ) {
		alpha = tqAlpha( data[ current ] );
		resultData[ current ] = tqRgba( tintColor.red(), tintColor.green(), tintColor.blue(), alpha );
	}
	return *result;
}



} // namespace

// Extended KWin plugin interface
extern "C" KDE_EXPORT KDecorationFactory* create_factory()
{
	return new Domino::DominoHandler();
}

#include "dominoclient.moc"