~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kwin/clients/laptop/laptopclient.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/********************************************************************
 
2
  Laptop KWin Decoration
 
3
 
 
4
  Copyright (c) 2005 Sandro Giessl <sandro@giessl.com>
 
5
  Port of this decoration to KDE 3.2, accessibility enhancement are
 
6
  Copyright (c) 2003 Luciano Montanaro <mikelima@cirulla.net>
 
7
 
 
8
This program is free software; you can redistribute it and/or modify
 
9
it under the terms of the GNU General Public License as published by
 
10
the Free Software Foundation; either version 2 of the License, or
 
11
(at your option) any later version.
 
12
 
 
13
This program is distributed in the hope that it will be useful,
 
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
GNU General Public License for more details.
 
17
 
 
18
You should have received a copy of the GNU General Public License
 
19
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
*********************************************************************/
 
21
 
 
22
#include <kconfig.h> // up here to avoid X11 header conflict :P
 
23
#include "laptopclient.h"
 
24
#include <QPixmap>
 
25
#include <QPaintEvent>
 
26
#include <QBitmap>
 
27
#include <QPainter>
 
28
#include <kglobal.h>
 
29
#include <klocale.h>
 
30
 
 
31
namespace Laptop {
 
32
 
 
33
static const unsigned char iconify_bits[] = {
 
34
    0xff, 0xff, 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18};
 
35
 
 
36
static const unsigned char close_bits[] = {
 
37
    0x42, 0xe7, 0x7e, 0x3c, 0x3c, 0x7e, 0xe7, 0x42};
 
38
 
 
39
static const unsigned char maximize_bits[] = {
 
40
    0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0xff, 0xff };
 
41
 
 
42
static const unsigned char r_minmax_bits[] = {
 
43
    0x0c, 0x18, 0x33, 0x67, 0xcf, 0x9f, 0x3f, 0x3f};
 
44
 
 
45
static const unsigned char l_minmax_bits[] = {
 
46
    0x30, 0x18, 0xcc, 0xe6, 0xf3, 0xf9, 0xfc, 0xfc};
 
47
 
 
48
static const unsigned char question_bits[] = {
 
49
    0x3c, 0x66, 0x60, 0x30, 0x18, 0x00, 0x18, 0x18};
 
50
 
 
51
static const unsigned char unsticky_bits[] = {
 
52
   0x3c, 0x42, 0x99, 0xbd, 0xbd, 0x99, 0x42, 0x3c};
 
53
 
 
54
static const unsigned char sticky_bits[] = {
 
55
   0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
 
56
 
 
57
static QPixmap *titlePix;
 
58
static QPixmap *aUpperGradient;
 
59
static QPixmap *iUpperGradient;
 
60
// buttons active, inactive, up, down, and 2 sizes :P
 
61
static QPixmap *btnPix1;
 
62
static QPixmap *iBtnPix1;
 
63
static QPixmap *btnDownPix1;
 
64
static QPixmap *iBtnDownPix1;
 
65
static QPixmap *btnPix2;
 
66
static QPixmap *btnDownPix2;
 
67
static QPixmap *iBtnPix2;
 
68
static QPixmap *iBtnDownPix2;
 
69
static QColor btnForeground;
 
70
 
 
71
static int titleHeight = 14;
 
72
static int btnWidth1 = 17;
 
73
static int btnWidth2 = 27;
 
74
 
 
75
static int handleSize = 8;      // the resize handle size in pixels
 
76
 
 
77
static bool pixmaps_created = false;
 
78
 
 
79
// =====================================
 
80
 
 
81
extern "C" KDE_EXPORT KDecorationFactory* create_factory()
 
82
{
 
83
    return new Laptop::LaptopClientFactory();
 
84
}
 
85
 
 
86
// =====================================
 
87
 
 
88
static inline const KDecorationOptions* options()
 
89
{
 
90
    return KDecoration::options();
 
91
}
 
92
 
 
93
static void gradientFill(QPixmap *pixmap, const QColor &color1, const QColor &color2, bool diagonal = false)
 
94
{
 
95
        QPainter p(pixmap);
 
96
        QLinearGradient gradient(0, 0, diagonal ? pixmap->width() : 0, pixmap->height());
 
97
        gradient.setColorAt(0.0, color1);
 
98
        gradient.setColorAt(1.0, color2);
 
99
        QBrush brush(gradient);
 
100
        p.fillRect(pixmap->rect(), brush);
 
101
}
 
102
 
 
103
static void drawButtonFrame(QPixmap *pix, const QPalette &g, bool sunken)
 
104
{
 
105
    QPainter p;
 
106
    int w = pix->width();
 
107
    int h = pix->height();
 
108
    int x2 = w-1;
 
109
    int y2 = h-1;
 
110
    p.begin(pix);
 
111
 
 
112
    if(sunken){
 
113
        qDrawShadePanel(&p, 0, 0, w, h, g, true, 2);
 
114
    }
 
115
    else{
 
116
        p.setPen(g.color(QPalette::Dark ));
 
117
        p.drawRect(0, 0, w-2, h-2);
 
118
        p.setPen(g.color(QPalette::Light));
 
119
        p.drawLine(x2, 0, x2, y2);
 
120
        p.drawLine(0, y2, x2, y2);
 
121
        p.drawLine(1, 1, x2-2, 1);
 
122
        p.drawLine(1, 1, 1, y2-2);
 
123
        p.end();
 
124
    }
 
125
}
 
126
 
 
127
static void create_pixmaps()
 
128
{
 
129
    if(pixmaps_created)
 
130
        return;
 
131
    pixmaps_created = true;
 
132
 
 
133
    titleHeight = QFontMetrics(options()->font(true)).height();
 
134
    if (titleHeight < handleSize) titleHeight = handleSize;
 
135
    titleHeight &= ~1; // Make title height even
 
136
    if (titleHeight < 14) titleHeight = 14;
 
137
 
 
138
    btnWidth1 = titleHeight + 3;
 
139
    btnWidth2 = 3*titleHeight/2 + 6;
 
140
 
 
141
    // titlebar
 
142
    QPainter p;
 
143
    QPainter maskPainter;
 
144
    int i, x, y;
 
145
    titlePix = new QPixmap(33, 12);
 
146
    titlePix->fill( Qt::transparent );
 
147
    QBitmap mask(33, 12);
 
148
    mask.fill(Qt::color0);
 
149
 
 
150
    p.begin(titlePix);
 
151
    maskPainter.begin(&mask);
 
152
    maskPainter.setPen(Qt::color1);
 
153
    for(i=0, y=2; i < 3; ++i, y+=4){
 
154
        for(x=1; x <= 33; x+=3){
 
155
            p.setPen(options()->color(KDecoration::ColorTitleBar, true).light(150));
 
156
            p.drawPoint(x, y);
 
157
            maskPainter.drawPoint(x, y);
 
158
            p.setPen(options()->color(KDecoration::ColorTitleBar, true).dark(150));
 
159
            p.drawPoint(x+1, y+1);
 
160
            maskPainter.drawPoint(x+1, y+1);
 
161
        }
 
162
    }
 
163
    p.end();
 
164
    maskPainter.end();
 
165
    titlePix->setMask(mask);
 
166
 
 
167
    if(QPixmap::defaultDepth() > 8){
 
168
        aUpperGradient = new QPixmap(32, titleHeight+2);
 
169
        iUpperGradient = new QPixmap(32, titleHeight+2);
 
170
        QColor bgColor = options()->color(KDecoration::ColorTitleBar, true);
 
171
        gradientFill(aUpperGradient, bgColor.light(120), bgColor.dark(120));
 
172
        bgColor = options()->color(KDecoration::ColorTitleBar, false);
 
173
        gradientFill(iUpperGradient, bgColor.light(120), bgColor.dark(120));
 
174
    }
 
175
    // buttons (active/inactive, sunken/unsunken, 2 sizes each)
 
176
    QPalette g = options()->palette(KDecoration::ColorButtonBg, true);
 
177
    g.setCurrentColorGroup( QPalette::Active );
 
178
    QColor c = g.color( QPalette::Background );
 
179
    btnPix1 = new QPixmap(btnWidth1, titleHeight);
 
180
    btnDownPix1 = new QPixmap(btnWidth1, titleHeight);
 
181
    btnPix2 = new QPixmap(btnWidth2, titleHeight);
 
182
    btnDownPix2 = new QPixmap(btnWidth2, titleHeight);
 
183
    iBtnPix1 = new QPixmap(btnWidth1, titleHeight);
 
184
    iBtnDownPix1 = new QPixmap(btnWidth1, titleHeight);
 
185
    iBtnPix2 = new QPixmap(btnWidth2, titleHeight);
 
186
    iBtnDownPix2 = new QPixmap(btnWidth2, titleHeight);
 
187
    if(QPixmap::defaultDepth() > 8){
 
188
        gradientFill(btnPix1, c.light(120), c.dark(130), true);
 
189
        gradientFill(btnPix2, c.light(120), c.dark(130), true);
 
190
        gradientFill(btnDownPix1, c.light(120), c.dark(130), true);
 
191
        gradientFill(btnDownPix2, c.light(120), c.dark(130), true);
 
192
        g = options()->palette(KDecoration::ColorButtonBg, false);
 
193
        g.setCurrentColorGroup( QPalette::Active );
 
194
        c = g.color(QPalette::Background);
 
195
        gradientFill(iBtnPix1, c.light(120), c.dark(130), true);
 
196
        gradientFill(iBtnPix2, c.light(120), c.dark(130), true);
 
197
        gradientFill(iBtnDownPix1, c.light(120), c.dark(130), true);
 
198
        gradientFill(iBtnDownPix2, c.light(120), c.dark(130), true);
 
199
    }
 
200
    else{
 
201
        btnPix1->fill(c.rgb());
 
202
        btnDownPix1->fill(c.rgb());
 
203
        btnPix2->fill(c.rgb());
 
204
        btnDownPix2->fill(c.rgb());
 
205
        g = options()->palette(KDecoration::ColorButtonBg, false);
 
206
        g.setCurrentColorGroup( QPalette::Active );
 
207
        c = g.background().color();
 
208
        iBtnPix1->fill(c.rgb());
 
209
        iBtnDownPix1->fill(c.rgb());
 
210
        iBtnPix2->fill(c.rgb());
 
211
        iBtnDownPix2->fill(c.rgb());
 
212
    }
 
213
    g = options()->palette(KDecoration::ColorButtonBg, true);
 
214
    g.setCurrentColorGroup( QPalette::Active );
 
215
    c = g.background().color();
 
216
    drawButtonFrame(btnPix1, g, false);
 
217
    drawButtonFrame(btnDownPix1, g, true);
 
218
    drawButtonFrame(btnPix2, g, false);
 
219
    drawButtonFrame(btnDownPix2, g, true);
 
220
    g = options()->palette(KDecoration::ColorButtonBg, false);
 
221
    g.setCurrentColorGroup( QPalette::Active );
 
222
    c = g.background().color();
 
223
    drawButtonFrame(iBtnPix1, g, false);
 
224
    drawButtonFrame(iBtnDownPix1, g, true);
 
225
    drawButtonFrame(iBtnPix2, g, false);
 
226
    drawButtonFrame(iBtnDownPix2, g, true);
 
227
 
 
228
    if(qGray(options()->color(KDecoration::ColorButtonBg, true).rgb()) > 128)
 
229
        btnForeground = Qt::black;
 
230
    else
 
231
        btnForeground = Qt::white;
 
232
}
 
233
 
 
234
static void delete_pixmaps()
 
235
{
 
236
    delete titlePix;
 
237
    if(aUpperGradient){
 
238
        delete aUpperGradient;
 
239
        delete iUpperGradient;
 
240
        delete btnPix1;
 
241
        delete btnDownPix1;
 
242
        delete iBtnPix1;
 
243
        delete iBtnDownPix1;
 
244
        delete btnPix2;
 
245
        delete btnDownPix2;
 
246
        delete iBtnPix2;
 
247
        delete iBtnDownPix2;
 
248
    }
 
249
    pixmaps_created = false;
 
250
}
 
251
 
 
252
// =====================================
 
253
 
 
254
LaptopButton::LaptopButton(ButtonType type, LaptopClient *parent, const char *name)
 
255
    : KCommonDecorationButton(type, parent)
 
256
{
 
257
    Q_UNUSED( name );
 
258
    setAttribute(Qt::WA_NoSystemBackground, true);
 
259
}
 
260
 
 
261
void LaptopButton::reset(unsigned long changed)
 
262
{
 
263
    if (changed&DecorationReset || changed&ManualReset || changed&SizeChange || changed&StateChange) {
 
264
        switch (type() ) {
 
265
            case CloseButton:
 
266
                setBitmap(close_bits);
 
267
                break;
 
268
            case HelpButton:
 
269
                setBitmap(question_bits);
 
270
                break;
 
271
            case MinButton:
 
272
                setBitmap(iconify_bits);
 
273
                break;
 
274
            case MaxButton:
 
275
                if (isChecked() ) {
 
276
                    setBitmap(isLeft() ? l_minmax_bits : r_minmax_bits);
 
277
                } else {
 
278
                    setBitmap(maximize_bits);
 
279
                }
 
280
                break;
 
281
            case OnAllDesktopsButton:
 
282
                setBitmap( isChecked() ? unsticky_bits : sticky_bits );
 
283
                break;
 
284
            default:
 
285
                setBitmap(0);
 
286
                break;
 
287
        }
 
288
 
 
289
        this->update();
 
290
    }
 
291
}
 
292
 
 
293
void LaptopButton::setBitmap(const unsigned char *bitmap)
 
294
{
 
295
    if (bitmap)
 
296
        deco = QBitmap::fromData( QSize(8,  8),  bitmap);
 
297
    else {
 
298
        deco = QBitmap(8,8);
 
299
        deco.fill(Qt::color0);
 
300
    }
 
301
    deco.setMask(deco);
 
302
    repaint();
 
303
}
 
304
 
 
305
void LaptopButton::paintEvent(QPaintEvent *)
 
306
{
 
307
    QPainter p(this);
 
308
    drawButton(&p);
 
309
}
 
310
 
 
311
void LaptopButton::drawButton(QPainter *p)
 
312
{
 
313
    bool smallBtn = width() == btnWidth1;
 
314
    if(btnPix1){
 
315
        if(decoration()->isActive()){
 
316
            if(isDown())
 
317
                p->drawPixmap(0, 0, smallBtn ? *btnDownPix1 : *btnDownPix2);
 
318
            else
 
319
                p->drawPixmap(0, 0, smallBtn ? *btnPix1 : *btnPix2);
 
320
        }
 
321
        else{
 
322
            if(isDown())
 
323
                p->drawPixmap(0, 0, smallBtn ? *iBtnDownPix1 : *iBtnDownPix2);
 
324
            else
 
325
                p->drawPixmap(0, 0, smallBtn ? *iBtnPix1 : *iBtnPix2);
 
326
        }
 
327
    }
 
328
    else{
 
329
        QPalette g = options()->palette(KDecoration::ColorButtonBg, decoration()->isActive());
 
330
        g.setCurrentColorGroup( QPalette::Active );
 
331
        int w = width();
 
332
        int h = height();
 
333
        p->fillRect(1, 1, w-2, h-2, isDown() ? g.color(QPalette::Mid) : g.color(QPalette::Button) );
 
334
        p->setPen(isDown() ? g.color( QPalette::Dark ) : g.color( QPalette::Light ));
 
335
        p->drawLine(0, 0, w-1, 0);
 
336
        p->drawLine(0, 0, 0, w-1);
 
337
        p->setPen(isDown() ? g.color( QPalette::Light ) : g.color( QPalette::Dark ));
 
338
        p->drawLine(w-1, 0, w-1, h-1);
 
339
        p->drawLine(0, h-1, w-1, h-1);
 
340
    }
 
341
 
 
342
    QPainterPath path;
 
343
    path.addRegion( deco );
 
344
    
 
345
    QPoint offset( (width()-8)/2, (height()-8)/2 );
 
346
    if( isDown() ) offset += QPoint( 1, 1 );
 
347
    p->translate( offset );
 
348
    p->setPen( Qt::NoPen );
 
349
    p->setBrush( btnForeground );
 
350
    p->drawPath( path );
 
351
    
 
352
}
 
353
 
 
354
// =====================================
 
355
 
 
356
void LaptopClient::reset(unsigned long changed)
 
357
{
 
358
    KCommonDecoration::reset(changed);
 
359
}
 
360
 
 
361
LaptopClient::LaptopClient(KDecorationBridge *b, KDecorationFactory *f)
 
362
    : KCommonDecoration(b, f)
 
363
{
 
364
}
 
365
 
 
366
LaptopClient::~LaptopClient()
 
367
{
 
368
}
 
369
 
 
370
QString LaptopClient::visibleName() const
 
371
{
 
372
    return i18n("Laptop");
 
373
}
 
374
 
 
375
QString LaptopClient::defaultButtonsLeft() const
 
376
{
 
377
    return "X";
 
378
}
 
379
 
 
380
QString LaptopClient::defaultButtonsRight() const
 
381
{
 
382
    return "HSIA";
 
383
}
 
384
 
 
385
bool LaptopClient::decorationBehaviour(DecorationBehaviour behaviour) const
 
386
{
 
387
    switch (behaviour) {
 
388
        case DB_MenuClose:
 
389
            return false;
 
390
 
 
391
        case DB_WindowMask:
 
392
            return true;
 
393
 
 
394
        case DB_ButtonHide:
 
395
            return true;
 
396
 
 
397
        default:
 
398
            return KCommonDecoration::decorationBehaviour(behaviour);
 
399
    }
 
400
}
 
401
 
 
402
int LaptopClient::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *btn) const
 
403
{
 
404
    switch (lm) {
 
405
        case LM_TitleEdgeLeft:
 
406
        case LM_TitleEdgeRight:
 
407
        case LM_BorderLeft:
 
408
        case LM_BorderRight:
 
409
            return 4;
 
410
 
 
411
        case LM_BorderBottom:
 
412
            return mustDrawHandle() ? handleSize : 4;
 
413
 
 
414
        case LM_TitleEdgeTop:
 
415
            return 3;
 
416
 
 
417
        case LM_TitleEdgeBottom:
 
418
            return 1;
 
419
 
 
420
        case LM_TitleBorderLeft:
 
421
        case LM_TitleBorderRight:
 
422
            return 0;
 
423
 
 
424
        case LM_ButtonWidth:
 
425
        {
 
426
            if (btn && (btn->type()==HelpButton||btn->type()==OnAllDesktopsButton) ) {
 
427
                return btnWidth1;
 
428
            } else {
 
429
                return btnWidth2;
 
430
            }
 
431
        }
 
432
 
 
433
        case LM_ButtonHeight:
 
434
        case LM_TitleHeight:
 
435
            if (isToolWindow() )
 
436
                return titleHeight-2;
 
437
            else
 
438
                return titleHeight;
 
439
 
 
440
        case LM_ButtonSpacing:
 
441
            return 0;
 
442
 
 
443
        default:
 
444
            return KCommonDecoration::layoutMetric(lm, respectWindowState, btn);
 
445
    }
 
446
}
 
447
 
 
448
KCommonDecorationButton *LaptopClient::createButton(ButtonType type)
 
449
{
 
450
    switch (type) {
 
451
        case OnAllDesktopsButton:
 
452
            return new LaptopButton(OnAllDesktopsButton, this, "on_all_desktops");
 
453
 
 
454
        case HelpButton:
 
455
            return new LaptopButton(HelpButton, this, "help");
 
456
 
 
457
        case MinButton:
 
458
            return new LaptopButton(MinButton, this, "minimize");
 
459
 
 
460
        case MaxButton:
 
461
            return new LaptopButton(MaxButton, this, "maximize");
 
462
 
 
463
        case CloseButton:
 
464
            return new LaptopButton(CloseButton, this, "close");
 
465
 
 
466
        default:
 
467
            return 0;
 
468
    }
 
469
}
 
470
 
 
471
void LaptopClient::init()
 
472
{
 
473
    bufferDirty = true;
 
474
 
 
475
    KCommonDecoration::init();
 
476
}
 
477
 
 
478
void LaptopClient::captionChange()
 
479
{
 
480
    bufferDirty = true;
 
481
 
 
482
    KCommonDecoration::captionChange();
 
483
}
 
484
 
 
485
void LaptopClient::paintEvent( QPaintEvent* )
 
486
{
 
487
    QPainter p(widget());
 
488
    QPalette g = options()->palette(KDecoration::ColorFrame, isActive());
 
489
    g.setCurrentColorGroup( QPalette::Active );
 
490
 
 
491
    QRect r(widget()->rect());
 
492
    p.setPen(Qt::black);
 
493
    p.drawRect(r.adjusted(0, 0, -1, -1));
 
494
 
 
495
    // fill mid frame...
 
496
    p.setPen(g.background().color());
 
497
    p.drawLine(r.x()+2, r.y()+2, r.right()-2, r.y()+2);
 
498
    p.drawLine(r.left()+2, r.y()+3, r.left()+2, r.bottom()-layoutMetric(LM_BorderBottom)+1);
 
499
    p.drawLine(r.right()-2, r.y()+3, r.right()-2, r.bottom()-layoutMetric(LM_BorderBottom)+1);
 
500
    p.drawLine(r.left()+3, r.y()+3, r.left()+3, r.y()+layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)+layoutMetric(LM_TitleEdgeTop) );
 
501
    p.drawLine(r.right()-3, r.y()+3, r.right()-3, r.y()+layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)+layoutMetric(LM_TitleEdgeTop) );
 
