~ubuntu-branches/ubuntu/gutsy/kdebase-workspace/gutsy-backports

« back to all changes in this revision

Viewing changes to kwin/clients/kwmtheme/kwmthemeclient.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2007-09-05 20:45:14 UTC
  • Revision ID: james.westby@ubuntu.com-20070905204514-632hhspl0nvrc84i
Tags: upstream-3.93.0
ImportĀ upstreamĀ versionĀ 3.93.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "kwmthemeclient.h"
 
2
 
 
3
#include <kconfig.h>
 
4
#include <kglobal.h>
 
5
#include <QLayout>
 
6
#include <qdrawutil.h>
 
7
#include <QPainter>
 
8
#include <kpixmapeffect.h>
 
9
#include <kstandarddirs.h>
 
10
#include <kdebug.h>
 
11
#include <klocale.h>
 
12
#include <QBitmap>
 
13
#include <QStyle>
 
14
#include <QLabel>
 
15
 
 
16
 
 
17
namespace KWMTheme {
 
18
 
 
19
 
 
20
/* static QPixmap stretchPixmap(QPixmap& src, bool stretchVert){
 
21
  QPixmap dest;
 
22
  QBitmap *srcMask, *destMask;
 
23
  int w, h, w2, h2;
 
24
  QPainter p;
 
25
 
 
26
  if (src.isNull()) return src;
 
27
 
 
28
  w = src.width();
 
29
  h = src.height();
 
30
 
 
31
  if (stretchVert){
 
32
    w2 = w;
 
33
    for (h2=h; h2<100; h2=h2<<1)
 
34
      ;
 
35
  }
 
36
  else{
 
37
    h2 = h;
 
38
    for (w2=w; w2<100; w2=w2<<1)
 
39
      ;
 
40
  }
 
41
  if (w2==w && h2==h) return src;
 
42
 
 
43
  dest = src;
 
44
  dest.resize(w2, h2);
 
45
 
 
46
  p.begin(&dest);
 
47
  p.drawTiledPixmap(0, 0, w2, h2, src);
 
48
  p.end();
 
49
 
 
50
  srcMask = (QBitmap*)src.mask();
 
51
  if (srcMask){
 
52
    destMask = (QBitmap*)dest.mask();
 
53
    p.begin(destMask);
 
54
    p.drawTiledPixmap(0, 0, w2, h2, *srcMask);
 
55
    p.end();
 
56
  }
 
57
  return dest;
 
58
} */
 
59
 
 
60
 
 
61
inline const KDecorationOptions* options() { return KDecoration::options(); }
 
62
 
 
63
enum FramePixmap{FrameTop=0, FrameBottom, FrameLeft, FrameRight, FrameTopLeft,
 
64
   FrameTopRight, FrameBottomLeft, FrameBottomRight};
 
65
 
 
66
static QPixmap *framePixmaps[8];
 
67
static QPixmap *menuPix, *iconifyPix, *closePix, *maxPix, *minmaxPix,
 
68
    *pinupPix, *pindownPix;
 
69
static QPixmap *aTitlePix = 0;
 
70
static QPixmap *iTitlePix = 0;
 
71
static KPixmapEffect::GradientType grType;
 
72
static int maxExtent, titleAlign;
 
73
static bool titleGradient = true;
 
74
static bool pixmaps_created = false;
 
75
static bool titleSunken = false;
 
76
static bool titleTransparent;
 
77
 
 
78
static void create_pixmaps()
 
79
{
 
80
    const char *keys[] = {"wm_top", "wm_bottom", "wm_left", "wm_right",
 
81
    "wm_topleft", "wm_topright", "wm_bottomleft", "wm_bottomright"};
 
82
 
 
83
    if(pixmaps_created)
 
84
        return;
 
85
    pixmaps_created = true;
 
86
    
 
87
    KSharedConfig::Ptr _config = KGlobal::config();
 
88
    KConfigGroup config(_config, "General");
 
89
    
 
90
    QString tmpStr;
 
91
 
 
92
    for(int i=0; i < 8; ++i)
 
93
    {
 
94
        framePixmaps[i] = new QPixmap(locate("data",
 
95
                                      "kwin/pics/"+config.readEntry(keys[i], " ")));
 
96
        if(framePixmaps[i]->isNull())
 
97
            kWarning() << "Unable to load frame pixmap for " << keys[i] ;
 
98
    }
 
99
/*
 
100
    *framePixmaps[FrameTop] = stretchPixmap(*framePixmaps[FrameTop], false);
 
101
    *framePixmaps[FrameBottom] = stretchPixmap(*framePixmaps[FrameBottom], false);
 
102
    *framePixmaps[FrameLeft] = stretchPixmap(*framePixmaps[FrameLeft], true);
 
103
    *framePixmaps[FrameRight] = stretchPixmap(*framePixmaps[FrameRight], true);
 
104
*/
 
105
    maxExtent = framePixmaps[FrameTop]->height();
 
106
    if(framePixmaps[FrameBottom]->height() > maxExtent)
 
107
        maxExtent = framePixmaps[FrameBottom]->height();
 
108
    if(framePixmaps[FrameLeft]->width() > maxExtent)
 
109
        maxExtent = framePixmaps[FrameLeft]->width();
 
110
    if(framePixmaps[FrameRight]->width() > maxExtent)
 
111
        maxExtent = framePixmaps[FrameRight]->width();
 
112
 
 
113
    maxExtent++;
 
114
 
 
115
    menuPix = new QPixmap(locate("data",
 
116
                                 "kwin/pics/"+config.readEntry("menu", " ")));
 
117
    iconifyPix = new QPixmap(locate("data",
 
118
                                    "kwin/pics/"+config.readEntry("iconify", " ")));
 
119
    maxPix = new QPixmap(locate("appdata",
 
120
                                "pics/"+config.readEntry("maximize", " ")));
 
121
    minmaxPix = new QPixmap(locate("data",
 
122
                                   "kwin/pics/"+config.readEntry("maximizedown", " ")));
 
123
    closePix = new QPixmap(locate("data",
 
124
                                  "kwin/pics/"+config.readEntry("close", " ")));
 
125
    pinupPix = new QPixmap(locate("data",
 
126
                                  "kwin/pics/"+config.readEntry("pinup", " ")));
 
127
    pindownPix = new QPixmap(locate("data",
 
128
                                    "kwin/pics/"+config.readEntry("pindown", " ")));
 
129
    if(menuPix->isNull())                           
 
130
        menuPix->load(locate("data", "kwin/pics/menu.png"));
 
131
    if(iconifyPix->isNull())
 
132
        iconifyPix->load(locate("data", "kwin/pics/iconify.png"));
 
133
    if(maxPix->isNull())
 
134
        maxPix->load(locate("data", "kwin/pics/maximize.png"));
 
135
    if(minmaxPix->isNull())
 
136
        minmaxPix->load(locate("data", "kwin/pics/maximizedown.png"));
 
137
    if(closePix->isNull())
 
138
        closePix->load(locate("data", "kwin/pics/close.png"));
 
139
    if(pinupPix->isNull())
 
140
        pinupPix->load(locate("data", "kwin/pics/pinup.png"));
 
141
    if(pindownPix->isNull())
 
142
        pindownPix->load(locate("data", "kwin/pics/pindown.png"));
 
143
    
 
144
    tmpStr = config.readEntry("TitleAlignment");
 
145
    if(tmpStr == "right")
 
146
        titleAlign = Qt::AlignRight | Qt::AlignVCenter;
 
147
    else if(tmpStr == "middle")
 
148
        titleAlign = Qt::AlignCenter;
 
149
    else
 
150
        titleAlign = Qt::AlignLeft | Qt::AlignVCenter;
 
151
    titleSunken = config.readEntry("TitleFrameShaded", true );
 
152
    // titleSunken = true; // is this fixed?
 
153
    titleTransparent = config.readEntry("PixmapUnderTitleText", true);
 
154
 
 
155
    tmpStr = config.readEntry("TitlebarLook");
 
156
    if(tmpStr == "shadedVertical"){
 
157
        aTitlePix = new QPixmap;
 
158
        aTitlePix->resize(32, 20);
 
159
        KPixmapEffect::gradient(*aTitlePix,
 
160
                                options()->color(KDecorationOptions::ColorTitleBar, true),
 
161
                                options()->color(KDecorationOptions::ColorTitleBlend, true),
 
162
                                KPixmapEffect::VerticalGradient);
 
163
        iTitlePix = new QPixmap;
 
164
        iTitlePix->resize(32, 20);
 
165
        KPixmapEffect::gradient(*iTitlePix,
 
166
                                options()->color(KDecorationOptions::ColorTitleBar, false),
 
167
                                options()->color(KDecorationOptions::ColorTitleBlend, false),
 
168
                                KPixmapEffect::VerticalGradient);
 
169
        titleGradient = false; // we can just tile this
 
170
 
 
171
    }
 
172
    else if(tmpStr == "shadedHorizontal")
 
173
        grType = KPixmapEffect::HorizontalGradient;
 
174
    else if(tmpStr == "shadedDiagonal")
 
175
        grType = KPixmapEffect::DiagonalGradient;
 
176
    else if(tmpStr == "shadedCrossDiagonal")
 
177
        grType = KPixmapEffect::CrossDiagonalGradient;
 
178
    else if(tmpStr == "shadedPyramid")
 
179
        grType = KPixmapEffect::PyramidGradient;
 
180
    else if(tmpStr == "shadedRectangle")
 
181
        grType = KPixmapEffect::RectangleGradient;
 
182
    else if(tmpStr == "shadedPipeCross")
 
183
        grType = KPixmapEffect::PipeCrossGradient;
 
184
    else if(tmpStr == "shadedElliptic")
 
185
        grType = KPixmapEffect::EllipticGradient;
 
186
    else{
 
187
        titleGradient = false;
 
188
        tmpStr = config.readEntry("TitlebarPixmapActive", "");
 
189
        if(!tmpStr.isEmpty()){
 
190
            aTitlePix = new QPixmap;
 
191
            aTitlePix->load(locate("data", "kwin/pics/" + tmpStr));
 
192
        }
 
193
        else
 
194
            aTitlePix = NULL;
 
195
        tmpStr = config.readEntry("TitlebarPixmapInactive", "");
 
196
        if(!tmpStr.isEmpty()){
 
197
            iTitlePix = new QPixmap;
 
198
            iTitlePix->load(locate("data", "kwin/pics/" + tmpStr));
 
199
        }
 
200
        else
 
201
            iTitlePix = NULL;
 
202
    }
 
203
}
 
204
 
 
205
static void delete_pixmaps()
 
206
{
 
207
   for(int i=0; i < 8; ++i)
 
208
        delete framePixmaps[i];
 
209
 
 
210
   delete menuPix;
 
211
   delete iconifyPix;
 
212
   delete closePix;
 
213
   delete maxPix;
 
214
   delete minmaxPix;
 
215
   delete pinupPix;
 
216
   delete pindownPix;
 
217
   delete aTitlePix;
 
218
   aTitlePix = 0;
 
219
   delete iTitlePix;
 
220
   iTitlePix = 0;
 
221
 
 
222
   titleGradient = true;
 
223
   pixmaps_created = false;
 
224
   titleSunken = false;
 
225
}
 
226
 
 
227
void MyButton::drawButtonLabel(QPainter *p)
 
228
{
 
229
    if(pixmap()){
 
230
        // If we have a theme who's button covers the entire width or
 
231
        // entire height, we shift down/right by 1 pixel so we have
 
232
        // some visual notification of button presses. i.e. for MGBriezh
 
233
        int offset = (isDown() && ((pixmap()->width() >= width()) || 
 
234
                         (pixmap()->height() >= height()))) ? 1 : 0;
 
235
        style().drawItem(p, QRect( offset, offset, width(), height() ), 
 
236
                         AlignCenter, colorGroup(),
 
237
                         true, pixmap(), QString());
 
238
    }
 
239
}
 
240
 
 
241
KWMThemeClient::KWMThemeClient( KDecorationBridge* b, KDecorationFactory* f )
 
242
    : KDecoration( b, f )
 
243
{
 
244
}
 
245
 
 
246
void KWMThemeClient::init()
 
247
{
 
248
    createMainWidget( WResizeNoErase | WStaticContents );
 
249
    widget()->installEventFilter( this );
 
250
 
 
251
    stickyBtn = maxBtn = mnuBtn = 0;
 
252
    layout = new QGridLayout(widget());
 
253
    layout->addColSpacing(0, maxExtent);
 
254
    layout->addColSpacing(2, maxExtent);
 
255
 
 
256
    layout->addRowSpacing(0, maxExtent);
 
257
 
 
258
    layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Fixed,
 
259
                                    QSizePolicy::Expanding));
 
