Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / kwin / clients / kwmtheme / kwmthemeclient.cpp
blobbf17fe81e917cce05f06ef8c9ea26f9309f187a5
1 /********************************************************************
2 This program is free software; you can redistribute it and/or modify
3 it under the terms of the GNU General Public License as published by
4 the Free Software Foundation; either version 2 of the License, or
5 (at your option) any later version.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *********************************************************************/
16 #include "kwmthemeclient.h"
18 #include <kconfig.h>
19 #include <kglobal.h>
20 #include <QLayout>
21 #include <qdrawutil.h>
22 #include <QPainter>
23 #include <kpixmapeffect.h>
24 #include <kstandarddirs.h>
25 #include <kdebug.h>
26 #include <klocale.h>
27 #include <QBitmap>
28 #include <QStyle>
29 #include <QLabel>
32 namespace KWMTheme {
35 /* static QPixmap stretchPixmap(QPixmap& src, bool stretchVert){
36 QPixmap dest;
37 QBitmap *srcMask, *destMask;
38 int w, h, w2, h2;
39 QPainter p;
41 if (src.isNull()) return src;
43 w = src.width();
44 h = src.height();
46 if (stretchVert){
47 w2 = w;
48 for (h2=h; h2<100; h2=h2<<1)
51 else{
52 h2 = h;
53 for (w2=w; w2<100; w2=w2<<1)
56 if (w2==w && h2==h) return src;
58 dest = src;
59 dest.resize(w2, h2);
61 p.begin(&dest);
62 p.drawTiledPixmap(0, 0, w2, h2, src);
63 p.end();
65 srcMask = (QBitmap*)src.mask();
66 if (srcMask){
67 destMask = (QBitmap*)dest.mask();
68 p.begin(destMask);
69 p.drawTiledPixmap(0, 0, w2, h2, *srcMask);
70 p.end();
72 return dest;
73 } */
76 inline const KDecorationOptions* options() { return KDecoration::options(); }
78 enum FramePixmap{FrameTop=0, FrameBottom, FrameLeft, FrameRight, FrameTopLeft,
79 FrameTopRight, FrameBottomLeft, FrameBottomRight};
81 static QPixmap *framePixmaps[8];
82 static QPixmap *menuPix, *iconifyPix, *closePix, *maxPix, *minmaxPix,
83 *pinupPix, *pindownPix;
84 static QPixmap *aTitlePix = 0;
85 static QPixmap *iTitlePix = 0;
86 static KPixmapEffect::GradientType grType;
87 static int maxExtent, titleAlign;
88 static bool titleGradient = true;
89 static bool pixmaps_created = false;
90 static bool titleSunken = false;
91 static bool titleTransparent;
93 static void create_pixmaps()
95 const char *keys[] = {"wm_top", "wm_bottom", "wm_left", "wm_right",
96 "wm_topleft", "wm_topright", "wm_bottomleft", "wm_bottomright"};
98 if(pixmaps_created)
99 return;
100 pixmaps_created = true;
102 KSharedConfig::Ptr _config = KGlobal::config();
103 KConfigGroup config(_config, "General");
105 QString tmpStr;
107 for(int i=0; i < 8; ++i)
109 framePixmaps[i] = new QPixmap(locate("data",
110 "kwin/pics/"+config.readEntry(keys[i], " ")));
111 if(framePixmaps[i]->isNull())
112 kWarning() << "Unable to load frame pixmap for " << keys[i] ;
115 *framePixmaps[FrameTop] = stretchPixmap(*framePixmaps[FrameTop], false);
116 *framePixmaps[FrameBottom] = stretchPixmap(*framePixmaps[FrameBottom], false);
117 *framePixmaps[FrameLeft] = stretchPixmap(*framePixmaps[FrameLeft], true);
118 *framePixmaps[FrameRight] = stretchPixmap(*framePixmaps[FrameRight], true);
120 maxExtent = framePixmaps[FrameTop]->height();
121 if(framePixmaps[FrameBottom]->height() > maxExtent)
122 maxExtent = framePixmaps[FrameBottom]->height();
123 if(framePixmaps[FrameLeft]->width() > maxExtent)
124 maxExtent = framePixmaps[FrameLeft]->width();
125 if(framePixmaps[FrameRight]->width() > maxExtent)
126 maxExtent = framePixmaps[FrameRight]->width();
128 maxExtent++;
130 menuPix = new QPixmap(locate("data",
131 "kwin/pics/"+config.readEntry("menu", " ")));
132 iconifyPix = new QPixmap(locate("data",
133 "kwin/pics/"+config.readEntry("iconify", " ")));
134 maxPix = new QPixmap(locate("appdata",
135 "pics/"+config.readEntry("maximize", " ")));
136 minmaxPix = new QPixmap(locate("data",
137 "kwin/pics/"+config.readEntry("maximizedown", " ")));
138 closePix = new QPixmap(locate("data",
139 "kwin/pics/"+config.readEntry("close", " ")));
140 pinupPix = new QPixmap(locate("data",
141 "kwin/pics/"+config.readEntry("pinup", " ")));
142 pindownPix = new QPixmap(locate("data",
143 "kwin/pics/"+config.readEntry("pindown", " ")));
144 if(menuPix->isNull())
145 menuPix->load(locate("data", "kwin/pics/menu.png"));
146 if(iconifyPix->isNull())
147 iconifyPix->load(locate("data", "kwin/pics/iconify.png"));
148 if(maxPix->isNull())
149 maxPix->load(locate("data", "kwin/pics/maximize.png"));
150 if(minmaxPix->isNull())
151 minmaxPix->load(locate("data", "kwin/pics/maximizedown.png"));
152 if(closePix->isNull())
153 closePix->load(locate("data", "kwin/pics/close.png"));
154 if(pinupPix->isNull())
155 pinupPix->load(locate("data", "kwin/pics/pinup.png"));
156 if(pindownPix->isNull())
157 pindownPix->load(locate("data", "kwin/pics/pindown.png"));
159 tmpStr = config.readEntry("TitleAlignment");
160 if(tmpStr == "right")
161 titleAlign = Qt::AlignRight | Qt::AlignVCenter;
162 else if(tmpStr == "middle")
163 titleAlign = Qt::AlignCenter;
164 else
165 titleAlign = Qt::AlignLeft | Qt::AlignVCenter;
166 titleSunken = config.readEntry("TitleFrameShaded", true );
167 // titleSunken = true; // is this fixed?
168 titleTransparent = config.readEntry("PixmapUnderTitleText", true);
170 tmpStr = config.readEntry("TitlebarLook");
171 if(tmpStr == "shadedVertical"){
172 aTitlePix = new QPixmap;
173 aTitlePix->resize(32, 20);
174 KPixmapEffect::gradient(*aTitlePix,
175 options()->color(KDecorationOptions::ColorTitleBar, true),
176 options()->color(KDecorationOptions::ColorTitleBlend, true),
177 KPixmapEffect::VerticalGradient);
178 iTitlePix = new QPixmap;
179 iTitlePix->resize(32, 20);
180 KPixmapEffect::gradient(*iTitlePix,
181 options()->color(KDecorationOptions::ColorTitleBar, false),
182 options()->color(KDecorationOptions::ColorTitleBlend, false),
183 KPixmapEffect::VerticalGradient);
184 titleGradient = false; // we can just tile this
187 else if(tmpStr == "shadedHorizontal")
188 grType = KPixmapEffect::HorizontalGradient;
189 else if(tmpStr == "shadedDiagonal")
190 grType = KPixmapEffect::DiagonalGradient;
191 else if(tmpStr == "shadedCrossDiagonal")
192 grType = KPixmapEffect::CrossDiagonalGradient;
193 else if(tmpStr == "shadedPyramid")
194 grType = KPixmapEffect::PyramidGradient;
195 else if(tmpStr == "shadedRectangle")
196 grType = KPixmapEffect::RectangleGradient;
197 else if(tmpStr == "shadedPipeCross")
198 grType = KPixmapEffect::PipeCrossGradient;
199 else if(tmpStr == "shadedElliptic")
200 grType = KPixmapEffect::EllipticGradient;
201 else{
202 titleGradient = false;
203 tmpStr = config.readEntry("TitlebarPixmapActive", "");
204 if(!tmpStr.isEmpty()){
205 aTitlePix = new QPixmap;
206 aTitlePix->load(locate("data", "kwin/pics/" + tmpStr));
208 else
209 aTitlePix = NULL;
210 tmpStr = config.readEntry("TitlebarPixmapInactive", "");
211 if(!tmpStr.isEmpty()){
212 iTitlePix = new QPixmap;
213 iTitlePix->load(locate("data", "kwin/pics/" + tmpStr));
215 else
216 iTitlePix = NULL;
220 static void delete_pixmaps()
222 for(int i=0; i < 8; ++i)
223 delete framePixmaps[i];
225 delete menuPix;
226 delete iconifyPix;
227 delete closePix;
228 delete maxPix;
229 delete minmaxPix;
230 delete pinupPix;
231 delete pindownPix;
232 delete aTitlePix;
233 aTitlePix = 0;
234 delete iTitlePix;
235 iTitlePix = 0;
237 titleGradient = true;
238 pixmaps_created = false;
239 titleSunken = false;
242 void MyButton::drawButtonLabel(QPainter *p)
244 if(pixmap()){
245 // If we have a theme who's button covers the entire width or
246 // entire height, we shift down/right by 1 pixel so we have
247 // some visual notification of button presses. i.e. for MGBriezh
248 int offset = (isDown() && ((pixmap()->width() >= width()) ||
249 (pixmap()->height() >= height()))) ? 1 : 0;
250 style().drawItem(p, QRect( offset, offset, width(), height() ),
251 AlignCenter, colorGroup(),
252 true, pixmap(), QString());
256 KWMThemeClient::KWMThemeClient( KDecorationBridge* b, KDecorationFactory* f )
257 : KDecoration( b, f )
261 void KWMThemeClient::init()
263 createMainWidget( WResizeNoErase | WStaticContents );
264 widget()->installEventFilter( this );
266 stickyBtn = maxBtn = mnuBtn = 0;
267 layout = new QGridLayout(widget());
268 layout->addColSpacing(0, maxExtent);
269 layout->addColSpacing(2, maxExtent);
271 layout->addRowSpacing(0, maxExtent);
273 layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Fixed,
274 QSizePolicy::Expanding));
276 if( isPreview())
277 layout->addWidget( new QLabel( i18n( "<center><b>KWMTheme</b></center>" ), widget()), 2, 1);
278 else
279 layout->addItem( new QSpacerItem( 0, 0 ), 2, 1);
281 // Without the next line, shading flickers
282 layout->addItem( new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding) );
283 layout->addRowSpacing(3, maxExtent);
284 layout->setRowStretch(2, 10);
285 layout->setColumnStretch(1, 10);
287 QBoxLayout* hb = new QBoxLayout(0, QBoxLayout::LeftToRight, 0, 0, 0);
288 layout->addLayout( hb, 1, 1 );
290 KSharedConfig::Ptr _config = KGlobal::config();
291 KConfigGroup config(_config, "Buttons");
292 QString val;
293 MyButton *btn;
294 int i;
295 static const char *defaultButtons[]={"Menu","Sticky","Off","Iconify",
296 "Maximize","Close"};
297 static const char keyOffsets[]={"ABCDEF"};
298 for(i=0; i < 6; ++i){
299 if(i == 3){
300 titlebar = new QSpacerItem(10, 20, QSizePolicy::Expanding,
301 QSizePolicy::Minimum );
302 hb->addItem( titlebar );
304 QString key("Button");
305 key += QChar(keyOffsets[i]);
306 val = config.readEntry(key, defaultButtons[i]);
307 if(val == "Menu"){
308 mnuBtn = new MyButton(widget(), "menu");
309 mnuBtn->setToolTip( i18n("Menu"));
310 iconChange();
311 hb->addWidget(mnuBtn);
312 mnuBtn->setFixedSize(20, 20);
313 connect(mnuBtn, SIGNAL(pressed()), this,
314 SLOT(menuButtonPressed()));
316 else if(val == "Sticky"){
317 stickyBtn = new MyButton(widget(), "sticky");
318 stickyBtn->setToolTip( i18n("Sticky"));
319 if (isOnAllDesktops())
320 stickyBtn->setPixmap(*pindownPix);
321 else
322 stickyBtn->setPixmap(*pinupPix);
323 connect(stickyBtn, SIGNAL( clicked() ), this, SLOT(toggleOnAllDesktops()));
324 hb->addWidget(stickyBtn);
325 stickyBtn->setFixedSize(20, 20);
327 else if((val == "Iconify") && isMinimizable()){
328 btn = new MyButton(widget(), "iconify");
329 btn->setToolTip( i18n("Minimize"));
330 btn->setPixmap(*iconifyPix);
331 connect(btn, SIGNAL(clicked()), this, SLOT(minimize()));
332 hb->addWidget(btn);
333 btn->setFixedSize(20, 20);
335 else if((val == "Maximize") && isMaximizable()){
336 maxBtn = new MyButton(widget(), "max");
337 maxBtn->setToolTip( i18n("Maximize"));
338 maxBtn->setPixmap(*maxPix);
339 connect(maxBtn, SIGNAL(clicked()), this, SLOT(maximize()));
340 hb->addWidget(maxBtn);
341 maxBtn->setFixedSize(20, 20);
343 else if((val == "Close") && isCloseable()){
344 btn = new MyButton(widget(), "close");
345 btn->setToolTip( i18n("Close"));
346 btn->setPixmap(*closePix);
347 connect(btn, SIGNAL(clicked()), this, SLOT(closeWindow()));
348 hb->addWidget(btn);
349 btn->setFixedSize(20, 20);
351 else{
352 if((val != "Off") &&
353 ((val == "Iconify") && !isMinimizable()) &&
354 ((val == "Maximize") && !isMaximizable()))
355 kWarning() << "KWin: Unrecognized button value: " << val ;
359 if(titleGradient){
360 aGradient = new QPixmap;
361 iGradient = new QPixmap;
363 else{
364 aGradient = 0;
365 iGradient = 0;
367 widget()->setBackgroundMode(NoBackground);
370 void KWMThemeClient::drawTitle(QPainter &dest)
372 QRect titleRect = titlebar->geometry();
373 QRect r(0, 0, titleRect.width(), titleRect.height());
374 QPixmap buffer;
376 if(buffer.width() == r.width())
377 return;
379 buffer.resize(r.size());
380 QPainter p;
381 p.begin(&buffer);
383 if(titleSunken){
384 qDrawShadeRect(&p, r, options()->palette(KDecorationOptions::ColorFrame, isActive()).active(),
385 true, 1, 0);
386 r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2);
389 QPixmap *fill = isActive() ? aTitlePix : iTitlePix;
390 if(fill)
391 p.drawTiledPixmap(r, *fill);
392 else if(titleGradient){
393 fill = isActive() ? aGradient : iGradient;
394 if(fill->width() != r.width()){
395 fill->resize(r.width(), 20);
396 KPixmapEffect::gradient(*fill,
397 options()->color(KDecorationOptions::ColorTitleBar, isActive()),
398 options()->color(KDecorationOptions::ColorTitleBlend, isActive()),
399 grType);
401 p.drawTiledPixmap(r, *fill);
403 else{
404 p.fillRect(r, options()->palette(KDecorationOptions::ColorTitleBar, isActive()).active().
405 brush(QPalette::Button));
407 p.setFont(options()->font(isActive()));
408 p.setPen(options()->color(KDecorationOptions::ColorFont, isActive()));
409 // Add left & right margin
410 r.setLeft(r.left()+5);
411 r.setRight(r.right()-5);
412 p.drawText(r, titleAlign, caption());
413 p.end();
415 dest.drawPixmap(titleRect.x(), titleRect.y(), buffer);
419 void KWMThemeClient::resizeEvent( QResizeEvent* )
421 doShape();
422 widget()->repaint();
425 void KWMThemeClient::captionChange()
427 widget()->repaint( titlebar->geometry(), false );
430 void KWMThemeClient::paintEvent( QPaintEvent *)
432 QPainter p;
433 p.begin(widget());
434 int x,y;
435 // first the corners
436 int w1 = framePixmaps[FrameTopLeft]->width();
437 int h1 = framePixmaps[FrameTopLeft]->height();
438 if (w1 > width()/2) w1 = width()/2;
439 if (h1 > height()/2) h1 = height()/2;
440 p.drawPixmap(0,0,*framePixmaps[FrameTopLeft],
441 0,0,w1, h1);
442 int w2 = framePixmaps[FrameTopRight]->width();
443 int h2 = framePixmaps[FrameTopRight]->height();
444 if (w2 > width()/2) w2 = width()/2;
445 if (h2 > height()/2) h2 = height()/2;
446 p.drawPixmap(width()-w2,0,*framePixmaps[FrameTopRight],
447 framePixmaps[FrameTopRight]->width()-w2,0,w2, h2);
449 int w3 = framePixmaps[FrameBottomLeft]->width();
450 int h3 = framePixmaps[FrameBottomLeft]->height();
451 if (w3 > width()/2) w3 = width()/2;
452 if (h3 > height()/2) h3 = height()/2;
453 p.drawPixmap(0,height()-h3,*framePixmaps[FrameBottomLeft],
454 0,framePixmaps[FrameBottomLeft]->height()-h3,w3, h3);
456 int w4 = framePixmaps[FrameBottomRight]->width();
457 int h4 = framePixmaps[FrameBottomRight]->height();
458 if (w4 > width()/2) w4 = width()/2;
459 if (h4 > height()/2) h4 = height()/2;
460 p.drawPixmap(width()-w4,height()-h4,*(framePixmaps[FrameBottomRight]),
461 framePixmaps[FrameBottomRight]->width()-w4,
462 framePixmaps[FrameBottomRight]->height()-h4,
463 w4, h4);
465 QPixmap pm;
466 QMatrix m;
467 int n,s,w;
468 //top
469 pm = *framePixmaps[FrameTop];
471 if (pm.width() > 0){
472 s = width()-w2-w1;
473 n = s/pm.width();
474 w = n>0?s/n:s;
475 m.reset();
476 m.scale(w/(float)pm.width(), 1);
477 pm = pm.transformed(m);
479 x = w1;
480 while (1){
481 if (pm.width() < width()-w2-x){
482 p.drawPixmap(x,maxExtent-pm.height()-1,
483 pm);
484 x += pm.width();
486 else {
487 p.drawPixmap(x,maxExtent-pm.height()-1,
489 0,0,width()-w2-x,pm.height());
490 break;
495 //bottom
496 pm = *framePixmaps[FrameBottom];
498 if (pm.width() > 0){
499 s = width()-w4-w3;
500 n = s/pm.width();
501 w = n>0?s/n:s;
502 m.reset();
503 m.scale(w/(float)pm.width(), 1);
504 pm = pm.transformed(m);
506 x = w3;
507 while (1){
508 if (pm.width() < width()-w4-x){
509 p.drawPixmap(x,height()-maxExtent+1,pm);
510 x += pm.width();
512 else {
513 p.drawPixmap(x,height()-maxExtent+1,pm,
514 0,0,width()-w4-x,pm.height());
515 break;
520 //left
521 pm = *framePixmaps[FrameLeft];
523 if (pm.height() > 0){
524 s = height()-h3-h1;
525 n = s/pm.height();
526 w = n>0?s/n:s;
527 m.reset();
528 m.scale(1, w/(float)pm.height());
529 pm = pm.transformed(m);
531 y = h1;
532 while (1){
533 if (pm.height() < height()-h3-y){
534 p.drawPixmap(maxExtent-pm.width()-1, y,
535 pm);
536 y += pm.height();
538 else {
539 p.drawPixmap(maxExtent-pm.width()-1, y,
541 0,0, pm.width(),
542 height()-h3-y);
543 break;
548 //right
549 pm = *framePixmaps[FrameRight];
551 if (pm.height() > 0){
552 s = height()-h4-h2;
553 n = s/pm.height();
554 w = n>0?s/n:s;
555 m.reset();
556 m.scale(1, w/(float)pm.height());
557 pm = pm.transformed(m);
559 y = h2;
560 while (1){
561 if (pm.height() < height()-h4-y){
562 p.drawPixmap(width()-maxExtent+1, y,
563 pm);
564 y += pm.height();
566 else {
567 p.drawPixmap(width()-maxExtent+1, y,
569 0,0, pm.width(),
570 height()-h4-y);
571 break;
575 drawTitle(p);
577 QColor c = widget()->colorGroup().background();
579 // KWM evidently had a 1 pixel border around the client window. We
580 // emulate it here, but should be removed at some point in order to
581 // seamlessly mesh widget themes
582 p.setPen(c);
583 p.drawRect(maxExtent-1, maxExtent-1, width()-(maxExtent-1)*2,
584 height()-(maxExtent-1)*2);
586 // We fill the area behind the wrapped widget to ensure that
587 // shading animation is drawn as smoothly as possible
588 QRect r(layout->cellGeometry(2, 1));
589 p.fillRect( r.x(), r.y(), r.width(), r.height(), c);
590 p.end();
593 void KWMThemeClient::doShape()
596 QBitmap shapemask(width(), height());
597 shapemask.fill(color0);
598 QPainter p;
599 p.begin(&shapemask);
600 p.setBrush(color1);
601 p.setPen(color1);
602 int x,y;
603 // first the corners
604 int w1 = framePixmaps[FrameTopLeft]->width();
605 int h1 = framePixmaps[FrameTopLeft]->height();
606 if (w1 > width()/2) w1 = width()/2;
607 if (h1 > height()/2) h1 = height()/2;
608 if (framePixmaps[FrameTopLeft]->mask())
609 p.drawPixmap(0,0,*framePixmaps[FrameTopLeft]->mask(),
610 0,0,w1, h1);
611 else
612 p.fillRect(0,0,w1,h1,color1);
613 int w2 = framePixmaps[FrameTopRight]->width();
614 int h2 = framePixmaps[FrameTopRight]->height();
615 if (w2 > width()/2) w2 = width()/2;
616 if (h2 > height()/2) h2 = height()/2;
617 if (framePixmaps[FrameTopRight]->mask())
618 p.drawPixmap(width()-w2,0,*framePixmaps[FrameTopRight]->mask(),
619 framePixmaps[FrameTopRight]->width()-w2,0,w2, h2);
620 else
621 p.fillRect(width()-w2,0,w2, h2,color1);
623 int w3 = framePixmaps[FrameBottomLeft]->width();
624 int h3 = framePixmaps[FrameBottomLeft]->height();
625 if (w3 > width()/2) w3 = width()/2;
626 if (h3 > height()/2) h3 = height()/2;
627 if (framePixmaps[FrameBottomLeft]->mask())
628 p.drawPixmap(0,height()-h3,*framePixmaps[FrameBottomLeft]->mask(),
629 0,framePixmaps[FrameBottomLeft]->height()-h3,w3, h3);
630 else
631 p.fillRect(0,height()-h3,w3,h3,color1);
633 int w4 = framePixmaps[FrameBottomRight]->width();
634 int h4 = framePixmaps[FrameBottomRight]->height();
635 if (w4 > width()/2) w4 = width()/2;
636 if (h4 > height()/2) h4 = height()/2;
637 if (framePixmaps[FrameBottomRight]->mask())
638 p.drawPixmap(width()-w4,height()-h4,*framePixmaps[FrameBottomRight]->mask(),
639 framePixmaps[FrameBottomRight]->width()-w4,
640 framePixmaps[FrameBottomRight]->height()-h4,
641 w4, h4);
642 else
643 p.fillRect(width()-w4,height()-h4,w4,h4,color1);
645 QPixmap pm;
646 QMatrix m;
647 int n,s,w;
648 //top
649 if (framePixmaps[FrameTop]->mask())
651 pm = *framePixmaps[FrameTop]->mask();
653 s = width()-w2-w1;
654 n = s/pm.width();
655 w = n>0?s/n:s;
656 m.reset();
657 m.scale(w/(float)pm.width(), 1);
658 pm = pm.transformed(m);
660 x = w1;
661 while (1){
662 if (pm.width() < width()-w2-x){
663 p.drawPixmap(x,maxExtent-pm.height()-1,
664 pm);
665 x += pm.width();
667 else {
668 p.drawPixmap(x,maxExtent-pm.height()-1,
670 0,0,width()-w2-x,pm.height());
671 break;
676 //bottom
677 if (framePixmaps[FrameBottom]->mask())
679 pm = *framePixmaps[FrameBottom]->mask();
681 s = width()-w4-w3;
682 n = s/pm.width();
683 w = n>0?s/n:s;
684 m.reset();
685 m.scale(w/(float)pm.width(), 1);
686 pm = pm.transformed(m);
688 x = w3;
689 while (1){
690 if (pm.width() < width()-w4-x){
691 p.drawPixmap(x,height()-maxExtent+1,pm);
692 x += pm.width();
694 else {
695 p.drawPixmap(x,height()-maxExtent+1,pm,
696 0,0,width()-w4-x,pm.height());
697 break;
702 //left
703 if (framePixmaps[FrameLeft]->mask())
705 pm = *framePixmaps[FrameLeft]->mask();
707 s = height()-h3-h1;
708 n = s/pm.height();
709 w = n>0?s/n:s;
710 m.reset();
711 m.scale(1, w/(float)pm.height());
712 pm = pm.transformed(m);
714 y = h1;
715 while (1){
716 if (pm.height() < height()-h3-y){
717 p.drawPixmap(maxExtent-pm.width()-1, y,
718 pm);
719 y += pm.height();
721 else {
722 p.drawPixmap(maxExtent-pm.width()-1, y,
724 0,0, pm.width(),
725 height()-h3-y);
726 break;
731 //right
732 if (framePixmaps[FrameRight]->mask())
734 pm = *framePixmaps[FrameRight]->mask();
736 s = height()-h4-h2;
737 n = s/pm.height();
738 w = n>0?s/n:s;
739 m.reset();
740 m.scale(1, w/(float)pm.height());
741 pm = pm.transformed(m);
743 y = h2;
744 while (1){
745 if (pm.height() < height()-h4-y){
746 p.drawPixmap(width()-maxExtent+1, y,
747 pm);
748 y += pm.height();
750 else {
751 p.drawPixmap(width()-maxExtent+1, y,
753 0,0, pm.width(),
754 height()-h4-y);
755 break;
759 p.fillRect(maxExtent-1, maxExtent-1, width()-2*maxExtent+2, height()-2*maxExtent+2, color1);
760 setMask(shapemask);
764 void KWMThemeClient::showEvent(QShowEvent *)
766 doShape();
767 widget()->repaint(false);
770 void KWMThemeClient::mouseDoubleClickEvent( QMouseEvent * e )
772 if (e->button() == LeftButton && titlebar->geometry().contains( e->pos() ) )
773 titlebarDblClickOperation();
776 void KWMThemeClient::desktopChange()
778 if (stickyBtn) {
779 bool on = isOnAllDesktops();
780 stickyBtn->setPixmap(on ? *pindownPix : *pinupPix);
781 stickyBtn->setToolTip( on ? i18n("Unsticky") : i18n("Sticky") );
785 void KWMThemeClient::maximizeChange()
787 if (maxBtn) {
788 bool m = maximizeMode() == MaximizeFull;
789 maxBtn->setPixmap(m ? *minmaxPix : *maxPix);
790 maxBtn->setToolTip( m ? i18n("Restore") : i18n("Maximize"));
794 void KWMThemeClient::slotMaximize()
796 maximize( maximizeMode() == MaximizeFull ? MaximizeRestore : MaximizeFull );
799 void KWMThemeClient::activeChange()
801 widget()->update();
804 KDecoration::Position KWMThemeClient::mousePosition(const QPoint &p) const
806 Position m = KDecoration::mousePosition(p);
807 // corners
808 if(p.y() < framePixmaps[FrameTop]->height() &&
809 p.x() < framePixmaps[FrameLeft]->width()){
810 m = PositionTopLeft;
812 else if(p.y() < framePixmaps[FrameTop]->height() &&
813 p.x() > width()-framePixmaps[FrameRight]->width()){
814 m = PositionTopRight;
816 else if(p.y() > height()-framePixmaps[FrameBottom]->height() &&
817 p.x() < framePixmaps[FrameLeft]->width()){
818 m = PositionBottomLeft;
820 else if(p.y() > height()-framePixmaps[FrameBottom]->height() &&
821 p.x() > width()-framePixmaps[FrameRight]->width()){
822 m = PositionBottomRight;
823 } // edges
824 else if(p.y() < framePixmaps[FrameTop]->height())
825 m = PositionTop;
826 else if(p.y() > height()-framePixmaps[FrameBottom]->height())
827 m = PositionBottom;
828 else if(p.x() < framePixmaps[FrameLeft]->width())
829 m = PositionLeft;
830 else if(p.x() > width()-framePixmaps[FrameRight]->width())
831 m = PositionRight;
832 return(m);
835 void KWMThemeClient::menuButtonPressed()
837 mnuBtn->setDown(false); // will stay down if I don't do this
838 QPoint pos = mnuBtn->mapToGlobal(mnuBtn->rect().bottomLeft());
839 showWindowMenu( pos );
842 void KWMThemeClient::iconChange()
844 if(mnuBtn){
845 if( icon().pixmap( QIcon::Small, QIcon::Normal ).isNull()){
846 mnuBtn->setPixmap(*menuPix);
848 else{
849 mnuBtn->setPixmap(icon().pixmap( QIcon::Small, QIcon::Normal ));
854 bool KWMThemeClient::eventFilter( QObject* o, QEvent* e )
856 if ( o != widget() )
857 return false;
859 switch ( e->type() )
861 case QEvent::Resize:
862 resizeEvent( static_cast< QResizeEvent* >( e ) );
863 return true;
865 case QEvent::Paint:
866 paintEvent( static_cast< QPaintEvent* >( e ) );
867 return true;
869 case QEvent::MouseButtonDblClick:
870 mouseDoubleClickEvent( static_cast< QMouseEvent* >( e ) );
871 return true;
873 case QEvent::MouseButtonPress:
874 processMousePressEvent( static_cast< QMouseEvent* >( e ) );
875 return true;
877 case QEvent::Show:
878 showEvent( static_cast< QShowEvent* >( e ) );
879 return true;
881 default:
882 return false;
886 QSize KWMThemeClient::minimumSize() const
888 return widget()->minimumSize().expandedTo( QSize( 100, 50 ));
891 void KWMThemeClient::resize( const QSize& s )
893 widget()->resize( s );
896 void KWMThemeClient::borders( int& left, int& right, int& top, int& bottom ) const
898 left =
899 right =
900 top =
901 bottom =
903 TODO
906 KWMThemeFactory::KWMThemeFactory()
908 create_pixmaps();
911 KWMThemeFactory::~KWMThemeFactory()
913 delete_pixmaps();
916 KDecoration* KWMThemeFactory::createDecoration( KDecorationBridge* b )
918 return new KWMThemeClient( b, this );
921 bool KWMThemeFactory::reset( unsigned long mask )
923 bool needHardReset = false;
925 TODO
927 // doesn't obey the Border size setting
928 if( mask & ( SettingFont | SettingButtons ))
929 needHardReset = true;
931 if( mask & ( SettingFont | SettingColors )) {
932 KWMTheme::delete_pixmaps();
933 KWMTheme::create_pixmaps();
936 if( !needHardReset )
937 resetDecorations( mask );
938 return needHardReset;
943 extern "C"
945 KDE_EXPORT KDecorationFactory *create_factory()
947 return new KWMTheme::KWMThemeFactory();
951 #include "kwmthemeclient.moc"