502
    if (!mustDrawHandle() )
 
503
        p.drawLine(r.left()+1, r.bottom()-2, r.right()-1, r.bottom()-2);
 
504
 
 
505
    // outer frame
 
506
    p.setPen(g.color(QPalette::Light));
 
507
    p.drawLine(r.x()+1, r.y()+1, r.right()-1, r.y()+1);
 
508
    p.drawLine(r.x()+1, r.y()+1, r.x()+1, r.bottom()-1);
 
509
    p.setPen(g.dark().color());
 
510
    p.drawLine(r.right()-1, r.y()+1, r.right()-1, r.bottom()-1);
 
511
    p.drawLine(r.x()+1, r.bottom()-1, r.right()-1, r.bottom()-1);
 
512
 
 
513
    int th = titleHeight;
 
514
    int bb = handleSize + 2; // Bottom border
 
515
    int bs = handleSize - 2; // inner size of bottom border
 
516
    if (!mustDrawHandle()) {
 
517
        bb = 6;
 
518
        bs = 0;
 
519
    }
 
520
    if ( isToolWindow() )
 
521
        th -= 2;
 
522
 
 
523
    // inner rect
 
524
    p.drawRect(r.x() + 3, r.y() + th + 3, r.width() - 7, r.height() - th - bb - 1);
 
