1 /* Plastik KWin window decoration
2 Copyright (C) 2003-2005 Sandro Giessl <sandro@giessl.com>
4 based on the window decoration "Web":
5 Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org>
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
30 #include "plastik.moc"
31 #include "plastikclient.h"
32 #include "plastikbutton.h"
33 #include <QApplication>
35 #include <KConfigGroup>
36 #include <KColorUtils>
37 #include <KColorScheme>
38 #include <KGlobalSettings>
43 PlastikHandler::PlastikHandler()
45 memset(m_pixmaps
, 0, sizeof(QPixmap
*)*NumPixmaps
*2*2); // set elements to 0
46 memset(m_bitmaps
, 0, sizeof(QBitmap
*)*NumButtonIcons
*2);
51 PlastikHandler::~PlastikHandler()
53 for (int t
=0; t
< 2; ++t
)
54 for (int a
=0; a
< 2; ++a
)
55 for (int i
=0; i
< NumPixmaps
; ++i
)
56 delete m_pixmaps
[t
][a
][i
];
57 for (int t
=0; t
< 2; ++t
)
58 for (int i
=0; i
< NumButtonIcons
; ++i
)
59 delete m_bitmaps
[t
][i
];
62 bool PlastikHandler::reset(unsigned long changed
)
64 // we assume the active font to be the same as the inactive font since the control
65 // center doesn't offer different settings anyways.
66 m_titleFont
= KDecoration::options()->font(true, false); // not small
67 m_titleFontTool
= KDecoration::options()->font(true, true); // small
69 switch(KDecoration::options()->preferredBorderSize( this )) {
93 // check if we are in reverse layout mode
94 m_reverse
= QApplication::isRightToLeft();
96 // read in the configuration
99 // pixmaps probably need to be updated, so delete the cache.
100 for (int t
=0; t
< 2; ++t
) {
101 for (int a
=0; a
< 2; ++a
) {
102 for (int i
=0; i
< NumPixmaps
; i
++) {
103 if (m_pixmaps
[t
][a
][i
]) {
104 delete m_pixmaps
[t
][a
][i
];
105 m_pixmaps
[t
][a
][i
] = 0;
110 for (int t
=0; t
< 2; ++t
) {
111 for (int i
=0; i
< NumButtonIcons
; i
++) {
112 if (m_bitmaps
[t
][i
]) {
113 delete m_bitmaps
[t
][i
];
119 // Do we need to "hit the wooden hammer" ?
120 bool needHardReset
= true;
121 // TODO: besides the Color and Font settings I can maybe handle more changes
122 // without a hard reset. I will do this later...
123 if ((changed
& ~(SettingColors
| SettingFont
| SettingButtons
)) == 0 )
125 needHardReset
= false;
131 resetDecorations(changed
);
136 KDecoration
* PlastikHandler::createDecoration( KDecorationBridge
* bridge
)
138 return ( new PlastikClient( bridge
, this ))->decoration();
141 bool PlastikHandler::supports( Ability ability
) const
146 case AbilityAnnounceButtons
:
147 case AbilityAnnounceColors
:
149 case AbilityButtonMenu
:
150 case AbilityButtonOnAllDesktops
:
151 case AbilityButtonSpacer
:
152 case AbilityButtonHelp
:
153 case AbilityButtonMinimize
:
154 case AbilityButtonMaximize
:
155 case AbilityButtonClose
:
156 case AbilityButtonAboveOthers
:
157 case AbilityButtonBelowOthers
:
158 case AbilityButtonShade
:
160 case AbilityColorTitleBack
:
161 case AbilityColorTitleFore
:
162 case AbilityColorFrame
:
169 void PlastikHandler::readConfig()
171 // create a config object
172 KConfig
configFile("kwinplastikrc");
173 const KConfigGroup
config( &configFile
, "General");
176 m_titleShadow
= config
.readEntry("TitleShadow", true);
178 QFontMetrics
fm(m_titleFont
); // active font = inactive font
179 int titleHeightMin
= config
.readEntry("MinTitleHeight", 16);
180 // The title should stretch with bigger font sizes!
181 m_titleHeight
= qMax(titleHeightMin
, fm
.height() + 4); // 4 px for the shadow etc.
182 // have an even title/button size so the button icons are fully centered...
183 if ( m_titleHeight
%2 == 0)
186 fm
= QFontMetrics(m_titleFontTool
); // active font = inactive font
187 int titleHeightToolMin
= config
.readEntry("MinTitleHeightTool", 13);
188 // The title should stretch with bigger font sizes!
189 m_titleHeightTool
= qMax(titleHeightToolMin
, fm
.height() ); // don't care about the shadow etc.
190 // have an even title/button size so the button icons are fully centered...
191 if ( m_titleHeightTool
%2 == 0)
194 QString value
= config
.readEntry("TitleAlignment", "AlignLeft");
195 if (value
== "AlignLeft") m_titleAlign
= Qt::AlignLeft
;
196 else if (value
== "AlignHCenter") m_titleAlign
= Qt::AlignHCenter
;
197 else if (value
== "AlignRight") m_titleAlign
= Qt::AlignRight
;
199 m_coloredBorder
= config
.readEntry("ColoredBorder", true);
200 m_animateButtons
= config
.readEntry("AnimateButtons", true);
201 m_menuClose
= config
.readEntry("CloseOnMenuDoubleClick", true);
204 QColor
PlastikHandler::getColor(KWinPlastik::ColorType type
, const bool active
)
206 double c
= KGlobalSettings::contrastF();
209 return KColorScheme::shade(KDecoration::options()->color(ColorTitleBar
, active
), KColorScheme::DarkShade
, c
);
211 return KColorScheme::shade(KDecoration::options()->color(ColorTitleBar
, active
), KColorScheme::MidlightShade
, c
-0.4);
214 return KColorScheme::shade(KDecoration::options()->color(ColorTitleBar
, active
), KColorScheme::MidShade
, c
-0.4);
217 return KDecoration::options()->color(ColorTitleBar
, active
);
219 case ShadeTitleLight
:
220 return KColorScheme::shade(KDecoration::options()->color(ColorTitleBar
, active
), KColorScheme::LightShade
, active
?c
-0.4:c
-0.8);
223 return KColorScheme::shade(KDecoration::options()->color(ColorTitleBar
, active
), KColorScheme::DarkShade
, active
?c
-0.4:c
-0.8);
226 return KDecoration::options()->color(ColorFrame
, active
);
228 return KDecoration::options()->color(ColorFont
, active
);
234 const QPixmap
&PlastikHandler::pixmap(Pixmaps type
, bool active
, bool toolWindow
)
236 if (m_pixmaps
[toolWindow
][active
][type
])
237 return *m_pixmaps
[toolWindow
][active
][type
];
242 case TitleBarTileTop
:
245 const int titleBarTileHeight
= (toolWindow
? m_titleHeightTool
: m_titleHeight
)+2;
246 // gradient used as well in TitleBarTileTop as TitleBarTile
247 const int gradientHeight
= 2 + titleBarTileHeight
-1;
248 QPixmap
gradient(1, gradientHeight
);
249 QPainter
painter(&gradient
);
250 painter
.setPen(Qt::NoPen
);
251 QLinearGradient
grad(0, 0, 0, gradientHeight
);
252 grad
.setColorAt(0.0, getColor(TitleGradient1
, active
));
253 grad
.setColorAt(4.0 / (double)gradientHeight
, getColor(TitleGradient2
, active
));
254 grad
.setColorAt(1.0, getColor(TitleGradient3
, active
));
255 painter
.setBrush(grad
);
256 painter
.drawRect(0, 0, 1, gradientHeight
);
259 // actual titlebar tiles
260 if (type
== TitleBarTileTop
) {
261 pm
= new QPixmap(1, 4);
264 painter
.setPen(getColor(WindowContour
, active
) );
265 painter
.drawPoint(0,0);
267 painter
.setPen(getColor(ShadeTitleLight
, active
) );
268 painter
.drawPoint(0,1);
270 painter
.drawPixmap(0, 2, gradient
);
273 pm
= new QPixmap(1, titleBarTileHeight
);
275 painter
.drawPixmap(0, 0, gradient
, 0,2 ,-1,-1);
276 if (m_coloredBorder
) {
277 painter
.setPen(KColorScheme::shade(getColor(TitleGradient3
, active
), KColorScheme::MidShade
) );
279 painter
.setPen(getColor(TitleGradient3
, active
) );
281 painter
.drawPoint(0,titleBarTileHeight
-1);
290 const int w
= m_borderSize
;
291 const int h
= 4 + (toolWindow
? m_titleHeightTool
: m_titleHeight
) + 2;
293 pm
= new QPixmap(w
, h
);
294 QPainter
painter(pm
);
296 painter
.drawTiledPixmap(0,0, w
, 4, pixmap(TitleBarTileTop
, active
, toolWindow
) );
297 painter
.drawTiledPixmap(0,4, w
, h
-4, pixmap(TitleBarTile
, active
, toolWindow
) );
299 painter
.setPen(getColor(WindowContour
, active
) );
300 painter
.drawLine(0,0, 0,h
);
301 painter
.drawPoint(1,1);
303 const QColor highlightTitleLeft
= getColor(ShadeTitleLight
, active
);
304 painter
.setPen(highlightTitleLeft
);
305 painter
.drawLine(1,2, 1,h
);
307 if (m_coloredBorder
) {
308 painter
.setPen(getColor(TitleGradient3
, active
) );
309 painter
.drawLine(2,h
-1, w
-1,h
-1);
312 // outside the region normally masked by doShape
313 painter
.setPen(QColor(0,0,0) );
314 painter
.drawLine(0, 0, 1, 0 );
315 painter
.drawPoint(0, 1);
322 const int w
= m_borderSize
;
323 const int h
= 4 + (toolWindow
? m_titleHeightTool
: m_titleHeight
) + 2;
325 pm
= new QPixmap(w
, h
);
326 QPainter
painter(pm
);
328 painter
.drawTiledPixmap(0,0, w
, 4, pixmap(TitleBarTileTop
, active
, toolWindow
) );
329 painter
.drawTiledPixmap(0,4, w
, h
-4, pixmap(TitleBarTile
, active
, toolWindow
) );
331 painter
.setPen(getColor(WindowContour
, active
) );
332 painter
.drawLine(w
-1,0, w
-1,h
);
333 painter
.drawPoint(w
-2,1);
335 const QColor highlightTitleRight
= getColor(ShadeTitleDark
, active
);
336 painter
.setPen(highlightTitleRight
);
337 painter
.drawLine(w
-2,2, w
-2,h
);
339 if (m_coloredBorder
) {
340 painter
.setPen(getColor(TitleGradient3
, active
) );
341 painter
.drawLine(0,h
-1, w
-3,h
-1);
344 // outside the region normally masked by doShape
345 painter
.setPen(QColor(0,0,0) );
346 painter
.drawLine(w
-2, 0, w
-1, 0 );
347 painter
.drawPoint(w
-1, 1);
354 const int w
= m_borderSize
;
356 pm
= new QPixmap(w
, 1);
357 QPainter
painter(pm
);
358 if (m_coloredBorder
) {
359 painter
.setPen(getColor(WindowContour
, active
) );
360 painter
.drawPoint(0, 0);
361 painter
.setPen(getColor(ShadeTitleLight
, active
) );
362 painter
.drawPoint(1, 0);
364 painter
.setPen(getColor(TitleGradient3
, active
) );
365 painter
.drawLine(2,0, w
-2,0);
367 painter
.setPen(KColorScheme::shade(getColor(TitleGradient3
, active
), KColorScheme::MidShade
) );
368 painter
.drawPoint(w
-1,0);
370 painter
.setPen(getColor(WindowContour
, active
) );
371 painter
.drawPoint(0, 0);
372 painter
.setPen(KColorUtils::mix(getColor(Border
, active
), getColor(ShadeTitleLight
, active
) ) );
373 painter
.drawPoint(1, 0);
374 painter
.setPen(getColor(Border
, active
) );
375 painter
.drawLine(2,0, w
-1,0);
383 case BorderRightTile
:
385 const int w
= m_borderSize
;
387 pm
= new QPixmap(w
, 1);
388 QPainter
painter(pm
);
389 if (m_coloredBorder
) {
390 painter
.setPen(KColorScheme::shade(getColor(TitleGradient3
, active
), KColorScheme::MidShade
) );
391 painter
.drawPoint(0,0);
393 painter
.setPen(getColor(TitleGradient3
, active
) );
394 painter
.drawLine(1,0, w
-3,0);
396 painter
.setPen(getColor(ShadeTitleDark
, active
) );
397 painter
.drawPoint(w
-2, 0);
398 painter
.setPen(getColor(WindowContour
, active
) );
399 painter
.drawPoint(w
-1, 0);
401 painter
.setPen(getColor(Border
, active
) );
402 painter
.drawLine(0,0, w
-3,0);
403 painter
.setPen(KColorUtils::mix(getColor(Border
, active
), getColor(ShadeTitleDark
, active
) ) );
404 painter
.drawPoint(w
-2, 0);
405 painter
.setPen(getColor(WindowContour
, active
) );
406 painter
.drawPoint(w
-1, 0);
413 case BorderBottomLeft
:
415 const int w
= m_borderSize
;
416 const int h
= m_borderSize
;
418 pm
= new QPixmap(w
, h
);
419 QPainter
painter(pm
);
420 painter
.drawTiledPixmap(0,0,w
,h
, pixmap(BorderBottomTile
, active
, toolWindow
) );
421 painter
.setPen(getColor(WindowContour
, active
) );
422 painter
.drawLine(0,0, 0,h
);
423 if (m_coloredBorder
) {
425 painter
.setPen(getColor(ShadeTitleLight
, active
) );
426 painter
.drawLine(1,0, 1,h
-2);
429 painter
.setPen(getColor(TitleGradient3
, active
) );
430 painter
.drawLine(2,0, w
-1,0);
432 painter
.setPen(KColorUtils::mix(getColor(Border
, active
), getColor(ShadeTitleLight
, active
) ) );
433 painter
.drawLine(1,0, 1,h
-2);
441 case BorderBottomRight
:
443 const int w
= m_borderSize
;
444 const int h
= m_borderSize
;
446 pm
= new QPixmap(w
, h
);
447 QPainter
painter(pm
);
448 painter
.drawTiledPixmap(0,0,w
,h
, pixmap(BorderBottomTile
, active
, toolWindow
) );
449 painter
.setPen(getColor(WindowContour
, active
) );
450 painter
.drawLine(w
-1,0, w
-1,h
);
451 if (m_coloredBorder
) {
452 painter
.setPen(getColor(ShadeTitleDark
, active
) );
453 painter
.drawLine(w
-2,0, w
-2,h
-2);
455 painter
.setPen(getColor(TitleGradient3
, active
) );
456 painter
.drawLine(0,0, w
-3,0);
458 painter
.setPen(KColorUtils::mix(getColor(Border
, active
), getColor(ShadeTitleDark
, active
) ) );
459 painter
.drawLine(w
-2,0, w
-2,h
-2);
467 case BorderBottomTile
:
470 const int h
= m_borderSize
;
472 pm
= new QPixmap(1, m_borderSize
);
473 QPainter
painter(pm
);
475 if (m_coloredBorder
) {
476 painter
.setPen(KColorScheme::shade(getColor(TitleGradient3
, active
), KColorScheme::MidShade
) );
477 painter
.drawPoint(0,0);
478 painter
.setPen(getColor(TitleGradient3
, active
) );
479 painter
.drawLine(0,1, 0,h
-3);
480 painter
.setPen(getColor(ShadeTitleDark
, active
) );
481 painter
.drawPoint(0, h
-2);
483 painter
.setPen(getColor(Border
, active
) );
484 painter
.drawLine(0,0, 0,h
-3);
485 painter
.setPen(KColorUtils::mix(getColor(Border
, active
), getColor(ShadeTitleDark
, active
) ) );
486 painter
.drawPoint(0, h
-2);
488 painter
.setPen(getColor(WindowContour
, active
) );
489 painter
.drawPoint(0, h
-1);
496 m_pixmaps
[toolWindow
][active
][type
] = pm
;
500 const QBitmap
&PlastikHandler::buttonBitmap(ButtonIcon type
, const QSize
&size
, bool toolWindow
)
502 int typeIndex
= type
;
505 int reduceW
= 0, reduceH
= 0;
506 if(size
.width()>14) {
507 reduceW
= static_cast<int>(2*(size
.width()/3.5) );
512 reduceH
= static_cast<int>(2*(size
.height()/3.5) );
516 int w
= size
.width() - reduceW
;
517 int h
= size
.height() - reduceH
;
519 if (m_bitmaps
[toolWindow
][typeIndex
] && m_bitmaps
[toolWindow
][typeIndex
]->size()==QSize(w
,h
) )
520 return *m_bitmaps
[toolWindow
][typeIndex
];
522 // no matching pixmap found, create a new one...
524 delete m_bitmaps
[toolWindow
][typeIndex
];
525 m_bitmaps
[toolWindow
][typeIndex
] = 0;
527 QBitmap bmp
= IconEngine::icon(type
/*icon*/, qMin(w
,h
) );
528 QBitmap
*bitmap
= new QBitmap(bmp
);
529 m_bitmaps
[toolWindow
][typeIndex
] = bitmap
;
533 QList
< PlastikHandler::BorderSize
>
534 PlastikHandler::borderSizes() const
536 // the list must be sorted
537 return QList
< BorderSize
>() << BorderTiny
<< BorderNormal
<<
538 BorderLarge
<< BorderVeryLarge
<< BorderHuge
<<
539 BorderVeryHuge
<< BorderOversized
;
542 // make the handler accessible to other classes...
543 static PlastikHandler
*handler
= 0;
544 PlastikHandler
* Handler()
551 //////////////////////////////////////////////////////////////////////////////
553 //////////////////////////////////////////////////////////////////////////////
557 KDE_EXPORT KDecorationFactory
*create_factory()
559 KWinPlastik::handler
= new KWinPlastik::PlastikHandler();
560 return KWinPlastik::handler
;