260
 
 
261
    if( isPreview())
 
262
        layout->addWidget( new QLabel( i18n( "<center><b>KWMTheme</b></center>" ), widget()), 2, 1);
 
263
    else
 
264
        layout->addItem( new QSpacerItem( 0, 0 ), 2, 1);
 
265
 
 
266
    // Without the next line, shading flickers
 
267
    layout->addItem( new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding) );
 
268
    layout->addRowSpacing(3, maxExtent);
 
269
    layout->setRowStretch(2, 10);
 
270
    layout->setColumnStretch(1, 10);
 
271
    
 
272
    QBoxLayout* hb = new QBoxLayout(0, QBoxLayout::LeftToRight, 0, 0, 0);
 
273
    layout->addLayout( hb, 1, 1 );
 
274
 
 
275
    KSharedConfig::Ptr _config = KGlobal::config();
 
276
    KConfigGroup config(_config, "Buttons");
 
277
    QString val;
 
278
    MyButton *btn;
 
279
    int i;
 
280
    static const char *defaultButtons[]={"Menu","Sticky","Off","Iconify",
 
281
        "Maximize","Close"};
 
282
    static const char keyOffsets[]={"ABCDEF"};
 
283
    for(i=0; i < 6; ++i){
 
284
        if(i == 3){
 
285
            titlebar = new QSpacerItem(10, 20, QSizePolicy::Expanding,
 
286
                               QSizePolicy::Minimum );
 
287
            hb->addItem( titlebar );
 
288
        }
 
289
        QString key("Button");
 
290
        key += QChar(keyOffsets[i]);
 
291
        val = config.readEntry(key, defaultButtons[i]);
 
292
        if(val == "Menu"){
 
293
            mnuBtn = new MyButton(widget(), "menu");
 
294
            mnuBtn->setToolTip( i18n("Menu"));
 
295
            iconChange();
 
296
            hb->addWidget(mnuBtn);
 
297
            mnuBtn->setFixedSize(20, 20);
 
298
            connect(mnuBtn, SIGNAL(pressed()), this,
 
299
                    SLOT(menuButtonPressed()));
 
300
        }
 
301
        else if(val == "Sticky"){
 
302
            stickyBtn = new MyButton(widget(), "sticky");
 
303
            stickyBtn->setToolTip( i18n("Sticky"));
 
304
            if (isOnAllDesktops())
 
305
                stickyBtn->setPixmap(*pindownPix);
 
306
            else
 
307
                stickyBtn->setPixmap(*pinupPix);
 
308
            connect(stickyBtn, SIGNAL( clicked() ), this, SLOT(toggleOnAllDesktops()));
 
309
            hb->addWidget(stickyBtn);
 
310
            stickyBtn->setFixedSize(20, 20);
 
311
        }
 
312
        else if((val == "Iconify") && isMinimizable()){
 
313
            btn = new MyButton(widget(), "iconify");
 
314
            btn->setToolTip( i18n("Minimize"));
 
315
            btn->setPixmap(*iconifyPix);
 
316
            connect(btn, SIGNAL(clicked()), this, SLOT(minimize()));
 
317
            hb->addWidget(btn);
 
318
            btn->setFixedSize(20, 20);
 
319
        }
 
320
        else if((val == "Maximize") && isMaximizable()){
 
321
            maxBtn = new MyButton(widget(), "max");
 
322
            maxBtn->setToolTip( i18n("Maximize"));
 
323
            maxBtn->setPixmap(*maxPix);
 
324
            connect(maxBtn, SIGNAL(clicked()), this, SLOT(maximize()));
 
325
            hb->addWidget(maxBtn);
 
326
            maxBtn->setFixedSize(20, 20);
 
327
        }
 
328
        else if((val == "Close") && isCloseable()){
 
329
            btn = new MyButton(widget(), "close");
 
330
            btn->setToolTip( i18n("Close"));
 
331
            btn->setPixmap(*closePix);
 
332
            connect(btn, SIGNAL(clicked()), this, SLOT(closeWindow()));
 
333
            hb->addWidget(btn);
 
334
            btn->setFixedSize(20, 20);
 
335
        }
 
336
        else{
 
337
            if((val != "Off") && 
 
338
               ((val == "Iconify") && !isMinimizable()) &&
 
339
               ((val == "Maximize") && !isMaximizable()))
 
340
                kWarning() << "KWin: Unrecognized button value: " << val ;
 
341
 
 
342
        }
 
343
    }
 