525
 
 
526
    // handles
 
527
    if (mustDrawHandle()) {
 
528
        if (r.width() > 3*handleSize + 20) {
 
529
            int range = 8 + 3*handleSize/2;
 
530
            qDrawShadePanel(&p, r.x() + 1, r.bottom() - bs, range,
 
531
                            handleSize - 2, g, false, 1, &g.brush(QPalette::Mid));
 
532
            qDrawShadePanel(&p, r.x() + range + 1, r.bottom() - bs,
 
533
                    r.width() - 2*range - 2, handleSize - 2, g, false, 1,
 
534
                    isActive() ? &g.brush(QPalette::Background) :
 
535
                                 &g.brush(QPalette::Mid));
 
536
            qDrawShadePanel(&p, r.right() - range, r.bottom() - bs,
 
537
                    range, bs, g, false, 1, &g.brush(QPalette::Mid));
 
538
        } else {
 
539
            qDrawShadePanel(&p, r.x() + 1, r.bottom() - bs,
 
540
                    r.width() - 2, bs, g, false, 1,
 
541
                    isActive() ?  &g.brush(QPalette::Background) :
 
542
                                  &g.brush(QPalette::Mid));
 
543
        }
 
544
    }
 
545
 
 
546
    r = titleRect();
 
547
 
 
548
    if(isActive()){
 
549
        updateActiveBuffer();
 
550
        p.drawPixmap(r.x(), r.y(), activeBuffer);
 
551
        p.setPen(g.background().color());
 
552
        p.drawPoint(r.x(), r.y());
 
553
        p.drawPoint(r.right(), r.y());
 
554
        p.drawLine(r.right()+1, r.y(), r.right()+1, r.bottom());
 
555
    }
 
