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;