kwin/clients/laptop/laptopclient.cpp
Daniel M. Duley 0c77d7383e Trying to make the titlebar buttons easier to hit on laptops by increasing the
width. The issue here is I want to make the buttons as wide as possible for
laptop mice without having the titlebar be all buttons and no title ;-) My
solution so far is making the common buttons bigger and the uncommon ones
smaller. It's not consistent but let's me make the areas frequently hit
wide as hell, which is good for a laptop :) Close, iconify, and maximize are
larger - sticky and help are smaller.

Another updated shot is at:
http://www.mosfet.org/kwinlaptop.gif

svn path=/trunk/kdebase/kwin/; revision=44698
2000-03-25 21:37:49 +00:00

410 lines
12 KiB
C++

#include "laptopclient.h"
#include <qapplication.h>
#include <qcursor.h>
#include <qabstractlayout.h>
#include <qlayout.h>
#include <qtoolbutton.h>
#include <qlabel.h>
#include <qdrawutil.h>
#include <kpixmapeffect.h>
#include <kdrawutil.h>
#include <kapp.h>
#include <qbitmap.h>
#include "../../workspace.h"
#include "../../options.h"
extern "C"
{
Client *allocate(Workspace *ws, WId w)
{
return(new LaptopClient(ws, w));
}
}
static unsigned char iconify_bits[] = {
0xff, 0xff, 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18};
static unsigned char close_bits[] = {
0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00 };
static unsigned char maximize_bits[] = {
0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0xff, 0xff };
static unsigned char minmax_bits[] = {
0x0c, 0x18, 0x33, 0x67, 0xcf, 0x9f, 0x3f, 0x3f};
static unsigned char unsticky_bits[] = {
0x00, 0x18, 0x18, 0x7e, 0x7e, 0x18, 0x18, 0x00};
static unsigned char sticky_bits[] = {
0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00};
static unsigned char question_bits[] = {
0x3c, 0x66, 0x60, 0x30, 0x18, 0x00, 0x18, 0x18};
static QPixmap *titlePix=0;
static KPixmap *aUpperGradient=0;
static KPixmap *iUpperGradient=0;
static bool pixmaps_created = false;
static void create_pixmaps()
{
if(pixmaps_created)
return;
pixmaps_created = true;
// titlebar
QPainter p;
QPainter maskPainter;
int i, x, y;
titlePix = new QPixmap(32, 12);
QBitmap mask(32, 12);
mask.fill(Qt::color0);
p.begin(titlePix);
maskPainter.begin(&mask);
maskPainter.setPen(Qt::color1);
for(i=0, y=2; i < 3; ++i, y+=4){
for(x=1; x < 30; x+=4){
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);
}
}
p.end();
maskPainter.end();
titlePix->setMask(mask);
if(QPixmap::defaultDepth() > 8){
aUpperGradient = new KPixmap;
aUpperGradient->resize(32, 16);
iUpperGradient = new KPixmap;
iUpperGradient->resize(32, 16);
//QColor bgColor = kapp->palette().normal().background();
QColor bgColor = options->color(Options::TitleBar, true);
KPixmapEffect::gradient(*aUpperGradient,
bgColor.light(120),
bgColor.dark(120),
KPixmapEffect::VerticalGradient);
bgColor = options->color(Options::TitleBar, false);
KPixmapEffect::gradient(*iUpperGradient,
bgColor.light(120),
bgColor.dark(120),
KPixmapEffect::VerticalGradient);
}
}
SystemButton::SystemButton(int w, int h, QWidget *parent, const char *name,
const unsigned char *bitmap)
: QButton(parent, name)
{
setFixedSize(w, h);
aBackground.resize(w, h);
iBackground.resize(w, h);
reset();
//resize(22, 12);
if(bitmap)
setBitmap(bitmap);
}
/*
QSize SystemButton::sizeHint() const
{
return(QSize(22, 12));
}*/
void SystemButton::reset()
{
QPainter p;
int w = width();
int h = height();
QColor hColor(options->color(Options::ButtonBg, true));
QColor lColor(options->color(Options::ButtonBlend, true));
KPixmapEffect::gradient(aBackground, hColor.light(150), lColor.dark(150),
KPixmapEffect::DiagonalGradient);
p.begin(&aBackground);
p.setPen(options->colorGroup(Options::ButtonBg, false).dark());
p.drawLine(0, 0, w-1, 0);
p.drawLine(0, 0, 0, w-1);
p.setPen(options->colorGroup(Options::ButtonBg, false).light());
p.drawLine(w-1, 0, w-1, h-1);
p.drawLine(0, h-1, w-1, h-1);
p.end();
hColor = (options->color(Options::ButtonBg, false));
lColor = (options->color(Options::ButtonBlend, false));
KPixmapEffect::gradient(iBackground, hColor.light(150), lColor.dark(150),
KPixmapEffect::DiagonalGradient);
p.begin(&iBackground);
p.setPen(options->colorGroup(Options::ButtonBg, false).light());
p.drawLine(0, 0, w-1, 0);
p.drawLine(0, 0, 0, h-1);
p.setPen(options->colorGroup(Options::ButtonBg, false).dark());
p.drawLine(w-1, 0, w-1, h-1);
p.drawLine(0, h-1, w-1, h-1);
p.end();
}
void SystemButton::setBitmap(const unsigned char *bitmap)
{
deco = QBitmap(8, 8, bitmap, true);
deco.setMask(deco);
repaint();
}
void SystemButton::drawButton(QPainter *p)
{
if(isDown())
p->drawPixmap(0, 0, aBackground);
else
p->drawPixmap(0, 0, iBackground);
p->setPen(options->color(Options::ButtonFg, isDown()));
int xOff = (width()-8)/2;
int yOff = (height()-8)/2;
p->drawPixmap(isDown() ? xOff+1: xOff, isDown() ? yOff+1 : yOff, deco);
}
void LaptopClient::slotReset()
{
delete titlePix;
if(aUpperGradient){
delete aUpperGradient;
delete iUpperGradient;
}
pixmaps_created = false;
create_pixmaps();
button[0]->reset();
button[1]->reset();
button[2]->reset();
button[3]->reset();
if(button[4])
button[4]->reset();
repaint();
}
LaptopClient::LaptopClient( Workspace *ws, WId w, QWidget *parent,
const char *name )
: Client( ws, w, parent, name, WResizeNoErase )
{
create_pixmaps();
connect(options, SIGNAL(resetClients()), this, SLOT(slotReset()));
bool help = providesContextHelp();
QGridLayout* g = new QGridLayout(this, 0, 0, 0);
g->addRowSpacing(0, 3);
g->addRowSpacing(2, 1);
g->addWidget(windowWrapper(), 3, 1);
g->setRowStretch(3, 10);
g->addRowSpacing(4, 12);
g->addColSpacing(0, 4);
g->addColSpacing(2, 4);
g->addColSpacing(2, 12);
button[0] = new SystemButton(24, 12, this, "close", close_bits);
button[1] = new SystemButton(16, 12, this, "sticky");
if(isSticky())
button[1]->setBitmap(unsticky_bits);
else
button[1]->setBitmap(sticky_bits);
button[2] = new SystemButton(24, 12, this, "iconify", iconify_bits);
button[3] = new SystemButton(24, 12, this, "maximize", maximize_bits);
if(help){
button[4] = new SystemButton(16, 12, this, "help", question_bits);
connect( button[4], SIGNAL( clicked() ), this, ( SLOT( contextHelp() ) ) );
}
else
button[4] = NULL;
connect( button[0], SIGNAL( clicked() ), this, ( SLOT( closeWindow() ) ) );
connect( button[1], SIGNAL( clicked() ), this, ( SLOT( toggleSticky() ) ) );
connect( button[2], SIGNAL( clicked() ), this, ( SLOT( iconify() ) ) );
connect( button[3], SIGNAL( clicked() ), this, ( SLOT( maximize() ) ) );
QHBoxLayout* hb = new QHBoxLayout();
hb->setResizeMode(QLayout::FreeResize);
g->addLayout( hb, 1, 1 );
hb->addWidget( button[0]);
hb->addSpacing(3);
titlebar = new QSpacerItem(10, 14, QSizePolicy::Expanding,
QSizePolicy::Minimum);
hb->addItem(titlebar);
hb->addSpacing(3);
if(help){
hb->addWidget( button[4]);
}
hb->addWidget( button[1]);
hb->addWidget( button[2]);
hb->addWidget( button[3]);
/*
for ( int i = 0; i < (help ? 5 : 4); i++) {
button[i]->setFixedSize(22, 12);
}*/
}
void LaptopClient::resizeEvent( QResizeEvent* e)
{
Client::resizeEvent( e );
doShape();
if ( isVisibleToTLW() && !testWFlags( WNorthWestGravity )) {
QPainter p( this );
QRect t = titlebar->geometry();
t.setTop( 0 );
QRegion r = rect();
r = r.subtract( t );
p.setClipRegion( r );
p.eraseRect( rect() );
}
}
void LaptopClient::captionChange( const QString& )
{
repaint( titlebar->geometry(), false );
}
void LaptopClient::paintEvent( QPaintEvent* )
{
QPainter p(this);
QColorGroup g = options->colorGroup(Options::Frame, isActive());
// bottom handle
QRect r(width()-33, height()-33, 33, 33);
p.setPen(Qt::black);
p.drawRect(r);
qDrawShadePanel(&p, r.x()+1, r.y()+1, r.width()-2, r.height()-2, g, false, 1,
&g.brush(QColorGroup::Background));
p.setPen(g.light());
p.drawLine(r.right()-7, r.y()+1, r.right()-7, r.bottom()-8);
p.drawLine(r.x()+1, r.bottom()-7, r.right()-7, r.bottom()-7);
// frame
r = QRect(rect());
r.setHeight(r.height()-8);
r.setWidth(r.width()-8);
p.setPen(Qt::black);
p.drawRect(r);
qDrawShadeRect(&p, r.x()+1, r.y()+1, r.width()-2, r.height()-2, g, false,
1, 0, &g.brush(QColorGroup::Background));
qDrawShadePanel(&p, r.x()+3, r.y()+17, r.width()-6, r.height()-20, g,
true, 1);
r = titlebar->geometry();
KPixmap *grPix = isActive() ? aUpperGradient : iUpperGradient;
if(grPix){
p.drawTiledPixmap(r.x(), r.y(), r.width(), r.height()-1, *grPix);
}
else
p.fillRect(r.x(), r.y(), r.width(), r.height()-1,
options->color(Options::TitleBar, isActive()));
if(titlePix && isActive())
p.drawTiledPixmap(r, *titlePix);
if(grPix){ // needs to happen after the above
p.setPen(options->color(Options::TitleBar, isActive()));
p.drawRect(r.x(), r.y(), r.width(), r.height()-1);
}
QButton *rBtn = providesContextHelp() ? button[4] : button[1];
int x2 = button[3]->x()+button[3]->width();
g = options->colorGroup(Options::Frame, isActive());
p.setPen(g.dark());
p.drawLine(rBtn->x()-1, rBtn->y()-1, x2, rBtn->y()-1);
p.drawLine(rBtn->x()-1, rBtn->y()-1, rBtn->x()-1, rBtn->y()+12);
p.setPen(g.midlight());
p.drawLine(x2, rBtn->y()-1, x2, rBtn->y()+12);
p.drawLine(rBtn->x()-1, rBtn->y()+12, x2, rBtn->y()+12);
rBtn = button[0];
x2 = button[0]->x()+24;
p.setPen(g.dark());
p.drawLine(rBtn->x()-1, rBtn->y()-1, x2, rBtn->y()-1);
p.drawLine(rBtn->x()-1, rBtn->y()-1, rBtn->x()-1, rBtn->y()+12);
p.setPen(g.midlight());
p.drawLine(x2, rBtn->y()-1, x2, rBtn->y()+12);
p.drawLine(rBtn->x()-1, rBtn->y()+12, x2, rBtn->y()+12);
p.setPen(options->color(Options::Font, isActive()));
p.setFont(options->font(isActive()));
QFontMetrics fm(options->font(true));
g = options->colorGroup(Options::TitleBar, isActive());
if(isActive()){
if(grPix)
p.drawTiledPixmap(r.x()+((r.width()-fm.width(caption()))/2)-4,
r.y(), fm.width(caption())+8, r.height()-1,
*grPix);
else
p.fillRect(r.x()+((r.width()-fm.width(caption()))/2)-4, r.y(),
fm.width(caption())+8, r.height(),
g.brush(QColorGroup::Background));
}
p.drawText(r.x(), r.y(), r.width(), r.height()-1,
AlignCenter, caption() );
}
#define QCOORDARRLEN(x) sizeof(x)/(sizeof(QCOORD)*2)
void LaptopClient::doShape()
{
QRegion mask(QRect(0, 0, width()-8, height()-8));
mask += QRect(width()-33, height()-33, 33, 33);
mask -= QRect(0, 0, 1, 1);
mask -= QRect(width()-9, 0, 1, 1);
mask -= QRect(0, height()-9, 1, 1);
// handle
mask -= QRect(width()-1, height()-33, 1, 1);
mask -= QRect(width()-33, height()-1, 1, 1);
mask -= QRect(width()-1, height()-1, 1, 1);
setMask(mask);
}
void LaptopClient::showEvent(QShowEvent *ev)
{
Client::showEvent(ev);
doShape();
repaint();
}
void LaptopClient::windowWrapperShowEvent( QShowEvent* )
{
doShape();
}
void LaptopClient::mouseDoubleClickEvent( QMouseEvent * e )
{
if (titlebar->geometry().contains( e->pos() ) )
setShade( !isShade() );
workspace()->requestFocus( this );
}
void LaptopClient::stickyChange(bool on)
{
button[1]->setBitmap(on ? unsticky_bits : sticky_bits);
}
void LaptopClient::maximizeChange(bool m)
{
button[3]->setBitmap(m ? minmax_bits : maximize_bits);
}
void LaptopClient::init()
{
//
}