344
    if(titleGradient){
 
345
        aGradient = new QPixmap;
 
346
        iGradient = new QPixmap;
 
347
    }
 
348
    else{
 
349
        aGradient = 0;
 
350
        iGradient = 0;
 
351
    }
 
352
    widget()->setBackgroundMode(NoBackground);
 
353
}
 
354
 
 
355
void KWMThemeClient::drawTitle(QPainter &dest)
 
356
{
 
357
    QRect titleRect = titlebar->geometry();
 
358
    QRect r(0, 0, titleRect.width(), titleRect.height());
 
359
    QPixmap buffer;
 
360
 
 
361
    if(buffer.width() == r.width())
 
362
        return;
 
363
 
 
364
    buffer.resize(r.size());
 
365
    QPainter p;
 
366
    p.begin(&buffer);
 
367
 
 
368
    if(titleSunken){
 
369
                        qDrawShadeRect(&p, r, options()->palette(KDecorationOptions::ColorFrame, isActive()).active(),
 
370
                       true, 1, 0);
 
371
        r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2);
 
372
    }
 
373
    
 
374
    QPixmap *fill = isActive() ? aTitlePix : iTitlePix;
 
375
    if(fill)
 
376
        p.drawTiledPixmap(r, *fill);
 
377
    else if(titleGradient){
 
378
        fill = isActive() ? aGradient : iGradient;
 
379
        if(fill->width() != r.width()){
 
380
            fill->resize(r.width(), 20);
 
381
            KPixmapEffect::gradient(*fill,
 
382
                                    options()->color(KDecorationOptions::ColorTitleBar, isActive()),
 
383
                                    options()->color(KDecorationOptions::ColorTitleBlend, isActive()),
 
384
                                    grType);
 
385
        }
 
386
        p.drawTiledPixmap(r, *fill);
 
387
    }
 