556
    else{
 
557
        if(iUpperGradient)
 
558
            p.drawTiledPixmap(r.x(), r.y(), r.width(), r.height()-1,
 
559
                              *iUpperGradient);
 
560
        else
 
561
            p.fillRect(r.x(), r.y(), r.width(), r.height()-1,
 
562
                       options()->color(KDecoration::ColorTitleBar, false));
 
563
 
 
564
        p.setFont(options()->font(false, isToolWindow() ));
 
565
        QFontMetrics fm(options()->font(false));
 
566
        g = options()->palette(KDecoration::ColorTitleBar, false);
 
567
        g.setCurrentColorGroup( QPalette::Active );
 
568
        if(iUpperGradient)
 
569
            p.drawTiledPixmap(r.x()+((r.width()-fm.width(caption()))/2)-4,
 
570
                              r.y(), fm.width(caption())+8, r.height()-1,
 
571
                              *iUpperGradient);
 
572
        else
 
573
            p.fillRect(r.x()+((r.width()-fm.width(caption()))/2)-4, r.y(),
 
574
                       fm.width(caption())+8, r.height()-1,
 
575
                       g.brush(QPalette::Background));
 
576
        p.setPen(g.mid().color());
 
577
        p.drawLine(r.x(), r.y(), r.right(), r.y());
 
578
        p.drawLine(r.x(), r.y(), r.x(), r.bottom());
 
579
        p.setPen(g.color(QPalette::Button));
 
580
        p.drawLine(r.right(), r.y(), r.right(), r.bottom());
 
581
        p.drawLine(r.x(), r.bottom(), r.right(), r.bottom());
 
582
        p.setPen(options()->color(KDecoration::ColorFont, false));
 
583
        p.drawText(r.x(), r.y()+1, r.width(), r.height()-1,
 
584
                   Qt::AlignCenter, caption() );
 
585
        g = options()->palette(KDecoration::ColorFrame, true);
 
586
        g.setCurrentColorGroup( QPalette::Active );
 
587
        p.setPen(g.background().color());
 
588
        p.drawPoint(r.x(), r.y());
 
589
        p.drawPoint(r.right(), r.y());
 
590
        p.drawLine(r.right()+1, r.y(), r.right()+1, r.bottom());
 
591
    }
 
