summaryrefslogtreecommitdiffstats
path: root/client/polyester.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'client/polyester.cpp')
-rwxr-xr-xclient/polyester.cpp1858
1 files changed, 1858 insertions, 0 deletions
diff --git a/client/polyester.cpp b/client/polyester.cpp
new file mode 100755
index 0000000..91c06fe
--- /dev/null
+++ b/client/polyester.cpp
@@ -0,0 +1,1858 @@
+//////////////////////////////////////////////////////////////////////////////
+// polyester.cc
+// -------------------
+// Polyester window decoration for KDE
+// Copyright (c) 2006 Marco Martin
+// -------------------
+// derived from Smooth Blend
+// Copyright (c) 2005 Ryan Nickell
+// -------------------
+// Shadow engine from Plastik decoration
+// Copyright (C) 2003 Sandro Giessl <[email protected]>
+// -------------------
+// Please see the header file for copyright and license information.
+//////////////////////////////////////////////////////////////////////////////
+
+
+#include <tdeconfig.h>
+#include <tdeversion.h>
+#include <tdeglobal.h>
+#include <tdeglobalsettings.h>
+#include <tdelocale.h>
+#include <kpixmap.h>
+#include <kimageeffect.h>
+#include <kpixmapeffect.h>
+#include <kpixmap.h>
+
+#include <tqbitmap.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqpainter.h>
+#include <tqtooltip.h>
+#include <tqtimer.h>
+#include <tqapplication.h>
+#include <tqsettings.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "polyester.h"
+#include "buttons.h"
+#include "shadow.h"
+#include "../style/misc.h"
+
+using namespace polyester;
+
+//////////////////////////////////////////////////////////////////////////////
+// polyesterFactory Class
+//////////////////////////////////////////////////////////////////////////////
+polyesterFactory* factory=NULL;
+
+bool polyesterFactory::initialized_ = false;
+TQt::AlignmentFlags polyesterFactory::titlealign_ = TQt::AlignHCenter;
+int polyesterFactory::contrast_ = 6;
+bool polyesterFactory::cornerflags_ = true;
+int polyesterFactory::titlesize_ = 22;
+int polyesterFactory::buttonsize_ = 18;
+bool polyesterFactory::squareButton_ = false;
+int polyesterFactory::framesize_ = 2;
+int polyesterFactory::roundsize_ = 50;
+int polyesterFactory::titleBarStyle_ = 0;
+int polyesterFactory::buttonStyle_ = 1;
+bool polyesterFactory::titleshadow_ = true;
+bool polyesterFactory::nomodalbuttons = false;
+bool polyesterFactory::lightBorder_ = true;
+bool polyesterFactory::animatebuttons = true;
+int polyesterFactory::btnComboBox = 0;
+bool polyesterFactory::menuClose = false;
+
+// global constants
+static const int TOPMARGIN = 4; // do not change
+static const int DECOHEIGHT = 4; // do not change
+static const int SIDETITLEMARGIN = 2;
+// Default button layout
+const char default_left[] = "M";
+const char default_right[] = "HIAX";
+
+static const uint TIMERINTERVAL = 25; // msec
+static const uint ANIMATIONSTEPS = 20;
+
+extern "C" KDE_EXPORT KDecorationFactory* create_factory() {
+ return new polyester::polyesterFactory();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// polyesterFactory()
+// ----------------
+// Constructor
+
+polyesterFactory::polyesterFactory() {
+ readConfig();
+ initialized_ = true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// ~polyesterFactory()
+// -----------------
+// Destructor
+
+polyesterFactory::~polyesterFactory() {
+ initialized_ = false;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// createDecoration()
+// -----------------
+// Create the decoration
+
+KDecoration* polyesterFactory::createDecoration(KDecorationBridge* b) {
+ return new polyesterClient(b, this);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// reset()
+// -------
+// Reset the handler. Returns true if decorations need to be remade, false if
+// only a repaint is necessary
+
+bool polyesterFactory::reset(unsigned long changed) {
+ // read in the configuration
+ initialized_ = false;
+ bool confchange = readConfig();
+ initialized_ = true;
+
+ if (confchange ||
+ (changed & (SettingDecoration | SettingButtons | SettingBorder))) {
+ return true;
+ } else {
+ resetDecorations(changed);
+ return false;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// readConfig()
+// ------------
+// Read in the configuration file
+
+bool polyesterFactory::readConfig() {
+ // create a config object
+ TDEConfig config("twinpolyesterrc");
+ config.setGroup("General");
+
+ // grab settings
+ TQString value = config.readEntry("TitleAlignment", "AlignHCenter");
+ if (value == "AlignLeft")
+ titlealign_ = TQt::AlignLeft;
+ else if (value == "AlignHCenter")
+ titlealign_ = TQt::AlignHCenter;
+ else if (value == "AlignRight")
+ titlealign_ = TQt::AlignRight;
+
+ TQSettings globalSettings;
+ contrast_ = globalSettings.readNumEntry("/TQt/KDE/contrast", 6);
+ cornerflags_ = config.readBoolEntry("RoundCorners", true);
+ titlesize_ = config.readNumEntry("TitleSize",20);
+ titleBarStyle_ = config.readNumEntry("TitleBarStyle", 0);
+ buttonStyle_ = config.readNumEntry("ButtonStyle", 1);
+
+ buttonsize_ = config.readNumEntry("ButtonSize",18);
+ squareButton_ = config.readBoolEntry("SquareButton", false);
+ framesize_ = config.readNumEntry("FrameSize",2);
+ roundsize_ = config.readNumEntry("RoundPercent",50);
+
+
+ titleshadow_ = config.readBoolEntry("TitleShadow", true);
+ lightBorder_ = config.readBoolEntry("LightBorder", true);
+ animatebuttons = config.readBoolEntry("AnimateButtons", true);
+ nomodalbuttons = config.readBoolEntry("NoModalButtons", false);
+ btnComboBox = config.readNumEntry("ButtonComboBox", 0);
+ menuClose = config.readBoolEntry("CloseOnMenuDoubleClick");
+
+ if(buttonsize_ > titlesize_ - framesize_)
+ {
+ buttonsize_ = titlesize_-framesize_;
+ }
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// polyesterButton Class
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+// polyesterButton()
+// ---------------
+// Constructor
+polyesterButton::polyesterButton(polyesterClient *parent, const char *name, const TQString& tip, ButtonType type, int button_size, bool squareButton, bool toggle): TQButton(parent->widget(), name),
+ client_(parent),
+ type_(type),
+ size_(button_size),
+ deco_(0),
+ lastmouse_(NoButton),
+ buttonImgActive_created(false),
+ buttonImgInactive_created(false),
+ hover_(false)
+{
+ setBackgroundMode(NoBackground);
+
+ int buttonWidth = button_size;
+ if( squareButton )
+ buttonProportions_ = 1;
+ else
+ {
+ buttonProportions_ = sqrt(2);
+ buttonWidth = (int)round(button_size*buttonProportions_);
+ //makes always centered icons
+ if( buttonWidth % 2 != 0 )
+ buttonWidth++;
+ }
+
+ setFixedSize( buttonWidth, button_size);
+ setCursor(arrowCursor);
+ TQToolTip::add(this, tip);
+ setToggleButton(toggle);
+ //button animation setup
+ animTmr = new TQTimer(this);
+ connect(animTmr, TQ_SIGNAL(timeout() ), this, TQ_SLOT(animate() ) );
+ connect(this, TQ_SIGNAL(pressed() ), this, TQ_SLOT(buttonClicked() ) );
+ connect(this, TQ_SIGNAL(released() ), this, TQ_SLOT(buttonReleased() ) );
+ animProgress = 0;
+ m_clicked=false;
+}
+
+polyesterButton::~polyesterButton() {
+ if ( deco_ )
+ delete deco_;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// sizeHint()
+// ----------
+// Return size hint
+
+TQSize polyesterButton::sizeHint() const {
+ return TQSize(size_, size_);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// buttonClicked()
+// ----------
+// Button animation progress reset so we don't get any leave event animation
+// when the mouse is still pressed
+void polyesterButton::buttonClicked() {
+ m_clicked=true;
+ animProgress=0;
+}
+void polyesterButton::buttonReleased() {
+ //This doesn't work b/c a released() TQ_SIGNAL is thrown when a leaveEvent occurs
+ //m_clicked=false;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// animate()
+// ----------
+// Button animation timing
+void polyesterButton::animate() {
+ animTmr->stop();
+ if (!::factory->animateButtons() )
+ return;
+
+ if(hover_) {
+ if(animProgress < ANIMATIONSTEPS) {
+ animProgress++;
+ animTmr->start(TIMERINTERVAL, true); // single-shot
+ }
+ } else {
+ if(animProgress > 0) {
+ animProgress--;
+ animTmr->start(TIMERINTERVAL, true); // single-shot
+ }
+ }
+ repaint(false);
+}
+//////////////////////////////////////////////////////////////////////////////
+// enterEvent()
+// ------------
+// Mouse has entered the button
+
+void polyesterButton::enterEvent(TQEvent *e) {
+ // we wanted to pass on the event
+ TQButton::enterEvent(e);
+ // we want to do mouseovers, so keep track of it here
+ hover_=true;
+ if(!m_clicked)
+ {
+ animate();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// leaveEvent()
+// ------------
+// Mouse has left the button
+
+void polyesterButton::leaveEvent(TQEvent *e) {
+ // we wanted to pass on the event
+ TQButton::leaveEvent(e);
+ // we want to do mouseovers, so keep track of it here
+ hover_=false;
+ if(!m_clicked)
+ {
+ animate();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// mousePressEvent()
+// -----------------
+// Button has been pressed
+
+void polyesterButton::mousePressEvent(TQMouseEvent* e) {
+ lastmouse_ = e->button();
+
+ // translate and pass on mouse event
+ int button = LeftButton;
+ if ((type_ != ButtonMax) && (e->button() != LeftButton)) {
+ button = NoButton; // middle & right buttons inappropriate
+ }
+ TQMouseEvent me(e->type(), e->pos(), e->globalPos(),
+ button, e->state());
+ TQButton::mousePressEvent(&me);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// mouseReleaseEvent()
+// -----------------
+// Button has been released
+
+void polyesterButton::mouseReleaseEvent(TQMouseEvent* e) {
+ lastmouse_ = e->button();
+
+ // translate and pass on mouse event
+ int button = LeftButton;
+ if ((type_ != ButtonMax) && (e->button() != LeftButton)) {
+ button = NoButton; // middle & right buttons inappropriate
+ }
+ TQMouseEvent me(e->type(), e->pos(), e->globalPos(), button, e->state());
+ TQButton::mouseReleaseEvent(&me);
+ if(m_clicked)
+ {
+ m_clicked=false;
+ }
+}
+
+void polyesterButton::setOn(bool on)
+{
+ TQButton::setOn(on);
+}
+
+void polyesterButton::setDown(bool on)
+{
+ TQButton::setDown(on);
+}
+
+//////////////////////////////////////////////////////////
+// getButtonImage()
+// ----------------
+// get the button TQImage based on type and window mode
+TQImage polyesterButton::getButtonImage(ButtonType type)
+{
+ TQImage finalImage;
+ switch(type) {
+ case ButtonClose:
+ finalImage = uic_findImage( "close.png" );
+ break;
+ case ButtonHelp:
+ finalImage = uic_findImage( "help.png" );
+ break;
+ case ButtonMin:
+ finalImage = uic_findImage( "minimize.png" );
+ break;
+ case ButtonMax:
+ if(client_->maximizeMode() == KDecorationDefines::MaximizeFull)
+ {
+ finalImage = uic_findImage( "restore.png" );
+ }
+ else
+ {
+ finalImage = uic_findImage( "maximize.png" );
+ }
+ break;
+ case ButtonSticky:
+ if(client_->isOnAllDesktops())
+ {
+ finalImage = uic_findImage( "circle2.png" );
+ }
+ else
+ {
+ finalImage = uic_findImage( "circle.png" );
+ }
+ break;
+ case ButtonShade:
+ if(client_->isShade())
+ {
+ finalImage = uic_findImage( "unsplat.png" );
+ }
+ else
+ {
+ finalImage = uic_findImage( "splat.png" );
+ }
+ break;
+ case ButtonAbove:
+ if(client_->keepAbove())
+ {
+ finalImage = uic_findImage( "keep_above_lit.png" );
+ }
+ else
+ {
+ finalImage = uic_findImage( "keep_above.png" );
+ }
+ break;
+ case ButtonBelow:
+ if(client_->keepBelow())
+ {
+ finalImage = uic_findImage( "keep_below_lit.png" );
+ }
+ else
+ {
+ finalImage = uic_findImage( "keep_below.png" );
+ }
+ break;
+ default:
+ finalImage = uic_findImage( "splat.png" );
+ break;
+ }
+ if(tqGray(KDecoration::options()->color(KDecoration::ColorButtonBg, client_->isActive()).rgb()) < 150)
+ finalImage.invertPixels();
+
+ return finalImage;
+}
+
+//////////////////////////////////////////////////////////
+// drawButton()
+// -------------------------
+// draw the pixmap button
+
+void polyesterButton::drawButton( TQPainter *painter ) {
+ if ( !polyesterFactory::initialized() )
+ return ;
+
+ int newWidth = width() - 2;
+ int newHeight = height() - 2;
+ int dx = (width() - newWidth) / 2;
+ int dy = (height() - newHeight) / 2;
+ TQImage tmpResult;
+ TQColorGroup group;
+ TQColor redColor(red);
+ bool active = client_->isActive();
+
+ genButtonPix(active);
+
+ TQPixmap backgroundTile = client_->getTitleBarTile(active);
+ group = KDecoration::options()->colorGroup(KDecoration::ColorButtonBg, active);
+
+ //draw the titlebar behind the buttons and app icons
+ if ((client_->maximizeMode()==client_->MaximizeFull) && !KDecoration::options()->moveResizeMaximizedWindows())
+ {
+ painter->drawTiledPixmap(0, 0, width(), height(), backgroundTile, 0, 1);
+ }
+ else
+ {
+ painter->drawTiledPixmap(0, 0, width(), height(), backgroundTile,
+ 0, y()-::factory->frameSize());
+ }
+
+ //the menu button doesn't have a button appearance
+ if (type_ == ButtonMenu)
+ {
+ //slight movement to show the menu button is depressed
+ if (isDown()) {
+ dx++;
+ dy++;
+ }
+ TQPixmap menuButtonPixmap(client_->icon().pixmap(TQIconSet::Small, TQIconSet::Normal));
+ TQImage menuButtonImage(menuButtonPixmap.convertToImage());
+ //draw the menu button the same size as the other buttons
+ //using TQIconSet::Large gives us a 32x32 icon to resize, resizing larger than
+ //that may produce pixilation of the image
+ //painter->setPen(group.background());
+
+ painter->drawImage( dx+(int)round(abs(width()-size_)/2), dy, menuButtonImage.smoothScale(size_-2, newHeight) );
+ return;
+ }
+
+ //build the button image with the icon superimposed to the button
+ TQImage buttonImage = (active?(buttonImgActive):(buttonImgInactive))->copy();
+ KImageEffect::blendOnLower( (int)round(abs(width()-size_)/2), 0,
+ getButtonImage(type_).smoothScale( size_,size_),
+ buttonImage );
+
+ //highlight on a mouse over repaint
+ double factor = animProgress * 0.05;//0.13;
+
+ //do the animation thing
+ if( !isDown() && factor != 0.0 )
+ {
+ tmpResult = buttonImage.copy();
+ //always colorize with a threatening red color the close button
+ if( type_ == ButtonClose)
+ {
+ //tmpResult = KImageEffect::blend( TQColor(180, 50, 50), buttonImage, factor );
+ KImageEffect::desaturate( tmpResult, factor );
+ KImageEffect::channelIntensity( tmpResult, factor/3, KImageEffect::Red );
+ KImageEffect::channelIntensity( tmpResult, -factor/2, KImageEffect::Green );
+ KImageEffect::channelIntensity( tmpResult, -factor/2, KImageEffect::Blue );
+ }
+ else
+ switch(::factory->getBtnComboBox())
+ {
+ //colorize
+ case 0:
+ if( type_ == ButtonMax)
+ {
+ KImageEffect::desaturate( tmpResult, factor );
+ KImageEffect::channelIntensity( tmpResult, -factor/3, KImageEffect::Red );
+ KImageEffect::channelIntensity( tmpResult, factor/2, KImageEffect::Green );
+ KImageEffect::channelIntensity( tmpResult, -factor/3, KImageEffect::Blue );
+ }
+ else if( type_ == ButtonMin)
+ {
+ KImageEffect::desaturate( tmpResult, factor );
+ KImageEffect::channelIntensity( tmpResult, factor/4, KImageEffect::Red );
+ KImageEffect::channelIntensity( tmpResult, factor/4, KImageEffect::Green );
+ KImageEffect::channelIntensity( tmpResult, -factor/2, KImageEffect::Blue );
+ }
+ else if( type_ == ButtonSticky)
+ {
+ KImageEffect::desaturate( tmpResult, factor );
+ KImageEffect::channelIntensity( tmpResult, -factor/3, KImageEffect::Red );
+ KImageEffect::channelIntensity( tmpResult, -factor/3, KImageEffect::Green );
+ KImageEffect::channelIntensity( tmpResult, factor/2, KImageEffect::Blue );
+ }
+ else
+ {
+ KImageEffect::desaturate( tmpResult, factor );
+ KImageEffect::channelIntensity( tmpResult, -factor/2, KImageEffect::Red );
+ KImageEffect::channelIntensity( tmpResult, factor/3, KImageEffect::Green );
+ KImageEffect::channelIntensity( tmpResult, factor/3, KImageEffect::Blue );
+ }
+ break;
+ //intensify
+ case 1:
+ KImageEffect::intensity( tmpResult, factor);
+ break;
+ //fade
+ case 2:
+ KImageEffect::intensity( tmpResult, -factor/2);
+
+ break;
+ }
+ }
+
+ KImageEffect::blendOnLower(tmpResult, TQPoint(1,1), buttonImage, TQRect(1,1,width()-2, height()-2) );
+
+ TQPixmap finalButton = TQPixmap(buttonImage);
+
+ painter->drawPixmap( 0, 0, finalButton );
+}
+
+void polyesterButton::genButtonPix( bool active )
+{
+ if(active && buttonImgActive_created) return;
+ else if(!active && buttonImgInactive_created) return;
+
+ KPixmap tempPixmap;
+ TQPixmap *tempButton = new TQPixmap(width(), height());
+ TQPainter painter(tempButton);
+
+ TQColorGroup group;
+ group = KDecoration::options()->colorGroup(KDecoration::ColorButtonBg, client_->isActive());
+
+ if( ::factory->buttonStyle() == BUTTON_GLASS )
+ tempPixmap.resize(width()-2, (height()/2)-1);
+ else
+ tempPixmap.resize(width()-2, height()-2);
+
+ /*
+ if( ::factory->buttonStyle() != BUTTON_FLAT )
+ {
+ tempPixmap = KPixmapEffect::gradient(tempPixmap,
+ group.background().light(100+(::factory->buttonStyle()!=BUTTON_REVGRADIENT?60:-20)),
+ group.background().light(100+(::factory->buttonStyle()!=BUTTON_GLASS?
+ (::factory->buttonStyle()==BUTTON_REVGRADIENT?
+ 60:-20)
+ :0)),
+ KPixmapEffect::VerticalGradient
+ );
+ }
+ else
+ {
+ tempPixmap = KPixmapEffect::gradient(tempPixmap,
+ group.background(),
+ group.background(),
+ KPixmapEffect::VerticalGradient
+ );
+ }
+*/
+
+ int contrast = ::factory->contrast();
+
+ switch( ::factory->buttonStyle() )
+ {
+ case BUTTON_GRADIENT:
+ tempPixmap = KPixmapEffect::gradient(tempPixmap,
+ group.background().light(105+contrast*8),
+ group.background().dark(100+contrast*2),
+ KPixmapEffect::VerticalGradient
+ );
+ break;
+ case BUTTON_GLASS:
+ tempPixmap = KPixmapEffect::gradient(tempPixmap,
+ group.background().light(105+contrast*8),
+ group.background(),
+ KPixmapEffect::VerticalGradient
+ );
+ break;
+ case BUTTON_REVGRADIENT:
+ tempPixmap = KPixmapEffect::gradient(tempPixmap,
+ group.background().dark(100+contrast*2),
+ group.background().light(105+contrast*8),
+ KPixmapEffect::VerticalGradient
+ );
+ break;
+
+ //case BUTTON_FLAT:
+ default:
+ tempPixmap = KPixmapEffect::gradient(tempPixmap,
+ group.background(),
+ group.background(),
+ KPixmapEffect::VerticalGradient
+ );
+ break;
+ }
+
+ //draw the main area of the buttons
+ //painter.begin(tempButton);
+ painter.drawPixmap(1, 1, tempPixmap);
+
+ //if the button is glass create the second gradient
+ if( ::factory->buttonStyle() == BUTTON_GLASS )
+ {
+ tempPixmap = KPixmapEffect::gradient(tempPixmap,
+ group.background().dark(105+contrast),
+ group.background(),
+ KPixmapEffect::VerticalGradient
+ );
+
+ painter.drawPixmap(1, (height()/2), tempPixmap);
+ }
+
+ //border
+ TQColor borderColor = group.background().dark(160);
+ painter.setPen( borderColor );
+ painter.drawLine(0, 2, 0, height()-3);
+ painter.drawLine(width()-1, 2, width()-1, height()-3);
+ painter.drawLine(2, 0, width()-3, 0);
+ painter.drawLine(2, height()-1, width()-3, height()-1);
+ painter.drawPoint(1, 1);
+ painter.drawPoint(width()-2, 1);
+ painter.drawPoint(1, height()-2);
+ painter.drawPoint(width()-2, height()-2);
+
+ //little 3d effect
+ painter.setPen( group.background().light(140) );
+ painter.drawLine(1, 2, 1, height()-3);
+ painter.drawLine(2, 1, width()-3, 1);
+ if(!::factory->lightBorder())
+ painter.setPen( group.background().dark(110) );
+ painter.drawLine(width()-2, 2, width()-2, height()-3);
+ painter.drawLine(2, height()-2, width()-3, height()-2);
+ painter.end();
+
+ //border antialiasing
+ TQImage *tempAlphaImg = new TQImage( tempButton->convertToImage() );
+ //tempAlphaImg = tempPixmap.convertToImage();
+ tempAlphaImg->setAlphaBuffer(true);
+ int borderRed = borderColor.red();
+ int borderGreen = borderColor.green();
+ int borderBlue = borderColor.blue();
+
+ tempAlphaImg->setPixel(0,0, tqRgba(borderRed, borderGreen , borderBlue, 40));
+ tempAlphaImg->setPixel(width()-1, 0, tqRgba(borderRed, borderGreen , borderBlue, 40));
+ tempAlphaImg->setPixel(0,height()-1, tqRgba(borderRed, borderGreen , borderBlue, 40));
+ tempAlphaImg->setPixel(width()-1,height()-1, tqRgba(borderRed, borderGreen , borderBlue, 40));
+
+ tempAlphaImg->setPixel(0,1, tqRgba(borderRed, borderGreen , borderBlue, 127));
+ tempAlphaImg->setPixel(1,0, tqRgba(borderRed, borderGreen , borderBlue, 127));
+
+ tempAlphaImg->setPixel(width()-2,0, tqRgba(borderRed, borderGreen , borderBlue, 127));
+ tempAlphaImg->setPixel(width()-1,1, tqRgba(borderRed, borderGreen , borderBlue, 127));
+
+ tempAlphaImg->setPixel(0,height()-2, tqRgba(borderRed, borderGreen , borderBlue, 127));
+ tempAlphaImg->setPixel(1,height()-1, tqRgba(borderRed, borderGreen , borderBlue, 127));
+
+ tempAlphaImg->setPixel(width()-1,height()-2, tqRgba(borderRed, borderGreen , borderBlue, 127));
+ tempAlphaImg->setPixel(width()-2,height()-1, tqRgba(borderRed, borderGreen , borderBlue, 127));
+
+
+ if( client_->isActive() )
+ {
+ buttonImgActive = tempAlphaImg;
+ buttonImgActive_created = true;
+ }
+ else
+ {
+ buttonImgInactive = tempAlphaImg;
+ buttonImgInactive_created = true;
+ }
+
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// polyesterClient Class
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+// polyesterClient()
+// ---------------
+// Constructor
+
+polyesterClient::polyesterClient(KDecorationBridge *b, KDecorationFactory *f)
+ : KDecoration(b, f),
+ mainLayout_(0),
+ titleLayout_(0),
+ topSpacer_(0),
+ titleSpacer_(0),
+ leftTitleSpacer_(0), rightTitleSpacer_(0),
+ decoSpacer_(0),
+ leftSpacer_(0), rightSpacer_(0),
+ bottomSpacer_(0), windowSpacer_(0),
+ aCaptionBuffer(0), iCaptionBuffer(0),
+ aTitleBarTile(0), iTitleBarTile(0), aTitleBarTopTile(0), iTitleBarTopTile(0),
+ pixmaps_created(false),
+ //captionBufferDirty(true),
+ closing(false),
+ s_titleHeight(0),
+ s_titleFont(TQFont()),
+ maskDirty(true),
+ aDoubleBufferDirty(true),
+ iDoubleBufferDirty(true)
+ {
+ aCaptionBuffer = new TQPixmap();
+ iCaptionBuffer = new TQPixmap();
+
+ //copying the most used configuration options
+ frameSize = ::factory->frameSize();
+
+ NET::WindowType type = windowType(NET::NormalMask | NET::DesktopMask |
+ NET::DockMask | NET::ToolbarMask |
+ NET::MenuMask | NET::DialogMask|
+ NET::OverrideMask | NET::TopMenuMask |
+ NET::UtilityMask | NET::SplashMask);
+ if( type == NET::Utility || type == NET::Menu || type == NET::Toolbar )
+ {
+ titleSize = (int)((double)::factory->titleSize()/1.2);
+ buttonSize = titleSize - 2;
+ roundedCorners = false;
+ }
+ else
+ {
+ titleSize = ::factory->titleSize();
+ //don't allow buttonSize > titleSize
+ buttonSize = titleSize - 2 < ::factory->buttonSize()?
+ titleSize - 2 :
+ ::factory->buttonSize();
+ roundedCorners = ::factory->roundedCorners();
+ }
+
+ //s_titleFont = isTool()?polyesterFactory::titleFontTool():polyesterFactory::titleFont();
+ s_titleFont = options()->font();
+ s_titleHeight = titleSize;
+ }
+
+//////////////////////////////////////////////////////////////////////////////////
+// ~polyesterClient()
+// --------------------
+// Destructor
+polyesterClient::~polyesterClient() {
+ delete aCaptionBuffer;
+ delete iCaptionBuffer;
+}
+
+void polyesterClient::create_pixmaps() {
+ if(pixmaps_created)
+ return;
+ KPixmap tempPixmap;
+ TQPainter painter;
+
+
+ // active top title bar tile
+ tempPixmap.resize(1, s_titleHeight+frameSize);
+ tempPixmap = KPixmapEffect::gradient(tempPixmap,
+ KDecoration::options()->color(ColorTitleBar, true).light(160),
+ KDecoration::options()->color(ColorTitleBlend, true).light(104),
+ KPixmapEffect::VerticalGradient
+ );
+ // tempPixmap.fill(KDecoration::options()->color(ColorTitleBar, true).light(150));
+ aTitleBarTopTile = new TQPixmap(1, s_titleHeight+frameSize);
+ painter.begin(aTitleBarTopTile);
+ painter.drawPixmap(0, 0, tempPixmap);
+ painter.end();
+
+ // inactive top title bar tile
+ tempPixmap = KPixmapEffect::gradient(tempPixmap,
+ KDecoration::options()->color(ColorTitleBar, false).light(160),
+ KDecoration::options()->color(ColorTitleBlend, false),
+ KPixmapEffect::VerticalGradient
+ );
+ iTitleBarTopTile = new TQPixmap(1, s_titleHeight+frameSize);
+ painter.begin(iTitleBarTopTile);
+ painter.drawPixmap(0, 0, tempPixmap);
+ painter.end();
+
+ // active title bar tile
+ if( ::factory->titleBarStyle() == TITLEBAR_GLASS)
+ tempPixmap.resize(1, ((s_titleHeight+frameSize)/2) - 1 );
+ else
+ tempPixmap.resize(1, s_titleHeight+frameSize);
+
+ TQColor color1;
+ TQColor color2;
+ TQColor glassColor;
+ if( ::factory->titleBarStyle() == TITLEBAR_GLASS )
+ {
+ glassColor = alphaBlendColors( KDecoration::options()->color(ColorTitleBar, true),
+ KDecoration::options()->color(ColorTitleBlend, true),
+ 127 );
+ color1 = glassColor.light(105+::factory->contrast()*4);
+ color2 = glassColor;
+ }
+ else
+ {
+ color1 = KDecoration::options()->color(ColorTitleBar, true);
+ color2 = KDecoration::options()->color(ColorTitleBlend, true);
+ }
+
+ tempPixmap = KPixmapEffect::gradient(tempPixmap,
+ color1,
+ color2,
+ KPixmapEffect::VerticalGradient
+ );
+
+ aTitleBarTile = new TQPixmap(1, s_titleHeight+frameSize);
+ painter.begin(aTitleBarTile);
+ painter.drawPixmap(0, 0, tempPixmap);
+
+ if( ::factory->titleBarStyle() == TITLEBAR_GLASS )
+ {
+ int y = tempPixmap.height();
+ tempPixmap.resize(1, (s_titleHeight+frameSize)-y );
+ tempPixmap = KPixmapEffect::gradient(tempPixmap,
+ glassColor.dark(105+::factory->contrast()),
+ glassColor,
+ KPixmapEffect::VerticalGradient
+ );
+ painter.drawPixmap(0, y, tempPixmap);
+ }
+ // painter.drawPixmap(0, 0, *aTitleBarTopTile);
+ painter.end();
+
+ // inactive title bar tile
+ //de-glassify inactive titlebar
+ if( ::factory->titleBarStyle() == TITLEBAR_GLASS )
+ tempPixmap.resize(1, s_titleHeight+frameSize);
+ tempPixmap = KPixmapEffect::gradient(tempPixmap,
+ KDecoration::options()->color(ColorTitleBar, false),
+ KDecoration::options()->color(ColorTitleBlend, false),
+ KPixmapEffect::VerticalGradient
+ );
+ iTitleBarTile = new TQPixmap(1, s_titleHeight+frameSize);
+ painter.begin(iTitleBarTile);
+ painter.drawPixmap(0, 0, tempPixmap);
+ painter.end();
+
+
+ pixmaps_created = true;
+}
+
+void polyesterClient::delete_pixmaps() {
+ delete aTitleBarTopTile;
+ aTitleBarTopTile = 0;
+
+ delete iTitleBarTopTile;
+ iTitleBarTopTile = 0;
+
+ delete aTitleBarTile;
+ aTitleBarTile = 0;
+
+ delete iTitleBarTile;
+ iTitleBarTile = 0;
+
+ pixmaps_created = false;
+}
+//////////////////////////////////////////////////////////////////////////////
+// init()
+// ------
+// Actual initializer for class
+
+void polyesterClient::init() {
+ createMainWidget( WResizeNoErase | WRepaintNoErase);
+ widget()->installEventFilter(this);
+ handlebar = frameSize < 4 ? 4 - frameSize : 0;
+
+ // for flicker-free redraws
+ widget()->setBackgroundMode(NoBackground);
+
+ create_pixmaps();
+ _resetLayout();
+
+}
+void polyesterClient::_resetLayout()
+{
+ // basic layout:
+ // _______________________________________________________________
+ // | topSpacer |
+ // |_______________________________________________________________|
+ // | leftTitleSpacer | btns | titlebar | bts | rightTitleSpacer |
+ // |_________________|______|_____________|_____|__________________|
+ // | decoSpacer |
+ // |_______________________________________________________________|
+ // | | | |
+ // | | windowWrapper | |
+ // | | | |
+ // |leftSpacer rightSpacer|
+ // |_|___________________________________________________________|_|
+ // | bottomSpacer |
+ // |_______________________________________________________________|
+ //
+ if (!::factory->initialized()) return;
+
+ delete mainLayout_;
+ delete titleLayout_;
+ delete topSpacer_;
+ delete titleSpacer_;
+ delete leftTitleSpacer_;
+ delete rightTitleSpacer_;
+ delete decoSpacer_;
+ delete leftSpacer_;
+ delete rightSpacer_;
+ delete bottomSpacer_;
+ delete windowSpacer_;
+
+ mainLayout_ = new TQVBoxLayout(widget());
+ // title
+ titleLayout_ = new TQHBoxLayout();
+ TQHBoxLayout *windowLayout_ = new TQHBoxLayout();
+
+
+ topSpacer_ = new TQSpacerItem(1, frameSize, TQSizePolicy::Expanding, TQSizePolicy::Fixed);
+ titlebar_ = new TQSpacerItem(1, s_titleHeight,
+ TQSizePolicy::Expanding, TQSizePolicy::Fixed);
+ leftTitleSpacer_ = new TQSpacerItem(frameSize, s_titleHeight,
+ TQSizePolicy::Fixed, TQSizePolicy::Fixed);
+ rightTitleSpacer_ = new TQSpacerItem(frameSize, s_titleHeight,
+ TQSizePolicy::Fixed, TQSizePolicy::Fixed);
+ decoSpacer_ = new TQSpacerItem(1, frameSize, TQSizePolicy::Expanding, TQSizePolicy::Fixed);
+ leftSpacer_ = new TQSpacerItem(frameSize, 1,
+ TQSizePolicy::Fixed, TQSizePolicy::Expanding);
+ rightSpacer_ = new TQSpacerItem(frameSize, 1,
+ TQSizePolicy::Fixed, TQSizePolicy::Expanding);
+ bottomSpacer_ = new TQSpacerItem(1, frameSize,
+ TQSizePolicy::Expanding, TQSizePolicy::Fixed);
+
+ // sizeof(...) is calculated at compile time
+ memset(button, 0, sizeof(polyesterButton *) * ButtonTypeCount);
+
+ // message in preview widget
+ if (isPreview()) {
+ windowLayout_->addWidget(
+ new TQLabel( i18n("<b><center>Polyester Preview</center></b>"), widget() ), 1 );
+ } else {
+ windowLayout_->addItem(new TQSpacerItem(0, 0));
+ }
+
+ // setup titlebar buttons
+ for (int n=0; n<ButtonTypeCount; n++)
+ button[n] = 0;
+ //Deal with the title and buttons
+ titleLayout_->addItem(leftTitleSpacer_);
+
+ if( !::factory->noModalButtons() || !isModal() || isResizable())
+ addButtons(titleLayout_,
+ options()->customButtonPositions() ? options()->titleButtonsLeft() : TQString(default_left),
+ buttonSize);
+ titleLayout_->addItem(titlebar_);
+ if( !::factory->noModalButtons() || !isModal() || isResizable())
+ addButtons(titleLayout_,
+ options()->customButtonPositions() ? options()->titleButtonsRight() : TQString(default_right),
+ buttonSize);
+ titleLayout_->addItem(rightTitleSpacer_);
+
+ //Mid - left side, middle contents and right side
+ TQHBoxLayout * midLayout_ = new TQHBoxLayout();
+ midLayout_->addItem(leftSpacer_);
+ midLayout_->addLayout(windowLayout_);
+ midLayout_->addItem(rightSpacer_);
+
+ //Layout order
+ mainLayout_->addItem( topSpacer_ );
+ mainLayout_->addLayout( titleLayout_ );
+ mainLayout_->addItem( decoSpacer_ );
+ mainLayout_->addLayout( midLayout_ );
+ mainLayout_->addItem( bottomSpacer_ );
+
+ // connections
+ //TODO: probably these two connections could be removed
+ // connect(this, TQ_SIGNAL(keepAboveChanged(bool)), TQ_SLOT(keepAboveChange(bool)));
+ // connect(this, TQ_SIGNAL(keepBelowChanged(bool)), TQ_SLOT(keepBelowChange(bool)));
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// addButtons()
+// ------------
+// Add buttons to title layout
+
+void polyesterClient::addButtons(TQBoxLayout *layout, const TQString& s, int button_size) {
+ TQString tip;
+ if (s.length() > 0) {
+ for (unsigned n=0; n < s.length(); n++) {
+ switch (s[n]) {
+ case 'M': // Menu button
+ if (!button[ButtonMenu]) {
+ button[ButtonMenu] =
+ new polyesterButton(this, "splat.png", i18n("Menu"),ButtonMenu,button_size,::factory->squareButton());
+ connect(button[ButtonMenu], TQ_SIGNAL(pressed()), this, TQ_SLOT(menuButtonPressed()));
+ connect(button[ButtonMenu], TQ_SIGNAL(released()), this, TQ_SLOT(menuButtonReleased()));
+ layout->addWidget(button[ButtonMenu]);
+ if (n < s.length()-1) layout->addSpacing(1);
+ }
+ break;
+
+ case 'S': // Sticky button
+ if (!button[ButtonSticky]) {
+ if (isOnAllDesktops()) {
+ tip = i18n("Un-Sticky");
+ } else {
+ tip = i18n("Sticky");
+ }
+ button[ButtonSticky] =
+ new polyesterButton(this, "circle.png", tip, ButtonSticky, button_size,::factory->squareButton(), true);
+ connect(button[ButtonSticky], TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(toggleOnAllDesktops()));
+ layout->addWidget(button[ButtonSticky]);
+ if (n < s.length()-1) layout->addSpacing(1);
+ }
+ break;
+
+ case 'H': // Help button
+ if ((!button[ButtonHelp]) && providesContextHelp()) {
+ button[ButtonHelp] =
+ new polyesterButton(this, "help.png", i18n("Help"), ButtonHelp, button_size, ::factory->squareButton());
+ connect(button[ButtonHelp], TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(showContextHelp()));
+ layout->addWidget(button[ButtonHelp]);
+ if (n < s.length()-1) layout->addSpacing(1);
+ }
+ break;
+
+ case 'I': // Minimize button
+ if ((!button[ButtonMin]) && isMinimizable()) {
+ button[ButtonMin] =
+ new polyesterButton(this, "minimize.png", i18n("Minimize"), ButtonMin, button_size,::factory->squareButton());
+ connect(button[ButtonMin], TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(minimize()));
+ layout->addWidget(button[ButtonMin]);
+ if (n < s.length()-1) layout->addSpacing(1);
+ }
+ break;
+
+ case 'A': // Maximize button
+ if ((!button[ButtonMax]) && isMaximizable()) {
+ if (maximizeMode() == MaximizeFull) {
+ tip = i18n("Restore");
+ } else {
+ tip = i18n("Maximize");
+ }
+ button[ButtonMax] =
+ new polyesterButton(this, "maximize.png", tip, ButtonMax, button_size,::factory->squareButton(), true);
+ connect(button[ButtonMax], TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(maxButtonPressed()));
+ layout->addWidget(button[ButtonMax]);
+ if (n < s.length()-1) layout->addSpacing(1);
+ }
+ break;
+
+ case 'X': // Close button
+ if ((!button[ButtonClose]) && isCloseable()) {
+ button[ButtonClose] =
+ new polyesterButton(this, "close.png", i18n("Close"), ButtonClose, button_size, ::factory->squareButton());
+ connect(button[ButtonClose], TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(closeWindow()));
+ layout->addWidget(button[ButtonClose]);
+ if (n < s.length()-1) layout->addSpacing(1);
+ }
+ break;
+
+ case 'F': // Above button
+ if ((!button[ButtonAbove])) {
+ button[ButtonAbove] =
+ new polyesterButton(this, "keep_above.png",
+ i18n("Keep Above Others"), ButtonAbove, button_size, ::factory->squareButton(), true);
+ connect(button[ButtonAbove], TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(aboveButtonPressed()));
+ layout->addWidget(button[ButtonAbove]);
+ if (n < s.length()-1) layout->addSpacing(1);
+ }
+ break;
+
+ case 'B': // Below button
+ if ((!button[ButtonBelow])) {
+ button[ButtonBelow] =
+ new polyesterButton(this, "keep_below.png",
+ i18n("Keep Below Others"), ButtonBelow, button_size, ::factory->squareButton(), true);
+ connect(button[ButtonBelow], TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(belowButtonPressed()));
+ layout->addWidget(button[ButtonBelow]);
+ if (n < s.length()-1) layout->addSpacing(1);
+ }
+ break;
+
+ case 'L': // Shade button
+ if ((!button[ButtonShade && isShadeable()])) {
+ if ( isSetShade()) {
+ tip = i18n("Unshade");
+ } else {
+ tip = i18n("Shade");
+ }
+ button[ButtonShade] =
+ new polyesterButton(this, "splat.png", tip, ButtonShade, button_size, ::factory->squareButton(), true);
+ connect(button[ButtonShade], TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(shadeButtonPressed()));
+ layout->addWidget(button[ButtonShade]);
+ if (n < s.length()-1) layout->addSpacing(1);
+ }
+ break;
+
+ case '_': // Spacer item
+ layout->addSpacing(frameSize);
+ }
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// activeChange()
+// --------------
+// window active state has changed
+
+void polyesterClient::activeChange() {
+ for (int n=0; n<ButtonTypeCount; n++)
+ if (button[n])
+ button[n]->reset();
+ maskDirty = true;
+ widget()->repaint(false);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// captionChange()
+// ---------------
+// The title has changed
+
+void polyesterClient::captionChange() {
+ aDoubleBufferDirty = iDoubleBufferDirty = true;
+ widget()->repaint(titlebar_->geometry(), false);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// desktopChange()
+// ---------------
+// Called when desktop/sticky changes
+
+void polyesterClient::desktopChange() {
+ bool d = isOnAllDesktops();
+ if (button[ButtonSticky]) {
+ TQToolTip::remove(button[ButtonSticky]);
+ TQToolTip::add(button[ButtonSticky], d ? i18n("Un-Sticky") : i18n("Sticky"));
+ button[ButtonSticky]->repaint(false);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// iconChange()
+// ------------
+// The title has changed
+
+void polyesterClient::iconChange() {
+ if (button[ButtonMenu]) {
+ button[ButtonMenu]->repaint(false);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// maximizeChange()
+// ----------------
+// Maximized state has changed
+
+void polyesterClient::maximizeChange() {
+ maskDirty = aDoubleBufferDirty = iDoubleBufferDirty = true;
+ bool m = (maximizeMode() == MaximizeFull);
+ if (button[ButtonMax]) {
+ TQToolTip::remove(button[ButtonMax]);
+ TQToolTip::add(button[ButtonMax], m ? i18n("Restore") : i18n("Maximize"));
+ button[ButtonMax]->repaint(false);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// shadeChange()
+// -------------
+// Called when window shading changes
+
+void polyesterClient::shadeChange() {
+ bool s = isSetShade();
+ if (button[ButtonShade]) {
+ TQToolTip::remove(button[ButtonShade]);
+ TQToolTip::add(button[ButtonShade], s ? i18n("Unshade") : i18n("Shade"));
+ button[ButtonShade]->repaint(false);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// TODO: probably these two functions can be removed
+// keepAboveChange()
+// ------------
+// The above state has changed
+
+void polyesterClient::keepAboveChange(bool a) {
+ if (button[ButtonAbove]) {
+ button[ButtonAbove]->setOn(a);
+ button[ButtonAbove]->repaint(false);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// keepBelowChange()
+// ------------
+// The below state has changed
+
+void polyesterClient::keepBelowChange(bool b) {
+ if (button[ButtonBelow]) {
+ button[ButtonBelow]->setOn(b);
+ button[ButtonBelow]->repaint(false);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// borders()
+// ----------
+// Get the size of the borders
+
+void polyesterClient::borders(int &left, int &right, int &top, int &bottom) const {
+
+ if ((maximizeMode()==MaximizeFull) && !options()->moveResizeMaximizedWindows()) {
+ left = right = bottom = 0;
+ top = s_titleHeight;
+
+ // update layout etc.
+ topSpacer_->changeSize(1, -1, TQSizePolicy::Expanding, TQSizePolicy::Fixed);
+ decoSpacer_->changeSize(1, 0, TQSizePolicy::Expanding, TQSizePolicy::Fixed);
+ leftSpacer_->changeSize(left, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding);
+ leftTitleSpacer_->changeSize(left, s_titleHeight, TQSizePolicy::Fixed, TQSizePolicy::Fixed);
+ rightSpacer_->changeSize(right, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding);
+ rightTitleSpacer_->changeSize(right, s_titleHeight, TQSizePolicy::Fixed, TQSizePolicy::Fixed);
+ bottomSpacer_->changeSize(1, bottom, TQSizePolicy::Expanding, TQSizePolicy::Fixed);
+ } else {
+ /*if the borders are rounded add more left and right borders*/
+ if( roundedCorners )
+ left = right = bottom = frameSize*2;
+ else
+ left = right = bottom = frameSize+1;
+ top = titleSize + (frameSize*2);
+
+ // update layout etc.
+ topSpacer_->changeSize(1, frameSize, TQSizePolicy::Expanding, TQSizePolicy::Fixed);
+ decoSpacer_->changeSize(1, frameSize, TQSizePolicy::Expanding, TQSizePolicy::Fixed);
+ leftSpacer_->changeSize(left, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding);
+ leftTitleSpacer_->changeSize(left, s_titleHeight, TQSizePolicy::Fixed, TQSizePolicy::Fixed);
+ rightSpacer_->changeSize(right, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding);
+ rightTitleSpacer_->changeSize(right,s_titleHeight,TQSizePolicy::Fixed, TQSizePolicy::Fixed);
+ bottomSpacer_->changeSize(1, bottom, TQSizePolicy::Expanding, TQSizePolicy::Fixed);
+ }
+ widget()->layout()->activate();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// resize()
+// --------
+// Called to resize the window
+
+void polyesterClient::resize(const TQSize &size) {
+ widget()->resize(size);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// minimumSize()
+// -------------
+// Return the minimum allowable size for this window
+
+TQSize polyesterClient::minimumSize() const {
+ return widget()->minimumSize();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// mousePosition()
+// ---------------
+// Return logical mouse position
+
+KDecoration::Position polyesterClient::mousePosition(const TQPoint &point) const {
+ const int corner = 24;
+ Position pos;
+ int fs = frameSize + handlebar;
+ //int fs = ::factory->frameSize();
+
+ if (point.y() <= fs) {
+ // inside top frame
+ if (point.x() <= corner)
+ pos = PositionTopLeft;
+ else if (point.x() >= (width()-corner))
+ pos = PositionTopRight;
+ else
+ pos = PositionTop;
+ } else if (point.y() >= (height()-fs*2)) {
+ // inside handle
+ if (point.x() <= corner)
+ pos = PositionBottomLeft;
+ else if (point.x() >= (width()-corner))
+ pos = PositionBottomRight;
+ else
+ pos = PositionBottom;
+ } else if (point.x() <= fs ) {
+ // on left frame
+ if (point.y() <= corner)
+ pos = PositionTopLeft;
+ else if (point.y() >= (height()-corner))
+ pos = PositionBottomLeft;
+ else
+ pos = PositionLeft;
+ } else if (point.x() >= width()-fs) {
+ // on right frame
+ if (point.y() <= corner)
+ pos = PositionTopRight;
+ else if (point.y() >= (height()-corner))
+ pos = PositionBottomRight;
+ else
+ pos = PositionRight;
+ } else {
+ // inside the frame
+ pos = PositionCenter;
+ }
+ return pos;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// eventFilter()
+// -------------
+// Event filter
+
+bool polyesterClient::eventFilter(TQObject *obj, TQEvent *e) {
+ if (obj != widget())
+ return false;
+
+ switch (e->type()) {
+ case TQEvent::MouseButtonDblClick: {
+ mouseDoubleClickEvent(static_cast<TQMouseEvent *>(e));
+ return true;
+ }
+ case TQEvent::MouseButtonPress: {
+ processMousePressEvent(static_cast<TQMouseEvent *>(e));
+ return true;
+ }
+ case TQEvent::Wheel: {
+ wheelEvent(static_cast< TQWheelEvent* >(e));
+ return true;
+ }
+ case TQEvent::Paint: {
+ paintEvent(static_cast<TQPaintEvent *>(e));
+ return true;
+ }
+ case TQEvent::Resize: {
+ resizeEvent(static_cast<TQResizeEvent *>(e));
+ return true;
+ }
+ case TQEvent::Show: {
+ showEvent(static_cast<TQShowEvent *>(e));
+ return true;
+ }
+ default: {
+ return false;
+ }
+ }
+
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// mouseDoubleClickEvent()
+// -----------------------
+// Doubleclick on title
+
+void polyesterClient::mouseDoubleClickEvent(TQMouseEvent *e) {
+ if (titlebar_->geometry().contains(e->pos()))
+ titlebarDblClickOperation();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// wheelEvent()
+// -----------------------
+// Mousewheel over titlebar
+
+void polyesterClient::wheelEvent(TQWheelEvent * e) {
+#if TDE_VERSION > TDE_MAKE_VERSION(3,4,3)
+if (titleLayout_->geometry().contains(e->pos()))
+titlebarMouseWheelOperation(e->delta());
+#endif
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// paintEvent()
+// ------------
+// Repaint the window
+
+void polyesterClient::paintEvent(TQPaintEvent* e) {
+ if (!::factory->initialized())
+ {
+ return;
+ }
+
+ //int frameSize = ::factory->frameSize();
+ const uint maxCaptionLength = 200; // truncate captions longer than this!
+ // FIXME: truncate related to window size
+//titlebar_->geometry().width()/(widget()->font().pointSize());
+ TQString captionText(caption());
+ if (captionText.length() > maxCaptionLength) {
+ captionText.truncate(maxCaptionLength);
+ captionText.append(" [...]");
+ }
+
+
+ TQColor blackColor(black);
+ TQColor redColor(red);
+ TQColorGroup group,widgetGroup;
+
+ bool active = isActive();
+
+ //doublebuffering everything to avoid the flicker
+ TQPainter finalPainter(widget());
+
+ //an ugly debug red border used to thest the speed...
+ //finalPainter.fillRect(e->rect(),red);return;
+
+ // mask off which corners we dont want
+ // otherwise recycle the old buffer
+ /*if( doubleBuff.width()>0 )
+ {
+ finalPainter.drawPixmap(0,0, doubleBuff);
+ finalPainter.end();
+ return;
+ }*/
+ if( maskDirty )
+ updateMask();
+ if( !(active?aDoubleBufferDirty:iDoubleBufferDirty) && ((active?activeBuff.width():inactiveBuff.width()) == widget()->width() ))
+ {
+ finalPainter.drawPixmap(0,0, active?activeBuff:inactiveBuff );
+ finalPainter.end();
+ return;
+ }
+
+
+ if( active )
+ activeBuff = TQPixmap(widget()->width(), widget()->height());
+ else
+ inactiveBuff = TQPixmap(widget()->width(), widget()->height());
+
+ TQPainter painter(active?&activeBuff:&inactiveBuff);
+ //get group information first
+ group = options()->colorGroup(KDecoration::ColorTitleBlend, active);
+ widgetGroup = widget()->colorGroup();
+
+ TQRect topRect( topSpacer_->geometry() );
+ TQRect titleRect( titleLayout_->geometry() );
+ TQRect textRect( titlebar_->geometry() );
+ TQRect Rltitle( leftTitleSpacer_->geometry() );
+ TQRect Rrtitle( rightTitleSpacer_->geometry() );
+ TQRect Rdeco( decoSpacer_->geometry() );
+ TQRect Rleft( leftSpacer_->geometry() );
+ TQRect Rright( rightSpacer_->geometry() );
+ TQRect Rbottom( bottomSpacer_->geometry() );
+ TQRect tempRect;
+
+
+ /*
+ if(active)
+ {
+ tqDebug("topRect.y() = %i\tbottom() = %i",topRect.top(),topRect.bottom());
+ tqDebug("titleRect.y() = %i\tbottom() = %i",titleRect.top(),titleRect.bottom());
+ tqDebug("textRect.y() = %i\tbottom() = %i",textRect.top(),textRect.bottom());
+ tqDebug("Rltitle.y() = %i\tbottom() = %i",Rltitle.top(),Rltitle.bottom());
+ tqDebug("Rrtitle.y() = %i\tbottom() = %i",Rrtitle.top(),Rrtitle.bottom());
+ tqDebug("Rdeco.y() = %i\tbottom() = %i",Rdeco.top(),Rdeco.bottom());
+ tqDebug("Rleft.y() = %i\tbottom() = %i",Rleft.top(),Rleft.bottom());
+ tqDebug("Rright.y() = %i\tbottom() = %i",Rright.top(),Rright.bottom());
+ tqDebug("Rbottom.y() = %i\tbottom() = %i",Rbottom.top(),Rbottom.bottom());
+ }
+ */
+
+ // top
+ painter.drawTiledPixmap(topRect, active ? *aTitleBarTopTile:*iTitleBarTopTile);
+ painter.drawTiledPixmap(titleRect.x(),
+ titleRect.y(),
+ titleRect.width(),
+ titleRect.height() + Rdeco.height(),
+ active ? *aTitleBarTile:*iTitleBarTile);
+
+ textRect.setRect(textRect.x()+SIDETITLEMARGIN,
+ textRect.y(),
+ textRect.width()-SIDETITLEMARGIN*2,
+ textRect.height());
+
+
+ //is the title text too long?
+ bool titleTooLong = false;
+ TQt::AlignmentFlags titleAlign = ::factory->titleAlign();
+ const int gradientWidth = 60;
+ if( TQFontMetrics(widget()->font()).width(captionText) > (textRect.width() - gradientWidth) )
+ {
+ titleTooLong = true;
+ titleAlign = TQt::AlignLeft;
+ }
+
+ //we are shadowing title bar text only if there is some text
+ if(::factory->titleShadow() && textRect.width()>0 && textRect.height()>0)
+ {
+ TQPixmap textPixmap;
+ TQPainter tempPainter;
+ TQColor shadowColor;
+
+ textPixmap = TQPixmap(textRect.width(), textRect.height());
+ textPixmap.fill(TQColor(0,0,0));
+ textPixmap.setMask( textPixmap.createHeuristicMask(TRUE) );
+ tempPainter.begin(&textPixmap);
+
+
+ //shadow text
+ tempPainter.setFont(options()->font(isActive(), false));
+
+ tempPainter.setPen(white);
+
+ tempPainter.drawText(1, 1, textRect.width(), textRect.height(),
+ titleAlign | AlignVCenter | TQt::SingleLine,
+ captionText);
+ tempPainter.end();
+
+ // make the cute blurred text shadow from Plastik engine
+ TQImage shadow;
+ ShadowEngine se;
+
+ //deciding if the shadow will be black or white
+ if(tqGray(options()->color(KDecoration::ColorFont, isActive()).rgb()) > 150)
+ shadowColor = blackColor;
+ else
+ shadowColor = white;
+
+ shadow = se.makeShadow(textPixmap, shadowColor);
+
+ painter.drawImage(textRect, shadow);
+
+ }
+
+ // draw title text
+ painter.setFont(options()->font(isActive(), false));
+ painter.setPen(options()->color(KDecoration::ColorFont, isActive()));
+ painter.drawText(textRect,
+ titleAlign | AlignVCenter | TQt::SingleLine,
+ captionText);
+
+ // make title fade out when the caption is too long, veery slow but veery cool :-)
+ if( titleTooLong )
+ {
+ int xGradient = textRect.right()-(gradientWidth-1);
+
+ TQPixmap backLayerP = TQPixmap(gradientWidth, textRect.height());
+ TQPainter layerPainter(&backLayerP);
+ layerPainter.drawTiledPixmap(backLayerP.rect(), active ? *aTitleBarTile:*iTitleBarTile);
+ layerPainter.end();
+ TQImage backLayer = backLayerP.convertToImage();
+
+ TQImage textLayer = ( active ?
+ activeBuff.convertToImage():
+ inactiveBuff.convertToImage()
+ ).copy( xGradient, textRect.y(),
+ gradientWidth, textRect.height()
+ );
+ KImageEffect::blend(backLayer, textLayer, KImageEffect::HorizontalGradient);
+ painter.drawImage(xGradient, textRect.y(), backLayer);
+
+ }
+
+ //left of buttons and title
+ painter.drawTiledPixmap(Rltitle.x(),
+ Rltitle.y(),
+ Rltitle.width(),
+ Rltitle.height()+Rdeco.height(),
+ active ? *aTitleBarTile:*iTitleBarTile);
+
+ //left 3d effect
+ painter.drawTiledPixmap(Rltitle.x(),
+ Rltitle.y(),
+ 2,
+ Rltitle.height()+Rdeco.height(),
+ active ? *aTitleBarTopTile:*iTitleBarTopTile);
+
+ // left mid layout
+ painter.fillRect(Rleft,widgetGroup.background());
+
+ // right of buttons and title
+ painter.drawTiledPixmap(Rrtitle.x(),
+ Rrtitle.y(),
+ Rrtitle.width(),
+ Rrtitle.height()+Rdeco.height(),
+ active ? *aTitleBarTile:*iTitleBarTile);
+ //right 3d effect
+ painter.drawTiledPixmap(width()-2,
+ Rltitle.y(),
+ 2,
+ Rltitle.height()+Rdeco.height(),
+ active ? *aTitleBarTopTile:*iTitleBarTopTile);
+
+ // right mid layout
+ painter.fillRect(Rright,widgetGroup.background());
+
+ // bottom
+ /*
+ if(isShade())
+ {
+ frame.setRect(0,::factory->titleSize()+FRAMESIZE, width(), FRAMESIZE);
+ }
+ else
+ {
+ frame.setRect(0, height() - (FRAMESIZE*2), width(), (FRAMESIZE*2));
+ }
+ */
+ painter.fillRect(Rbottom, KDecoration::options()->color(ColorTitleBlend, active));//widgetGroup.background());
+
+ //if the window is maximized the border is invisible
+ if( (maximizeMode()==MaximizeFull) && !options()->moveResizeMaximizedWindows() )
+ painter.setPen(KDecoration::options()->color(ColorTitleBar, active));
+ else
+ painter.setPen(group.background().dark(150));
+
+ // outline outside the frame but not the corners if they are rounded
+ tempRect = widget()->rect();
+ painter.drawRect(tempRect);
+
+ if(roundedCorners && !maximizeMode()) {
+ // local temp right and bottom
+ int r(width());
+ painter.setPen(group.background().dark(150));
+ painter.drawPoint(4, 1);
+ painter.drawPoint(3, 1);
+ painter.drawPoint(2, 2);
+ painter.drawPoint(1, 3);
+ painter.drawPoint(1, 4);
+ painter.drawPoint(r - 5, 1);
+ painter.drawPoint(r - 4, 1);
+ painter.drawPoint(r - 3, 2);
+ painter.drawPoint(r - 2, 3);
+ painter.drawPoint(r - 2, 4);
+
+ painter.setPen(KDecoration::options()->color(ColorTitleBar, active).light(160));
+ painter.drawPoint(4, 2);
+ painter.drawPoint(3, 2);
+ painter.drawPoint(2, 3);
+ painter.drawPoint(2, 4);
+
+ //painter.setPen(KDecoration::options()->color(ColorTitleBlend, active));
+ painter.drawPoint(r - 5, 2);
+ painter.drawPoint(r - 4, 2);
+ painter.drawPoint(r - 3, 3);
+ painter.drawPoint(r - 3, 4);
+ }
+
+ // finally copy the buffer into the widget
+ //finalPainter.begin(doubleBuff);
+ finalPainter.drawPixmap(0,0, active?activeBuff:inactiveBuff);
+ finalPainter.end();
+
+ if( active )
+ aDoubleBufferDirty = false;
+ else
+ iDoubleBufferDirty = false;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// updateMask()
+// ------------
+// update the frame mask
+void polyesterClient::updateMask() {
+
+ if ( (!options()->moveResizeMaximizedWindows() && maximizeMode() & MaximizeFull ) )
+ {
+ setMask(TQRegion(widget()->rect()));
+ return;
+ }
+
+ int r(width());
+ int b(height());
+ TQRegion mask;
+
+ mask=TQRegion(widget()->rect());
+ mask=TQRegion( 0, 0, r, b );
+
+ // Remove top-left corner.
+ if( roundedCorners &&
+ maximizeMode() != KDecorationDefines::MaximizeFull )
+ {
+ mask -= TQRegion(0, 0, 5, 1);
+ mask -= TQRegion(0, 1, 3, 1);
+ mask -= TQRegion(0, 2, 2, 1);
+ mask -= TQRegion(0, 3, 1, 2);
+ mask -= TQRegion(r - 5, 0, 5, 1);
+ mask -= TQRegion(r - 3, 1, 3, 1);
+ mask -= TQRegion(r - 2, 2, 2, 1);
+ mask -= TQRegion(r - 1, 3, 1, 2);
+ }
+ //always remove one corner pixel so it simulates a soft corner like plastik
+ mask -= TQRegion(0,0,1,1);
+ mask -= TQRegion(r-1,0,1,1);
+ mask -= TQRegion(0, b-1, 1,1);
+ mask -= TQRegion(r-1,b-1,1,1);
+
+ setMask(mask, 1);
+
+ maskDirty = false;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// resizeEvent()
+// -------------
+// Window is being resized
+
+void polyesterClient::resizeEvent(TQResizeEvent *) {
+ maskDirty = aDoubleBufferDirty = iDoubleBufferDirty = true;
+ if (widget()->isShown()) {
+ TQRegion region = widget()->rect();
+ region = region.subtract(titlebar_->geometry());
+ widget()->erase(region);
+ }
+ updateMask();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// showEvent()
+// -----------
+// Window is being shown
+
+void polyesterClient::showEvent(TQShowEvent *) {
+ widget()->repaint();
+ updateMask();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// maxButtonPressed()
+// -----------------
+// Max button was pressed
+
+void polyesterClient::maxButtonPressed() {
+ if (button[ButtonMax]) {
+#if KDE_IS_VERSION(3, 3, 0)
+ maximize(button[ButtonMax]->lastMousePress());
+#else
+
+ switch (button[ButtonMax]->lastMousePress()) {
+ case MidButton:
+ maximize(maximizeMode() ^ MaximizeVertical);
+ break;
+ case RightButton:
+ maximize(maximizeMode() ^ MaximizeHorizontal);
+ break;
+ default:
+ (maximizeMode() == MaximizeFull) ? maximize(MaximizeRestore)
+ : maximize(MaximizeFull);
+ }
+#endif
+
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// shadeButtonPressed()
+// -----------------
+// Shade button was pressed
+
+void polyesterClient::shadeButtonPressed() {
+ if (button[ButtonShade]) {
+ setShade( !isSetShade());
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// aboveButtonPressed()
+// -----------------
+// Above button was pressed
+
+void polyesterClient::aboveButtonPressed() {
+ if (button[ButtonAbove]) {
+ setKeepAbove( !keepAbove());
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// belowButtonPressed()
+// -----------------
+// Below button was pressed
+
+void polyesterClient::belowButtonPressed() {
+ if (button[ButtonBelow]) {
+ setKeepBelow( !keepBelow());
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// menuButtonPressed()
+// -------------------
+// Menu button was pressed (popup the menu)
+
+void polyesterClient::menuButtonPressed() {
+ static TQTime* t = NULL;
+ static polyesterClient* lastClient = NULL;
+ if (t == NULL)
+ t = new TQTime;
+ bool dbl = (lastClient==this && t->elapsed() <= TQApplication::doubleClickInterval());
+ lastClient = this;
+ t->start();
+ //if (button[ButtonMenu] && !dbl && !::factory->menuClosed()) {
+ if ( !dbl || !::factory->menuClosed()) {
+ TQPoint p(button[ButtonMenu]->rect().bottomLeft().x(),
+ button[ButtonMenu]->rect().bottomLeft().y());
+ KDecorationFactory* f = factory();
+ showWindowMenu(button[ButtonMenu]->mapToGlobal(p));
+ if (!f->exists(this))
+ return; // decoration was destroyed
+ button[ButtonMenu]->setDown(false);
+ }
+ else
+ {
+ closing = true;
+ }
+}
+
+void polyesterClient::menuButtonReleased()
+{
+ if(closing)
+ {
+ closeWindow();
+ }
+}
+
+#include "polyester.moc"