388
    else{
 
389
                        p.fillRect(r, options()->palette(KDecorationOptions::ColorTitleBar, isActive()).active().
 
390
                   brush(QPalette::Button));
 
391
    }
 
392
    p.setFont(options()->font(isActive()));
 
393
    p.setPen(options()->color(KDecorationOptions::ColorFont, isActive()));
 
394
    // Add left & right margin
 
395
    r.setLeft(r.left()+5);
 
396
    r.setRight(r.right()-5);
 
397
    p.drawText(r, titleAlign, caption());
 
398
    p.end();
 
399
 
 
400
    dest.drawPixmap(titleRect.x(), titleRect.y(), buffer);
 
401
}
 
402
 
 
403
 
 
404
void KWMThemeClient::resizeEvent( QResizeEvent* )
 
405
{
 
406
    doShape();
 
407
    widget()->repaint();
 
408
}
 
409
 
 
410
void KWMThemeClient::captionChange()
 
411
{
 
412
    widget()->repaint( titlebar->geometry(), false );
 
413
}
 
414
 
 
415
void KWMThemeClient::paintEvent( QPaintEvent *)
 
416
{
 
417
    QPainter p;
 
418
    p.begin(widget());
 
419
    int x,y;
 
420
    // first the corners
 
421
    int w1 = framePixmaps[FrameTopLeft]->width();
 
422
    int h1 = framePixmaps[FrameTopLeft]->height();
 
423
    if (w1 > width()/2) w1 = width()/2;
 
424
    if (h1 > height()/2) h1 = height()/2;
 
425
    p.drawPixmap(0,0,*framePixmaps[FrameTopLeft],
 
426
                 0,0,w1, h1);
 
427
    int w2 = framePixmaps[FrameTopRight]->width();
 
428
    int h2 = framePixmaps[FrameTopRight]->height();
 
429
    if (w2 > width()/2) w2 = width()/2;
 
430
    if (h2 > height()/2) h2 = height()/2;
 
431
    p.drawPixmap(width()-w2,0,*framePixmaps[FrameTopRight],
 
432
                 framePixmaps[FrameTopRight]->width()-w2,0,w2, h2);
 
433
 
 
434
    int w3 = framePixmaps[FrameBottomLeft]->width();
 
435
    int h3 = framePixmaps[FrameBottomLeft]->height();
 
436
    if (w3 > width()/2) w3 = width()/2;
 
437
    if (h3 > height()/2) h3 = height()/2;
 
438
    p.drawPixmap(0,height()-h3,*framePixmaps[FrameBottomLeft],
 
439
                 0,framePixmaps[FrameBottomLeft]->height()-h3,w3, h3);
 
440
 
 
441
    int w4 = framePixmaps[FrameBottomRight]->width();
 
442
    int h4 = framePixmaps[FrameBottomRight]->height();
 
443
    if (w4 > width()/2) w4 = width()/2;
 
444
    if (h4 > height()/2) h4 = height()/2;
 
445
    p.drawPixmap(width()-w4,height()-h4,*(framePixmaps[FrameBottomRight]),
 
446
                 framePixmaps[FrameBottomRight]->width()-w4,
 
447
                 framePixmaps[FrameBottomRight]->height()-h4,
 
448
                 w4, h4);
 
449
 
 
450
    QPixmap pm;
 
451
    QMatrix m;
 
452
    int n,s,w;
 
453
    //top
 
454
    pm = *framePixmaps[FrameTop];
 
455
 
 
456
    if (pm.width() > 0){
 
457
    s = width()-w2-w1;
 
458
    n = s/pm.width();
 
459
    w = n>0?s/n:s;
 
460
    m.reset();
 
461
    m.scale(w/(float)pm.width(), 1);
 
462
    pm = pm.transformed(m);
 
463
 
 
464
    x = w1;
 
465
    while (1){
 
466
      if (pm.width() < width()-w2-x){
 
467
        p.drawPixmap(x,maxExtent-pm.height()-1,
 
468
                     pm);
 
469
        x += pm.width();
 
470
      }
 
471
      else {
 
472
        p.drawPixmap(x,maxExtent-pm.height()-1,
 
473
                     pm,
 
474
                     0,0,width()-w2-x,pm.height());
 
475
        break;
 
476
      }
 
477
    }
 
478
    }
 
479
 
 
480
    //bottom
 
481
    pm = *framePixmaps[FrameBottom];
 
482
 
 
483
    if (pm.width() > 0){
 
484
    s = width()-w4-w3;
 
485
    n = s/pm.width();
 
486
    w = n>0?s/n:s;
 
487
    m.reset();
 
488
    m.scale(w/(float)pm.width(), 1);
 
489
    pm = pm.transformed(m);
 
490
 
 
491
    x = w3;
 
492
    while (1){
 
493
      if (pm.width() < width()-w4-x){
 
494
        p.drawPixmap(x,height()-maxExtent+1,pm);
 
495
        x += pm.width();
 
496
      }
 
497
      else {
 
498
        p.drawPixmap(x,height()-maxExtent+1,pm,
 
499
                     0,0,width()-w4-x,pm.height());
 
500
        break;
 
501
      }
 
502
    }
 
503
    }
 
504
 
 
505
    //left
 
506
    pm = *framePixmaps[FrameLeft];
 
507
 
 
508
    if (pm.height() > 0){
 
509
    s = height()-h3-h1;
 
510
    n = s/pm.height();
 
511
    w = n>0?s/n:s;
 
512
    m.reset();
 
513
    m.scale(1, w/(float)pm.height());
 
514
    pm = pm.transformed(m);
 
515
 
 
516
    y = h1;
 
517
    while (1){
 
518
      if (pm.height() < height()-h3-y){
 
519
        p.drawPixmap(maxExtent-pm.width()-1, y,
 
520
                     pm);
 
521
        y += pm.height();
 
522
      }
 
523
      else {
 
524
        p.drawPixmap(maxExtent-pm.width()-1, y,
 
525
                     pm,
 
526
                     0,0, pm.width(),
 
527
                     height()-h3-y);
 
528
        break;
 
529
      }
 
530
    }
 
531
    }
 
532
 
 
533
    //right
 
534
    pm = *framePixmaps[FrameRight];
 
535
 
 
536
    if (pm.height() > 0){
 
537
    s = height()-h4-h2;
 
538
    n = s/pm.height();
 
539
    w = n>0?s/n:s;
 
540
    m.reset();
 
541
    m.scale(1, w/(float)pm.height());
 
542
    pm = pm.transformed(m);
 
543
 
 
544
    y = h2;
 
545
    while (1){
 
546
      if (pm.height() < height()-h4-y){
 
547
        p.drawPixmap(width()-maxExtent+1, y,
 
548
                     pm);
 
549
        y += pm.height();
 
550
      }
 
551
      else {
 
552
        p.drawPixmap(width()-maxExtent+1, y,
 
553
                     pm,
 
554
                     0,0, pm.width(),
 
555
                     height()-h4-y);
 
556
        break;
 
557
      }
 
558
    }
 
559
    }
 
560
    drawTitle(p);
 
561
 
 
562
    QColor c = widget()->colorGroup().background();
 
563
 
 
564
    // KWM evidently had a 1 pixel border around the client window. We
 
565
    // emulate it here, but should be removed at some point in order to
 
566
    // seamlessly mesh widget themes
 
567
    p.setPen(c);
 
568
    p.drawRect(maxExtent-1, maxExtent-1, width()-(maxExtent-1)*2,
 
569
               height()-(maxExtent-1)*2);
 
570
 
 
571
    // We fill the area behind the wrapped widget to ensure that
 
572
    // shading animation is drawn as smoothly as possible
 
573
    QRect r(layout->cellGeometry(2, 1));
 
574
    p.fillRect( r.x(), r.y(), r.width(), r.height(), c);
 
575
    p.end();
 
576
}
 