592
}
 
593
 
 
594
QRegion LaptopClient::cornerShape(WindowCorner corner)
 
595
{
 
596
    switch (corner) {
 
597
        case WC_TopLeft:
 
598
            return QRect(0, 0, 1, 1);
 
599
 
 
600
        case WC_TopRight:
 
601
            return QRect(width()-1, 0, 1, 1);
 
602
 
 
603
        case WC_BottomLeft:
 
604
            return QRect(0, height()-1, 1, 1);
 
605
 
 
606
        case WC_BottomRight:
 
607
            return QRect(width()-1, height()-1, 1, 1);
 
608
 
 
609
        default:
 
610
            return QRegion();
 
611
    }
 
612
 
 
613
}
 
614
 
 
615
bool LaptopClient::mustDrawHandle() const
 
616
{
 
617
    bool drawSmallBorders = !options()->moveResizeMaximizedWindows();
 
618
    if (drawSmallBorders && (maximizeMode() & MaximizeVertical)) {
 
619
        return false;
 
620
    } else {
 
621
        return isResizable();
 
622
    }
 
623
}
 
624
 
 
625
void LaptopClient::updateActiveBuffer( )
 
626
{
 
627
    QRect rTitle = titleRect();
 
628
    if( !bufferDirty && (lastBufferWidth == rTitle.width()))
 
629
        return;
 
630
    if ( rTitle.width() <= 0 || rTitle.height() <= 0 )
 
631
        return;
 
632
    lastBufferWidth = rTitle.width();
 
633
    bufferDirty = false;
 
634
 
 
635
    activeBuffer = QPixmap(rTitle.width(), rTitle.height());
 
636
    QPainter p;
 
637
    QRect r(0, 0, activeBuffer.width(), activeBuffer.height());
 
638
    p.begin(&activeBuffer);
 
639
    if(aUpperGradient){
 
640
        p.drawTiledPixmap(r, *aUpperGradient);
 
641
    }
 
642
    else{
 
643
        p.fillRect(r, options()->color(KDecoration::ColorTitleBar, true));
 
644
    }
 
645
    if(titlePix)
 
646
        p.drawTiledPixmap(r, *titlePix);
 
647
 
 
648
    p.setFont(options()->font(true, isToolWindow() ));
 
649
    QFontMetrics fm(options()->font(true));
 
650
    QPalette g = options()->palette(KDecoration::ColorTitleBar, true);
 
651
    g.setCurrentColorGroup( QPalette::Active );
 
652
    if(aUpperGradient)
 
653
        p.drawTiledPixmap(r.x()+((r.width()-fm.width(caption()))/2)-4,
 
654
                          r.y(), fm.width(caption())+8, r.height()-1,
 
655
                          *aUpperGradient);
 
656
    else
 
657
        p.fillRect(r.x()+((r.width()-fm.width(caption()))/2)-4, 0,
 
658
                   fm.width(caption())+8, r.height(),
 
659
                   g.brush(QPalette::Background));
 
660
    p.setPen(g.mid().color());
 
661
    p.drawLine(r.x(), r.y(), r.right(), r.y());
 
662
    p.drawLine(r.x(), r.y(), r.x(), r.bottom());
 
663
    p.setPen(g.color(QPalette::Button));
 
664
    p.drawLine(r.right(), r.y(), r.right(), r.bottom());
 
665
    p.drawLine(r.x(), r.bottom(), r.right(), r.bottom());
 
666
    p.setPen(options()->color(KDecoration::ColorFont, true));
 
667
    p.drawText(r.x(), r.y()+1, r.width(), r.height()-1,
 
668
               Qt::AlignCenter, caption() );
 
669
    g = options()->palette(KDecoration::ColorFrame, true);
 
670
    g.setCurrentColorGroup( QPalette::Active );
 
671
    p.setPen(g.background().color());
 
672
    p.drawPoint(r.x(), r.y());
 
673
    p.drawPoint(r.right(), r.y());
 
674
    p.drawLine(r.right()+1, r.y(), r.right()+1, r.bottom());
 
675
    p.end();
 
676
}
 
