diff options
Diffstat (limited to 'client/crystalclient.cpp')
-rw-r--r-- | client/crystalclient.cpp | 1666 |
1 files changed, 1666 insertions, 0 deletions
diff --git a/client/crystalclient.cpp b/client/crystalclient.cpp new file mode 100644 index 0000000..90b3429 --- /dev/null +++ b/client/crystalclient.cpp @@ -0,0 +1,1666 @@ +/*************************************************************************** + * Copyright (C) 2006 by Sascha Hlusiak * + * [email protected] * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "config.h" +#include <tdeconfig.h> +#include <tdeglobal.h> +#include <tdeglobalsettings.h> +#include <tdelocale.h> +#include <kdebug.h> + +#include <tqbitmap.h> +#include <tqlabel.h> +#include <tqpainter.h> +#include <tqtooltip.h> +#include <tqapplication.h> +#include <tqimage.h> +#include <tqpopupmenu.h> +#include <twin.h> +#include <kprocess.h> + +#include "crystalclient.h" +#include "crystalbutton.h" +#include "buttonimage.h" +#include "imageholder.h" +#include "overlays.h" + +#include <X11/Xlib.h> +#include <X11/Xatom.h> + +// Button themes +#include "tiles.h" + + +CrystalFactory* factory=NULL; + +bool CrystalFactory::initialized_ = false; +TQt::AlignmentFlags CrystalFactory::titlealign_ = TQt::AlignHCenter; + + +extern "C" KDecorationFactory* create_factory() +{ + return new CrystalFactory(); +} + + +/***************** + * Tooltip class for the titlebar + **/ +class CCrystalTooltip:public TQToolTip +{ +private: + CrystalClient *client; +public: + CCrystalTooltip(TQWidget *widget,CrystalClient *vc):TQToolTip(widget),client(vc) {} + virtual void maybeTip(const TQPoint& p) + { + if (client->titlebar_->geometry().contains(p)) + { + tip(client->titlebar_->geometry(),client->caption()); + } + } +}; + + + + +CrystalFactory::CrystalFactory() +{ + for (int i=0;i<ButtonImageCount;i++) + buttonImages[i]=NULL; + + ::factory=this; + readConfig(); + initialized_ = true; + + if (transparency)image_holder=new QImageHolder(active.userdefinedPicture,inactive.userdefinedPicture); + else image_holder=NULL; + CreateButtonImages(); +} + +CrystalFactory::~CrystalFactory() +{ + initialized_ = false; + ::factory=NULL; + if (image_holder)delete image_holder; + for (int i=0;i<ButtonImageCount;i++) + { + if (buttonImages[i])delete buttonImages[i]; + buttonImages[i]=NULL; + } +} + +KDecoration* CrystalFactory::createDecoration(KDecorationBridge* b) +{ + return new CrystalClient(b,factory ); +} + +bool CrystalFactory::reset(unsigned long /*changed*/) +{ + initialized_ = false; + readConfig(); + initialized_ = true; + + if (transparency) + { + if (!image_holder)image_holder=new QImageHolder(active.userdefinedPicture,inactive.userdefinedPicture); + image_holder->setUserdefinedPictures(active.userdefinedPicture,inactive.userdefinedPicture); + image_holder->repaint(true); + }else{ + if (image_holder)delete image_holder; + image_holder=NULL; + } + CreateButtonImages(); + + return true; +} + +bool CrystalFactory::supports(Ability ability) +{ + switch (ability) + { +#if KDE_IS_VERSION(3,4,0) + case AbilityButtonResize: return false; +#endif + default: + return true; + } +} + +void setupOverlay(WND_CONFIG *cfg,int mode,TQString filename) +{ + cfg->overlay.resize(0,0); + switch(mode) + { + case 0: break; + case 1:{ + cfg->overlay.resize(0,0); + TQImage img=TQImage((uchar*)lighting_overlay_data,1,60,32,NULL,0,TQImage::LittleEndian); + img.setAlphaBuffer(true); + cfg->overlay.convertFromImage(img.smoothScale(256,::factory->titlesize)); + break; + } + case 2:{ + cfg->overlay.resize(0,0); + TQImage img=TQImage((uchar*)glass_overlay_data,20,64,32,NULL,0,TQImage::LittleEndian); + img.setAlphaBuffer(true); + cfg->overlay.convertFromImage(img.smoothScale(256,::factory->titlesize)); + break; + } + case 3:{ + cfg->overlay.resize(0,0); + TQImage img=TQImage((uchar*)steel_overlay_data,28,64,32,NULL,0,TQImage::LittleEndian); + img.setAlphaBuffer(true); + cfg->overlay.convertFromImage(img.smoothScale(256,::factory->titlesize)); + break; + } + case 4:{ + TQImage img; + if (img.load(filename)) + { + img.setAlphaBuffer(true); + cfg->overlay.convertFromImage(img.smoothScale(256,::factory->titlesize)); + } + break; + } + } +} + +bool CrystalFactory::readConfig() +{ + // create a config object + TDEConfig config("twincrystalrc"); + config.setGroup("General"); + TQColor c; + + 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; + + drawcaption=(bool)config.readBoolEntry("DrawCaption",true); + textshadow=(bool)config.readBoolEntry("TextShadow",true); + captiontooltip=(bool)config.readBoolEntry("CaptionTooltip",true); + wheelTask=(bool)config.readBoolEntry("WheelTask",false); + transparency=(bool)config.readBoolEntry("EnableTransparency",true); + trackdesktop=(bool)config.readBoolEntry("TrackDesktop",false); + + active.mode=config.readNumEntry("ActiveMode",0); + inactive.mode=config.readNumEntry("InactiveMode",1); + active.amount=(double)config.readNumEntry("ActiveShade",30)/100.0; + inactive.amount=(double)config.readNumEntry("InactiveShade",-30)/100.0; + active.outlineMode=(int)config.readNumEntry("ActiveFrame",1); + inactive.outlineMode=(int)config.readNumEntry("InactiveFrame",1); + c=TQColor(160,160,160); + active.frameColor=config.readColorEntry("FrameColor1",&c); + c=TQColor(128,128,128); + inactive.frameColor=config.readColorEntry("FrameColor2",&c); + + active.inlineMode=(int)config.readNumEntry("ActiveInline",0); + inactive.inlineMode=(int)config.readNumEntry("InactiveInline",0); + c=TQColor(160,160,160); + active.inlineColor=config.readColorEntry("InlineColor1",&c); + c=TQColor(160,160,160); + inactive.inlineColor=config.readColorEntry("InlineColor2",&c); + + active.blur=config.readNumEntry("ActiveBlur",0); + inactive.blur=config.readNumEntry("InactiveBlur",0); + + active.userdefinedPicture=TQImage(); + inactive.userdefinedPicture=TQImage(); + if ((bool)config.readBoolEntry("ActiveUserdefined",false)) + { + active.userdefinedPicture.load(config.readEntry("ActiveUserdefinedPicture")); + } + if ((bool)config.readBoolEntry("InactiveUserdefined",false)) + { + inactive.userdefinedPicture.load(config.readEntry("InactiveUserdefinedPicture")); + } + + borderwidth=config.readNumEntry("Borderwidth",5); + titlesize=config.readNumEntry("Titlebarheight",21); + + buttonColor_normal=TQColor(255,255,255); + buttonColor_normal=config.readColorEntry("ButtonColor",&buttonColor_normal); + buttonColor_hovered=config.readColorEntry("ButtonColor2",&buttonColor_normal); + buttonColor_pressed=config.readColorEntry("ButtonColor3",&buttonColor_normal); + minColor_normal=TQColor(255,255,255); + minColor_normal=config.readColorEntry("MinColor",&buttonColor_normal); + minColor_hovered=config.readColorEntry("MinColor2",&buttonColor_normal); + minColor_pressed=config.readColorEntry("MinColor3",&buttonColor_normal); + maxColor_normal=TQColor(255,255,255); + maxColor_normal=config.readColorEntry("MaxColor",&buttonColor_normal); + maxColor_hovered=config.readColorEntry("MaxColor2",&buttonColor_normal); + maxColor_pressed=config.readColorEntry("MaxColor3",&buttonColor_normal); + closeColor_normal=TQColor(255,255,255); + closeColor_normal=config.readColorEntry("CloseColor",&closeColor_normal); + closeColor_hovered=config.readColorEntry("CloseColor2",&closeColor_normal); + closeColor_pressed=config.readColorEntry("CloseColor3",&closeColor_normal); + + roundCorners=config.readNumEntry("RoundCorners",TOP_LEFT & TOP_RIGHT); + + hovereffect=config.readBoolEntry("HoverEffect",true); + animateHover=config.readBoolEntry("AnimateHover",true); + tintButtons=config.readBoolEntry("TintButtons",false); + menuImage=config.readBoolEntry("MenuImage",true); + repaintMode=config.readNumEntry("RepaintMode",1); + repaintTime=config.readNumEntry("RepaintTime",200); + buttontheme=config.readNumEntry("ButtonTheme",8); + + + setupOverlay(&active,config.readNumEntry("OverlayModeActive",0),config.readEntry("OverlayFileActive","")); + setupOverlay(&inactive,config.readNumEntry("OverlayModeInactive",0),config.readEntry("OverlayFileInactive","")); + + logoEnabled=config.readNumEntry("LogoAlignment",1); + logoStretch=config.readNumEntry("LogoStretch",0); + logoActive=config.readBoolEntry("LogoActive",0); + logoDistance=config.readNumEntry("LogoDistance",0); + TQString filename=config.readEntry("LogoFile",""); + if (!filename.isNull() && logoEnabled!=1) + { + if (logo.load(filename)) + { + if (logoStretch==0) + { + logo=logo.convertToImage().smoothScale((titlesize*logo.width())/logo.height(),titlesize); + } + }else logoEnabled=1; + }else logo.resize(0,0); + return true; +} + +void CrystalFactory::CreateButtonImages() +{ + for (int i=0;i<ButtonImageCount;i++) + { + if (buttonImages[i])buttonImages[i]->reset(); else + buttonImages[i]=new ButtonImage; + if (!tintButtons)buttonImages[i]->setColors(TQt::white,TQt::white,TQt::white); + else switch(i) + { + case ButtonImageMin: + buttonImages[i]->setColors(minColor_normal,minColor_hovered,minColor_pressed); + break; + case ButtonImageMax: + buttonImages[i]->setColors(maxColor_normal,maxColor_hovered,maxColor_pressed); + break; + case ButtonImageClose: + buttonImages[i]->setColors(closeColor_normal,closeColor_hovered,closeColor_pressed); + break; + + default: + buttonImages[i]->setColors(buttonColor_normal,buttonColor_hovered,buttonColor_pressed); + break; + } + } + + switch(buttontheme) + { + default: + case 0: // Crystal default + buttonImages[ButtonImageMenu]->SetNormal(crystal_menu_data); + buttonImages[ButtonImageHelp]->SetNormal(crystal_help_data); + buttonImages[ButtonImageMax]->SetNormal(crystal_max_data); + buttonImages[ButtonImageRestore]->SetNormal(crystal_restore_data); + buttonImages[ButtonImageMin]->SetNormal(crystal_min_data); + buttonImages[ButtonImageClose]->SetNormal(crystal_close_data); + buttonImages[ButtonImageSticky]->SetNormal(crystal_sticky_data); + buttonImages[ButtonImageUnSticky]->SetNormal(crystal_un_sticky_data); + buttonImages[ButtonImageShade]->SetNormal(crystal_shade_data); + buttonImages[ButtonImageUnShade]->SetNormal(crystal_shade_data); + + buttonImages[ButtonImageAbove]->SetNormal(crystal_above_data); + buttonImages[ButtonImageUnAbove]->SetNormal(crystal_unabove_data); + buttonImages[ButtonImageBelow]->SetNormal(crystal_below_data); + buttonImages[ButtonImageUnBelow]->SetNormal(crystal_unbelow_data); + break; + case 1: // Aqua buttons + buttonImages[ButtonImageMenu]->SetNormal(aqua_default_data,16,16); + buttonImages[ButtonImageHelp]->SetNormal(aqua_default_data,16,16); + buttonImages[ButtonImageMax]->SetNormal(aqua_default_data,16,16); + buttonImages[ButtonImageRestore]->SetNormal(aqua_default_data,16,16); + buttonImages[ButtonImageMin]->SetNormal(aqua_default_data,16,16); + buttonImages[ButtonImageClose]->SetNormal(aqua_default_data,16,16); + buttonImages[ButtonImageSticky]->SetNormal(aqua_sticky_data,16,16); + buttonImages[ButtonImageUnSticky]->SetNormal(aqua_default_data,16,16); + buttonImages[ButtonImageShade]->SetNormal(aqua_default_data,16,16); + buttonImages[ButtonImageUnShade]->SetNormal(aqua_default_data,16,16); + + buttonImages[ButtonImageAbove]->SetNormal(aqua_default_data,16,16); + buttonImages[ButtonImageUnAbove]->SetNormal(aqua_above_data,16,16); + buttonImages[ButtonImageBelow]->SetNormal(aqua_default_data,16,16); + buttonImages[ButtonImageUnBelow]->SetNormal(aqua_below_data,16,16); + + buttonImages[ButtonImageClose]->SetHovered(aqua_close_data); + buttonImages[ButtonImageMax]->SetHovered(aqua_max_data); + buttonImages[ButtonImageMin]->SetHovered(aqua_min_data); + buttonImages[ButtonImageRestore]->SetHovered(aqua_max_data); + buttonImages[ButtonImageUnSticky]->SetHovered(aqua_un_sticky_data); + buttonImages[ButtonImageHelp]->SetHovered(aqua_help_data); + buttonImages[ButtonImageAbove]->SetHovered(aqua_above_data); + buttonImages[ButtonImageBelow]->SetHovered(aqua_below_data); + buttonImages[ButtonImageShade]->SetHovered(aqua_shade_data); + buttonImages[ButtonImageUnShade]->SetHovered(aqua_shade_data); + break; + case 2: // Knifty buttons + buttonImages[ButtonImageHelp]->SetNormal(knifty_help_data); + buttonImages[ButtonImageMax]->SetNormal(knifty_max_data); + buttonImages[ButtonImageRestore]->SetNormal(knifty_restore_data); + buttonImages[ButtonImageMin]->SetNormal(knifty_min_data); + buttonImages[ButtonImageClose]->SetNormal(knifty_close_data); + buttonImages[ButtonImageSticky]->SetNormal(knifty_sticky_data); + buttonImages[ButtonImageUnSticky]->SetNormal(knifty_un_sticky_data); + buttonImages[ButtonImageShade]->SetNormal(knifty_shade_data); + buttonImages[ButtonImageUnShade]->SetNormal(knifty_shade_data); + + buttonImages[ButtonImageAbove]->SetNormal(knifty_above_data); + buttonImages[ButtonImageUnAbove]->SetNormal(knifty_unabove_data); + buttonImages[ButtonImageBelow]->SetNormal(knifty_below_data); + buttonImages[ButtonImageUnBelow]->SetNormal(knifty_unbelow_data); + break; + + case 3: // Handpainted + buttonImages[ButtonImageHelp]->SetNormal(handpainted_help_data); + buttonImages[ButtonImageMax]->SetNormal(handpainted_max_data); + buttonImages[ButtonImageRestore]->SetNormal(handpainted_restore_data); + buttonImages[ButtonImageMin]->SetNormal(handpainted_min_data); + buttonImages[ButtonImageClose]->SetNormal(handpainted_close_data); + buttonImages[ButtonImageSticky]->SetNormal(handpainted_sticky_data); + buttonImages[ButtonImageUnSticky]->SetNormal(handpainted_un_sticky_data); + buttonImages[ButtonImageShade]->SetNormal(handpainted_shade_data); + buttonImages[ButtonImageUnShade]->SetNormal(handpainted_un_shade_data); + + buttonImages[ButtonImageAbove]->SetNormal(handpainted_above_data); + buttonImages[ButtonImageUnAbove]->SetNormal(handpainted_unabove_data); + buttonImages[ButtonImageBelow]->SetNormal(handpainted_below_data); + buttonImages[ButtonImageUnBelow]->SetNormal(handpainted_unbelow_data); + break; + case 4: // SVG + buttonImages[ButtonImageMenu]->SetNormal(svg_menu_data); + buttonImages[ButtonImageHelp]->SetNormal(svg_help_data); + buttonImages[ButtonImageMax]->SetNormal(svg_max_data); + buttonImages[ButtonImageRestore]->SetNormal(svg_restore_data); + buttonImages[ButtonImageMin]->SetNormal(svg_min_data); + buttonImages[ButtonImageClose]->SetNormal(svg_close_data); + buttonImages[ButtonImageSticky]->SetNormal(svg_sticky_data); + buttonImages[ButtonImageUnSticky]->SetNormal(svg_unsticky_data); + buttonImages[ButtonImageShade]->SetNormal(svg_shade_data); + buttonImages[ButtonImageUnShade]->SetNormal(svg_shade_data); + + buttonImages[ButtonImageAbove]->SetNormal(svg_above_data); + buttonImages[ButtonImageUnAbove]->SetNormal(svg_above_data); + buttonImages[ButtonImageBelow]->SetNormal(svg_below_data); + buttonImages[ButtonImageUnBelow]->SetNormal(svg_below_data); + break; + case 5: // Vista + buttonImages[ButtonImageMenu]->SetNormal(vista_menu_data,26,15); + buttonImages[ButtonImageMenu]->SetHovered(vista_menu_hovered_data); + buttonImages[ButtonImageMenu]->SetPressed(vista_menu_pressed_data); + + buttonImages[ButtonImageHelp]->SetNormal(vista_help_data,26,15); + buttonImages[ButtonImageHelp]->SetHovered(vista_help_hovered_data); + buttonImages[ButtonImageHelp]->SetPressed(vista_help_pressed_data); + + buttonImages[ButtonImageMax]->SetNormal(vista_max_data,27,15); + buttonImages[ButtonImageMax]->SetHovered(vista_max_hovered_data); + buttonImages[ButtonImageMax]->SetPressed(vista_max_pressed_data); + buttonImages[ButtonImageRestore]->SetNormal(vista_restore_data,27,15); + buttonImages[ButtonImageRestore]->SetHovered(vista_restore_hovered_data); + buttonImages[ButtonImageRestore]->SetPressed(vista_restore_pressed_data); + buttonImages[ButtonImageMin]->SetNormal(vista_min_data,26,15); + buttonImages[ButtonImageMin]->SetHovered(vista_min_hovered_data); + buttonImages[ButtonImageMin]->SetPressed(vista_min_pressed_data); + buttonImages[ButtonImageClose]->SetNormal(vista_close_data,40,15); + buttonImages[ButtonImageClose]->SetHovered(vista_close_hovered_data); + buttonImages[ButtonImageClose]->SetPressed(vista_close_pressed_data); + + buttonImages[ButtonImageSticky]->SetNormal(vista_sticky_data,26,15); + buttonImages[ButtonImageSticky]->SetHovered(vista_sticky_hovered_data); + buttonImages[ButtonImageSticky]->SetPressed(vista_sticky_pressed_data); + buttonImages[ButtonImageUnSticky]->SetNormal(vista_un_sticky_data,26,15); + buttonImages[ButtonImageUnSticky]->SetHovered(vista_un_sticky_hovered_data); + buttonImages[ButtonImageUnSticky]->SetPressed(vista_un_sticky_pressed_data); + + buttonImages[ButtonImageAbove]->SetNormal(vista_above_data,26,15); + buttonImages[ButtonImageAbove]->SetHovered(vista_above_hovered_data); + buttonImages[ButtonImageAbove]->SetPressed(vista_above_pressed_data); + buttonImages[ButtonImageUnAbove]->SetNormal(vista_un_above_data,26,15); + buttonImages[ButtonImageUnAbove]->SetHovered(vista_un_above_hovered_data); + buttonImages[ButtonImageUnAbove]->SetPressed(vista_un_above_pressed_data); + + buttonImages[ButtonImageBelow]->SetNormal(vista_below_data,26,15); + buttonImages[ButtonImageBelow]->SetHovered(vista_below_hovered_data); + buttonImages[ButtonImageBelow]->SetPressed(vista_below_pressed_data); + buttonImages[ButtonImageUnBelow]->SetNormal(vista_un_below_data,26,15); + buttonImages[ButtonImageUnBelow]->SetHovered(vista_un_below_hovered_data); + buttonImages[ButtonImageUnBelow]->SetPressed(vista_un_below_pressed_data); + + buttonImages[ButtonImageShade]->SetNormal(vista_shade_data,26,15); + buttonImages[ButtonImageShade]->SetHovered(vista_shade_hovered_data); + buttonImages[ButtonImageShade]->SetPressed(vista_shade_pressed_data); + buttonImages[ButtonImageUnShade]->SetNormal(vista_un_shade_data,26,15); + buttonImages[ButtonImageUnShade]->SetHovered(vista_un_shade_hovered_data); + buttonImages[ButtonImageUnShade]->SetPressed(vista_un_shade_pressed_data); + + for (int i=0;i<ButtonImageCount;i++) + { + buttonImages[i]->setSpace(1,0); + buttonImages[i]->setDrawMode(1); + } + buttonImages[ButtonImageMax]->setSpace(0,0); + buttonImages[ButtonImageRestore]->setSpace(0,0); + buttonImages[ButtonImageMin]->setSpace(0,0); + buttonImages[ButtonImageClose]->setSpace(0,0); + + break; + case 6: // Kubuntu Dapper + buttonImages[ButtonImageMenu]->SetNormal(dapper_menu_data,28,17); + buttonImages[ButtonImageMenu]->SetHovered(dapper_menu_hovered_data); + buttonImages[ButtonImageMenu]->SetPressed(dapper_menu_pressed_data); + + buttonImages[ButtonImageHelp]->SetNormal(dapper_help_data,28,17); + buttonImages[ButtonImageHelp]->SetHovered(dapper_help_hovered_data); + buttonImages[ButtonImageHelp]->SetPressed(dapper_help_pressed_data); + + buttonImages[ButtonImageMax]->SetNormal(dapper_max_data,28,17); + buttonImages[ButtonImageMax]->SetHovered(dapper_max_hovered_data); + buttonImages[ButtonImageMax]->SetPressed(dapper_max_pressed_data); + buttonImages[ButtonImageRestore]->SetNormal(dapper_restore_data,28,17); + buttonImages[ButtonImageRestore]->SetHovered(dapper_restore_hovered_data); + buttonImages[ButtonImageRestore]->SetPressed(dapper_restore_pressed_data); + buttonImages[ButtonImageMin]->SetNormal(dapper_min_data,28,17); + buttonImages[ButtonImageMin]->SetHovered(dapper_min_hovered_data); + buttonImages[ButtonImageMin]->SetPressed(dapper_min_pressed_data); + buttonImages[ButtonImageClose]->SetNormal(dapper_close_data,28,17); + buttonImages[ButtonImageClose]->SetHovered(dapper_close_hovered_data); + buttonImages[ButtonImageClose]->SetPressed(dapper_close_pressed_data); + + buttonImages[ButtonImageSticky]->SetNormal(dapper_sticky_data,28,17); + buttonImages[ButtonImageSticky]->SetHovered(dapper_sticky_hovered_data); + buttonImages[ButtonImageSticky]->SetPressed(dapper_sticky_pressed_data); + buttonImages[ButtonImageUnSticky]->SetNormal(dapper_un_sticky_data,28,17); + buttonImages[ButtonImageUnSticky]->SetHovered(dapper_un_sticky_hovered_data); + buttonImages[ButtonImageUnSticky]->SetPressed(dapper_un_sticky_pressed_data); + + buttonImages[ButtonImageAbove]->SetNormal(dapper_above_data,28,17); + buttonImages[ButtonImageAbove]->SetHovered(dapper_above_hovered_data); + buttonImages[ButtonImageAbove]->SetPressed(dapper_above_pressed_data); + buttonImages[ButtonImageUnAbove]->SetNormal(dapper_un_above_data,28,17); + buttonImages[ButtonImageUnAbove]->SetHovered(dapper_un_above_hovered_data); + buttonImages[ButtonImageUnAbove]->SetPressed(dapper_un_above_pressed_data); + + + buttonImages[ButtonImageBelow]->SetNormal(dapper_below_data,28,17); + buttonImages[ButtonImageBelow]->SetHovered(dapper_below_hovered_data); + buttonImages[ButtonImageBelow]->SetPressed(dapper_below_pressed_data); + + buttonImages[ButtonImageUnBelow]->SetNormal(dapper_un_below_data,28,17); + buttonImages[ButtonImageUnBelow]->SetHovered(dapper_un_below_hovered_data); + buttonImages[ButtonImageUnBelow]->SetPressed(dapper_un_below_pressed_data); + + buttonImages[ButtonImageShade]->SetNormal(dapper_shade_data,28,17); + buttonImages[ButtonImageShade]->SetHovered(dapper_shade_hovered_data); + buttonImages[ButtonImageShade]->SetPressed(dapper_shade_pressed_data); + buttonImages[ButtonImageUnShade]->SetNormal(dapper_un_shade_data,28,17); + buttonImages[ButtonImageUnShade]->SetHovered(dapper_un_shade_hovered_data); + buttonImages[ButtonImageUnShade]->SetPressed(dapper_un_shade_pressed_data); + + for (int i=0;i<ButtonImageCount;i++) + { + buttonImages[i]->setSpace(1,0); + buttonImages[i]->setDrawMode(0); + } + buttonImages[ButtonImageMax]->setSpace(0,0); + buttonImages[ButtonImageRestore]->setSpace(0,0); + buttonImages[ButtonImageMin]->setSpace(0,0); + buttonImages[ButtonImageClose]->setSpace(0,0); + break; + + case 7: // Kubuntu-Edgy + buttonImages[ButtonImageMenu]->SetNormal(edgy_menu_data,28,17); + buttonImages[ButtonImageMenu]->SetHovered(edgy_menu_hovered_data); + buttonImages[ButtonImageMenu]->SetPressed(edgy_menu_pressed_data); + + buttonImages[ButtonImageHelp]->SetNormal(edgy_help_data,28,17); + buttonImages[ButtonImageHelp]->SetHovered(edgy_help_hovered_data); + buttonImages[ButtonImageHelp]->SetPressed(edgy_help_pressed_data); + + buttonImages[ButtonImageMax]->SetNormal(edgy_max_data,28,17); + buttonImages[ButtonImageMax]->SetHovered(edgy_max_hovered_data); + buttonImages[ButtonImageMax]->SetPressed(edgy_max_pressed_data); + buttonImages[ButtonImageRestore]->SetNormal(edgy_restore_data,28,17); + buttonImages[ButtonImageRestore]->SetHovered(edgy_restore_hovered_data); + buttonImages[ButtonImageRestore]->SetPressed(edgy_restore_pressed_data); + buttonImages[ButtonImageMin]->SetNormal(edgy_min_data,28,17); + buttonImages[ButtonImageMin]->SetHovered(edgy_min_hovered_data); + buttonImages[ButtonImageMin]->SetPressed(edgy_min_pressed_data); + buttonImages[ButtonImageClose]->SetNormal(edgy_close_data,28,17); + buttonImages[ButtonImageClose]->SetHovered(edgy_close_hovered_data); + buttonImages[ButtonImageClose]->SetPressed(edgy_close_pressed_data); + + buttonImages[ButtonImageSticky]->SetNormal(edgy_sticky_data,28,17); + buttonImages[ButtonImageSticky]->SetHovered(edgy_sticky_hovered_data); + buttonImages[ButtonImageSticky]->SetPressed(edgy_sticky_pressed_data); + buttonImages[ButtonImageUnSticky]->SetNormal(edgy_un_sticky_data,28,17); + buttonImages[ButtonImageUnSticky]->SetHovered(edgy_un_sticky_hovered_data); + buttonImages[ButtonImageUnSticky]->SetPressed(edgy_un_sticky_pressed_data); + + buttonImages[ButtonImageAbove]->SetNormal(edgy_above_data,28,17); + buttonImages[ButtonImageAbove]->SetHovered(edgy_above_hovered_data); + buttonImages[ButtonImageAbove]->SetPressed(edgy_above_pressed_data); + buttonImages[ButtonImageUnAbove]->SetNormal(edgy_un_above_data,28,17); + buttonImages[ButtonImageUnAbove]->SetHovered(edgy_un_above_hovered_data); + buttonImages[ButtonImageUnAbove]->SetPressed(edgy_un_above_pressed_data); + + + buttonImages[ButtonImageBelow]->SetNormal(edgy_below_data,28,17); + buttonImages[ButtonImageBelow]->SetHovered(edgy_below_hovered_data); + buttonImages[ButtonImageBelow]->SetPressed(edgy_below_pressed_data); + + buttonImages[ButtonImageUnBelow]->SetNormal(edgy_un_below_data,28,17); + buttonImages[ButtonImageUnBelow]->SetHovered(edgy_un_below_hovered_data); + buttonImages[ButtonImageUnBelow]->SetPressed(edgy_un_below_pressed_data); + + buttonImages[ButtonImageShade]->SetNormal(edgy_shade_data,28,17); + buttonImages[ButtonImageShade]->SetHovered(edgy_shade_hovered_data); + buttonImages[ButtonImageShade]->SetPressed(edgy_shade_pressed_data); + buttonImages[ButtonImageUnShade]->SetNormal(edgy_un_shade_data,28,17); + buttonImages[ButtonImageUnShade]->SetHovered(edgy_un_shade_hovered_data); + buttonImages[ButtonImageUnShade]->SetPressed(edgy_un_shade_pressed_data); + + for (int i=0;i<ButtonImageCount;i++) + { + buttonImages[i]->setSpace(1,0); + buttonImages[i]->setDrawMode(0); + } + buttonImages[ButtonImageMax]->setSpace(0,0); + buttonImages[ButtonImageRestore]->setSpace(0,0); + buttonImages[ButtonImageMin]->setSpace(0,0); + buttonImages[ButtonImageClose]->setSpace(0,0); + + break; + case 8: // Kubuntu-Feisty + buttonImages[ButtonImageMenu]->SetNormal(feisty_menu_data,21,17); + buttonImages[ButtonImageMenu]->SetHovered(feisty_menu_hovered_data); + buttonImages[ButtonImageMenu]->SetPressed(feisty_menu_pressed_data); + + buttonImages[ButtonImageHelp]->SetNormal(feisty_help_data,28,17); + buttonImages[ButtonImageHelp]->SetHovered(feisty_help_hovered_data); + buttonImages[ButtonImageHelp]->SetPressed(feisty_help_pressed_data); + + buttonImages[ButtonImageMax]->SetNormal(feisty_max_data,28,17); + buttonImages[ButtonImageMax]->SetHovered(feisty_max_hovered_data); + buttonImages[ButtonImageMax]->SetPressed(feisty_max_pressed_data); + buttonImages[ButtonImageRestore]->SetNormal(feisty_restore_data,28,17); + buttonImages[ButtonImageRestore]->SetHovered(feisty_restore_hovered_data); + buttonImages[ButtonImageRestore]->SetPressed(feisty_restore_pressed_data); + buttonImages[ButtonImageMin]->SetNormal(feisty_min_data,28,17); + buttonImages[ButtonImageMin]->SetHovered(feisty_min_hovered_data); + buttonImages[ButtonImageMin]->SetPressed(feisty_min_pressed_data); + buttonImages[ButtonImageClose]->SetNormal(feisty_close_data,28,17); + buttonImages[ButtonImageClose]->SetHovered(feisty_close_hovered_data); + buttonImages[ButtonImageClose]->SetPressed(feisty_close_pressed_data); + + buttonImages[ButtonImageSticky]->SetNormal(feisty_sticky_data,28,17); + buttonImages[ButtonImageSticky]->SetHovered(feisty_sticky_hovered_data); + buttonImages[ButtonImageSticky]->SetPressed(feisty_sticky_pressed_data); + buttonImages[ButtonImageUnSticky]->SetNormal(feisty_un_sticky_data,28,17); + buttonImages[ButtonImageUnSticky]->SetHovered(feisty_un_sticky_hovered_data); + buttonImages[ButtonImageUnSticky]->SetPressed(feisty_un_sticky_pressed_data); + + buttonImages[ButtonImageAbove]->SetNormal(feisty_above_data,28,17); + buttonImages[ButtonImageAbove]->SetHovered(feisty_above_hovered_data); + buttonImages[ButtonImageAbove]->SetPressed(feisty_above_pressed_data); + buttonImages[ButtonImageUnAbove]->SetNormal(feisty_un_above_data,28,17); + buttonImages[ButtonImageUnAbove]->SetHovered(feisty_un_above_hovered_data); + buttonImages[ButtonImageUnAbove]->SetPressed(feisty_un_above_pressed_data); + + + buttonImages[ButtonImageBelow]->SetNormal(feisty_below_data,28,17); + buttonImages[ButtonImageBelow]->SetHovered(feisty_below_hovered_data); + buttonImages[ButtonImageBelow]->SetPressed(feisty_below_pressed_data); + + buttonImages[ButtonImageUnBelow]->SetNormal(feisty_un_below_data,28,17); + buttonImages[ButtonImageUnBelow]->SetHovered(feisty_un_below_hovered_data); + buttonImages[ButtonImageUnBelow]->SetPressed(feisty_un_below_pressed_data); + + buttonImages[ButtonImageShade]->SetNormal(feisty_shade_data,28,17); + buttonImages[ButtonImageShade]->SetHovered(feisty_shade_hovered_data); + buttonImages[ButtonImageShade]->SetPressed(feisty_shade_pressed_data); + buttonImages[ButtonImageUnShade]->SetNormal(feisty_un_shade_data,28,17); + buttonImages[ButtonImageUnShade]->SetHovered(feisty_un_shade_hovered_data); + buttonImages[ButtonImageUnShade]->SetPressed(feisty_un_shade_pressed_data); + + for (int i=0;i<ButtonImageCount;i++) + { + buttonImages[i]->setSpace(1,0); + buttonImages[i]->setDrawMode(0); + } + buttonImages[ButtonImageMax]->setSpace(0,0); + buttonImages[ButtonImageRestore]->setSpace(0,0); + buttonImages[ButtonImageMin]->setSpace(0,0); + buttonImages[ButtonImageClose]->setSpace(0,0); + + break; + case 9: // Kubuntu-hardy + buttonImages[ButtonImageMenu]->SetNormal(hardy_menu_data,28,17); + buttonImages[ButtonImageMenu]->SetHovered(hardy_menu_hovered_data); + buttonImages[ButtonImageMenu]->SetPressed(hardy_menu_pressed_data); + + buttonImages[ButtonImageHelp]->SetNormal(hardy_help_data,28,17); + buttonImages[ButtonImageHelp]->SetHovered(hardy_help_hovered_data); + buttonImages[ButtonImageHelp]->SetPressed(hardy_help_pressed_data); + + buttonImages[ButtonImageMax]->SetNormal(hardy_max_data,28,17); + buttonImages[ButtonImageMax]->SetHovered(hardy_max_hovered_data); + buttonImages[ButtonImageMax]->SetPressed(hardy_max_pressed_data); + buttonImages[ButtonImageRestore]->SetNormal(hardy_restore_data,28,17); + buttonImages[ButtonImageRestore]->SetHovered(hardy_restore_hovered_data); + buttonImages[ButtonImageRestore]->SetPressed(hardy_restore_pressed_data); + buttonImages[ButtonImageMin]->SetNormal(hardy_min_data,28,17); + buttonImages[ButtonImageMin]->SetHovered(hardy_min_hovered_data); + buttonImages[ButtonImageMin]->SetPressed(hardy_min_pressed_data); + buttonImages[ButtonImageClose]->SetNormal(hardy_close_data,28,17); + buttonImages[ButtonImageClose]->SetHovered(hardy_close_hovered_data); + buttonImages[ButtonImageClose]->SetPressed(hardy_close_pressed_data); + + buttonImages[ButtonImageSticky]->SetNormal(hardy_sticky_data,28,17); + buttonImages[ButtonImageSticky]->SetHovered(hardy_sticky_hovered_data); + buttonImages[ButtonImageSticky]->SetPressed(hardy_sticky_pressed_data); + buttonImages[ButtonImageUnSticky]->SetNormal(hardy_un_sticky_data,28,17); + buttonImages[ButtonImageUnSticky]->SetHovered(hardy_un_sticky_hovered_data); + buttonImages[ButtonImageUnSticky]->SetPressed(hardy_un_sticky_pressed_data); + + buttonImages[ButtonImageAbove]->SetNormal(hardy_above_data,28,17); + buttonImages[ButtonImageAbove]->SetHovered(hardy_above_hovered_data); + buttonImages[ButtonImageAbove]->SetPressed(hardy_above_pressed_data); + buttonImages[ButtonImageUnAbove]->SetNormal(hardy_un_above_data,28,17); + buttonImages[ButtonImageUnAbove]->SetHovered(hardy_un_above_hovered_data); + buttonImages[ButtonImageUnAbove]->SetPressed(hardy_un_above_pressed_data); + + + buttonImages[ButtonImageBelow]->SetNormal(hardy_below_data,28,17); + buttonImages[ButtonImageBelow]->SetHovered(hardy_below_hovered_data); + buttonImages[ButtonImageBelow]->SetPressed(hardy_below_pressed_data); + + buttonImages[ButtonImageUnBelow]->SetNormal(hardy_un_below_data,28,17); + buttonImages[ButtonImageUnBelow]->SetHovered(hardy_un_below_hovered_data); + buttonImages[ButtonImageUnBelow]->SetPressed(hardy_un_below_pressed_data); + + buttonImages[ButtonImageShade]->SetNormal(hardy_shade_data,28,17); + buttonImages[ButtonImageShade]->SetHovered(hardy_shade_hovered_data); + buttonImages[ButtonImageShade]->SetPressed(hardy_shade_pressed_data); + buttonImages[ButtonImageUnShade]->SetNormal(hardy_un_shade_data,28,17); + buttonImages[ButtonImageUnShade]->SetHovered(hardy_un_shade_hovered_data); + buttonImages[ButtonImageUnShade]->SetPressed(hardy_un_shade_pressed_data); + + for (int i=0;i<ButtonImageCount;i++) + { + buttonImages[i]->setSpace(1,0); + buttonImages[i]->setDrawMode(0); + } + buttonImages[ButtonImageMax]->setSpace(0,0); + buttonImages[ButtonImageRestore]->setSpace(0,0); + buttonImages[ButtonImageMin]->setSpace(0,0); + buttonImages[ButtonImageClose]->setSpace(0,0); + + break; + + } + + + for (int i=0;i<ButtonImageCount;i++)buttonImages[i]->finish(); +} + + + + + + + + +CrystalClient::CrystalClient(KDecorationBridge *b,CrystalFactory *f) +: KDecoration(b,f) +{ + ::factory->clients.append(this); +} + +CrystalClient::~CrystalClient() +{ + ::factory->clients.remove(this); + for (int n=0; n<ButtonTypeCount; n++) { + if (button[n]) delete button[n]; + } +} + +void CrystalClient::init() +{ + createMainWidget(WResizeNoErase | WRepaintNoErase); + widget()->installEventFilter(this); + + FullMax=false; + if (!options()->moveResizeMaximizedWindows()) + FullMax=(maximizeMode()==MaximizeFull); + + // for flicker-free redraws + widget()->setBackgroundMode(NoBackground); + + // setup layout + mainlayout = new TQGridLayout(widget(), 4, 3); // 4x3 grid + titlelayout = new TQHBoxLayout(); + titlebar_ = new TQSpacerItem(1, ::factory->titlesize-1, TQSizePolicy::Expanding, + TQSizePolicy::Fixed); + + mainlayout->setResizeMode(TQLayout::FreeResize); + mainlayout->setRowSpacing(0, (::factory->buttontheme==5)?0:1); + mainlayout->setRowSpacing(3, ::factory->borderwidth*1); + + mainlayout->setColSpacing(2,borderSpacing()); + mainlayout->setColSpacing(0,borderSpacing()); + mainlayout->addLayout(titlelayout, 1, 1); + + if (isPreview()) { + char c[512]; + sprintf(c,"<center><b>Crystal %s Preview</b><br>Built: %s</center>",VERSION,__DATE__); + mainlayout->addItem(new TQSpacerItem(1, 1,TQSizePolicy::Expanding,TQSizePolicy::Fixed), 0, 1); + mainlayout->addItem(new TQSpacerItem(1, ::factory->borderwidth,TQSizePolicy::Expanding,TQSizePolicy::Expanding), 3, 1); + mainlayout->addWidget(new TQLabel(i18n(c),widget()), 2, 1); + } else { + mainlayout->addItem(new TQSpacerItem(0, 0), 2, 1); + } + + mainlayout->setRowStretch(2, 10); + mainlayout->setColStretch(1, 10); + + updateMask(); + + for (int n=0; n<ButtonTypeCount; n++) button[n] = 0; + addButtons(titlelayout, options()->titleButtonsLeft()); + titlelayout->addItem(titlebar_); + { + CrystalButton* lastbutton=addButtons(titlelayout, options()->titleButtonsRight()); + if (lastbutton)lastbutton->setFirstLast(false,true); + } + + if (::factory->captiontooltip) new CCrystalTooltip(widget(),this); + + connect( this, TQT_SIGNAL( keepAboveChanged( bool )), TQT_SLOT( keepAboveChange( bool ))); + connect( this, TQT_SIGNAL( keepBelowChanged( bool )), TQT_SLOT( keepBelowChange( bool ))); + + if (::factory->transparency)connect ( ::factory->image_holder,TQT_SIGNAL(repaintNeeded()),this,TQT_SLOT(Repaint())); + if (::factory->transparency)connect ( &timer,TQT_SIGNAL(timeout()),this,TQT_SLOT(Repaint())); + + updateLayout(); +} + +void CrystalClient::updateMask() +{ + if ((::factory->roundCorners==0)|| (!options()->moveResizeMaximizedWindows() && maximizeMode() & MaximizeFull ) ) + { + setMask(TQRegion(widget()->rect())); + return; + } + + int cornersFlag = ::factory->roundCorners; + int r(width()); + int b(height()); + TQRegion mask; + + mask=TQRegion(widget()->rect()); + + // Remove top-left corner. + if(cornersFlag & TOP_LEFT) { + mask -= TQRegion(0, 0, 5, 1); + mask -= TQRegion(0, 1, 3, 1); + mask -= TQRegion(0, 2, 2, 1); + mask -= TQRegion(0, 3, 1, 2); + } + // Remove top-right corner. + if(cornersFlag & TOP_RIGHT) { + 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); + } + // Remove bottom-left corner. + if(cornersFlag & BOT_LEFT) { + mask -= TQRegion(0, b - 5, 1, 3); + mask -= TQRegion(0, b - 3, 2, 1); + mask -= TQRegion(0, b - 2, 3, 1); + mask -= TQRegion(0, b - 1, 5, 1); + } + // Remove bottom-right corner. + if(cornersFlag & BOT_RIGHT) { + mask -= TQRegion(r - 5, b - 1, 5, 1); + mask -= TQRegion(r - 3, b - 2, 3, 1); + mask -= TQRegion(r - 2, b - 3, 2, 1); + mask -= TQRegion(r - 1, b - 5, 1, 2); + } + + setMask(mask); +} + +bool CrystalClient::isModalSystemNotification() +{ + unsigned char *data = 0; + Atom actual; + int format, result; + unsigned long n, left; + Atom kde_wm_system_modal_notification; + kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); + result = XGetWindowProperty(tqt_xdisplay(), windowId(), kde_wm_system_modal_notification, 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left, /*(unsigned char **)*/ &data); + if (result == Success && data != None && format == 32 ) + { + return TRUE; + } + return FALSE; +} + +CrystalButton* CrystalClient::addButtons(TQBoxLayout *layout, const TQString& s) +{ + ButtonImage *bitmap; + TQString tip; + CrystalButton *lastone=NULL; + + if (s.length() > 0) + { + for (unsigned n=0; n < s.length(); n++) + { + CrystalButton *current=NULL; + switch (s[n]) { + case 'M': // Menu button + if (!isModalSystemNotification()) { + if (!button[ButtonMenu]) { + button[ButtonMenu] = current = new CrystalButton(this, "menu", i18n("Menu"), ButtonMenu, ::factory->buttonImages[ButtonImageMenu]); + connect(button[ButtonMenu], TQT_SIGNAL(pressed()), this, TQT_SLOT(menuButtonPressed())); + } + } + break; + + case 'S': // Sticky button + if (!isModalSystemNotification()) { + if (!button[ButtonSticky]) { + if (isOnAllDesktops()) { + bitmap = ::factory->buttonImages[ButtonImageSticky]; + tip = i18n("Not on all desktops"); + } else { + bitmap = ::factory->buttonImages[ButtonImageUnSticky]; + tip = i18n("On All Desktops"); + } + button[ButtonSticky] =current=new CrystalButton(this, "sticky", tip,ButtonSticky, bitmap); + connect(button[ButtonSticky], TQT_SIGNAL(clicked()),this, TQT_SLOT(toggleOnAllDesktops())); + } + } + break; + + case 'H': // Help button + if (providesContextHelp()) { + button[ButtonHelp] =current= + new CrystalButton(this, "help", i18n("Help"),ButtonHelp, ::factory->buttonImages[ButtonImageHelp]); + connect(button[ButtonHelp], TQT_SIGNAL(clicked()),this, TQT_SLOT(showContextHelp())); + } + break; + + case 'I': // Minimize button + if ((!button[ButtonMin]) && isMinimizable()) { + button[ButtonMin] =current= + new CrystalButton(this, "iconify", i18n("Minimize"),ButtonMin, ::factory->buttonImages[ButtonImageMin]); + connect(button[ButtonMin], TQT_SIGNAL(clicked()),this, TQT_SLOT(minButtonPressed())); + } + break; + + case 'F': // Above button + if (!button[ButtonAbove]) { + button[ButtonAbove] =current= + new CrystalButton(this, "above", i18n("Keep Above Others"),ButtonAbove, ::factory->buttonImages[keepAbove()?ButtonImageUnAbove:ButtonImageAbove]); + connect(button[ButtonAbove], TQT_SIGNAL(clicked()),this, TQT_SLOT(aboveButtonPressed())); + } + break; + + case 'B': // Below button + if ((!button[ButtonBelow])) { + button[ButtonBelow] =current= + new CrystalButton(this, "below", i18n("Keep Below Others"),ButtonBelow, ::factory->buttonImages[keepBelow()?ButtonImageUnBelow:ButtonImageBelow]); + connect(button[ButtonBelow], TQT_SIGNAL(clicked()),this, TQT_SLOT(belowButtonPressed())); + } + break; + + case 'L': // Shade button + if ((!button[ButtonShade]) && isShadeable()) { + button[ButtonShade] =current= + new CrystalButton(this, "shade", i18n("Shade"),ButtonShade, ::factory->buttonImages[ButtonImageShade]); + connect(button[ButtonShade], TQT_SIGNAL(clicked()),this, TQT_SLOT(shadeButtonPressed())); + } + break; + + case 'A': // Maximize button + if ((!button[ButtonMax]) && isMaximizable()) + { + if (maximizeMode() == MaximizeFull) + { + bitmap = ::factory->buttonImages[ButtonImageRestore]; + tip = i18n("Restore"); + } else { + bitmap = ::factory->buttonImages[ButtonImageMax]; + tip = i18n("Maximize"); + } + button[ButtonMax] =current= + new CrystalButton(this, "maximize", tip,ButtonMax, bitmap); + connect(button[ButtonMax], TQT_SIGNAL(clicked()),this, TQT_SLOT(maxButtonPressed())); + } + break; + + case 'X': // Close button + if (isCloseable()) { + button[ButtonClose] =current= + new CrystalButton(this, "close", i18n("Close"),ButtonClose, ::factory->buttonImages[ButtonImageClose]); + connect(button[ButtonClose], TQT_SIGNAL(clicked()),this, TQT_SLOT(closeButtonPressed())); + } + break; + + case '_': // Spacer item + layout->addSpacing(4); + current=NULL; + break; + } + + if (current) + { + layout->addWidget(current); + if (layout->findWidget(current)==0)current->setFirstLast(true,false); + } + lastone=current; + } + } + return lastone; +} + +void CrystalClient::activeChange() +{ + Repaint(); + if (isActive()) ::factory->clients.at(::factory->clients.find(this)); +} + +void CrystalClient::captionChange() +{ + if (::factory->drawcaption) widget()->repaint(titlebar_->geometry(), false); +} + +void CrystalClient::desktopChange() +{ + bool d = isOnAllDesktops(); + if (button[ButtonSticky]) { + button[ButtonSticky]->setBitmap(::factory->buttonImages[d ? ButtonImageSticky : ButtonImageUnSticky ]); + TQToolTip::remove(button[ButtonSticky]); + TQToolTip::add(button[ButtonSticky], d ? i18n("Not on all desktops") : i18n("On All Desktops")); + } +} + +void CrystalClient::iconChange() +{ + if (button[ButtonMenu]) { + button[ButtonMenu]->setBitmap(::factory->buttonImages[ButtonImageMenu]); + } +} + +void CrystalClient::maximizeChange() +{ + bool m = (maximizeMode() == MaximizeFull); + if (button[ButtonMax]) { + button[ButtonMax]->setBitmap(::factory->buttonImages[ m ? ButtonImageRestore : ButtonImageMax ]); + TQToolTip::remove(button[ButtonMax]); + TQToolTip::add(button[ButtonMax], m ? i18n("Restore") : i18n("Maximize")); + } + + if (!options()->moveResizeMaximizedWindows()) + { + FullMax=m; + updateLayout(); + Repaint(); + } +} + +void CrystalClient::updateLayout() +{ + if (FullMax) + { + mainlayout->setColSpacing(0,0); + mainlayout->setColSpacing(2,0); + }else{ + mainlayout->setColSpacing(2,borderSpacing()); + mainlayout->setColSpacing(0,borderSpacing()); + } + + mainlayout->setRowSpacing(0, (FullMax||::factory->buttontheme==5)?0:1); + for (int i=0;i<ButtonTypeCount;i++)if (button[i]) + button[i]->resetSize(FullMax); + widget()->layout()->activate(); +} + +int CrystalClient::borderSpacing() +{ + if (::factory->roundCorners) + return (::factory->borderwidth<=5)?5: ::factory->borderwidth; + return (::factory->borderwidth<=1)?1: ::factory->borderwidth; +} + +void CrystalClient::shadeChange() +{ + if (button[ButtonShade]) + { + button[ButtonShade]->setBitmap(::factory->buttonImages[isShade()?ButtonImageUnShade:ButtonImageShade]); + } + if (!::factory->transparency)Repaint(); + return; +} + +void CrystalClient::borders(int &l, int &r, int &t, int &b) const +{ + l = r = ::factory->borderwidth; + t = ::factory->titlesize; + if (!isShade())b = ::factory->borderwidth; else b=0; + + if (!options()->moveResizeMaximizedWindows() ) + { + if ( maximizeMode() & MaximizeHorizontal )l=r=1; + if ( maximizeMode() & MaximizeVertical ) + { + b=isShade()?0:1; + if (!isShade() && ( maximizeMode() & MaximizeHorizontal ))b=0; + } + if ( (maximizeMode() & MaximizeFull)==MaximizeFull) + l=r=0; + } +} + +void CrystalClient::resize(const TQSize &size) +{ + widget()->resize(size); +} + +TQSize CrystalClient::minimumSize() const +{ + return widget()->minimumSize(); +} + +KDecoration::Position CrystalClient::mousePosition(const TQPoint &point) const +{ + const int corner = 20; + Position pos; + const int RESIZESIZE=::factory->borderwidth; + + if (isShade() || !isResizable()) pos=PositionCenter; + else if (point.y() <= 3) { + // 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()-RESIZESIZE)) { + // inside handle + if (point.x() <= corner) pos = PositionBottomLeft; + else if (point.x() >= (width()-corner)) pos = PositionBottomRight; + else pos = PositionBottom; + } else if (point.x() <= RESIZESIZE) { + // 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()-RESIZESIZE) { + // 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; +} + +bool CrystalClient::eventFilter(TQObject *obj, TQEvent *e) +{ + if (TQT_BASE_OBJECT(obj) != TQT_BASE_OBJECT(widget())) return false; + + switch (e->type()) { + case TQEvent::MouseButtonDblClick: + mouseDoubleClickEvent(TQT_TQMOUSEEVENT(e)); + return true; + case TQEvent::MouseButtonPress: + processMousePressEvent(TQT_TQMOUSEEVENT(e)); + return true; + case TQEvent::Paint: + paintEvent(TQT_TQPAINTEVENT(e)); + return true; + case TQEvent::Wheel: + mouseWheelEvent(TQT_TQWHEELEVENT(e)); + return true; + + case TQEvent::Resize: + resizeEvent(TQT_TQRESIZEEVENT(e)); + return true; + + case TQEvent::Show: + showEvent(TQT_TQSHOWEVENT(e)); + return true; + case TQEvent::Move: + moveEvent(TQT_TQMOVEEVENT(e)); + return true; + default:return false; + } + + return false; +} + +void CrystalClient::ClientWindows(Window* v_frame,Window* v_wrapper,Window *v_client) +{ + Window root=0,frame=0,wrapper=0,client=0,parent=0,*children=NULL; + uint numc; + if (v_frame) *v_frame=0; + if (v_wrapper) *v_wrapper=0; + if (v_client) *v_client=0; + // Our Deco is the child of a frame, get our parent + if (XQueryTree(tqt_xdisplay(),widget()->winId(),&root,&frame,&children,&numc) == 0) + return; + if (children!=NULL)XFree(children); + children=NULL; + + // frame has two children, us and a wrapper, get the wrapper + if (XQueryTree(tqt_xdisplay(),frame,&root,&parent,&children,&numc)==0) + return; + + for (uint i=0;i<numc;i++) + { + if (children[i]!=widget()->winId())wrapper=children[i]; + } + if (children!=NULL)XFree(children); + children=NULL; + + // wrapper has only one child, which is the client. We want this!! + if (XQueryTree(tqt_xdisplay(),wrapper,&root,&parent,&children,&numc)==0) + return; + if (numc==1)client=children[0]; + if (children!=NULL)XFree(children); + children=NULL; + if (v_client) *v_client=client; + if (v_wrapper) *v_wrapper=wrapper; + if (v_frame) *v_frame=frame; +} + +void CrystalClient::mouseDoubleClickEvent(TQMouseEvent *e) +{ + if (/*(titlebar_->geometry().contains(e->pos()))&&*/(e->button()==Qt::LeftButton)) titlebarDblClickOperation(); + else { + TQMouseEvent me(TQEvent::MouseButtonPress,e->pos(),e->button(),e->state()); + processMousePressEvent(&me); + } +} + +void CrystalClient::mouseWheelEvent(TQWheelEvent *e) +{ + if (::factory->wheelTask) + { + TQPtrList <CrystalClient> *l=&(::factory->clients); + + if (l->current()==NULL) for (unsigned int i=0;i<l->count();i++) if ((l->at(i))->isActive()) break; + + CrystalClient *n=this; + Window client,frame,wrapper; + do + { + if(e->delta()>0) + { + n=l->next(); + if (n==NULL)n=l->first(); + }else{ + n=l->prev(); + if (n==NULL)n=l->last(); + } + + n->ClientWindows(&frame,&wrapper,&client); + if (client == 0) { /* FALLBACK */ +#if KDE_IS_VERSION(3,5,0) + titlebarMouseWheelOperation(e->delta()); +#endif + return; + } + KWin::WindowInfo info=KWin::windowInfo(client); + if ((n->desktop()==desktop()) && !info.isMinimized())break; + }while(n!=this); + + KWin::activateWindow(client); + }else{ +#if KDE_IS_VERSION(3,5,0) + titlebarMouseWheelOperation(e->delta()); +#endif + } +} + +void CrystalClient::paintEvent(TQPaintEvent*) +{ + if (!CrystalFactory::initialized()) return; + + TQColorGroup group; + TQPainter painter(widget()); + + // draw the titlebar + group = options()->colorGroup(KDecoration::ColorTitleBar, isActive()); + WND_CONFIG* wndcfg=(isActive()?&::factory->active:&::factory->inactive); + + if (::factory->transparency && ::factory->trackdesktop) + ::factory->image_holder->repaint(false); // If other desktop than the last, regrab the root image + TQPixmap *background=::factory->transparency?::factory->image_holder->image(isActive()):NULL; + int drawFrame; + + { + TQRect r; + TQPoint p=widget()->mapToGlobal(TQPoint(0,0)); + int bl,br,bt,bb; + borders(bl,br,bt,bb); + + TQPixmap pufferPixmap; + pufferPixmap.resize(widget()->width(), bt); + TQPainter pufferPainter(&pufferPixmap); + + r=TQRect(p.x(),p.y(),widget()->width(),bt); + if (background && !background->isNull())pufferPainter.drawPixmap(TQPoint(0,0),*background,r); + else + { + pufferPainter.fillRect(widget()->rect(),group.background()); + } + if (!wndcfg->overlay.isNull()) + { + pufferPainter.drawTiledPixmap(0,0,widget()->width(),bt,wndcfg->overlay); + } + + if (::factory->drawcaption) + { + // draw title text + pufferPainter.setFont(options()->font(isActive(), false)); + + TQColor color=options()->color(KDecoration::ColorFont, isActive()); + r=titlebar_->geometry(); + r.moveBy(0,-1); + int logowidth=::factory->logo.width()+::factory->logoDistance; + if (::factory->logoEnabled!=1 && (isActive()||!::factory->logoActive)) + { + r.setWidth(r.width()-logowidth); + if (::factory->logoEnabled==0)r.moveLeft(r.left()+logowidth); + } + TQFontMetrics metrics(options()->font(isActive(), false)); + int textwidth=metrics.width(caption()); + int textalign=CrystalFactory::titleAlign(); + if (textwidth>r.width()) + textalign=AlignLeft, textwidth=r.width(); + if (::factory->textshadow && isActive()) + { + pufferPainter.translate(1,1); + pufferPainter.setPen(color.dark(300)); + pufferPainter.drawText(r,textalign | AlignVCenter,caption()); + pufferPainter.translate(-1,-1); + } + + pufferPainter.setPen(color); + pufferPainter.drawText(r, + textalign | AlignVCenter, + caption()); + + if (::factory->logoEnabled!=1 && (isActive()||!::factory->logoActive)) + { + int x=0; + if (::factory->logoEnabled==0 && textalign==AlignLeft)x=r.left()-logowidth; + if (::factory->logoEnabled==2 && textalign==AlignLeft)x=r.left()+textwidth+::factory->logoDistance; + + if (::factory->logoEnabled==0 && textalign==AlignRight)x=r.right()-textwidth-logowidth; + if (::factory->logoEnabled==2 && textalign==AlignRight)x=r.right()+::factory->logoDistance; + + if (::factory->logoEnabled==0 && textalign==AlignHCenter)x=(r.right()+r.left()-textwidth)/2-logowidth; + if (::factory->logoEnabled==2 && textalign==AlignHCenter)x=(r.right()+r.left()+textwidth)/2+::factory->logoDistance; + pufferPainter.drawPixmap(x,(::factory->titlesize-::factory->logo.height())/2,::factory->logo); + } + }else if (::factory->logoEnabled!=1 && (isActive()||!::factory->logoActive)) { + int x=0; + r=titlebar_->geometry(); + if (::factory->logoEnabled==0) x=r.left(); + if (::factory->logoEnabled==2) x=r.right()-::factory->logo.width(); + pufferPainter.drawPixmap(x,(::factory->titlesize-::factory->logo.height())/2,::factory->logo); + + } + + pufferPainter.end(); + painter.drawPixmap(0,0,pufferPixmap); + + drawFrame=0; + if (wndcfg->outlineMode && (options()->moveResizeMaximizedWindows() || isShade() || (maximizeMode() & MaximizeFull)!=MaximizeFull)) + drawFrame=1; + + if (::factory->borderwidth>0) + { + if (background && !background->isNull()) + { // Draw the side and bottom of the window with transparency + // Left + r=TQRect(p.x()+drawFrame,p.y()+bt,bl-drawFrame,widget()->height()-bt-drawFrame); + painter.drawPixmap(TQPoint(drawFrame,bt),*background,r); + + // Right + r=TQRect(widget()->width()-br+p.x(),p.y()+bt,br-drawFrame,widget()->height()-bt-drawFrame); + painter.drawPixmap(TQPoint(widget()->width()-br,bt),*background,r); + + // Bottom + r=TQRect(p.x()+bl,p.y()+widget()->height()-bb,widget()->width()-bl-br,bb-drawFrame); + painter.drawPixmap(TQPoint(bl,widget()->height()-bb),*background,r); + }else{ + r=TQRect(drawFrame,bt,bl-drawFrame,widget()->height()-bt-drawFrame); + painter.fillRect(r,group.background()); + + r=TQRect(widget()->width()-br,bt,br-drawFrame,widget()->height()-bt-drawFrame); + painter.fillRect(r,group.background()); + + r=TQRect(bl,widget()->height()-bb,widget()->width()-bl-br,bb-drawFrame); + painter.fillRect(r,group.background()); + } + } + + if (!isShade()) + { + if (wndcfg->inlineMode==1) { + painter.setPen(wndcfg->inlineColor); + painter.drawRect(bl-1,bt-1,widget()->width()-bl-br+2,widget()->height()-bt-bb+2); + } + if (wndcfg->inlineMode==2) { + painter.setPen(wndcfg->inlineColor.dark(150)); + painter.drawLine(bl-1,bt-1,widget()->width()-br,bt-1); + painter.drawLine(bl-1,bt-1,bl-1,widget()->height()-bb); + painter.setPen(wndcfg->inlineColor.light(150)); + painter.drawLine(widget()->width()-br,bt-1,widget()->width()-br,widget()->height()-bb); + painter.drawLine(bl-1,widget()->height()-bb,widget()->width()-br-1,widget()->height()-bb); + } + if (wndcfg->inlineMode==3) { + painter.setPen(wndcfg->inlineColor.light(150)); + painter.drawLine(bl-1,bt-1,widget()->width()-br,bt-1); + painter.drawLine(bl-1,bt-1,bl-1,widget()->height()-bb); + painter.setPen(wndcfg->inlineColor.dark(150)); + painter.drawLine(widget()->width()-br,bt-1,widget()->width()-br,widget()->height()-bb); + painter.drawLine(bl-1,widget()->height()-bb,widget()->width()-br-1,widget()->height()-bb); + } + } + } + if (background==NULL && ::factory->transparency) + { // We don't have a background image, draw a solid rectangle + // And notify image_holder that we need an update asap + if (::factory)if (::factory->image_holder) + // UnInit image_holder, on next Repaint it will be Init'ed again. + TQTimer::singleShot(500,::factory->image_holder,TQT_SLOT(CheckSanity())); + } + + if (drawFrame) + { + // outline the frame + TQRect r=widget()->rect(); + TQColor c1,c2; + c1=c2=wndcfg->frameColor; + if (wndcfg->outlineMode==2)c1=c1.dark(140),c2=c2.light(140); + if (wndcfg->outlineMode==3)c1=c1.light(140),c2=c2.dark(140); + + painter.setPen(c1); + painter.drawLine(r.left(),r.top(),r.right(),r.top()); + painter.drawLine(r.left(),r.top(),r.left(),r.bottom()); + + painter.setPen(c2); + painter.drawLine(r.right(),r.top(),r.right(),r.bottom()); + painter.drawLine(r.left(),r.bottom(),r.right(),r.bottom()); + + if ((::factory->roundCorners) && !(!options()->moveResizeMaximizedWindows() && maximizeMode() & MaximizeFull)) + { + int cornersFlag = ::factory->roundCorners; + int r=(width()); + int b=(height()); + + // Draw edge of top-left corner inside the area removed by the mask. + if(cornersFlag & TOP_LEFT) { + painter.setPen(c1); + painter.drawPoint(3, 1); + painter.drawPoint(4, 1); + painter.drawPoint(2, 2); + painter.drawPoint(1, 3); + painter.drawPoint(1, 4); + } + + // Draw edge of top-right corner inside the area removed by the mask. + if(cornersFlag & TOP_RIGHT) { + painter.setPen(c1); + 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); + } + + // Draw edge of bottom-left corner inside the area removed by the mask. + if(cornersFlag & BOT_LEFT) { + painter.setPen(c2); + painter.drawPoint(1, b - 5); + painter.drawPoint(1, b - 4); + painter.drawPoint(2, b - 3); + painter.drawPoint(3, b - 2); + painter.drawPoint(4, b - 2); + } + + // Draw edge of bottom-right corner inside the area removed by the mask. + if(cornersFlag & BOT_RIGHT) { + painter.setPen(c2); + painter.drawPoint(r - 2, b - 5); + painter.drawPoint(r - 2, b - 4); + painter.drawPoint(r - 3, b - 3); + painter.drawPoint(r - 4, b - 2); + painter.drawPoint(r - 5, b - 2); + } + } + } +} + +void CrystalClient::resizeEvent(TQResizeEvent *e) +{ + if (widget()->isShown()) + { + if (!::factory->transparency) ; + else if (::factory->repaintMode==1) + { + if (!timer.isActive())timer.start(0,true); +// Repaint(); + } + // repaint only every xxx ms + else if (::factory->repaintMode==3 || !timer.isActive()) + { + // Repaint only, when mode!=fade || amount<100 + WND_CONFIG* wnd=isActive()?&::factory->active:&::factory->inactive; + if (wnd->mode!=0 || wnd->amount<100) + timer.start(::factory->repaintTime,true); + } + } + if (e->size()!=e->oldSize()) + { + updateMask(); + } +} + +void CrystalClient::moveEvent(TQMoveEvent *) +{ + if (widget()->isShown()) + { + if (!::factory->transparency) return; + else if (::factory->repaintMode==1) + { + Repaint(); + } + // repaint every xxx ms, so constant moving does not take too much CPU + else if (::factory->repaintMode==3 || !timer.isActive()) + { + // Repaint only, when mode!=fade || value<100, because otherwise it is a plain color + WND_CONFIG* wnd=isActive()?&::factory->active:&::factory->inactive; + if (wnd->mode!=0 || wnd->amount<100) + timer.start(::factory->repaintTime,true); + } + } +} + +void CrystalClient::showEvent(TQShowEvent *) +{ + if (widget()->isShown()) + Repaint(); +} + +void CrystalClient::Repaint() +{ + widget()->repaint(false); + for (int n=0; n<ButtonTypeCount; n++) + if (button[n]) button[n]->reset(); +} + +void CrystalClient::maxButtonPressed() +{ + if (button[ButtonMax]) + { + switch (button[ButtonMax]->lastMousePress()) + { + case Qt::MidButton: + maximize(maximizeMode() ^ MaximizeVertical); + break; + case Qt::RightButton: + maximize(maximizeMode() ^ MaximizeHorizontal); + break; + default: + maximize((maximizeMode() == MaximizeFull) ? MaximizeRestore: MaximizeFull); + } + } +} + +void CrystalClient::minButtonPressed() +{ + if (button[ButtonMin]) { + switch (button[ButtonMin]->lastMousePress()) { + case Qt::MidButton:{ + performWindowOperation(LowerOp); + break; + } + case Qt::RightButton: + if (isShadeable()) setShade(!isShade()); + break; + default: + minimize(); + } + } +} + +void CrystalClient::aboveButtonPressed() +{ + setKeepAbove(!keepAbove()); +} + +void CrystalClient::belowButtonPressed() +{ + setKeepBelow(!keepBelow()); +} + +void CrystalClient::keepAboveChange(bool /*set*/) +{ + if (button[ButtonAbove]) + { + button[ButtonAbove]->setBitmap(::factory->buttonImages[keepAbove()?ButtonImageUnAbove:ButtonImageAbove]); + } +} + +void CrystalClient::keepBelowChange(bool /*set*/) +{ + if (button[ButtonBelow]) + { + button[ButtonBelow]->setBitmap(::factory->buttonImages[keepBelow()?ButtonImageUnBelow:ButtonImageBelow]); + } +} + +void CrystalClient::closeButtonPressed() +{ + if (button[ButtonClose]) + switch (button[ButtonClose]->lastMousePress()) { + case Qt::RightButton: + { + Window frame,wrapper,client; + char param[20]; + ClientWindows(&frame,&wrapper,&client); + if (client != 0) { + TDEProcess *proc = new TDEProcess; + + *proc << "kdocker"; + sprintf(param,"0x%lx",client); + *proc << "-d" << "-w" << param; + proc->start(TDEProcess::DontCare); + } else { /* Sorry man */ } + break; + } + default: + closeWindow(); + break; + } +} + +void CrystalClient::shadeButtonPressed() +{ + if (button[ButtonShade]) { + switch (button[ButtonShade]->lastMousePress()) { + case Qt::MidButton: + case Qt::RightButton: + break; + default: + if (isShadeable()) setShade(!isShade()); + } + } +} + +void CrystalClient::menuButtonPressed() +{ + if (!button[ButtonMenu])return; + + static TQTime* t = 0; + static CrystalClient* lastClient = 0; + if (t == 0) + t = new TQTime; + bool dbl = (lastClient == this && t->elapsed() <= TQApplication::doubleClickInterval()); + lastClient = this; + t->start(); + + if (dbl) + { // Double Click on Symbol, close window + closeWindow(); + return; + } + + menuPopUp(); +} + +void CrystalClient::menuPopUp() +{ + TQPoint p(button[ButtonMenu]->rect().bottomLeft().x(), + button[ButtonMenu]->rect().bottomLeft().y()+2); + KDecorationFactory* f = factory(); + showWindowMenu(button[ButtonMenu]->mapToGlobal(p)); + if (!f->exists(this)) return; // decoration was destroyed + button[ButtonMenu]->setDown(false); +} + +#include "crystalclient.moc" |