577
 
 
578
void KWMThemeClient::doShape()
 
579
{
 
580
 
 
581
    QBitmap shapemask(width(), height());
 
582
    shapemask.fill(color0);
 
583
    QPainter p;
 
584
    p.begin(&shapemask);
 
585
    p.setBrush(color1);
 
586
    p.setPen(color1);
 
587
    int x,y;
 
588
    // first the corners
 
589
    int w1 = framePixmaps[FrameTopLeft]->width();
 
590
    int h1 = framePixmaps[FrameTopLeft]->height();
 
591
    if (w1 > width()/2) w1 = width()/2;
 
592
    if (h1 > height()/2) h1 = height()/2;
 
593
    if (framePixmaps[FrameTopLeft]->mask())
 
594
        p.drawPixmap(0,0,*framePixmaps[FrameTopLeft]->mask(),
 
595
                     0,0,w1, h1);
 
596
    else
 
597
        p.fillRect(0,0,w1,h1,color1);
 
598
    int w2 = framePixmaps[FrameTopRight]->width();
 
599
    int h2 = framePixmaps[FrameTopRight]->height();
 
600
    if (w2 > width()/2) w2 = width()/2;
 
601
    if (h2 > height()/2) h2 = height()/2;
 
602
    if (framePixmaps[FrameTopRight]->mask())
 
603
        p.drawPixmap(width()-w2,0,*framePixmaps[FrameTopRight]->mask(),
 
604
                     framePixmaps[FrameTopRight]->width()-w2,0,w2, h2);
 
605
    else
 
606
        p.fillRect(width()-w2,0,w2, h2,color1);
 
607
 
 
608
    int w3 = framePixmaps[FrameBottomLeft]->width();
 
609
    int h3 = framePixmaps[FrameBottomLeft]->height();
 
610
    if (w3 > width()/2) w3 = width()/2;
 
611
    if (h3 > height()/2) h3 = height()/2;
 
612
    if (framePixmaps[FrameBottomLeft]->mask())
 
613
        p.drawPixmap(0,height()-h3,*framePixmaps[FrameBottomLeft]->mask(),
 
614
                     0,framePixmaps[FrameBottomLeft]->height()-h3,w3, h3);
 
615
    else
 
616
        p.fillRect(0,height()-h3,w3,h3,color1);
 
617
 
 
618
    int w4 = framePixmaps[FrameBottomRight]->width();
 
619
    int h4 = framePixmaps[FrameBottomRight]->height();
 
620
    if (w4 > width()/2) w4 = width()/2;
 
621
    if (h4 > height()/2) h4 = height()/2;
 
622
    if (framePixmaps[FrameBottomRight]->mask())
 
623
        p.drawPixmap(width()-w4,height()-h4,*framePixmaps[FrameBottomRight]->mask(),
 
624
                     framePixmaps[FrameBottomRight]->width()-w4,
 
625
                     framePixmaps[FrameBottomRight]->height()-h4,
 
626
                     w4, h4);
 
627
    else
 
628
        p.fillRect(width()-w4,height()-h4,w4,h4,color1);
 
629
 
 
630
    QPixmap pm;
 
631
    QMatrix m;
 
632
    int n,s,w;
 
633
    //top
 
634
    if (framePixmaps[FrameTop]->mask())
 
635
    {
 
636
        pm = *framePixmaps[FrameTop]->mask();
 
637
 
 
638
        s = width()-w2-w1;
 
639
        n = s/pm.width();
 
640
        w = n>0?s/n:s;
 
641
        m.reset();
 
642
        m.scale(w/(float)pm.width(), 1);
 
643
        pm = pm.transformed(m);
 
644
 
 
645
        x = w1;
 
646
        while (1){
 
647
            if (pm.width() < width()-w2-x){
 
648
                p.drawPixmap(x,maxExtent-pm.height()-1,
 
649
                             pm);
 
650
                x += pm.width();
 
651
            }
 
652
            else {
 
653
                p.drawPixmap(x,maxExtent-pm.height()-1,
 
654
                             pm,
 
655
                             0,0,width()-w2-x,pm.height());
 
656
                break;
 
657
            }
 
658
        }
 
659
    }
 
660
 
 
661
    //bottom
 
662
    if (framePixmaps[FrameBottom]->mask())
 
663
    {
 
664
        pm = *framePixmaps[FrameBottom]->mask();
 
665
 
 
666
        s = width()-w4-w3;
 
667
        n = s/pm.width();
 
668
        w = n>0?s/n:s;
 
669
        m.reset();
 
670
        m.scale(w/(float)pm.width(), 1);
 
671
        pm = pm.transformed(m);
 
672
 
 
673
        x = w3;
 
674
        while (1){
 
675
          if (pm.width() < width()-w4-x){
 
676
            p.drawPixmap(x,height()-maxExtent+1,pm);
 
677
            x += pm.width();
 
678
          }
 
679
          else {
 
680
            p.drawPixmap(x,height()-maxExtent+1,pm,
 
681
                         0,0,width()-w4-x,pm.height());
 
682
            break;
 
683
          }
 
684
        }
 
685
    }
 
686
 
 
687
    //left
 
688
    if (framePixmaps[FrameLeft]->mask())
 
689
    {
 
690
        pm = *framePixmaps[FrameLeft]->mask();
 
691
 
 
692
        s = height()-h3-h1;
 
693
        n = s/pm.height();
 
694
        w = n>0?s/n:s;
 
695
        m.reset();
 
696
        m.scale(1, w/(float)pm.height());
 
697
        pm = pm.transformed(m);
 
698
 
 
699
        y = h1;
 
700
        while (1){
 
701
          if (pm.height() < height()-h3-y){
 
702
            p.drawPixmap(maxExtent-pm.width()-1, y,
 
703
                         pm);
 
704
            y += pm.height();
 
705
          }
 
706
          else {
 
707
            p.drawPixmap(maxExtent-pm.width()-1, y,
 
708
                         pm,
 
709
                         0,0, pm.width(),
 
710
                         height()-h3-y);
 
711
            break;
 
712
          }
 
713
        }
 
714
    }
 
715
 
 
716
    //right
 
717
    if (framePixmaps[FrameRight]->mask())
 
718
    {
 
719
        pm = *framePixmaps[FrameRight]->mask();
 
720
 
 
721
        s = height()-h4-h2;
 
722
        n = s/pm.height();
 
723
        w = n>0?s/n:s;
 
724
        m.reset();
 
725
        m.scale(1, w/(float)pm.height());
 
726
        pm = pm.transformed(m);
 
727
 
 
728
        y = h2;
 
729
        while (1){
 
730
          if (pm.height() < height()-h4-y){
 
731
            p.drawPixmap(width()-maxExtent+1, y,
 
732
                         pm);
 
733
            y += pm.height();
 
734
          }
 
735
          else {
 
736
            p.drawPixmap(width()-maxExtent+1, y,
 
737
                         pm,
 
738
                         0,0, pm.width(),
 
739
                         height()-h4-y);
 
740
            break;
 
741
          }
 
742
        }
 
743
    }
 
744
    p.fillRect(maxExtent-1, maxExtent-1, width()-2*maxExtent+2, height()-2*maxExtent+2, color1);
 
745
    setMask(shapemask);
 
746
}
 
