fc23037d3a
but not explicitly the license, there I assumed they're licensed under the same license as the rest of KWin, which is GPLv2+ as of now. CC-ing all people mentioned as copyright holders just in case somebody wants some other license, e.g. the X11 license KWin used to be licensed under until KDE3.2. Please check with other relevant contributors and change accordingly in such case. CCMAIL: Karol Szwed <gallium@kde.org> CCMAIL: Luciano Montanaro <mikelima@cirulla.net> CCMAIL: Sandro Giessl <sandro@giessl.com> CCMAIL: Daniel M. Duley <mosfet@kde.org> CCMAIL: Chris Lee <clee@kde.org> svn path=/trunk/KDE/kdebase/workspace/; revision=742990
951 lines
27 KiB
C++
951 lines
27 KiB
C++
/********************************************************************
|
|
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, see <http://www.gnu.org/licenses/>.
|
|
*********************************************************************/
|
|
|
|
#include "kwmthemeclient.h"
|
|
|
|
#include <kconfig.h>
|
|
#include <kglobal.h>
|
|
#include <QLayout>
|
|
#include <qdrawutil.h>
|
|
#include <QPainter>
|
|
#include <kpixmapeffect.h>
|
|
#include <kstandarddirs.h>
|
|
#include <kdebug.h>
|
|
#include <klocale.h>
|
|
#include <QBitmap>
|
|
#include <QStyle>
|
|
#include <QLabel>
|
|
|
|
|
|
namespace KWMTheme {
|
|
|
|
|
|
/* static QPixmap stretchPixmap(QPixmap& src, bool stretchVert){
|
|
QPixmap dest;
|
|
QBitmap *srcMask, *destMask;
|
|
int w, h, w2, h2;
|
|
QPainter p;
|
|
|
|
if (src.isNull()) return src;
|
|
|
|
w = src.width();
|
|
h = src.height();
|
|
|
|
if (stretchVert){
|
|
w2 = w;
|
|
for (h2=h; h2<100; h2=h2<<1)
|
|
;
|
|
}
|
|
else{
|
|
h2 = h;
|
|
for (w2=w; w2<100; w2=w2<<1)
|
|
;
|
|
}
|
|
if (w2==w && h2==h) return src;
|
|
|
|
dest = src;
|
|
dest.resize(w2, h2);
|
|
|
|
p.begin(&dest);
|
|
p.drawTiledPixmap(0, 0, w2, h2, src);
|
|
p.end();
|
|
|
|
srcMask = (QBitmap*)src.mask();
|
|
if (srcMask){
|
|
destMask = (QBitmap*)dest.mask();
|
|
p.begin(destMask);
|
|
p.drawTiledPixmap(0, 0, w2, h2, *srcMask);
|
|
p.end();
|
|
}
|
|
return dest;
|
|
} */
|
|
|
|
|
|
inline const KDecorationOptions* options() { return KDecoration::options(); }
|
|
|
|
enum FramePixmap{FrameTop=0, FrameBottom, FrameLeft, FrameRight, FrameTopLeft,
|
|
FrameTopRight, FrameBottomLeft, FrameBottomRight};
|
|
|
|
static QPixmap *framePixmaps[8];
|
|
static QPixmap *menuPix, *iconifyPix, *closePix, *maxPix, *minmaxPix,
|
|
*pinupPix, *pindownPix;
|
|
static QPixmap *aTitlePix = 0;
|
|
static QPixmap *iTitlePix = 0;
|
|
static KPixmapEffect::GradientType grType;
|
|
static int maxExtent, titleAlign;
|
|
static bool titleGradient = true;
|
|
static bool pixmaps_created = false;
|
|
static bool titleSunken = false;
|
|
static bool titleTransparent;
|
|
|
|
static void create_pixmaps()
|
|
{
|
|
const char *keys[] = {"wm_top", "wm_bottom", "wm_left", "wm_right",
|
|
"wm_topleft", "wm_topright", "wm_bottomleft", "wm_bottomright"};
|
|
|
|
if(pixmaps_created)
|
|
return;
|
|
pixmaps_created = true;
|
|
|
|
KSharedConfig::Ptr _config = KGlobal::config();
|
|
KConfigGroup config(_config, "General");
|
|
|
|
QString tmpStr;
|
|
|
|
for(int i=0; i < 8; ++i)
|
|
{
|
|
framePixmaps[i] = new QPixmap(locate("data",
|
|
"kwin/pics/"+config.readEntry(keys[i], " ")));
|
|
if(framePixmaps[i]->isNull())
|
|
kWarning() << "Unable to load frame pixmap for " << keys[i] ;
|
|
}
|
|
/*
|
|
*framePixmaps[FrameTop] = stretchPixmap(*framePixmaps[FrameTop], false);
|
|
*framePixmaps[FrameBottom] = stretchPixmap(*framePixmaps[FrameBottom], false);
|
|
*framePixmaps[FrameLeft] = stretchPixmap(*framePixmaps[FrameLeft], true);
|
|
*framePixmaps[FrameRight] = stretchPixmap(*framePixmaps[FrameRight], true);
|
|
*/
|
|
maxExtent = framePixmaps[FrameTop]->height();
|
|
if(framePixmaps[FrameBottom]->height() > maxExtent)
|
|
maxExtent = framePixmaps[FrameBottom]->height();
|
|
if(framePixmaps[FrameLeft]->width() > maxExtent)
|
|
maxExtent = framePixmaps[FrameLeft]->width();
|
|
if(framePixmaps[FrameRight]->width() > maxExtent)
|
|
maxExtent = framePixmaps[FrameRight]->width();
|
|
|
|
maxExtent++;
|
|
|
|
menuPix = new QPixmap(locate("data",
|
|
"kwin/pics/"+config.readEntry("menu", " ")));
|
|
iconifyPix = new QPixmap(locate("data",
|
|
"kwin/pics/"+config.readEntry("iconify", " ")));
|
|
maxPix = new QPixmap(locate("appdata",
|
|
"pics/"+config.readEntry("maximize", " ")));
|
|
minmaxPix = new QPixmap(locate("data",
|
|
"kwin/pics/"+config.readEntry("maximizedown", " ")));
|
|
closePix = new QPixmap(locate("data",
|
|
"kwin/pics/"+config.readEntry("close", " ")));
|
|
pinupPix = new QPixmap(locate("data",
|
|
"kwin/pics/"+config.readEntry("pinup", " ")));
|
|
pindownPix = new QPixmap(locate("data",
|
|
"kwin/pics/"+config.readEntry("pindown", " ")));
|
|
if(menuPix->isNull())
|
|
menuPix->load(locate("data", "kwin/pics/menu.png"));
|
|
if(iconifyPix->isNull())
|
|
iconifyPix->load(locate("data", "kwin/pics/iconify.png"));
|
|
if(maxPix->isNull())
|
|
maxPix->load(locate("data", "kwin/pics/maximize.png"));
|
|
if(minmaxPix->isNull())
|
|
minmaxPix->load(locate("data", "kwin/pics/maximizedown.png"));
|
|
if(closePix->isNull())
|
|
closePix->load(locate("data", "kwin/pics/close.png"));
|
|
if(pinupPix->isNull())
|
|
pinupPix->load(locate("data", "kwin/pics/pinup.png"));
|
|
if(pindownPix->isNull())
|
|
pindownPix->load(locate("data", "kwin/pics/pindown.png"));
|
|
|
|
tmpStr = config.readEntry("TitleAlignment");
|
|
if(tmpStr == "right")
|
|
titleAlign = Qt::AlignRight | Qt::AlignVCenter;
|
|
else if(tmpStr == "middle")
|
|
titleAlign = Qt::AlignCenter;
|
|
else
|
|
titleAlign = Qt::AlignLeft | Qt::AlignVCenter;
|
|
titleSunken = config.readEntry("TitleFrameShaded", true );
|
|
// titleSunken = true; // is this fixed?
|
|
titleTransparent = config.readEntry("PixmapUnderTitleText", true);
|
|
|
|
tmpStr = config.readEntry("TitlebarLook");
|
|
if(tmpStr == "shadedVertical"){
|
|
aTitlePix = new QPixmap;
|
|
aTitlePix->resize(32, 20);
|
|
KPixmapEffect::gradient(*aTitlePix,
|
|
options()->color(KDecorationOptions::ColorTitleBar, true),
|
|
options()->color(KDecorationOptions::ColorTitleBlend, true),
|
|
KPixmapEffect::VerticalGradient);
|
|
iTitlePix = new QPixmap;
|
|
iTitlePix->resize(32, 20);
|
|
KPixmapEffect::gradient(*iTitlePix,
|
|
options()->color(KDecorationOptions::ColorTitleBar, false),
|
|
options()->color(KDecorationOptions::ColorTitleBlend, false),
|
|
KPixmapEffect::VerticalGradient);
|
|
titleGradient = false; // we can just tile this
|
|
|
|
}
|
|
else if(tmpStr == "shadedHorizontal")
|
|
grType = KPixmapEffect::HorizontalGradient;
|
|
else if(tmpStr == "shadedDiagonal")
|
|
grType = KPixmapEffect::DiagonalGradient;
|
|
else if(tmpStr == "shadedCrossDiagonal")
|
|
grType = KPixmapEffect::CrossDiagonalGradient;
|
|
else if(tmpStr == "shadedPyramid")
|
|
grType = KPixmapEffect::PyramidGradient;
|
|
else if(tmpStr == "shadedRectangle")
|
|
grType = KPixmapEffect::RectangleGradient;
|
|
else if(tmpStr == "shadedPipeCross")
|
|
grType = KPixmapEffect::PipeCrossGradient;
|
|
else if(tmpStr == "shadedElliptic")
|
|
grType = KPixmapEffect::EllipticGradient;
|
|
else{
|
|
titleGradient = false;
|
|
tmpStr = config.readEntry("TitlebarPixmapActive", "");
|
|
if(!tmpStr.isEmpty()){
|
|
aTitlePix = new QPixmap;
|
|
aTitlePix->load(locate("data", "kwin/pics/" + tmpStr));
|
|
}
|
|
else
|
|
aTitlePix = NULL;
|
|
tmpStr = config.readEntry("TitlebarPixmapInactive", "");
|
|
if(!tmpStr.isEmpty()){
|
|
iTitlePix = new QPixmap;
|
|
iTitlePix->load(locate("data", "kwin/pics/" + tmpStr));
|
|
}
|
|
else
|
|
iTitlePix = NULL;
|
|
}
|
|
}
|
|
|
|
static void delete_pixmaps()
|
|
{
|
|
for(int i=0; i < 8; ++i)
|
|
delete framePixmaps[i];
|
|
|
|
delete menuPix;
|
|
delete iconifyPix;
|
|
delete closePix;
|
|
delete maxPix;
|
|
delete minmaxPix;
|
|
delete pinupPix;
|
|
delete pindownPix;
|
|
delete aTitlePix;
|
|
aTitlePix = 0;
|
|
delete iTitlePix;
|
|
iTitlePix = 0;
|
|
|
|
titleGradient = true;
|
|
pixmaps_created = false;
|
|
titleSunken = false;
|
|
}
|
|
|
|
void MyButton::drawButtonLabel(QPainter *p)
|
|
{
|
|
if(pixmap()){
|
|
// If we have a theme who's button covers the entire width or
|
|
// entire height, we shift down/right by 1 pixel so we have
|
|
// some visual notification of button presses. i.e. for MGBriezh
|
|
int offset = (isDown() && ((pixmap()->width() >= width()) ||
|
|
(pixmap()->height() >= height()))) ? 1 : 0;
|
|
style().drawItem(p, QRect( offset, offset, width(), height() ),
|
|
AlignCenter, colorGroup(),
|
|
true, pixmap(), QString());
|
|
}
|
|
}
|
|
|
|
KWMThemeClient::KWMThemeClient( KDecorationBridge* b, KDecorationFactory* f )
|
|
: KDecoration( b, f )
|
|
{
|
|
}
|
|
|
|
void KWMThemeClient::init()
|
|
{
|
|
createMainWidget( WResizeNoErase | WStaticContents );
|
|
widget()->installEventFilter( this );
|
|
|
|
stickyBtn = maxBtn = mnuBtn = 0;
|
|
layout = new QGridLayout(widget());
|
|
layout->addColSpacing(0, maxExtent);
|
|
layout->addColSpacing(2, maxExtent);
|
|
|
|
layout->addRowSpacing(0, maxExtent);
|
|
|
|
layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Fixed,
|
|
QSizePolicy::Expanding));
|
|
|
|
if( isPreview())
|
|
layout->addWidget( new QLabel( i18n( "<center><b>KWMTheme</b></center>" ), widget()), 2, 1);
|
|
else
|
|
layout->addItem( new QSpacerItem( 0, 0 ), 2, 1);
|
|
|
|
// Without the next line, shading flickers
|
|
layout->addItem( new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding) );
|
|
layout->addRowSpacing(3, maxExtent);
|
|
layout->setRowStretch(2, 10);
|
|
layout->setColumnStretch(1, 10);
|
|
|
|
QBoxLayout* hb = new QBoxLayout(0, QBoxLayout::LeftToRight, 0, 0, 0);
|
|
layout->addLayout( hb, 1, 1 );
|
|
|
|
KSharedConfig::Ptr _config = KGlobal::config();
|
|
KConfigGroup config(_config, "Buttons");
|
|
QString val;
|
|
MyButton *btn;
|
|
int i;
|
|
static const char *defaultButtons[]={"Menu","Sticky","Off","Iconify",
|
|
"Maximize","Close"};
|
|
static const char keyOffsets[]={"ABCDEF"};
|
|
for(i=0; i < 6; ++i){
|
|
if(i == 3){
|
|
titlebar = new QSpacerItem(10, 20, QSizePolicy::Expanding,
|
|
QSizePolicy::Minimum );
|
|
hb->addItem( titlebar );
|
|
}
|
|
QString key("Button");
|
|
key += QChar(keyOffsets[i]);
|
|
val = config.readEntry(key, defaultButtons[i]);
|
|
if(val == "Menu"){
|
|
mnuBtn = new MyButton(widget(), "menu");
|
|
mnuBtn->setToolTip( i18n("Menu"));
|
|
iconChange();
|
|
hb->addWidget(mnuBtn);
|
|
mnuBtn->setFixedSize(20, 20);
|
|
connect(mnuBtn, SIGNAL(pressed()), this,
|
|
SLOT(menuButtonPressed()));
|
|
}
|
|
else if(val == "Sticky"){
|
|
stickyBtn = new MyButton(widget(), "sticky");
|
|
stickyBtn->setToolTip( i18n("Sticky"));
|
|
if (isOnAllDesktops())
|
|
stickyBtn->setPixmap(*pindownPix);
|
|
else
|
|
stickyBtn->setPixmap(*pinupPix);
|
|
connect(stickyBtn, SIGNAL( clicked() ), this, SLOT(toggleOnAllDesktops()));
|
|
hb->addWidget(stickyBtn);
|
|
stickyBtn->setFixedSize(20, 20);
|
|
}
|
|
else if((val == "Iconify") && isMinimizable()){
|
|
btn = new MyButton(widget(), "iconify");
|
|
btn->setToolTip( i18n("Minimize"));
|
|
btn->setPixmap(*iconifyPix);
|
|
connect(btn, SIGNAL(clicked()), this, SLOT(minimize()));
|
|
hb->addWidget(btn);
|
|
btn->setFixedSize(20, 20);
|
|
}
|
|
else if((val == "Maximize") && isMaximizable()){
|
|
maxBtn = new MyButton(widget(), "max");
|
|
maxBtn->setToolTip( i18n("Maximize"));
|
|
maxBtn->setPixmap(*maxPix);
|
|
connect(maxBtn, SIGNAL(clicked()), this, SLOT(maximize()));
|
|
hb->addWidget(maxBtn);
|
|
maxBtn->setFixedSize(20, 20);
|
|
}
|
|
else if((val == "Close") && isCloseable()){
|
|
btn = new MyButton(widget(), "close");
|
|
btn->setToolTip( i18n("Close"));
|
|
btn->setPixmap(*closePix);
|
|
connect(btn, SIGNAL(clicked()), this, SLOT(closeWindow()));
|
|
hb->addWidget(btn);
|
|
btn->setFixedSize(20, 20);
|
|
}
|
|
else{
|
|
if((val != "Off") &&
|
|
((val == "Iconify") && !isMinimizable()) &&
|
|
((val == "Maximize") && !isMaximizable()))
|
|
kWarning() << "KWin: Unrecognized button value: " << val ;
|
|
|
|
}
|
|
}
|
|
if(titleGradient){
|
|
aGradient = new QPixmap;
|
|
iGradient = new QPixmap;
|
|
}
|
|
else{
|
|
aGradient = 0;
|
|
iGradient = 0;
|
|
}
|
|
widget()->setBackgroundMode(NoBackground);
|
|
}
|
|
|
|
void KWMThemeClient::drawTitle(QPainter &dest)
|
|
{
|
|
QRect titleRect = titlebar->geometry();
|
|
QRect r(0, 0, titleRect.width(), titleRect.height());
|
|
QPixmap buffer;
|
|
|
|
if(buffer.width() == r.width())
|
|
return;
|
|
|
|
buffer.resize(r.size());
|
|
QPainter p;
|
|
p.begin(&buffer);
|
|
|
|
if(titleSunken){
|
|
qDrawShadeRect(&p, r, options()->palette(KDecorationOptions::ColorFrame, isActive()).active(),
|
|
true, 1, 0);
|
|
r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2);
|
|
}
|
|
|
|
QPixmap *fill = isActive() ? aTitlePix : iTitlePix;
|
|
if(fill)
|
|
p.drawTiledPixmap(r, *fill);
|
|
else if(titleGradient){
|
|
fill = isActive() ? aGradient : iGradient;
|
|
if(fill->width() != r.width()){
|
|
fill->resize(r.width(), 20);
|
|
KPixmapEffect::gradient(*fill,
|
|
options()->color(KDecorationOptions::ColorTitleBar, isActive()),
|
|
options()->color(KDecorationOptions::ColorTitleBlend, isActive()),
|
|
grType);
|
|
}
|
|
p.drawTiledPixmap(r, *fill);
|
|
}
|
|
else{
|
|
p.fillRect(r, options()->palette(KDecorationOptions::ColorTitleBar, isActive()).active().
|
|
brush(QPalette::Button));
|
|
}
|
|
p.setFont(options()->font(isActive()));
|
|
p.setPen(options()->color(KDecorationOptions::ColorFont, isActive()));
|
|
// Add left & right margin
|
|
r.setLeft(r.left()+5);
|
|
r.setRight(r.right()-5);
|
|
p.drawText(r, titleAlign, caption());
|
|
p.end();
|
|
|
|
dest.drawPixmap(titleRect.x(), titleRect.y(), buffer);
|
|
}
|
|
|
|
|
|
void KWMThemeClient::resizeEvent( QResizeEvent* )
|
|
{
|
|
doShape();
|
|
widget()->repaint();
|
|
}
|
|
|
|
void KWMThemeClient::captionChange()
|
|
{
|
|
widget()->repaint( titlebar->geometry(), false );
|
|
}
|
|
|
|
void KWMThemeClient::paintEvent( QPaintEvent *)
|
|
{
|
|
QPainter p;
|
|
p.begin(widget());
|
|
int x,y;
|
|
// first the corners
|
|
int w1 = framePixmaps[FrameTopLeft]->width();
|
|
int h1 = framePixmaps[FrameTopLeft]->height();
|
|
if (w1 > width()/2) w1 = width()/2;
|
|
if (h1 > height()/2) h1 = height()/2;
|
|
p.drawPixmap(0,0,*framePixmaps[FrameTopLeft],
|
|
0,0,w1, h1);
|
|
int w2 = framePixmaps[FrameTopRight]->width();
|
|
int h2 = framePixmaps[FrameTopRight]->height();
|
|
if (w2 > width()/2) w2 = width()/2;
|
|
if (h2 > height()/2) h2 = height()/2;
|
|
p.drawPixmap(width()-w2,0,*framePixmaps[FrameTopRight],
|
|
framePixmaps[FrameTopRight]->width()-w2,0,w2, h2);
|
|
|
|
int w3 = framePixmaps[FrameBottomLeft]->width();
|
|
int h3 = framePixmaps[FrameBottomLeft]->height();
|
|
if (w3 > width()/2) w3 = width()/2;
|
|
if (h3 > height()/2) h3 = height()/2;
|
|
p.drawPixmap(0,height()-h3,*framePixmaps[FrameBottomLeft],
|
|
0,framePixmaps[FrameBottomLeft]->height()-h3,w3, h3);
|
|
|
|
int w4 = framePixmaps[FrameBottomRight]->width();
|
|
int h4 = framePixmaps[FrameBottomRight]->height();
|
|
if (w4 > width()/2) w4 = width()/2;
|
|
if (h4 > height()/2) h4 = height()/2;
|
|
p.drawPixmap(width()-w4,height()-h4,*(framePixmaps[FrameBottomRight]),
|
|
framePixmaps[FrameBottomRight]->width()-w4,
|
|
framePixmaps[FrameBottomRight]->height()-h4,
|
|
w4, h4);
|
|
|
|
QPixmap pm;
|
|
QMatrix m;
|
|
int n,s,w;
|
|
//top
|
|
pm = *framePixmaps[FrameTop];
|
|
|
|
if (pm.width() > 0){
|
|
s = width()-w2-w1;
|
|
n = s/pm.width();
|
|
w = n>0?s/n:s;
|
|
m.reset();
|
|
m.scale(w/(float)pm.width(), 1);
|
|
pm = pm.transformed(m);
|
|
|
|
x = w1;
|
|
while (1){
|
|
if (pm.width() < width()-w2-x){
|
|
p.drawPixmap(x,maxExtent-pm.height()-1,
|
|
pm);
|
|
x += pm.width();
|
|
}
|
|
else {
|
|
p.drawPixmap(x,maxExtent-pm.height()-1,
|
|
pm,
|
|
0,0,width()-w2-x,pm.height());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//bottom
|
|
pm = *framePixmaps[FrameBottom];
|
|
|
|
if (pm.width() > 0){
|
|
s = width()-w4-w3;
|
|
n = s/pm.width();
|
|
w = n>0?s/n:s;
|
|
m.reset();
|
|
m.scale(w/(float)pm.width(), 1);
|
|
pm = pm.transformed(m);
|
|
|
|
x = w3;
|
|
while (1){
|
|
if (pm.width() < width()-w4-x){
|
|
p.drawPixmap(x,height()-maxExtent+1,pm);
|
|
x += pm.width();
|
|
}
|
|
else {
|
|
p.drawPixmap(x,height()-maxExtent+1,pm,
|
|
0,0,width()-w4-x,pm.height());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//left
|
|
pm = *framePixmaps[FrameLeft];
|
|
|
|
if (pm.height() > 0){
|
|
s = height()-h3-h1;
|
|
n = s/pm.height();
|
|
w = n>0?s/n:s;
|
|
m.reset();
|
|
m.scale(1, w/(float)pm.height());
|
|
pm = pm.transformed(m);
|
|
|
|
y = h1;
|
|
while (1){
|
|
if (pm.height() < height()-h3-y){
|
|
p.drawPixmap(maxExtent-pm.width()-1, y,
|
|
pm);
|
|
y += pm.height();
|
|
}
|
|
else {
|
|
p.drawPixmap(maxExtent-pm.width()-1, y,
|
|
pm,
|
|
0,0, pm.width(),
|
|
height()-h3-y);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//right
|
|
pm = *framePixmaps[FrameRight];
|
|
|
|
if (pm.height() > 0){
|
|
s = height()-h4-h2;
|
|
n = s/pm.height();
|
|
w = n>0?s/n:s;
|
|
m.reset();
|
|
m.scale(1, w/(float)pm.height());
|
|
pm = pm.transformed(m);
|
|
|
|
y = h2;
|
|
while (1){
|
|
if (pm.height() < height()-h4-y){
|
|
p.drawPixmap(width()-maxExtent+1, y,
|
|
pm);
|
|
y += pm.height();
|
|
}
|
|
else {
|
|
p.drawPixmap(width()-maxExtent+1, y,
|
|
pm,
|
|
0,0, pm.width(),
|
|
height()-h4-y);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
drawTitle(p);
|
|
|
|
QColor c = widget()->colorGroup().background();
|
|
|
|
// KWM evidently had a 1 pixel border around the client window. We
|
|
// emulate it here, but should be removed at some point in order to
|
|
// seamlessly mesh widget themes
|
|
p.setPen(c);
|
|
p.drawRect(maxExtent-1, maxExtent-1, width()-(maxExtent-1)*2,
|
|
height()-(maxExtent-1)*2);
|
|
|
|
// We fill the area behind the wrapped widget to ensure that
|
|
// shading animation is drawn as smoothly as possible
|
|
QRect r(layout->cellGeometry(2, 1));
|
|
p.fillRect( r.x(), r.y(), r.width(), r.height(), c);
|
|
p.end();
|
|
}
|
|
|
|
void KWMThemeClient::doShape()
|
|
{
|
|
|
|
QBitmap shapemask(width(), height());
|
|
shapemask.fill(color0);
|
|
QPainter p;
|
|
p.begin(&shapemask);
|
|
p.setBrush(color1);
|
|
p.setPen(color1);
|
|
int x,y;
|
|
// first the corners
|
|
int w1 = framePixmaps[FrameTopLeft]->width();
|
|
int h1 = framePixmaps[FrameTopLeft]->height();
|
|
if (w1 > width()/2) w1 = width()/2;
|
|
if (h1 > height()/2) h1 = height()/2;
|
|
if (framePixmaps[FrameTopLeft]->mask())
|
|
p.drawPixmap(0,0,*framePixmaps[FrameTopLeft]->mask(),
|
|
0,0,w1, h1);
|
|
else
|
|
p.fillRect(0,0,w1,h1,color1);
|
|
int w2 = framePixmaps[FrameTopRight]->width();
|
|
int h2 = framePixmaps[FrameTopRight]->height();
|
|
if (w2 > width()/2) w2 = width()/2;
|
|
if (h2 > height()/2) h2 = height()/2;
|
|
if (framePixmaps[FrameTopRight]->mask())
|
|
p.drawPixmap(width()-w2,0,*framePixmaps[FrameTopRight]->mask(),
|
|
framePixmaps[FrameTopRight]->width()-w2,0,w2, h2);
|
|
else
|
|
p.fillRect(width()-w2,0,w2, h2,color1);
|
|
|
|
int w3 = framePixmaps[FrameBottomLeft]->width();
|
|
int h3 = framePixmaps[FrameBottomLeft]->height();
|
|
if (w3 > width()/2) w3 = width()/2;
|
|
if (h3 > height()/2) h3 = height()/2;
|
|
if (framePixmaps[FrameBottomLeft]->mask())
|
|
p.drawPixmap(0,height()-h3,*framePixmaps[FrameBottomLeft]->mask(),
|
|
0,framePixmaps[FrameBottomLeft]->height()-h3,w3, h3);
|
|
else
|
|
p.fillRect(0,height()-h3,w3,h3,color1);
|
|
|
|
int w4 = framePixmaps[FrameBottomRight]->width();
|
|
int h4 = framePixmaps[FrameBottomRight]->height();
|
|
if (w4 > width()/2) w4 = width()/2;
|
|
if (h4 > height()/2) h4 = height()/2;
|
|
if (framePixmaps[FrameBottomRight]->mask())
|
|
p.drawPixmap(width()-w4,height()-h4,*framePixmaps[FrameBottomRight]->mask(),
|
|
framePixmaps[FrameBottomRight]->width()-w4,
|
|
framePixmaps[FrameBottomRight]->height()-h4,
|
|
w4, h4);
|
|
else
|
|
p.fillRect(width()-w4,height()-h4,w4,h4,color1);
|
|
|
|
QPixmap pm;
|
|
QMatrix m;
|
|
int n,s,w;
|
|
//top
|
|
if (framePixmaps[FrameTop]->mask())
|
|
{
|
|
pm = *framePixmaps[FrameTop]->mask();
|
|
|
|
s = width()-w2-w1;
|
|
n = s/pm.width();
|
|
w = n>0?s/n:s;
|
|
m.reset();
|
|
m.scale(w/(float)pm.width(), 1);
|
|
pm = pm.transformed(m);
|
|
|
|
x = w1;
|
|
while (1){
|
|
if (pm.width() < width()-w2-x){
|
|
p.drawPixmap(x,maxExtent-pm.height()-1,
|
|
pm);
|
|
x += pm.width();
|
|
}
|
|
else {
|
|
p.drawPixmap(x,maxExtent-pm.height()-1,
|
|
pm,
|
|
0,0,width()-w2-x,pm.height());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//bottom
|
|
if (framePixmaps[FrameBottom]->mask())
|
|
{
|
|
pm = *framePixmaps[FrameBottom]->mask();
|
|
|
|
s = width()-w4-w3;
|
|
n = s/pm.width();
|
|
w = n>0?s/n:s;
|
|
m.reset();
|
|
m.scale(w/(float)pm.width(), 1);
|
|
pm = pm.transformed(m);
|
|
|
|
x = w3;
|
|
while (1){
|
|
if (pm.width() < width()-w4-x){
|
|
p.drawPixmap(x,height()-maxExtent+1,pm);
|
|
x += pm.width();
|
|
}
|
|
else {
|
|
p.drawPixmap(x,height()-maxExtent+1,pm,
|
|
0,0,width()-w4-x,pm.height());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//left
|
|
if (framePixmaps[FrameLeft]->mask())
|
|
{
|
|
pm = *framePixmaps[FrameLeft]->mask();
|
|
|
|
s = height()-h3-h1;
|
|
n = s/pm.height();
|
|
w = n>0?s/n:s;
|
|
m.reset();
|
|
m.scale(1, w/(float)pm.height());
|
|
pm = pm.transformed(m);
|
|
|
|
y = h1;
|
|
while (1){
|
|
if (pm.height() < height()-h3-y){
|
|
p.drawPixmap(maxExtent-pm.width()-1, y,
|
|
pm);
|
|
y += pm.height();
|
|
}
|
|
else {
|
|
p.drawPixmap(maxExtent-pm.width()-1, y,
|
|
pm,
|
|
0,0, pm.width(),
|
|
height()-h3-y);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//right
|
|
if (framePixmaps[FrameRight]->mask())
|
|
{
|
|
pm = *framePixmaps[FrameRight]->mask();
|
|
|
|
s = height()-h4-h2;
|
|
n = s/pm.height();
|
|
w = n>0?s/n:s;
|
|
m.reset();
|
|
m.scale(1, w/(float)pm.height());
|
|
pm = pm.transformed(m);
|
|
|
|
y = h2;
|
|
while (1){
|
|
if (pm.height() < height()-h4-y){
|
|
p.drawPixmap(width()-maxExtent+1, y,
|
|
pm);
|
|
y += pm.height();
|
|
}
|
|
else {
|
|
p.drawPixmap(width()-maxExtent+1, y,
|
|
pm,
|
|
0,0, pm.width(),
|
|
height()-h4-y);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
p.fillRect(maxExtent-1, maxExtent-1, width()-2*maxExtent+2, height()-2*maxExtent+2, color1);
|
|
setMask(shapemask);
|
|
}
|
|
|
|
|
|
void KWMThemeClient::showEvent(QShowEvent *)
|
|
{
|
|
doShape();
|
|
widget()->repaint(false);
|
|
}
|
|
|
|
void KWMThemeClient::mouseDoubleClickEvent( QMouseEvent * e )
|
|
{
|
|
if (e->button() == LeftButton && titlebar->geometry().contains( e->pos() ) )
|
|
titlebarDblClickOperation();
|
|
}
|
|
|
|
void KWMThemeClient::desktopChange()
|
|
{
|
|
if (stickyBtn) {
|
|
bool on = isOnAllDesktops();
|
|
stickyBtn->setPixmap(on ? *pindownPix : *pinupPix);
|
|
stickyBtn->setToolTip( on ? i18n("Unsticky") : i18n("Sticky") );
|
|
}
|
|
}
|
|
|
|
void KWMThemeClient::maximizeChange()
|
|
{
|
|
if (maxBtn) {
|
|
bool m = maximizeMode() == MaximizeFull;
|
|
maxBtn->setPixmap(m ? *minmaxPix : *maxPix);
|
|
maxBtn->setToolTip( m ? i18n("Restore") : i18n("Maximize"));
|
|
}
|
|
}
|
|
|
|
void KWMThemeClient::slotMaximize()
|
|
{
|
|
maximize( maximizeMode() == MaximizeFull ? MaximizeRestore : MaximizeFull );
|
|
}
|
|
|
|
void KWMThemeClient::activeChange()
|
|
{
|
|
widget()->update();
|
|
}
|
|
|
|
KDecoration::Position KWMThemeClient::mousePosition(const QPoint &p) const
|
|
{
|
|
Position m = KDecoration::mousePosition(p);
|
|
// corners
|
|
if(p.y() < framePixmaps[FrameTop]->height() &&
|
|
p.x() < framePixmaps[FrameLeft]->width()){
|
|
m = PositionTopLeft;
|
|
}
|
|
else if(p.y() < framePixmaps[FrameTop]->height() &&
|
|
p.x() > width()-framePixmaps[FrameRight]->width()){
|
|
m = PositionTopRight;
|
|
}
|
|
else if(p.y() > height()-framePixmaps[FrameBottom]->height() &&
|
|
p.x() < framePixmaps[FrameLeft]->width()){
|
|
m = PositionBottomLeft;
|
|
}
|
|
else if(p.y() > height()-framePixmaps[FrameBottom]->height() &&
|
|
p.x() > width()-framePixmaps[FrameRight]->width()){
|
|
m = PositionBottomRight;
|
|
} // edges
|
|
else if(p.y() < framePixmaps[FrameTop]->height())
|
|
m = PositionTop;
|
|
else if(p.y() > height()-framePixmaps[FrameBottom]->height())
|
|
m = PositionBottom;
|
|
else if(p.x() < framePixmaps[FrameLeft]->width())
|
|
m = PositionLeft;
|
|
else if(p.x() > width()-framePixmaps[FrameRight]->width())
|
|
m = PositionRight;
|
|
return(m);
|
|
}
|
|
|
|
void KWMThemeClient::menuButtonPressed()
|
|
{
|
|
mnuBtn->setDown(false); // will stay down if I don't do this
|
|
QPoint pos = mnuBtn->mapToGlobal(mnuBtn->rect().bottomLeft());
|
|
showWindowMenu( pos );
|
|
}
|
|
|
|
void KWMThemeClient::iconChange()
|
|
{
|
|
if(mnuBtn){
|
|
if( icon().pixmap( QIcon::Small, QIcon::Normal ).isNull()){
|
|
mnuBtn->setPixmap(*menuPix);
|
|
}
|
|
else{
|
|
mnuBtn->setPixmap(icon().pixmap( QIcon::Small, QIcon::Normal ));
|
|
}
|
|
}
|
|
}
|
|
|
|
bool KWMThemeClient::eventFilter( QObject* o, QEvent* e )
|
|
{
|
|
if ( o != widget() )
|
|
return false;
|
|
|
|
switch ( e->type() )
|
|
{
|
|
case QEvent::Resize:
|
|
resizeEvent( static_cast< QResizeEvent* >( e ) );
|
|
return true;
|
|
|
|
case QEvent::Paint:
|
|
paintEvent( static_cast< QPaintEvent* >( e ) );
|
|
return true;
|
|
|
|
case QEvent::MouseButtonDblClick:
|
|
mouseDoubleClickEvent( static_cast< QMouseEvent* >( e ) );
|
|
return true;
|
|
|
|
case QEvent::MouseButtonPress:
|
|
processMousePressEvent( static_cast< QMouseEvent* >( e ) );
|
|
return true;
|
|
|
|
case QEvent::Show:
|
|
showEvent( static_cast< QShowEvent* >( e ) );
|
|
return true;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
QSize KWMThemeClient::minimumSize() const
|
|
{
|
|
return widget()->minimumSize().expandedTo( QSize( 100, 50 ));
|
|
}
|
|
|
|
void KWMThemeClient::resize( const QSize& s )
|
|
{
|
|
widget()->resize( s );
|
|
}
|
|
|
|
void KWMThemeClient::borders( int& left, int& right, int& top, int& bottom ) const
|
|
{
|
|
left =
|
|
right =
|
|
top =
|
|
bottom =
|
|
|
|
TODO
|
|
}
|
|
|
|
KWMThemeFactory::KWMThemeFactory()
|
|
{
|
|
create_pixmaps();
|
|
}
|
|
|
|
KWMThemeFactory::~KWMThemeFactory()
|
|
{
|
|
delete_pixmaps();
|
|
}
|
|
|
|
KDecoration* KWMThemeFactory::createDecoration( KDecorationBridge* b )
|
|
{
|
|
return new KWMThemeClient( b, this );
|
|
}
|
|
|
|
bool KWMThemeFactory::reset( unsigned long mask )
|
|
{
|
|
bool needHardReset = false;
|
|
|
|
TODO
|
|
|
|
// doesn't obey the Border size setting
|
|
if( mask & ( SettingFont | SettingButtons ))
|
|
needHardReset = true;
|
|
|
|
if( mask & ( SettingFont | SettingColors )) {
|
|
KWMTheme::delete_pixmaps();
|
|
KWMTheme::create_pixmaps();
|
|
}
|
|
|
|
if( !needHardReset )
|
|
resetDecorations( mask );
|
|
return needHardReset;
|
|
}
|
|
|
|
}
|
|
|
|
extern "C"
|
|
{
|
|
KDE_EXPORT KDecorationFactory *create_factory()
|
|
{
|
|
return new KWMTheme::KWMThemeFactory();
|
|
}
|
|
}
|
|
|
|
#include "kwmthemeclient.moc"
|