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
834 lines
24 KiB
C++
834 lines
24 KiB
C++
/********************************************************************
|
|
|
|
Gallium-Quartz KWin client
|
|
|
|
Copyright (C) 2005 Sandro Giessl <sandro@giessl.com>
|
|
Copyright 2001
|
|
Karol Szwed <gallium@kde.org>
|
|
http://gallium.n3.net/
|
|
|
|
Based on the KDE default client.
|
|
|
|
Includes mini titlebars for ToolWindow Support.
|
|
Button positions are now customizable.
|
|
|
|
drawColorBitmaps orignally from kdefx:
|
|
Copyright (C) 1999 Daniel M. Duley <mosfet@kde.org>
|
|
|
|
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 <kconfiggroup.h>
|
|
#include <kglobal.h>
|
|
#include <klocale.h>
|
|
#include <QBitmap>
|
|
#include <QImage>
|
|
#include <QPixmap>
|
|
#include <QApplication>
|
|
#include <QPaintEvent>
|
|
#include <QPainter>
|
|
|
|
#include "quartz.h"
|
|
|
|
|
|
namespace Quartz {
|
|
|
|
static const unsigned char iconify_bits[] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00,
|
|
0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
|
|
|
static const unsigned char close_bits[] = {
|
|
0x00, 0x00, 0x86, 0x01, 0xcc, 0x00, 0x78, 0x00, 0x30, 0x00, 0x78, 0x00,
|
|
0xcc, 0x00, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
static const unsigned char maximize_bits[] = {
|
|
0xff, 0x01, 0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x01, 0x01, 0xff, 0x01, 0x00, 0x00};
|
|
|
|
static const unsigned char minmax_bits[] = {
|
|
0xfc, 0x00, 0xfc, 0x00, 0x84, 0x00, 0xbf, 0x00, 0xbf, 0x00, 0xe1, 0x00,
|
|
0x21, 0x00, 0x21, 0x00, 0x3f, 0x00, 0x00, 0x00};
|
|
|
|
static const unsigned char question_bits[] = {
|
|
0x00, 0x00, 0x3c, 0x00, 0x66, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00,
|
|
0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00};
|
|
|
|
static const unsigned char pindown_white_bits[] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x1f, 0xa0, 0x03,
|
|
0xb0, 0x01, 0x30, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x20, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
static const unsigned char pindown_gray_bits[] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
|
|
0x00, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x80, 0x07, 0xc0, 0x03, 0xe0, 0x01,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
static const unsigned char pindown_dgray_bits[] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x10, 0x70, 0x20, 0x50, 0x20,
|
|
0x48, 0x30, 0xc8, 0x38, 0x08, 0x1f, 0x08, 0x18, 0x10, 0x1c, 0x10, 0x0e,
|
|
0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
static const unsigned char pinup_white_bits[] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x11,
|
|
0x3f, 0x15, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
static const unsigned char pinup_gray_bits[] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x80, 0x0a, 0xbf, 0x0a, 0x80, 0x15, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
static const unsigned char pinup_dgray_bits[] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x40, 0x31, 0x40, 0x2e,
|
|
0x40, 0x20, 0x40, 0x20, 0x7f, 0x2a, 0x40, 0x3f, 0xc0, 0x31, 0xc0, 0x20,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
static const unsigned char above_on_bits[] = {
|
|
0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x30, 0x00, 0xfc, 0x00, 0x78, 0x00,
|
|
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
static const unsigned char above_off_bits[] = {
|
|
0x30, 0x00, 0x78, 0x00, 0xfc, 0x00, 0x30, 0x00, 0xfe, 0x01, 0xfe, 0x01,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
static const unsigned char below_on_bits[] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x78, 0x00, 0xfc, 0x00,
|
|
0x30, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00};
|
|
|
|
static const unsigned char below_off_bits[] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01,
|
|
0x30, 0x00, 0xfc, 0x00, 0x78, 0x00, 0x30, 0x00};
|
|
|
|
static const unsigned char shade_on_bits[] = {
|
|
0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x02, 0x01, 0x02, 0x01,
|
|
0x02, 0x01, 0x02, 0x01, 0xfe, 0x01, 0x00, 0x00};
|
|
|
|
static const unsigned char shade_off_bits[] = {
|
|
0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
void drawColorBitmaps(QPainter *p, const QPalette &pal, int x, int y, int w, int h,
|
|
const uchar *lightColor, const uchar *midColor, const uchar *blackColor)
|
|
{
|
|
const uchar *data[]={lightColor, midColor, blackColor};
|
|
|
|
QColor colors[]={pal.color(QPalette::Light), pal.color(QPalette::Mid), Qt::black};
|
|
|
|
int i;
|
|
QSize s(w,h);
|
|
for(i=0; i < 3; ++i){
|
|
QBitmap b = QBitmap::fromData(s, data[i], QImage::Format_MonoLSB );
|
|
b.setMask(b);
|
|
p->setPen(colors[i]);
|
|
p->drawPixmap(x, y, b);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// Titlebar button positions
|
|
bool onAllDesktopsButtonOnLeft = true;
|
|
bool coloredFrame = true;
|
|
bool extraSlim = false;
|
|
|
|
QPixmap* titleBlocks = NULL;
|
|
QPixmap* ititleBlocks = NULL;
|
|
QPixmap* pinDownPix = NULL;
|
|
QPixmap* pinUpPix = NULL;
|
|
QPixmap* ipinDownPix = NULL;
|
|
QPixmap* ipinUpPix = NULL;
|
|
static int normalTitleHeight;
|
|
static int toolTitleHeight;
|
|
static int borderWidth;
|
|
|
|
bool quartz_initialized = false;
|
|
QuartzHandler* clientHandler;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
QuartzHandler::QuartzHandler()
|
|
{
|
|
quartz_initialized = false;
|
|
readConfig();
|
|
createPixmaps();
|
|
quartz_initialized = true;
|
|
}
|
|
|
|
|
|
QuartzHandler::~QuartzHandler()
|
|
{
|
|
quartz_initialized = false;
|
|
freePixmaps();
|
|
}
|
|
|
|
|
|
KDecoration* QuartzHandler::createDecoration( KDecorationBridge* bridge )
|
|
{
|
|
return ( new QuartzClient( bridge, this ))->decoration();
|
|
}
|
|
|
|
|
|
bool QuartzHandler::reset(unsigned long changed)
|
|
{
|
|
quartz_initialized = false;
|
|
freePixmaps();
|
|
readConfig();
|
|
createPixmaps();
|
|
quartz_initialized = true;
|
|
|
|
// Do we need to "hit the wooden hammer" ?
|
|
bool needHardReset = true;
|
|
if ((changed & ~(SettingColors | SettingButtons)) == 0)
|
|
{
|
|
needHardReset = false;
|
|
}
|
|
|
|
if (needHardReset) {
|
|
return true;
|
|
} else {
|
|
resetDecorations(changed);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool QuartzHandler::supports( Ability ability ) const
|
|
{
|
|
switch( ability )
|
|
{
|
|
case AbilityAnnounceButtons:
|
|
case AbilityButtonMenu:
|
|
case AbilityButtonOnAllDesktops:
|
|
case AbilityButtonHelp:
|
|
case AbilityButtonMinimize:
|
|
case AbilityButtonMaximize:
|
|
case AbilityButtonClose:
|
|
case AbilityButtonAboveOthers:
|
|
case AbilityButtonBelowOthers:
|
|
case AbilityButtonShade:
|
|
case AbilityButtonSpacer:
|
|
return true;
|
|
default:
|
|
return false;
|
|
};
|
|
}
|
|
|
|
|
|
void QuartzHandler::readConfig()
|
|
{
|
|
KConfig configFile("kwinquartzrc");
|
|
KConfigGroup conf( &configFile, "General");
|
|
coloredFrame = conf.readEntry( "UseTitleBarBorderColors", true);
|
|
extraSlim = conf.readEntry( "UseQuartzExtraSlim", false);
|
|
|
|
// A small hack to make the on all desktops button look nicer
|
|
onAllDesktopsButtonOnLeft = KDecoration::options()->titleButtonsLeft().contains( 'S' );
|
|
if ( QApplication::isRightToLeft() )
|
|
onAllDesktopsButtonOnLeft = !onAllDesktopsButtonOnLeft;
|
|
switch(options()->preferredBorderSize(this)) {
|
|
case BorderLarge:
|
|
borderWidth = 8;
|
|
break;
|
|
case BorderVeryLarge:
|
|
borderWidth = 12;
|
|
break;
|
|
case BorderHuge:
|
|
borderWidth = 18;
|
|
break;
|
|
case BorderVeryHuge:
|
|
borderWidth = 27;
|
|
break;
|
|
case BorderOversized:
|
|
borderWidth = 40;
|
|
break;
|
|
case BorderTiny:
|
|
case BorderNormal:
|
|
default:
|
|
borderWidth = extraSlim?2:4;
|
|
}
|
|
|
|
normalTitleHeight = QFontMetrics(options()->font(true)).height() - 2;
|
|
int nTH_limit=extraSlim?14:18;
|
|
normalTitleHeight = QFontMetrics(options()->font(true)).height()-(extraSlim?1:0);
|
|
if (normalTitleHeight < nTH_limit) normalTitleHeight = nTH_limit;
|
|
if (normalTitleHeight < borderWidth) normalTitleHeight = borderWidth;
|
|
|
|
toolTitleHeight = QFontMetrics(options()->font(true, true)).height() - 2;
|
|
if (toolTitleHeight < 12) toolTitleHeight = 12;
|
|
if (toolTitleHeight < borderWidth) toolTitleHeight = borderWidth;
|
|
}
|
|
|
|
|
|
// This does the colour transition magic. (You say "Oh, is that it?")
|
|
// This may be made configurable at a later stage
|
|
void QuartzHandler::drawBlocks( QPixmap *pi, QPixmap &p, const QColor &c1, const QColor &c2 )
|
|
{
|
|
QPainter px;
|
|
|
|
px.begin( pi );
|
|
|
|
// Draw a background gradient first
|
|
QPainter gp(&p);
|
|
QLinearGradient grad(0, 0, p.width(), 0);
|
|
grad.setColorAt(0.0, c1);
|
|
grad.setColorAt(1.0, c2);
|
|
gp.setPen(Qt::NoPen);
|
|
gp.setBrush(grad);
|
|
gp.drawRect(p.rect());
|
|
|
|
int factor = (pi->height()-2)/4;
|
|
int square = factor - (factor+2)/4;
|
|
|
|
int x = pi->width() - 5*factor - square;
|
|
int y = (pi->height() - 4*factor)/2;
|
|
|
|
px.fillRect( x, y, square, square, c1.light(120) );
|
|
px.fillRect( x, y+factor, square, square, c1 );
|
|
px.fillRect( x, y+2*factor, square, square, c1.light(110) );
|
|
px.fillRect( x, y+3*factor, square, square, c1 );
|
|
|
|
px.fillRect( x+factor, y, square, square, c1.light(110) );
|
|
px.fillRect( x+factor, y+factor, square, square, c2.light(110) );
|
|
px.fillRect( x+factor, y+2*factor, square, square, c1.light(120) );
|
|
px.fillRect( x+factor, y+3*factor, square, square, c2.light(130) );
|
|
|
|
px.fillRect( x+2*factor, y+factor, square, square, c1.light(110) );
|
|
px.fillRect( x+2*factor, y+2*factor, square, square, c2.light(120) );
|
|
px.fillRect( x+2*factor, y+3*factor, square, square, c2.light(150) );
|
|
|
|
px.fillRect( x+3*factor, y, square, square, c1.dark(110) );
|
|
px.fillRect( x+3*factor, y+2*factor, square, square, c2.light(120) );
|
|
px.fillRect( x+3*factor, y+3*factor, square, square, c1.dark(120) );
|
|
|
|
px.fillRect( x+4*factor, y+factor, square, square, c1.light(110) );
|
|
px.fillRect( x+4*factor, y+3*factor, square, square, c1.dark(110) );
|
|
|
|
px.fillRect( x+5*factor, y+2*factor, square, square, c2.light(120));
|
|
px.fillRect( x+5*factor, y+3*factor, square, square, c2.light(110) );
|
|
}
|
|
|
|
|
|
// This paints the button pixmaps upon loading the style.
|
|
void QuartzHandler::createPixmaps()
|
|
{
|
|
// Obtain titlebar blend colours, and create the block stuff on pixmaps.
|
|
QPalette g2 = options()->palette(ColorTitleBlend, true);
|
|
g2.setCurrentColorGroup( QPalette::Active );
|
|
QColor c2 = g2.color( QPalette::Background );
|
|
g2 = options()->palette(ColorTitleBar, true );
|
|
g2.setCurrentColorGroup( QPalette::Active );
|
|
QColor c = g2.color(QPalette::Background).light(130);
|
|
|
|
titleBlocks = new QPixmap( normalTitleHeight*25/18, normalTitleHeight );
|
|
drawBlocks( titleBlocks, *titleBlocks, c, c2 );
|
|
|
|
g2 = options()->palette(ColorTitleBlend, false);
|
|
g2.setCurrentColorGroup( QPalette::Active );
|
|
c2 = g2.color( QPalette::Background );
|
|
g2 = options()->palette(ColorTitleBar, false );
|
|
g2.setCurrentColorGroup( QPalette::Active );
|
|
c = g2.color(QPalette::Background).light(130);
|
|
|
|
ititleBlocks = new QPixmap( normalTitleHeight*25/18, normalTitleHeight );
|
|
drawBlocks( ititleBlocks, *ititleBlocks, c, c2 );
|
|
|
|
// Set the on all desktops pin pixmaps;
|
|
QPalette g;
|
|
QPainter p;
|
|
|
|
g = options()->palette( onAllDesktopsButtonOnLeft ? ColorTitleBar : ColorTitleBlend, true );
|
|
g.setCurrentColorGroup( QPalette::Active );
|
|
c = onAllDesktopsButtonOnLeft ? g.color(QPalette::Background).light(130) : g.color(QPalette::Background);
|
|
g2 = options()->palette( ColorButtonBg, true );
|
|
g2.setCurrentColorGroup( QPalette::Active );
|
|
|
|
QImage pinImg = QImage(16, 16, QImage::Format_ARGB32_Premultiplied);
|
|
p.begin(&pinImg);
|
|
p.fillRect( 0, 0, 16, 16, c);
|
|
drawColorBitmaps( &p, g2, 0, 1, 16, 16, pinup_white_bits, pinup_gray_bits, pinup_dgray_bits );
|
|
p.end();
|
|
pinUpPix = new QPixmap(QPixmap::fromImage(pinImg));
|
|
|
|
p.begin(&pinImg);
|
|
p.fillRect( 0, 0, 16, 16, c);
|
|
drawColorBitmaps( &p, g2, 0, 1, 16, 16, pindown_white_bits, pindown_gray_bits, pindown_dgray_bits );
|
|
p.end();
|
|
pinDownPix = new QPixmap(QPixmap::fromImage(pinImg));
|
|
|
|
// Inactive pins
|
|
g = options()->palette( onAllDesktopsButtonOnLeft ? ColorTitleBar : ColorTitleBlend, false );
|
|
g.setCurrentColorGroup( QPalette::Active );
|
|
c = onAllDesktopsButtonOnLeft ? g.color(QPalette::Background).light(130) : g.color( QPalette::Background );
|
|
g2 = options()->palette( ColorButtonBg, false );
|
|
g2.setCurrentColorGroup( QPalette::Active );
|
|
|
|
p.begin(&pinImg);
|
|
p.fillRect( 0, 0, 16, 16, c);
|
|
drawColorBitmaps( &p, g2, 0, 1, 16, 16, pinup_white_bits, pinup_gray_bits, pinup_dgray_bits );
|
|
p.end();
|
|
ipinUpPix = new QPixmap(QPixmap::fromImage(pinImg));
|
|
|
|
p.begin(&pinImg);
|
|
p.fillRect( 0, 0, 16, 16, c);
|
|
drawColorBitmaps( &p, g2, 0, 1, 16, 16, pindown_white_bits, pindown_gray_bits, pindown_dgray_bits );
|
|
p.end();
|
|
ipinDownPix = new QPixmap(QPixmap::fromImage(pinImg));
|
|
}
|
|
|
|
|
|
void QuartzHandler::freePixmaps()
|
|
{
|
|
delete titleBlocks;
|
|
delete ititleBlocks;
|
|
|
|
// On all desktops pin images
|
|
delete pinUpPix;
|
|
delete ipinUpPix;
|
|
delete pinDownPix;
|
|
delete ipinDownPix;
|
|
}
|
|
|
|
|
|
QList< QuartzHandler::BorderSize > QuartzHandler::borderSizes() const
|
|
{ // the list must be sorted
|
|
return QList< BorderSize >() << BorderNormal << BorderLarge <<
|
|
BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized;
|
|
}
|
|
|
|
|
|
QuartzButton::QuartzButton(ButtonType type, QuartzClient *parent, const char *name)
|
|
: KCommonDecorationButton(type, parent)
|
|
{
|
|
setObjectName( name );
|
|
// Eliminate any possible background flicker
|
|
setAttribute(Qt::WA_NoSystemBackground, false);
|
|
|
|
deco = 0;
|
|
}
|
|
|
|
|
|
QuartzButton::~QuartzButton()
|
|
{
|
|
delete deco;
|
|
}
|
|
|
|
void QuartzButton::reset(unsigned long changed)
|
|
{
|
|
if (changed&DecorationReset || changed&ManualReset || changed&SizeChange || changed&StateChange) {
|
|
switch (type() ) {
|
|
case CloseButton:
|
|
setBitmap(close_bits);
|
|
break;
|
|
case HelpButton:
|
|
setBitmap(question_bits);
|
|
break;
|
|
case MinButton:
|
|
setBitmap(iconify_bits);
|
|
break;
|
|
case MaxButton:
|
|
setBitmap( isChecked() ? minmax_bits : maximize_bits );
|
|
break;
|
|
case OnAllDesktopsButton:
|
|
setBitmap(0);
|
|
break;
|
|
case ShadeButton:
|
|
setBitmap( isChecked() ? shade_on_bits : shade_off_bits );
|
|
break;
|
|
case AboveButton:
|
|
setBitmap( isChecked() ? above_on_bits : above_off_bits );
|
|
break;
|
|
case BelowButton:
|
|
setBitmap( isChecked() ? below_on_bits : below_off_bits );
|
|
break;
|
|
default:
|
|
setBitmap(0);
|
|
break;
|
|
}
|
|
|
|
this->update();
|
|
}
|
|
}
|
|
|
|
void QuartzButton::setBitmap(const unsigned char *bitmap)
|
|
{
|
|
delete deco;
|
|
deco = 0;
|
|
|
|
if (bitmap) {
|
|
deco = new QBitmap(10, 10, bitmap, true);
|
|
deco->setMask( *deco );
|
|
repaint( );
|
|
}
|
|
}
|
|
|
|
void QuartzButton::paintEvent(QPaintEvent *)
|
|
{
|
|
QPainter p(this);
|
|
drawButton(&p);
|
|
}
|
|
|
|
void QuartzButton::drawButton(QPainter *p)
|
|
{
|
|
// Never paint if the pixmaps have not been created
|
|
if (!quartz_initialized)
|
|
return;
|
|
|
|
QColor c;
|
|
|
|
if (isLeft() )
|
|
c = KDecoration::options()->color(KDecoration::ColorTitleBar, decoration()->isActive()).light(130);
|
|
else
|
|
c = KDecoration::options()->color(KDecoration::ColorTitleBlend, decoration()->isActive());
|
|
|
|
// Fill the button background with an appropriate color
|
|
p->fillRect(0, 0, width(), height(), c );
|
|
|
|
// If we have a decoration bitmap, then draw that
|
|
// otherwise we paint a menu button (with mini icon), or a onAllDesktops button.
|
|
if( deco )
|
|
{
|
|
int xOff = (width()-10)/2;
|
|
int yOff = (height()-10)/2;
|
|
p->setPen( Qt::black );
|
|
p->drawPixmap(isDown() ? xOff+2: xOff+1, isDown() ? yOff+2 : yOff+1, *deco);
|
|
p->setPen( KDecoration::options()->color(KDecoration::ColorButtonBg, decoration()->isActive()).light(150) );
|
|
p->drawPixmap(isDown() ? xOff+1: xOff, isDown() ? yOff+1 : yOff, *deco);
|
|
} else
|
|
{
|
|
QPixmap btnpix;
|
|
int Offset = 0;
|
|
|
|
if (type() == OnAllDesktopsButton)
|
|
{
|
|
if (isDown())
|
|
Offset = 1;
|
|
|
|
// Select the right onAllDesktops button to paint
|
|
if (decoration()->isActive())
|
|
btnpix = isChecked() ? *pinDownPix : *pinUpPix;
|
|
else
|
|
btnpix = isChecked() ? *ipinDownPix : *ipinUpPix;
|
|
|
|
} else
|
|
btnpix = decoration()->icon().pixmap( QIcon::Small, QIcon::Normal);
|
|
|
|
// Shrink the miniIcon for tiny titlebars.
|
|
if ( height() < 16)
|
|
{
|
|
// Smooth scale the image
|
|
QPixmap tmpPix = btnpix.scaled(height(), height(), Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
|
|
p->drawPixmap( 0, 0, tmpPix );
|
|
} else {
|
|
Offset += (height() - 16)/2;
|
|
p->drawPixmap( Offset, Offset, btnpix );
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
QuartzClient::QuartzClient(KDecorationBridge* bridge, KDecorationFactory* factory)
|
|
: KCommonDecoration (bridge, factory)
|
|
{
|
|
}
|
|
|
|
QString QuartzClient::visibleName() const
|
|
{
|
|
return i18n("Quartz");
|
|
}
|
|
|
|
QString QuartzClient::defaultButtonsLeft() const
|
|
{
|
|
return "M";
|
|
}
|
|
|
|
QString QuartzClient::defaultButtonsRight() const
|
|
{
|
|
return "HIAX";
|
|
}
|
|
|
|
bool QuartzClient::decorationBehaviour(DecorationBehaviour behaviour) const
|
|
{
|
|
switch (behaviour) {
|
|
case DB_MenuClose:
|
|
return false;
|
|
|
|
case DB_WindowMask:
|
|
return false;
|
|
|
|
case DB_ButtonHide:
|
|
return true;
|
|
|
|
default:
|
|
return KCommonDecoration::decorationBehaviour(behaviour);
|
|
}
|
|
}
|
|
|
|
int QuartzClient::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *btn) const
|
|
{
|
|
bool maximized = maximizeMode()==MaximizeFull && !options()->moveResizeMaximizedWindows();
|
|
|
|
switch (lm) {
|
|
case LM_BorderLeft:
|
|
case LM_BorderRight:
|
|
case LM_BorderBottom:
|
|
case LM_TitleEdgeLeft:
|
|
case LM_TitleEdgeRight:
|
|
{
|
|
if (respectWindowState && maximized) {
|
|
return 0;
|
|
} else {
|
|
return borderSize;
|
|
}
|
|
}
|
|
|
|
case LM_TitleEdgeTop:
|
|
return borderSize-1;
|
|
|
|
case LM_TitleEdgeBottom:
|
|
return 1;
|
|
|
|
case LM_TitleBorderLeft:
|
|
case LM_TitleBorderRight:
|
|
return 5;
|
|
|
|
case LM_TitleHeight:
|
|
return titleHeight;
|
|
|
|
case LM_ButtonWidth:
|
|
case LM_ButtonHeight:
|
|
return titleHeight-2;
|
|
|
|
case LM_ButtonSpacing:
|
|
return 1;
|
|
|
|
case LM_ExplicitButtonSpacer:
|
|
return 3;
|
|
|
|
default:
|
|
return KCommonDecoration::layoutMetric(lm, respectWindowState, btn);
|
|
}
|
|
}
|
|
|
|
KCommonDecorationButton *QuartzClient::createButton(ButtonType type)
|
|
{
|
|
switch (type) {
|
|
case MenuButton:
|
|
return new QuartzButton(MenuButton, this, "menu");
|
|
|
|
case OnAllDesktopsButton:
|
|
return new QuartzButton(OnAllDesktopsButton, this, "on_all_desktops");
|
|
|
|
case HelpButton:
|
|
return new QuartzButton(HelpButton, this, "help");
|
|
|
|
case MinButton:
|
|
return new QuartzButton(MinButton, this, "minimize");
|
|
|
|
case MaxButton:
|
|
return new QuartzButton(MaxButton, this, "maximize");
|
|
|
|
case CloseButton:
|
|
return new QuartzButton(CloseButton, this, "close");
|
|
|
|
case AboveButton:
|
|
return new QuartzButton(AboveButton, this, "above");
|
|
|
|
case BelowButton:
|
|
return new QuartzButton(BelowButton, this, "below");
|
|
|
|
case ShadeButton:
|
|
return new QuartzButton(ShadeButton, this, "shade");
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
void QuartzClient::init()
|
|
{
|
|
// Finally, toolWindows look small
|
|
if ( isToolWindow() ) {
|
|
titleHeight = toolTitleHeight;
|
|
largeButtons = false;
|
|
}
|
|
else {
|
|
titleHeight = normalTitleHeight;
|
|
largeButtons = true;
|
|
}
|
|
|
|
borderSize = borderWidth;
|
|
|
|
KCommonDecoration::init();
|
|
}
|
|
|
|
void QuartzClient::reset( unsigned long changed )
|
|
{
|
|
if (changed & SettingColors || changed & SettingFont)
|
|
{
|
|
// repaint the whole thing
|
|
widget()->repaint();
|
|
}
|
|
|
|
KCommonDecoration::reset(changed);
|
|
}
|
|
|
|
|
|
// Quartz Paint magic goes here.
|
|
void QuartzClient::paintEvent( QPaintEvent* )
|
|
{
|
|
// Never paint if the pixmaps have not been created
|
|
if (!quartz_initialized)
|
|
return;
|
|
|
|
const bool maxFull = (maximizeMode()==MaximizeFull) && !options()->moveResizeMaximizedWindows();
|
|
|
|
QPalette g;
|
|
QPainter p(widget());
|
|
|
|
// Obtain widget bounds.
|
|
QRect r(widget()->rect());
|
|
int x = r.x();
|
|
int y = r.y();
|
|
int x2 = r.width() - 1;
|
|
int y2 = r.height() - 1;
|
|
int w = r.width();
|
|
int h = r.height();
|
|
|
|
// Draw part of the frame that is the title color
|
|
|
|
if( coloredFrame )
|
|
g = options()->palette(ColorTitleBar, isActive());
|
|
else
|
|
g = options()->palette(ColorFrame, isActive());
|
|
g.setCurrentColorGroup( QPalette::Active );
|
|
|
|
// Draw outer highlights and lowlights
|
|
p.setPen( g.color(QPalette::Light).light(120) );
|
|
p.drawLine( x, y, x2-1, y );
|
|
p.drawLine( x, y+1, x, y2-1 );
|
|
p.setPen( g.color(QPalette::Dark).light(120) );
|
|
p.drawLine( x2, y, x2, y2 );
|
|
p.drawLine( x, y2, x2, y2 );
|
|
|
|
// Fill out the border edges
|
|
QColor frameColor;
|
|
if ( coloredFrame)
|
|
frameColor = g.color(QPalette::Background).light(130);
|
|
else
|
|
frameColor = g.color( QPalette::Background );
|
|
if (borderSize > 2) {
|
|
p.fillRect(x+1, y+1, w-2, borderSize-2, frameColor); // top
|
|
if (!maxFull) {
|
|
p.fillRect(x+1, y+h-(borderSize-1), w-2, borderSize-2, frameColor); // bottom
|
|
p.fillRect(x+1, y+borderSize-1, borderSize-1, h-2*(borderSize-1), frameColor); // left
|
|
p.fillRect(x+w-(borderSize), y+borderSize-1, borderSize-1, h-2*(borderSize-1), frameColor); // right
|
|
}
|
|
}
|
|
|
|
// Draw a frame around the wrapped widget.
|
|
p.setPen( g.color(QPalette::Background) );
|
|
if (maxFull) {
|
|
p.drawLine(x+1, y+titleHeight+(borderSize-1), w-2, y+titleHeight+(borderSize-1));
|
|
} else {
|
|
p.drawRect( x+(borderSize-1), y+titleHeight+(borderSize-1), w-2*(borderSize-1), h-titleHeight-2*(borderSize-1) );
|
|
}
|
|
|
|
// Drawing this extra line removes non-drawn areas when shaded
|
|
p.drawLine( x+borderSize, y2-borderSize, x2-borderSize, y2-borderSize);
|
|
|
|
// Highlight top corner
|
|
p.setPen( g.color(QPalette::Light).light(160) );
|
|
p.drawPoint( x, y );
|
|
p.setPen( g.color(QPalette::Light).light(140) );
|
|
p.drawPoint( x+1, y );
|
|
p.drawPoint( x, y+1 );
|
|
|
|
// Draw the title bar.
|
|
// ===================
|
|
int r_x, r_y, r_x2, r_y2;
|
|
widget()->rect().getCoords(&r_x, &r_y, &r_x2, &r_y2);
|
|
const int titleEdgeLeft = layoutMetric(LM_TitleEdgeLeft);
|
|
const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop);
|
|
const int titleEdgeRight = layoutMetric(LM_TitleEdgeRight);
|
|
const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom);
|
|
const int ttlHeight = layoutMetric(LM_TitleHeight);
|
|
const int titleEdgeBottomBottom = r_y+titleEdgeTop+ttlHeight+titleEdgeBottom-1;
|
|
r = QRect(r_x+titleEdgeLeft+buttonsLeftWidth(), r_y+titleEdgeTop,
|
|
r_x2-titleEdgeRight-buttonsRightWidth()-(r_x+titleEdgeLeft+buttonsLeftWidth()),
|
|
titleEdgeBottomBottom-(r_y+titleEdgeTop) );
|
|
|
|
// Obtain titlebar blend colours
|
|
QColor c1 = options()->color(ColorTitleBar, isActive() ).light(130);
|
|
QColor c2 = options()->color(ColorTitleBlend, isActive() );
|
|
|
|
// Create a disposable pixmap buffer for the titlebar
|
|
QPixmap* titleBuffer = new QPixmap( maxFull?w-2:(w-2*(borderSize-1)), titleHeight );
|
|
|
|
QPainter p2( titleBuffer );
|
|
|
|
// subtract titleBlocks pixmap width and some
|
|
int rightoffset = r.x()+r.width()-titleBlocks->width()-borderSize;
|
|
|
|
p2.fillRect( 0, 0, w, r.height(), c1 );
|
|
p2.fillRect( rightoffset, 0, maxFull?w-rightoffset:w-rightoffset-2*(borderSize-1), r.height(), c2 );
|
|
|
|
// 8 bit displays will be a bit dithered, but they still look ok.
|
|
if ( isActive() )
|
|
p2.drawPixmap( rightoffset, 0, *titleBlocks );
|
|
else
|
|
p2.drawPixmap( rightoffset, 0, *ititleBlocks );
|
|
|
|
// Draw the title text on the pixmap, and with a smaller font
|
|
// for toolwindows than the default.
|
|
QFont fnt;
|
|
if ( largeButtons ) {
|
|
fnt = options()->font(true, false); // font not small
|
|
} else {
|
|
fnt = options()->font(true, true); // font small
|
|
fnt.setWeight( QFont::Normal ); // and disable bold
|
|
}
|
|
p2.setFont( fnt );
|
|
|
|
p2.setPen( options()->color(ColorFont, isActive() ));
|
|
p2.drawText(r.x()+4-borderSize, 0, r.width()-3, r.height(),
|
|
Qt::AlignLeft | Qt::AlignVCenter, caption() );
|
|
p2.end();
|
|
|
|
p.drawPixmap( maxFull?1:borderSize-1, borderSize-1, *titleBuffer );
|
|
|
|
delete titleBuffer;
|
|
}
|
|
|
|
}
|
|
|
|
// Extended KWin plugin interface
|
|
/////////////////////////////////
|
|
extern "C"
|
|
{
|
|
KDE_EXPORT KDecorationFactory *create_factory()
|
|
{
|
|
Quartz::clientHandler = new Quartz::QuartzHandler();
|
|
return Quartz::clientHandler;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#include "quartz.moc"
|
|
// vim: ts=4
|
|
// kate: space-indent off; tab-width 4;
|