747
 
 
748
 
 
749
void KWMThemeClient::showEvent(QShowEvent *)
 
750
{
 
751
    doShape();
 
752
    widget()->repaint(false);
 
753
}
 
754
 
 
755
void KWMThemeClient::mouseDoubleClickEvent( QMouseEvent * e )
 
756
{
 
757
    if (e->button() == LeftButton && titlebar->geometry().contains( e->pos() ) )
 
758
        titlebarDblClickOperation();
 
759
}
 
760
 
 
761
void KWMThemeClient::desktopChange()
 
762
{
 
763
    if (stickyBtn) {
 
764
       bool on = isOnAllDesktops();
 
765
       stickyBtn->setPixmap(on ? *pindownPix : *pinupPix);
 
766
       stickyBtn->setToolTip( on ? i18n("Unsticky") : i18n("Sticky") );
 
767
    }
 
768
}
 
769
 
 
770
void KWMThemeClient::maximizeChange()
 
771
{
 
772
    if (maxBtn) {
 
773
       bool m = maximizeMode() == MaximizeFull;
 
774
       maxBtn->setPixmap(m ? *minmaxPix : *maxPix);
 
775
       maxBtn->setToolTip( m ? i18n("Restore") : i18n("Maximize"));
 
776
    }
 
777
}
 
