You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
twin-style-crystal/client/crystalclient.cc

1667 lines
60 KiB

/***************************************************************************
* Copyright (C) 2006 by Sascha Hlusiak *
* Spam84@gmx.de *
* *
* 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 <kconfig.h>
#include <kglobal.h>
#include <kglobalsettings.h>
#include <klocale.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 <kwin.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
KConfig config("kwincrystalrc");
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(qt_xdisplay(), "_KDE_WM_MODAL_SYS_NOTIFICATION", False);
result = XGetWindowProperty(qt_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(qt_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(qt_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(qt_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) {
KProcess *proc = new KProcess;
*proc << "kdocker";
sprintf(param,"0x%lx",client);
*proc << "-d" << "-w" << param;
proc->start(KProcess::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"