kwin/clients/quartz/quartz.cpp
Karol Szwed a33f4313ab - Removing patch by Diego Iastrubini that attempted to fix the bidi issues in
clients by adding an unnecessary 'enable-bidi' checkbox which was never agreed
  upon on the kwin mailing list.

  The use of --reverse is sufficient without needing this checkbox.
  Please discuss largish patches like these first, especially during a feature
  freeze!

  (Everyone also seems to forget the kwin-styles in kdeartwork)

- Make clients look the same with --reverse instead of the broken state they
  were in previously. If the button ordering is not to your liking in reverse
  mode, just change the button positions. (Or send patches for those clients
  that have not got these features yet).

- Clean up popupMenu handling somewhat.

- Remove a global static object in keramik.

svn path=/trunk/kdebase/kwin/; revision=174079
2002-08-27 15:12:14 +00:00

828 lines
22 KiB
C++

/*
* $Id$
*
* Gallium-Quartz KWin client
*
* 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.
*
*/
#include <kconfig.h>
#include <kglobal.h>
#include <kpixmapeffect.h>
#include <kdrawutil.h>
#include <klocale.h>
#include <qlayout.h>
#include <qdrawutil.h>
#include <qbitmap.h>
#include "../../workspace.h"
#include "../../options.h"
#include "quartz.h"
#include <qimage.h>
using namespace KWinInternal;
static unsigned char iconify_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00,
0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static 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 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 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 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 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 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};
///////////////////////////////////////////////////////////////////////////
// Titlebar button positions
bool stickyButtonOnLeft = true;
bool coloredFrame = true;
KPixmap* titleBlocks = NULL;
KPixmap* ititleBlocks = NULL;
KPixmap* pinDownPix = NULL;
KPixmap* pinUpPix = NULL;
KPixmap* ipinDownPix = NULL;
KPixmap* ipinUpPix = NULL;
bool quartz_initialized = false;
QuartzHandler* clientHandler;
///////////////////////////////////////////////////////////////////////////
QuartzHandler::QuartzHandler()
{
quartz_initialized = false;
readConfig();
createPixmaps();
quartz_initialized = true;
connect( options, SIGNAL(resetClients()), this, SLOT(slotReset()) );
}
QuartzHandler::~QuartzHandler()
{
quartz_initialized = false;
freePixmaps();
}
void QuartzHandler::slotReset()
{
quartz_initialized = false;
freePixmaps();
readConfig();
createPixmaps();
quartz_initialized = true;
// Make kwin create new clients for each window
Workspace::self()->slotResetAllClientsDelayed();
}
void QuartzHandler::readConfig()
{
KConfig conf("kwinquartzrc");
conf.setGroup("General");
coloredFrame = conf.readBoolEntry( "UseTitleBarBorderColors", true );
// A small hack to make the sticky button look nicer
stickyButtonOnLeft = (bool)options->titleButtonsLeft().contains( 'S' );
}
// This does the colour transition magic. (You say "Oh, is that it?")
// This may be made configurable at a later stage
void QuartzHandler::drawBlocks( KPixmap *pi, KPixmap &p, const QColor &c1, const QColor &c2 )
{
QPainter px;
px.begin( pi );
// Draw a background gradient first
KPixmapEffect::gradient(p, c1, c2, KPixmapEffect::HorizontalGradient);
px.fillRect( 2, 1, 3, 3, c1.light(120) );
px.fillRect( 2, 5, 3, 3, c1 );
px.fillRect( 2, 9, 3, 3, c1.light(110) );
px.fillRect( 2, 13, 3, 3, c1 );
px.fillRect( 6, 1, 3, 3, c1.light(110) );
px.fillRect( 6, 5, 3, 3, c2.light(110) );
px.fillRect( 6, 9, 3, 3, c1.light(120) );
px.fillRect( 6, 13, 3, 3, c2.light(130) );
px.fillRect( 10, 5, 3, 3, c1.light(110) );
px.fillRect( 10, 9, 3, 3, c2.light(120) );
px.fillRect( 10, 13, 3, 3, c2.light(150) );
px.fillRect( 14, 1, 3, 3, c1.dark(110) );
px.fillRect( 14, 9, 3, 3, c2.light(120) );
px.fillRect( 14, 13, 3, 3, c1.dark(120) );
px.fillRect( 18, 5, 3, 3, c1.light(110) );
px.fillRect( 18, 13, 3, 3, c1.dark(110) );
px.fillRect( 22, 9, 3, 3, c2.light(120));
px.fillRect( 22, 13, 3, 3, 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.
QColorGroup g2 = options->colorGroup(Options::TitleBlend, true);
QColor c2 = g2.background();
g2 = options->colorGroup(Options::TitleBar, true );
QColor c = g2.background().light(130);
titleBlocks = new KPixmap();
titleBlocks->resize( 25, 18 );
drawBlocks( titleBlocks, *titleBlocks, c, c2 );
g2 = options->colorGroup(Options::TitleBlend, false);
c2 = g2.background();
g2 = options->colorGroup(Options::TitleBar, false );
c = g2.background().light(130);
ititleBlocks = new KPixmap();
ititleBlocks->resize( 25, 18 );
drawBlocks( ititleBlocks, *ititleBlocks, c, c2 );
// Set the sticky pin pixmaps;
QColorGroup g;
QPainter p;
g = options->colorGroup( stickyButtonOnLeft ? Options::TitleBar : Options::TitleBlend, true );
c = stickyButtonOnLeft ? g.background().light(130) : g.background();
g2 = options->colorGroup( Options::ButtonBg, true );
pinUpPix = new KPixmap();
pinUpPix->resize(16, 16);
p.begin( pinUpPix );
p.fillRect( 0, 0, 16, 16, c);
kColorBitmaps( &p, g2, 0, 1, 16, 16, true, pinup_white_bits,
pinup_gray_bits, NULL, NULL, pinup_dgray_bits, NULL );
p.end();
pinDownPix = new KPixmap();
pinDownPix->resize(16, 16);
p.begin( pinDownPix );
p.fillRect( 0, 0, 16, 16, c);
kColorBitmaps( &p, g2, 0, 1, 16, 16, true, pindown_white_bits,
pindown_gray_bits, NULL, NULL, pindown_dgray_bits, NULL );
p.end();
// Inactive pins
g = options->colorGroup( stickyButtonOnLeft ? Options::TitleBar : Options::TitleBlend, false );
c = stickyButtonOnLeft ? g.background().light(130) : g.background();
g2 = options->colorGroup( Options::ButtonBg, false );
ipinUpPix = new KPixmap();
ipinUpPix->resize(16, 16);
p.begin( ipinUpPix );
p.fillRect( 0, 0, 16, 16, c);
kColorBitmaps( &p, g2, 0, 1, 16, 16, true, pinup_white_bits,
pinup_gray_bits, NULL, NULL, pinup_dgray_bits, NULL );
p.end();
ipinDownPix = new KPixmap();
ipinDownPix->resize(16, 16);
p.begin( ipinDownPix );
p.fillRect( 0, 0, 16, 16, c);
kColorBitmaps( &p, g2, 0, 1, 16, 16, true, pindown_white_bits,
pindown_gray_bits, NULL, NULL, pindown_dgray_bits, NULL );
p.end();
}
void QuartzHandler::freePixmaps()
{
// Title images
if (titleBlocks)
delete titleBlocks;
if (ititleBlocks)
delete ititleBlocks;
// Sticky pin images
if (pinUpPix)
delete pinUpPix;
if (ipinUpPix)
delete ipinUpPix;
if (pinDownPix)
delete pinDownPix;
if (ipinDownPix)
delete ipinDownPix;
}
QuartzButton::QuartzButton(Client *parent, const char *name, bool largeButton,
bool isLeftButton, bool isStickyButton, const unsigned char *bitmap,
const QString& tip)
: KWinButton(parent, name, tip)
{
// Eliminate any possible background flicker
setBackgroundMode( QWidget::NoBackground );
setToggleButton( isStickyButton );
deco = NULL;
large = largeButton;
isLeft = isLeftButton;
isSticky = isStickyButton;
client = parent;
if ( large )
setFixedSize(16, 16);
else
setFixedSize(10, 10);
if(bitmap)
setBitmap(bitmap);
}
QuartzButton::~QuartzButton()
{
if (deco)
delete deco;
}
QSize QuartzButton::sizeHint() const
{
if ( large )
return( QSize(16,16) );
else
return( QSize(10,10) );
}
void QuartzButton::setBitmap(const unsigned char *bitmap)
{
if (deco)
delete deco;
deco = new QBitmap(10, 10, bitmap, true);
deco->setMask( *deco );
repaint( false );
}
void QuartzButton::drawButton(QPainter *p)
{
// Never paint if the pixmaps have not been created
if (!quartz_initialized)
return;
QColor c;
if (isLeft)
c = options->color(Options::TitleBar, client->isActive()).light(130);
else
c = options->color(Options::TitleBlend, client->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 sticky 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( options->color(Options::ButtonBg, client->isActive()).light(150) );
p->drawPixmap(isDown() ? xOff+1: xOff, isDown() ? yOff+1 : yOff, *deco);
} else
{
QPixmap btnpix;
int Offset = 0;
if (isSticky)
{
if (isDown())
Offset = 1;
// Select the right sticky button to paint
if (client->isActive())
btnpix = isOn() ? *pinDownPix : *pinUpPix;
else
btnpix = isOn() ? *ipinDownPix : *ipinUpPix;
} else
btnpix = client->miniIcon();
// Shrink the miniIcon for tiny titlebars.
if ( !large )
{
QPixmap tmpPix;
// Smooth scale the image
tmpPix.convertFromImage( btnpix.convertToImage().smoothScale(10, 10));
p->drawPixmap( 0, 0, tmpPix );
} else
p->drawPixmap( Offset, Offset, btnpix );
}
}
// Make the protected member public
void QuartzButton::turnOn( bool isOn )
{
if ( isToggleButton() )
setOn( isOn );
}
void QuartzButton::mousePressEvent( QMouseEvent* e )
{
last_button = e->button();
QMouseEvent me( e->type(), e->pos(), e->globalPos(),
LeftButton, e->state() );
KWinButton::mousePressEvent( &me );
}
void QuartzButton::mouseReleaseEvent( QMouseEvent* e )
{
last_button = e->button();
QMouseEvent me( e->type(), e->pos(), e->globalPos(),
LeftButton, e->state() );
KWinButton::mouseReleaseEvent( &me );
}
///////////////////////////////////////////////////////////////////////////
QuartzClient::QuartzClient( 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 < QuartzClient::BtnCount; i++)
button[i] = NULL;
// Finally, toolWindows look small
if ( isTool() ) {
titleHeight = 12;
largeButtons = false;
}
else {
titleHeight = 18;
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->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
g->addRowSpacing(2, 1); // line under titlebar
g->addRowSpacing(4, 4); // bottom handles
g->addColSpacing(0, 4);
g->addColSpacing(2, 4);
// Pack the titlebar HBox with items
hb = new QBoxLayout(0, QBoxLayout::LeftToRight, 0, 0, 0);
hb->setResizeMode( QLayout::FreeResize );
g->addLayout ( hb, 1, 1 );
addClientButtons( options->titleButtonsLeft() );
titlebar = new QSpacerItem( 10, titleHeight, QSizePolicy::Expanding, QSizePolicy::Minimum );
hb->addItem(titlebar);
hb->addSpacing(2);
addClientButtons( options->titleButtonsRight(), false );
hb->addSpacing(2);
}
void QuartzClient::addClientButtons( const QString& s, bool isLeft )
{
if (s.length() > 0)
for(unsigned int i = 0; i < s.length(); i++)
{
switch( s[i].latin1() )
{
// Menu button
case 'M':
if (!button[BtnMenu])
{
button[BtnMenu] = new QuartzButton(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 QuartzButton(this, "sticky",
largeButtons, isLeft, true, NULL, i18n("Sticky"));
button[BtnSticky]->turnOn( isSticky() );
connect( button[BtnSticky], SIGNAL(clicked()),
this, SLOT(toggleSticky()) );
hb->addSpacing(1);
hb->addWidget( button[BtnSticky] );
hb->addSpacing(1);
}
break;
// Help button
case 'H':
if( providesContextHelp() && (!button[BtnHelp]) )
{
button[BtnHelp] = new QuartzButton(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 QuartzButton(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 QuartzButton(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 QuartzButton(this, "close",
largeButtons, isLeft, true, close_bits, i18n("Close"));
connect( button[BtnClose], SIGNAL( clicked()),
this, SLOT(closeWindow()) );
hb->addWidget( button[BtnClose] );
}
}
}
}
void QuartzClient::iconChange()
{
if (button[BtnMenu] && button[BtnMenu]->isVisible())
button[BtnMenu]->repaint(false);
}
void QuartzClient::stickyChange(bool on)
{
if (button[BtnSticky])
{
button[BtnSticky]->turnOn(on);
button[BtnSticky]->repaint(false);
button[BtnSticky]->setTipText(on ? i18n("Un-Sticky") : i18n("Sticky"));
}
}
void QuartzClient::slotMaximize()
{
if ( button[BtnMax]->last_button == MidButton )
maximize( MaximizeVertical );
else if ( button[BtnMax]->last_button == RightButton )
maximize( MaximizeHorizontal );
else
maximize();
}
void QuartzClient::resizeEvent( QResizeEvent* e)
{
Client::resizeEvent( e );
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 QuartzClient::captionChange( const QString& )
{
repaint( titlebar->geometry(), false );
}
// Quartz Paint magic goes here.
void QuartzClient::paintEvent( QPaintEvent* )
{
// Never paint if the pixmaps have not been created
if (!quartz_initialized)
return;
QColorGroup g;
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();
// Draw part of the frame that is the title color
if( coloredFrame )
g = options->colorGroup(Options::TitleBar, isActive());
else
g = options->colorGroup(Options::Frame, isActive());
// Draw outer highlights and lowlights
p.setPen( g.light().light(120) );
p.drawLine( x, y, x2-1, y );
p.drawLine( x, y+1, x, y2-1 );
p.setPen( g.dark().light(120) );
p.drawLine( x2, y, x2, y2 );
p.drawLine( x, y2, x2, y2 );
// Fill out the border edges
if ( coloredFrame)
p.setPen( g.background().light(130) );
else
p.setPen( g.background() );
p.drawRect( x+1, y+1, w-2, h-2 );
p.drawRect( x+2, y+2, w-4, h-4 );
// Draw a frame around the wrapped widget.
p.setPen( g.background() );
p.drawRect( x+3, y + titleHeight + 3, w-6, h-titleHeight-6 );
// Drawing this extra line removes non-drawn areas when shaded
p.drawLine( x+4, y2-4, x2-4, y2-4);
// Highlight top corner
p.setPen( g.light().light(160) );
p.drawPoint( x, y );
p.setPen( g.light().light(140) );
p.drawPoint( x+1, y );
p.drawPoint( x, y+1 );
// Draw the title bar.
// ===================
r = titlebar->geometry();
// Obtain titlebar blend colours
QColor c1 = options->color(Options::TitleBar, isActive() ).light(130);
QColor c2 = options->color(Options::TitleBlend, isActive() );
// Create a disposable pixmap buffer for the titlebar
KPixmap* titleBuffer = new KPixmap;
titleBuffer->resize( w-6, titleHeight );
QPainter p2( titleBuffer, this );
int rightoffset = r.x()+r.width()-25-4; // subtract titleBlocks pixmap width and some
p2.fillRect( 0, 0, w, r.height(), c1 );
p2.fillRect( rightoffset, 0, w-rightoffset-6, 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 = options->font(true);
if ( !largeButtons )
{
fnt.setPointSize( fnt.pointSize() - 3 ); // Shrink font by 3pt
fnt.setWeight( QFont::Normal ); // and disable bold
}
p2.setFont( fnt );
p2.setPen( options->color(Options::Font, isActive() ));
p2.drawText(r.x(), 0, r.width()-3, r.height(),
AlignLeft | AlignVCenter, caption() );
p2.end();
p.drawPixmap( 3, 3, *titleBuffer );
delete titleBuffer;
}
void QuartzClient::showEvent(QShowEvent *ev)
{
calcHiddenButtons();
show();
Client::showEvent(ev);
}
void QuartzClient::mouseDoubleClickEvent( QMouseEvent * e )
{
if (titlebar->geometry().contains( e->pos() ) )
workspace()->performWindowOperation( this, options->operationTitlebarDblClick() );
}
void QuartzClient::maximizeChange(bool m)
{
if (button[BtnMax]) {
button[BtnMax]->setBitmap(m ? minmax_bits : maximize_bits);
button[BtnMax]->setTipText(m ? i18n("Restore") : i18n("Maximize"));
}
}
void QuartzClient::activeChange(bool)
{
for(int i=QuartzClient::BtnHelp; i < QuartzClient::BtnCount; i++)
if(button[i])
button[i]->repaint(false);
repaint(false);
}
// The hiding button while shrinking, show button while expanding magic
void QuartzClient::calcHiddenButtons()
{
//Hide buttons in this order - Sticky, Help, Maximize, Menu, Minimize, Close.
QuartzButton* btnArray[] = { button[BtnSticky], button[BtnHelp], button[BtnMax],
button[BtnMenu], button[BtnIconify], button[BtnClose] };
int minwidth = largeButtons ? 180 : 140; // Start hiding buttons at this width
int btn_width = largeButtons ? 16 : 10;
int current_width = width();
int count = 0;
int i;
// Find out how many buttons we have 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();
}
}
// Make sure the menu button follows double click conventions set in kcontrol
void QuartzClient::menuButtonPressed()
{
QPoint menupoint ( button[BtnMenu]->rect().bottomLeft().x()-1,
button[BtnMenu]->rect().bottomLeft().y()+2 );
workspace()->showWindowMenu( button[BtnMenu]->mapToGlobal( menupoint ), this );
button[BtnMenu]->setDown(false);
}
// Extended KWin plugin interface
/////////////////////////////////
extern "C"
{
Client *allocate(Workspace *ws, WId w, int)
{
return(new QuartzClient(ws, w));
}
void init()
{
clientHandler = new QuartzHandler();
}
void reset()
{
// QuartzHandler takes care of this for us
}
void deinit()
{
delete clientHandler;
}
}
#include "quartz.moc"
// vim: ts=4