677
 
 
678
static const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask |
 
679
    NET::DesktopMask | NET::DockMask | NET::ToolbarMask | NET::MenuMask |
 
680
    NET::DialogMask | /*NET::OverrideMask |*/ NET::TopMenuMask |
 
681
    NET::UtilityMask | NET::SplashMask;
 
682
 
 
683
bool LaptopClient::isTransient() const
 
684
{
 
685
    NET::WindowType type = windowType(SUPPORTED_WINDOW_TYPES_MASK);
 
686
    return type == NET::Dialog;
 
687
}
 
688
 
 
689
// =====================================
 
690
 
 
691
LaptopClientFactory::LaptopClientFactory()
 
692
{
 
693
    create_pixmaps();
 
694
}
 
695
 
 
696
LaptopClientFactory::~LaptopClientFactory()
 
697
{
 
698
    delete_pixmaps();
 
699
}
 
700
 
 
701
KDecoration *LaptopClientFactory::createDecoration(KDecorationBridge *b)
 
702
{
 
703
    findPreferredHandleSize();
 
704
    return (new Laptop::LaptopClient(b, this))->decoration();
 
705
}
 
706
 
 
707
bool LaptopClientFactory::reset(unsigned long changed)
 
708
{
 
709
    findPreferredHandleSize();
 
710
 
 
711
    // TODO Do not recreate decorations if it is not needed. Look at
 
712
    // ModernSystem for how to do that
 
713
    Laptop::delete_pixmaps();
 
714
    Laptop::create_pixmaps();
 
715
 
 
716
    bool needHardReset = true;
 
717
    if ((changed & ~SettingButtons) == 0) {
 
718
                // handled by KCommonDecoration
 
719
        needHardReset = false;
 
720
    }
 
721
 
 
722
    if (needHardReset) {
 
723
        return true;
 
724
    } else {
 
725
        resetDecorations(changed);
 
726
        return false;
 
727
    }
 
728
}
 