778
 
 
779
void KWMThemeClient::slotMaximize()
 
780
{
 
781
    maximize( maximizeMode() == MaximizeFull ? MaximizeRestore : MaximizeFull );
 
782
}
 
783
 
 
784
void KWMThemeClient::activeChange()
 
785
{
 
786
    widget()->update();
 
787
}
 
788
 
 
789
KDecoration::Position KWMThemeClient::mousePosition(const QPoint &p) const
 
790
{
 
791
    Position m = KDecoration::mousePosition(p);
 
792
    // corners
 
793
    if(p.y() < framePixmaps[FrameTop]->height() &&
 
794
       p.x() < framePixmaps[FrameLeft]->width()){
 
795
        m = PositionTopLeft;
 
796
    }
 
797
    else if(p.y() < framePixmaps[FrameTop]->height() &&
 
798
            p.x() > width()-framePixmaps[FrameRight]->width()){
 
799
        m = PositionTopRight;
 
800
    }
 
801
    else if(p.y() > height()-framePixmaps[FrameBottom]->height() &&
 
802
            p.x() < framePixmaps[FrameLeft]->width()){
 
803
        m = PositionBottomLeft;
 
804
    }
 
805
    else if(p.y() > height()-framePixmaps[FrameBottom]->height() &&
 
806
            p.x() > width()-framePixmaps[FrameRight]->width()){
 
807
        m = PositionBottomRight;
 
808
    } // edges
 
809
    else if(p.y() < framePixmaps[FrameTop]->height())
 
810
        m = PositionTop;
 
811
    else if(p.y() > height()-framePixmaps[FrameBottom]->height())
 
812
        m = PositionBottom;
 
813
    else if(p.x()  < framePixmaps[FrameLeft]->width())
 
814
        m = PositionLeft;
 
815
    else if(p.x() > width()-framePixmaps[FrameRight]->width())
 
816
        m = PositionRight;
 
817
    return(m);
 
818
}
 
