kwin/clients/default/kdedefault.cpp
Diego Iastrubni 27998b71ac dded a new checkbox to kcontrol-> wm -> decorations ->general. By defaut this checkbox is on.
if it's on, kwin clients will reverse thire display when the desktop is reversed (arabic, hebrew etc).

Clinets updated to use this options, and options.h has a few more lines :)
see clients for the changes.

svn path=/trunk/kdebase/kwin/; revision=173581
2002-08-24 12:02:26 +00:00

1122 lines
30 KiB
C++

/*
* $Id$
*
* KDE2 Default KWin client
*
* Copyright (C) 1999, 2001 Daniel Duley <mosfet@kde.org>
* Matthias Ettrich <ettrich@kde.org>
* Karol Szwed <gallium@kde.org>
*
* Draws mini titlebars for tool windows.
* Many features are now customizable.
*/
#include <kconfig.h>
#include <kglobal.h>
#include <kpixmapeffect.h>
#include <kimageeffect.h>
#include <kdrawutil.h>
#include <klocale.h>
#include <qlayout.h>
#include <qdrawutil.h>
#include <qbitmap.h>
#include "../../workspace.h"
#include "../../options.h"
#include "kdedefault.h"
#include <qimage.h>
using namespace KWinInternal;
namespace
{
static unsigned char iconify_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00,
0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static unsigned char close_bits[] = {
0x00, 0x00, 0x84, 0x00, 0xce, 0x01, 0xfc, 0x00, 0x78, 0x00, 0x78, 0x00,
0xfc, 0x00, 0xce, 0x01, 0x84, 0x00, 0x00, 0x00};
static unsigned char maximize_bits[] = {
0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01,
0x86, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00};
static unsigned char minmax_bits[] = {
0x7f, 0x00, 0x7f, 0x00, 0x63, 0x00, 0xfb, 0x03, 0xfb, 0x03, 0x1f, 0x03,
0x1f, 0x03, 0x18, 0x03, 0xf8, 0x03, 0xf8, 0x03};
static unsigned char question_bits[] = {
0x00, 0x00, 0x78, 0x00, 0xcc, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00,
0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00};
static 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 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 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 unsigned char pindown_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x1f, 0xf0, 0x3f, 0xf0, 0x3f,
0xf8, 0x3f, 0xf8, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf0, 0x1f, 0xf0, 0x0f,
0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static 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 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 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 unsigned char pinup_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0xc0, 0x31, 0xc0, 0x3f,
0xff, 0x3f, 0xff, 0x3f, 0xff, 0x3f, 0xc0, 0x3f, 0xc0, 0x31, 0xc0, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
// ===========================================================================
QPixmap* titlePix = NULL;
KPixmap* titleBuffer = NULL;
KPixmap* aUpperGradient = NULL;
KPixmap* iUpperGradient = NULL;
KPixmap* pinDownPix = NULL;
KPixmap* pinUpPix = NULL;
KPixmap* ipinDownPix = NULL;
KPixmap* ipinUpPix = NULL;
KPixmap* rightBtnUpPix = NULL;
KPixmap* rightBtnDownPix = NULL;
KPixmap* irightBtnUpPix = NULL;
KPixmap* irightBtnDownPix = NULL;
KPixmap* leftBtnUpPix = NULL;
KPixmap* leftBtnDownPix = NULL;
KPixmap* ileftBtnUpPix = NULL;
KPixmap* ileftBtnDownPix = NULL;
KDEDefaultHandler* clientHandler;
bool KDEDefault_initialized = false;
bool useGradients;
bool showGrabBar;
bool showTitleBarStipple;
bool largeToolButtons;
int toolTitleHeight;
int normalTitleHeight;
}
// ===========================================================================
KDEDefaultHandler::KDEDefaultHandler()
{
readConfig();
createPixmaps();
KDEDefault_initialized = true;
}
KDEDefaultHandler::~KDEDefaultHandler()
{
KDEDefault_initialized = false;
freePixmaps();
}
void KDEDefaultHandler::reset()
{
KDEDefault_initialized = false;
freePixmaps();
readConfig();
createPixmaps();
KDEDefault_initialized = true;
Workspace::self()->slotResetAllClientsDelayed();
}
void KDEDefaultHandler::readConfig()
{
KConfig* conf = KGlobal::config();
conf->setGroup("KDEDefault");
showGrabBar = conf->readBoolEntry("ShowGrabBar", true);
showTitleBarStipple = conf->readBoolEntry("ShowTitleBarStipple", true);
useGradients = conf->readBoolEntry("UseGradients", true);
int size = conf->readNumEntry("TitleBarSize", 0);
if (size < 0) size = 0;
if (size > 2) size = 2;
normalTitleHeight = 16 + (4*size);
toolTitleHeight = normalTitleHeight - 4;
largeToolButtons = (toolTitleHeight >= 16) ? true : false;
}
// This paints the button pixmaps upon loading the style.
void KDEDefaultHandler::createPixmaps()
{
bool highcolor = useGradients && (QPixmap::defaultDepth() > 8);
// Make the titlebar stipple optional
if (showTitleBarStipple)
{
QPainter p;
QPainter maskPainter;
int i, x, y;
titlePix = new QPixmap(132, normalTitleHeight+2);
QBitmap mask(132, normalTitleHeight+2);
mask.fill(Qt::color0);
p.begin(titlePix);
maskPainter.begin(&mask);
maskPainter.setPen(Qt::color1);
for(i=0, y=2; i < 6; ++i, y+=4)
for(x=1; x <= 132; x+=3)
{
p.setPen(options->color(Options::TitleBar, true).light(150));
p.drawPoint(x, y);
maskPainter.drawPoint(x, y);
p.setPen(options->color(Options::TitleBar, true).dark(150));
p.drawPoint(x+1, y+1);
maskPainter.drawPoint(x+1, y+1);
}
maskPainter.end();
p.end();
titlePix->setMask(mask);
} else
titlePix = NULL;
QColor activeTitleColor1(options->color(Options::TitleBar, true));
QColor activeTitleColor2(options->color(Options::TitleBlend, true));
QColor inactiveTitleColor1(options->color(Options::TitleBar, false));
QColor inactiveTitleColor2(options->color(Options::TitleBlend, false));
// Create titlebar gradient images if required
aUpperGradient = NULL;
iUpperGradient = NULL;
if(highcolor)
{
// Create the titlebar gradients
if (activeTitleColor1 != activeTitleColor2)
{
aUpperGradient = new KPixmap;
aUpperGradient->resize(128, normalTitleHeight+2);
KPixmapEffect::gradient(*aUpperGradient,
activeTitleColor1,
activeTitleColor2,
KPixmapEffect::VerticalGradient);
}
if (inactiveTitleColor1 != inactiveTitleColor2)
{
iUpperGradient = new KPixmap;
iUpperGradient->resize(128, normalTitleHeight+2);
KPixmapEffect::gradient(*iUpperGradient,
inactiveTitleColor1,
inactiveTitleColor2,
KPixmapEffect::VerticalGradient);
}
}
// Set the sticky pin pixmaps;
QColorGroup g;
QPainter p;
// Active pins
g = options->colorGroup( Options::ButtonBg, true );
pinUpPix = new KPixmap();
pinUpPix->resize(16, 16);
p.begin( pinUpPix );
kColorBitmaps( &p, g, 0, 0, 16, 16, true, pinup_white_bits,
pinup_gray_bits, NULL, NULL, pinup_dgray_bits, NULL );
p.end();
pinUpPix->setMask( QBitmap(16, 16, pinup_mask_bits, true) );
pinDownPix = new KPixmap();
pinDownPix->resize(16, 16);
p.begin( pinDownPix );
kColorBitmaps( &p, g, 0, 0, 16, 16, true, pindown_white_bits,
pindown_gray_bits, NULL, NULL, pindown_dgray_bits, NULL );
p.end();
pinDownPix->setMask( QBitmap(16, 16, pindown_mask_bits, true) );
// Inactive pins
g = options->colorGroup( Options::ButtonBg, false );
ipinUpPix = new KPixmap();
ipinUpPix->resize(16, 16);
p.begin( ipinUpPix );
kColorBitmaps( &p, g, 0, 0, 16, 16, true, pinup_white_bits,
pinup_gray_bits, NULL, NULL, pinup_dgray_bits, NULL );
p.end();
ipinUpPix->setMask( QBitmap(16, 16, pinup_mask_bits, true) );
ipinDownPix = new KPixmap();
ipinDownPix->resize(16, 16);
p.begin( ipinDownPix );
kColorBitmaps( &p, g, 0, 0, 16, 16, true, pindown_white_bits,
pindown_gray_bits, NULL, NULL, pindown_dgray_bits, NULL );
p.end();
ipinDownPix->setMask( QBitmap(16, 16, pindown_mask_bits, true) );
// Create a title buffer for flicker-free painting
titleBuffer = new KPixmap();
// Cache all possible button states
leftBtnUpPix = new KPixmap();
leftBtnUpPix->resize(16, 16);
leftBtnDownPix = new KPixmap();
leftBtnDownPix->resize(16, 16);
ileftBtnUpPix = new KPixmap();
ileftBtnUpPix->resize(16, 16);
ileftBtnDownPix = new KPixmap();
ileftBtnDownPix->resize(16, 16);
rightBtnUpPix = new KPixmap();
rightBtnUpPix->resize(16, 16);
rightBtnDownPix = new KPixmap();
rightBtnDownPix->resize(16, 16);
irightBtnUpPix = new KPixmap();
irightBtnUpPix->resize(16, 16);
irightBtnDownPix = new KPixmap();
irightBtnDownPix->resize(16, 16);
// Draw the button state pixmaps
g = options->colorGroup( Options::TitleBar, true );
drawButtonBackground( leftBtnUpPix, g, false );
drawButtonBackground( leftBtnDownPix, g, true );
g = options->colorGroup( Options::ButtonBg, true );
drawButtonBackground( rightBtnUpPix, g, false );
drawButtonBackground( rightBtnDownPix, g, true );
g = options->colorGroup( Options::TitleBar, false );
drawButtonBackground( ileftBtnUpPix, g, false );
drawButtonBackground( ileftBtnDownPix, g, true );
g = options->colorGroup( Options::ButtonBg, false );
drawButtonBackground( irightBtnUpPix, g, false );
drawButtonBackground( irightBtnDownPix, g, true );
}
void KDEDefaultHandler::freePixmaps()
{
// Free button pixmaps
if (rightBtnUpPix)
delete rightBtnUpPix;
if(rightBtnDownPix)
delete rightBtnDownPix;
if (irightBtnUpPix)
delete irightBtnUpPix;
if (irightBtnDownPix)
delete irightBtnDownPix;
if (leftBtnUpPix)
delete leftBtnUpPix;
if(leftBtnDownPix)
delete leftBtnDownPix;
if (ileftBtnUpPix)
delete ileftBtnUpPix;
if (ileftBtnDownPix)
delete ileftBtnDownPix;
// Title images
if (titleBuffer)
delete titleBuffer;
if (titlePix)
delete titlePix;
if (aUpperGradient)
delete aUpperGradient;
if (iUpperGradient)
delete iUpperGradient;
// Sticky pin images
if (pinUpPix)
delete pinUpPix;
if (ipinUpPix)
delete ipinUpPix;
if (pinDownPix)
delete pinDownPix;
if (ipinDownPix)
delete ipinDownPix;
}
void KDEDefaultHandler::drawButtonBackground(KPixmap *pix,
const QColorGroup &g, bool sunken)
{
QPainter p;
int w = pix->width();
int h = pix->height();
int x2 = w-1;
int y2 = h-1;
bool highcolor = useGradients && (QPixmap::defaultDepth() > 8);
QColor c = g.background();
// Fill the background with a gradient if possible
if (highcolor)
KPixmapEffect::gradient(*pix, c.light(130), c.dark(130),
KPixmapEffect::VerticalGradient);
else
pix->fill(c);
p.begin(pix);
// outer frame
p.setPen(g.mid());
p.drawLine(0, 0, x2, 0);
p.drawLine(0, 0, 0, y2);
p.setPen(g.light());
p.drawLine(x2, 0, x2, y2);
p.drawLine(0, x2, y2, x2);
p.setPen(g.dark());
p.drawRect(1, 1, w-2, h-2);
p.setPen(sunken ? g.mid() : g.light());
p.drawLine(2, 2, x2-2, 2);
p.drawLine(2, 2, 2, y2-2);
p.setPen(sunken ? g.light() : g.mid());
p.drawLine(x2-2, 2, x2-2, y2-2);
p.drawLine(2, x2-2, y2-2, x2-2);
}
// ===========================================================================
KDEDefaultButton::KDEDefaultButton(Client *parent, const char *name,
bool largeButton, bool isLeftButton, bool isStickyButton,
const unsigned char *bitmap, const QString& tip )
: KWinButton(parent, name, tip)
{
setBackgroundMode( QWidget::NoBackground );
setToggleButton( isStickyButton );
isMouseOver = false;
deco = NULL;
large = largeButton;
isLeft = isLeftButton;
isSticky = isStickyButton;
client = parent;
if (large)
setFixedSize(16, 16);
else
setFixedSize(12, 12);
if (bitmap)
setBitmap(bitmap);
}
KDEDefaultButton::~KDEDefaultButton()
{
if (deco)
delete deco;
}
QSize KDEDefaultButton::sizeHint() const
{
if ( large )
return( QSize(16,16) );
else
return( QSize(12,12) );
}
void KDEDefaultButton::setBitmap(const unsigned char *bitmap)
{
if (deco)
delete deco;
deco = new QBitmap(10, 10, bitmap, true);
deco->setMask( *deco );
repaint( false );
}
void KDEDefaultButton::drawButton(QPainter *p)
{
if (!KDEDefault_initialized)
return;
if (deco) {
// Fill the button background with an appropriate button image
KPixmap btnbg;
if (isLeft) {
if (isDown())
btnbg = client->isActive() ?
*leftBtnDownPix : *ileftBtnDownPix;
else
btnbg = client->isActive() ?
*leftBtnUpPix : *ileftBtnUpPix;
} else {
if (isDown())
btnbg = client->isActive() ?
*rightBtnDownPix : *irightBtnDownPix;
else
btnbg = client->isActive() ?
*rightBtnUpPix : *irightBtnUpPix;
}
// Scale the background image if required
// This is slow, but we assume this isn't done too often
if ( !large ) {
btnbg.detach();
btnbg.convertFromImage(btnbg.convertToImage().smoothScale(12, 12));
}
p->drawPixmap( 0, 0, btnbg );
} else if ( isLeft ) {
// Fill the button background with an appropriate color/gradient
// This is for sticky and menu buttons
KPixmap* grad = client->isActive() ? aUpperGradient : iUpperGradient;
if (!grad) {
QColor c = options->color(Options::TitleBar, client->isActive());
p->fillRect(0, 0, width(), height(), c );
} else
p->drawPixmap( 0, 0, *grad, 0,((normalTitleHeight-height())/2)+1,
16, 16 );
} else {
// Draw a plain background for menus or sticky buttons on RHS
QColor c = options->color(Options::Frame, client->isActive());
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 sticky button.
if( deco ) {
// Select the appropriate button decoration color
bool darkDeco = qGray( options->color(
isLeft? Options::TitleBar : Options::ButtonBg,
client->isActive()).rgb() ) > 127;
if (isMouseOver)
p->setPen( darkDeco ? Qt::darkGray : Qt::lightGray );
else
p->setPen( darkDeco ? Qt::black : Qt::white );
int xOff = (width()-10)/2;
int yOff = (height()-10)/2;
p->drawPixmap(isDown() ? xOff+1: xOff, isDown() ? yOff+1 : yOff, *deco);
} else {
KPixmap btnpix;
if (isSticky) {
if (client->isActive())
btnpix = isOn() ? *pinDownPix : *pinUpPix;
else
btnpix = isOn() ? *ipinDownPix : *ipinUpPix;
} else
btnpix = client->miniIcon();
// Intensify the image if required
if (isMouseOver) {
btnpix = KPixmapEffect::intensity(btnpix, 0.8);
}
// Smooth scale the pixmap for small titlebars
// This is slow, but we assume this isn't done too often
if ( !large )
btnpix.convertFromImage(btnpix.convertToImage().smoothScale(12, 12));
p->drawPixmap( 0, 0, btnpix );
}
}
// Make the protected member public
void KDEDefaultButton::turnOn( bool isOn )
{
if ( isToggleButton() )
setOn( isOn );
}
void KDEDefaultButton::enterEvent(QEvent *e)
{
isMouseOver=true;
repaint(false);
KWinButton::enterEvent(e);
}
void KDEDefaultButton::leaveEvent(QEvent *e)
{
isMouseOver=false;
repaint(false);
KWinButton::leaveEvent(e);
}
void KDEDefaultButton::mousePressEvent( QMouseEvent* e )
{
last_button = e->button();
QMouseEvent me( e->type(), e->pos(), e->globalPos(),
LeftButton, e->state() );
KWinButton::mousePressEvent( &me );
}
void KDEDefaultButton::mouseReleaseEvent( QMouseEvent* e )
{
last_button = e->button();
QMouseEvent me( e->type(), e->pos(), e->globalPos(),
LeftButton, e->state() );
KWinButton::mouseReleaseEvent( &me );
}
// ===========================================================================
KDEDefaultClient::KDEDefaultClient( Workspace *ws, WId w, QWidget *parent,
const char *name )
: Client( ws, w, parent, name, WResizeNoErase | WStaticContents |
WRepaintNoErase )
{
// No flicker thanks
setBackgroundMode( QWidget::NoBackground );
// Set button pointers to NULL so we can track things
for(int i=0; i < KDEDefaultClient::BtnCount; i++)
button[i] = NULL;
// Finally, toolWindows look small
if ( isTool() ) {
titleHeight = toolTitleHeight;
largeButtons = largeToolButtons;
}
else {
titleHeight = normalTitleHeight;
largeButtons = true;
}
// Pack the windowWrapper() window within a grid
QGridLayout* g = new QGridLayout(this, 0, 0, 0);
g->setResizeMode(QLayout::FreeResize);
g->addRowSpacing(0, 3); // Top grab bar
g->addRowSpacing(2, 1); // line under titlebar
g->addWidget(windowWrapper(), 3, 1);
// without the next line, unshade flickers
g->addItem( new QSpacerItem( 0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding ) );
g->setRowStretch(3, 10); // Wrapped window
// Determine the size of the lower grab bar
if ( showGrabBar && (!isTool()) )
g->addRowSpacing(4, 8); // bottom handles
else
g->addRowSpacing(4, 4); // bottom handles
g->addColSpacing(0, 4);
g->addColSpacing(2, 4);
// Pack the titlebar HBox with items
hb = new QHBoxLayout();
hb->setResizeMode( QLayout::FreeResize );
g->addLayout ( hb, 1, 1 );
if (QApplication::reverseLayout() && (!options->reverseBIDIWindows()))
addClientButtons( options->titleButtonsRight() );
else
addClientButtons( options->titleButtonsLeft() );
titlebar = new QSpacerItem( 10, titleHeight, QSizePolicy::Expanding, QSizePolicy::Minimum );
hb->addItem(titlebar);
hb->addSpacing(2);
if (QApplication::reverseLayout() && (!options->reverseBIDIWindows()))
addClientButtons( options->titleButtonsLeft(), false );
else
addClientButtons( options->titleButtonsRight(), false );
}
void KDEDefaultClient::addClientButtons( const QString& s, bool isLeft )
{
if (s.length() > 0){
unsigned int i = 0;
if (QApplication::reverseLayout() && (!options->reverseBIDIWindows()))
i = s.length() - 1;
//for( ; (i < s.length()) && (i) ;) { // i>=0
for( ; ( i < s.length()) ;) { // i>=0
switch( s[i].latin1() )
{
// Menu button
case 'M':
if (!button[BtnMenu])
{
button[BtnMenu] = new KDEDefaultButton(this, "menu",
largeButtons, isLeft, false, NULL, i18n("Menu"));
connect( button[BtnMenu], SIGNAL(pressed()),
this, SLOT(menuButtonPressed()) );
hb->addWidget( button[BtnMenu] );
}
break;
// Sticky button
case 'S':
if (!button[BtnSticky])
{
button[BtnSticky] = new KDEDefaultButton(this, "sticky",
largeButtons, isLeft, true, NULL, i18n("Sticky"));
button[BtnSticky]->turnOn( isSticky() );
connect( button[BtnSticky], SIGNAL(clicked()),
this, SLOT(toggleSticky()) );
hb->addWidget( button[BtnSticky] );
}
break;
// Help button
case 'H':
if( providesContextHelp() && (!button[BtnHelp]) )
{
button[BtnHelp] = new KDEDefaultButton(this, "help",
largeButtons, isLeft, true, question_bits,
i18n("Help"));
connect( button[BtnHelp], SIGNAL( clicked() ),
this, SLOT( contextHelp() ));
hb->addWidget( button[BtnHelp] );
}
break;
// Minimize button
case 'I':
if ( (!button[BtnIconify]) && isMinimizable())
{
button[BtnIconify] = new KDEDefaultButton(this, "iconify",
largeButtons, isLeft, true, iconify_bits,
i18n("Minimize"));
connect( button[BtnIconify], SIGNAL( clicked()),
this, SLOT(iconify()) );
hb->addWidget( button[BtnIconify] );
}
break;
// Maximize button
case 'A':
if ( (!button[BtnMax]) && isMaximizable())
{
button[BtnMax] = new KDEDefaultButton(this, "maximize",
largeButtons, isLeft, true, maximize_bits,
i18n("Maximize"));
connect( button[BtnMax], SIGNAL( clicked()),
this, SLOT(slotMaximize()) );
hb->addWidget( button[BtnMax] );
}
break;
// Close button
case 'X':
if (!button[BtnClose])
{
button[BtnClose] = new KDEDefaultButton(this, "close",
largeButtons, isLeft, true, close_bits,
i18n("Close"));
connect( button[BtnClose], SIGNAL( clicked()),
this, SLOT(closeWindow()) );
hb->addWidget( button[BtnClose] );
}
break;
// Spacer item (only for non-tool windows)
case '_':
if ( !isTool() )
hb->addSpacing(2);
} // switch( ...
// this should be in the for() statment some how....
if (QApplication::reverseLayout() && (!options->reverseBIDIWindows()))
i--;
else
i++;
} // for( ...
} // if (s.length()....
}
void KDEDefaultClient::iconChange()
{
if (button[BtnMenu] && button[BtnMenu]->isVisible())
button[BtnMenu]->repaint(false);
}
void KDEDefaultClient::stickyChange(bool on)
{
if (button[BtnSticky]) {
button[BtnSticky]->turnOn(on);
button[BtnSticky]->repaint(false);
button[BtnSticky]->setTipText(on ? i18n("Un-Sticky") : i18n("Sticky"));
}
}
void KDEDefaultClient::slotMaximize()
{
if ( button[BtnMax]->last_button == MidButton )
maximize( MaximizeVertical );
else if ( button[BtnMax]->last_button == RightButton )
maximize( MaximizeHorizontal );
else
maximize();
}
void KDEDefaultClient::resizeEvent( QResizeEvent* e)
{
Client::resizeEvent( e );
doShape();
calcHiddenButtons();
if (isVisibleToTLW())
{
update(rect());
int dx = 0;
int dy = 0;
if ( e->oldSize().width() != width() )
dx = 32 + QABS( e->oldSize().width() - width() );
if ( e->oldSize().height() != height() )
dy = 8 + QABS( e->oldSize().height() - height() );
if ( dy )
update( 0, height() - dy + 1, width(), dy );
if ( dx )
{
update( width() - dx + 1, 0, dx, height() );
update( QRect( QPoint(4,4), titlebar->geometry().bottomLeft() -
QPoint(1,0) ) );
update( QRect( titlebar->geometry().topRight(), QPoint(width() - 4,
titlebar->geometry().bottom()) ) );
// Titlebar needs no paint event
QApplication::postEvent( this, new QPaintEvent(titlebar->geometry(),
FALSE) );
}
}
}
void KDEDefaultClient::captionChange( const QString& )
{
repaint( titlebar->geometry(), false );
}
void KDEDefaultClient::paintEvent( QPaintEvent* )
{
if (!KDEDefault_initialized)
return;
QColorGroup g;
int offset;
KPixmap* upperGradient = isActive() ? aUpperGradient : iUpperGradient;
QPainter p(this);
// Obtain widget bounds.
QRect r(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();
// Determine where to place the extended left titlebar
int leftFrameStart = (h > 42) ? y+titleHeight+26: y+titleHeight;
// Determine where to make the titlebar color transition
r = titlebar->geometry();
int rightOffset = r.x()+r.width()+1;
// Create a disposable pixmap buffer for the titlebar
// very early before drawing begins so there is no lag
// during painting pixels.
titleBuffer->resize( rightOffset-3, titleHeight+1 );
// Draw an outer black frame
p.setPen(Qt::black);
p.drawRect(x,y,w,h);
// Draw part of the frame that is the titlebar color
g = options->colorGroup(Options::TitleBar, isActive());
p.setPen(g.light());
p.drawLine(x+1, y+1, rightOffset-1, y+1);
p.drawLine(x+1, y+1, x+1, leftFrameStart);
// Draw titlebar colour separator line
p.setPen(g.dark());
p.drawLine(rightOffset-1, y+1, rightOffset-1, titleHeight+2);
// Finish drawing the titlebar extension
p.setPen(Qt::black);
p.drawLine(x+1, leftFrameStart, x+2, leftFrameStart-1);
p.setPen(g.mid());
p.drawLine(x+2, y+titleHeight+3, x+2, leftFrameStart-2);
// Fill out the border edges
g = options->colorGroup(Options::Frame, isActive());
p.setPen(g.light());
p.drawLine(rightOffset, y+1, x2-1, y+1);
p.drawLine(x+1, leftFrameStart+1, x+1, y2-1);
p.setPen(g.dark());
p.drawLine(x2-1, y+1, x2-1, y2-1);
p.drawLine(x+1, y2-1, x2-1, y2-1);
p.setPen(options->color(Options::Frame, isActive()));
p.drawLine(x+2, leftFrameStart, x+2, y2-2 );
p.drawLine(x2-2, y+titleHeight+3, x2-2, y2-2);
// Draw the bottom handle if required
if (showGrabBar && (!isTool()) )
{
if(w > 50)
{
qDrawShadePanel(&p, x+1, y2-6, 20, 6,
g, false, 1, &g.brush(QColorGroup::Mid));
qDrawShadePanel(&p, x+21, y2-6, w-42, 6,
g, false, 1, isActive() ?
&g.brush(QColorGroup::Background) :
&g.brush(QColorGroup::Mid));
qDrawShadePanel(&p, x2-20, y2-6, 20, 6,
g, false, 1, &g.brush(QColorGroup::Mid));
} else
qDrawShadePanel(&p, x+1, y2-6, w-2, 6,
g, false, 1, isActive() ?
&g.brush(QColorGroup::Background) :
&g.brush(QColorGroup::Mid));
offset = 4;
} else
{
p.drawLine(x+2, y2-2, x2-2, y2-2);
offset = 0;
}
// Draw a frame around the wrapped widget.
p.setPen( g.dark() );
p.drawRect( x+3, y+titleHeight+3, w-6, h-titleHeight-offset-6 );
// Draw the title bar.
r = titlebar->geometry();
// Obtain titlebar blend colours
QColor c1 = options->color(Options::TitleBar, isActive() );
QColor c2 = options->color(Options::Frame, isActive() );
// Fill with frame color behind RHS buttons
p.fillRect( rightOffset, y+2, x2-rightOffset-1, titleHeight+1, c2);
QPainter p2( titleBuffer, this );
// Draw the titlebar gradient
if (upperGradient)
p2.drawTiledPixmap(0, 0, rightOffset-3, titleHeight+1, *upperGradient);
else
p2.fillRect(0, 0, rightOffset-3, titleHeight+1, c1);
// Draw the title text on the pixmap, and with a smaller font
// for toolwindows than the default.
QFont fnt = options->font(true);
if ( isTool() )
fnt.setPointSize( fnt.pointSize()-2 ); // Shrink font by 2pt
p2.setFont( fnt );
// Draw the titlebar stipple if active and available
if (isActive() && titlePix)
{
QFontMetrics fm(fnt);
int captionWidth = fm.width(caption());
if (caption().isRightToLeft())
p2.drawTiledPixmap( r.x(), 0, r.width()-captionWidth-4, titleHeight+1, *titlePix );
else
p2.drawTiledPixmap( r.x()+captionWidth+3, 0, r.width()-captionWidth-4, titleHeight+1, *titlePix );
}
p2.setPen( options->color(Options::Font, isActive()) );
p2.drawText(r.x(), 1, r.width(), r.height(),
caption().isRightToLeft()?AlignRight:AlignLeft|AlignVCenter, caption() );
bitBlt( this, 2, 2, titleBuffer );
p2.end();
// Ensure a shaded window has no unpainted areas
p.setPen(c2);
p.drawLine(x+4, y+titleHeight+4, x2-4, y+titleHeight+4);
}
void KDEDefaultClient::doShape()
{
QRegion mask(QRect(0, 0, width(), height()));
mask -= QRect(0, 0, 1, 1);
mask -= QRect(width()-1, 0, 1, 1);
mask -= QRect(0, height()-1, 1, 1);
mask -= QRect(width()-1, height()-1, 1, 1);
setMask(mask);
}
void KDEDefaultClient::showEvent(QShowEvent *ev)
{
calcHiddenButtons();
doShape();
Client::showEvent(ev);
}
void KDEDefaultClient::mouseDoubleClickEvent( QMouseEvent * e )
{
if (titlebar->geometry().contains( e->pos() ) )
workspace()->performWindowOperation( this, options->operationTitlebarDblClick() );
}
void KDEDefaultClient::maximizeChange(bool m)
{
if (button[BtnMax]) {
button[BtnMax]->setBitmap(m ? minmax_bits : maximize_bits);
button[BtnMax]->setTipText(m ? i18n("Restore") : i18n("Maximize"));
}
}
void KDEDefaultClient::activeChange(bool)
{
for(int i=KDEDefaultClient::BtnHelp; i < KDEDefaultClient::BtnCount; i++)
if(button[i])
button[i]->repaint(false);
repaint(false);
}
// The hiding button while shrinking, show button while expanding magic
void KDEDefaultClient::calcHiddenButtons()
{
// Hide buttons in this order:
// Sticky, Help, Maximize, Minimize, Close, Menu.
KDEDefaultButton* btnArray[] = { button[BtnSticky], button[BtnHelp],
button[BtnMax], button[BtnIconify], button[BtnClose],
button[BtnMenu] };
int minwidth = largeButtons ? 160 : 120; // Start hiding at this width
int btn_width = largeButtons ? 16 : 12;
int current_width = width();
int count = 0;
int i;
// Find out how many buttons we need to hide.
while (current_width < minwidth)
{
current_width += btn_width;
count++;
}
// Bound the number of buttons to hide
if (count > 6) count = 6;
// Hide the required buttons...
for(i = 0; i < count; i++)
{
if (btnArray[i] && btnArray[i]->isVisible() )
btnArray[i]->hide();
}
// Show the rest of the buttons...
for(i = count; i < 6; i++)
{
if (btnArray[i] && (!btnArray[i]->isVisible()) )
btnArray[i]->show();
}
}
Client::MousePosition KDEDefaultClient::mousePosition( const QPoint& p ) const
{
MousePosition m = Nowhere;
// Modify the mouse position if we are using a grab bar.
if (showGrabBar && (!isTool()) )
if (p.y() < (height() - 8))
m = Client::mousePosition(p);
else
{
if (p.x() >= (width() - 20))
m = BottomRight;
else if (p.x() <= 20)
m = BottomLeft;
else
m = Bottom;
}
else
m = Client::mousePosition(p);
return m;
}
// Make sure the menu button follows double click conventions set in kcontrol
void KDEDefaultClient::menuButtonPressed()
{
QPoint menupoint ( button[BtnMenu]->rect().bottomLeft().x()-1,
button[BtnMenu]->rect().bottomLeft().y()+2 );
QPoint pos = button[BtnMenu]->mapToGlobal( menupoint );
workspace()->showWindowMenu( pos.x(), pos.y(), this );
}
// Extended KWin plugin interface
extern "C"
{
Client *allocate(Workspace *ws, WId w, int)
{
return(new KDEDefaultClient(ws, w));
}
void init()
{
clientHandler = new KDEDefaultHandler();
}
void reset()
{
clientHandler->reset();
}
void deinit()
{
delete clientHandler;
}
}
#include "kdedefault.moc"
// vim: ts=4