729
 
 
730
bool LaptopClientFactory::supports( Ability ability ) const
 
731
{
 
732
    switch( ability )
 
733
    {
 
734
        // announce
 
735
        case AbilityAnnounceButtons:
 
736
        case AbilityAnnounceColors:
 
737
        // buttons
 
738
        case AbilityButtonOnAllDesktops:
 
739
        case AbilityButtonHelp:
 
740
        case AbilityButtonMinimize:
 
741
        case AbilityButtonMaximize:
 
742
        case AbilityButtonClose:
 
743
        case AbilityButtonSpacer:
 
744
        // colors
 
745
        case AbilityColorTitleBack:
 
746
        case AbilityColorTitleFore:
 
747
        case AbilityColorButtonBack:
 
748
            return true;
 
749
        default:
 
750
            return false;
 
751
    };
 
752
}
 
753
 
 
754
QList< LaptopClientFactory::BorderSize >
 
755
LaptopClientFactory::borderSizes() const
 
756
{
 
757
    // the list must be sorted
 
758
    return QList< BorderSize >() << BorderNormal << BorderLarge <<
 
759
        BorderVeryLarge <<  BorderHuge << BorderVeryHuge << BorderOversized;
 
760
}
 
761
 
 
762
void LaptopClientFactory::findPreferredHandleSize()
 
763
{
 
764
    switch (options()->preferredBorderSize(this)) {
 
765
    case KDecoration::BorderLarge:
 
766
        handleSize = 11;
 
767
        break;
 
768
    case KDecoration::BorderVeryLarge:
 
769
        handleSize = 16;
 
770
        break;
 
771
    case KDecoration::BorderHuge:
 
772
        handleSize = 24;
 
773
        break;
 
774
    case KDecoration::BorderVeryHuge:
 
775
        handleSize = 32;
 
776
        break;
 
777
    case KDecoration::BorderOversized:
 
778
        handleSize = 40;
 
779
        break;
 
780
    case KDecoration::BorderTiny:
 
781
    case KDecoration::BorderNormal:
 
782
    default:
 
783
        handleSize = 8;
 
784
    }
 
785
}
 
786
 
 
787
} // Laptop namespace
 
788
 
 
789
// vim: sw=4