819
 
 
820
void KWMThemeClient::menuButtonPressed()
 
821
{
 
822
    mnuBtn->setDown(false); // will stay down if I don't do this
 
823
    QPoint pos = mnuBtn->mapToGlobal(mnuBtn->rect().bottomLeft());
 
824
    showWindowMenu( pos );
 
825
}
 
826
 
 
827
void KWMThemeClient::iconChange()
 
828
{
 
829
    if(mnuBtn){
 
830
        if( icon().pixmap( QIcon::Small, QIcon::Normal ).isNull()){
 
831
            mnuBtn->setPixmap(*menuPix);
 
832
        }
 
833
        else{
 
834
            mnuBtn->setPixmap(icon().pixmap( QIcon::Small, QIcon::Normal ));
 
835
        }
 
836
    }
 
837
}
 
838
 
 
839
bool KWMThemeClient::eventFilter( QObject* o, QEvent* e )
 
840
{
 
841
        if ( o != widget() )
 
842
                return false;
 
843
 
 
844
        switch ( e->type() )
 
845
        {
 
846
                case QEvent::Resize:
 
847
                        resizeEvent( static_cast< QResizeEvent* >( e ) );
 
848
                        return true;
 
849
 
 
850
                case QEvent::Paint:
 
851
                        paintEvent( static_cast< QPaintEvent* >( e ) );
 
852
                        return true;
 
853
 
 
854
                case QEvent::MouseButtonDblClick:
 
855
                        mouseDoubleClickEvent( static_cast< QMouseEvent* >( e ) );
 
856
                        return true;
 
857
 
 
858
                case QEvent::MouseButtonPress:
 
859
                        processMousePressEvent( static_cast< QMouseEvent* >( e ) );
 
860
                        return true;
 
861
 
 
862
                case QEvent::Show:
 
863
                        showEvent( static_cast< QShowEvent* >( e ) );
 
864
                        return true;
 
865
 
 
866
                default:
 
867
                        return false;
 
868
        }
 
869
}
 
870
 
 
871
QSize KWMThemeClient::minimumSize() const
 
872
{
 
873
    return widget()->minimumSize().expandedTo( QSize( 100, 50 ));
 
874
}
 
875
 
 
876
void KWMThemeClient::resize( const QSize& s )
 
877
{
 
878
    widget()->resize( s );
 
879
}
 
880
 
 
881
void KWMThemeClient::borders( int& left, int& right, int& top, int& bottom ) const
 
882
{
 
883
    left =
 
884
    right =
 
885
    top =
 
886
    bottom =
 
887
    
 
888
TODO
 
889
}
 
890
 
 
891
KWMThemeFactory::KWMThemeFactory()
 
892
{
 
893
    create_pixmaps();
 
894
}
 
895
 
 
896
KWMThemeFactory::~KWMThemeFactory()
 
897
{
 
898
    delete_pixmaps();
 
899
}
 
900
 
 
901
KDecoration* KWMThemeFactory::createDecoration( KDecorationBridge* b )
 
902
{
 
903
    return new KWMThemeClient( b, this );
 
904
}
 
905
 
 
906
bool KWMThemeFactory::reset( unsigned long mask )
 
907
{
 
908
    bool needHardReset = false;
 
909
 
 
910
TODO
 
911
 
 
912
    // doesn't obey the Border size setting
 
913
    if( mask & ( SettingFont | SettingButtons ))
 
914
        needHardReset = true;
 
915
 
 
916
    if( mask & ( SettingFont | SettingColors )) {
 
917
        KWMTheme::delete_pixmaps();
 
918
        KWMTheme::create_pixmaps();
 
919
    }
 
920
    
 
921
    if( !needHardReset )
 
922
        resetDecorations( mask );
 
923
    return needHardReset;
 
924
}
 
925
 
 
926
}
 
927
 
 
928
extern "C"
 
929
{
 
930
        KDE_EXPORT KDecorationFactory *create_factory()
 
931
        {
 
932
                return new KWMTheme::KWMThemeFactory();
 
933
        }
 
934
}
 
935
 
 
936
#include "kwmthemeclient.moc"