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.
23 #include "plastikclient.h"
28 #include <QFontMetrics>
34 #include <QDesktopWidget>
36 #include "plastikbutton.h"
38 #include <KColorScheme>
40 QColor
alphaColor(QColor color
, double alpha
)
44 color
.setAlphaF(qMax(0.0, alpha
) * color
.alphaF());
51 PlastikClient::PlastikClient(KDecorationBridge
* bridge
, KDecorationFactory
* factory
)
52 : KCommonDecoration (bridge
, factory
),
55 memset(m_captionPixmaps
, 0, sizeof(QPixmap
*)*2);
58 PlastikClient::~PlastikClient()
60 clearCaptionPixmaps();
63 QString
PlastikClient::visibleName() const
65 return i18n("Plastik");
68 bool PlastikClient::decorationBehaviour(DecorationBehaviour behaviour
) const
72 return Handler()->menuClose();
78 return KCommonDecoration::decorationBehaviour(behaviour
);
82 int PlastikClient::layoutMetric(LayoutMetric lm
, bool respectWindowState
, const KCommonDecorationButton
*btn
) const
84 bool maximized
= maximizeMode()==MaximizeFull
&& !options()->moveResizeMaximizedWindows();
91 if (respectWindowState
&& maximized
) {
94 return Handler()->borderSize();
100 if (respectWindowState
&& maximized
) {
107 case LM_TitleEdgeBottom
:
109 // if (respectWindowState && maximized) {
116 case LM_TitleEdgeLeft
:
117 case LM_TitleEdgeRight
:
119 if (respectWindowState
&& maximized
) {
126 case LM_TitleBorderLeft
:
127 case LM_TitleBorderRight
:
131 case LM_ButtonHeight
:
134 if (respectWindowState
&& isToolWindow()) {
135 return Handler()->titleHeightTool();
137 return Handler()->titleHeight();
141 case LM_ButtonSpacing
:
144 case LM_ButtonMarginTop
:
148 return KCommonDecoration::layoutMetric(lm
, respectWindowState
, btn
);
152 KCommonDecorationButton
*PlastikClient::createButton(ButtonType type
)
156 return new PlastikButton(MenuButton
, this);
158 case OnAllDesktopsButton
:
159 return new PlastikButton(OnAllDesktopsButton
, this);
162 return new PlastikButton(HelpButton
, this);
165 return new PlastikButton(MinButton
, this);
168 return new PlastikButton(MaxButton
, this);
171 return new PlastikButton(CloseButton
, this);
174 return new PlastikButton(AboveButton
, this);
177 return new PlastikButton(BelowButton
, this);
180 return new PlastikButton(ShadeButton
, this);
187 void PlastikClient::init()
189 s_titleFont
= isToolWindow() ? Handler()->titleFontTool() : Handler()->titleFont();
191 clearCaptionPixmaps();
193 KCommonDecoration::init();
196 QRegion
PlastikClient::cornerShape(WindowCorner corner
)
198 int w
= widget()->width();
199 int h
= widget()->height();
203 if (layoutMetric(LM_TitleEdgeLeft
) > 0)
204 return QRegion(0, 0, 1, 2) + QRegion(1, 0, 1, 1);
209 if (layoutMetric(LM_TitleEdgeRight
) > 0)
210 return QRegion(w
-1, 0, 1, 2) + QRegion(w
-2, 0, 1, 1);
215 if (layoutMetric(LM_BorderBottom
) > 0)
216 return QRegion(0, h
-1, 1, 1);
221 if (layoutMetric(LM_BorderBottom
) > 0)
222 return QRegion(w
-1, h
-1, 1, 1);
232 void PlastikClient::paintEvent(QPaintEvent
*e
)
234 QRegion region
= e
->region();
236 PlastikHandler
*handler
= Handler();
238 if (oldCaption
!= caption() )
239 clearCaptionPixmaps();
241 bool active
= isActive();
242 bool toolWindow
= isToolWindow();
244 QPainter
painter(widget() );
246 // often needed coordinates
247 QRect r
= widget()->rect();
250 // int r_h = r.height();
251 int r_x
, r_y
, r_x2
, r_y2
;
252 r
.getCoords(&r_x
, &r_y
, &r_x2
, &r_y2
);
253 const int borderLeft
= layoutMetric(LM_BorderLeft
);
254 const int borderRight
= layoutMetric(LM_BorderRight
);
255 const int borderBottom
= layoutMetric(LM_BorderBottom
);
256 const int titleHeight
= layoutMetric(LM_TitleHeight
);
257 const int titleEdgeTop
= layoutMetric(LM_TitleEdgeTop
);
258 const int titleEdgeBottom
= layoutMetric(LM_TitleEdgeBottom
);
259 const int titleEdgeLeft
= layoutMetric(LM_TitleEdgeLeft
);
260 const int titleEdgeRight
= layoutMetric(LM_TitleEdgeRight
);
262 const int borderBottomTop
= r_y2
-borderBottom
+1;
263 const int borderLeftRight
= r_x
+borderLeft
-1;
264 const int borderRightLeft
= r_x2
-borderRight
+1;
265 const int titleEdgeBottomBottom
= r_y
+titleEdgeTop
+titleHeight
+titleEdgeBottom
-1;
267 const int sideHeight
= borderBottomTop
-titleEdgeBottomBottom
-1;
269 QRect Rtitle
= QRect(r_x
+titleEdgeLeft
+buttonsLeftWidth(), r_y
+titleEdgeTop
,
270 r_x2
-titleEdgeRight
-buttonsRightWidth()-(r_x
+titleEdgeLeft
+buttonsLeftWidth()),
271 titleEdgeBottomBottom
-(r_y
+titleEdgeTop
) );
278 tempRect
.setRect(r_x
+2, r_y
, r_w
-2*2, titleEdgeTop
);
279 if (tempRect
.isValid() && region
.contains(tempRect
) ) {
280 painter
.drawTiledPixmap(tempRect
, handler
->pixmap(TitleBarTileTop
, active
, toolWindow
) );
285 int titleMarginLeft
= 0;
286 int titleMarginRight
= 0;
287 if(titleEdgeLeft
> 0)
289 tempRect
.setRect(r_x
, r_y
, borderLeft
, titleEdgeTop
+titleHeight
+titleEdgeBottom
);
290 if (tempRect
.isValid() && region
.contains(tempRect
) ) {
291 painter
.drawTiledPixmap(tempRect
, handler
->pixmap(TitleBarLeft
, active
, toolWindow
) );
292 titleMarginLeft
= borderLeft
;
297 if(titleEdgeRight
> 0)
299 tempRect
.setRect(borderRightLeft
, r_y
, borderRight
, titleEdgeTop
+titleHeight
+titleEdgeBottom
);
300 if (tempRect
.isValid() && region
.contains(tempRect
) ) {
301 painter
.drawTiledPixmap(tempRect
, handler
->pixmap(TitleBarRight
, active
, toolWindow
) );
302 titleMarginRight
= borderRight
;
307 const QPixmap
&caption
= captionPixmap();
308 if(Rtitle
.width() > 0)
310 m_captionRect
= captionRect(); // also update m_captionRect!
311 if (m_captionRect
.isValid() && region
.contains(m_captionRect
) )
313 painter
.drawTiledPixmap(m_captionRect
, caption
);
317 tempRect
.setRect(r_x
+titleMarginLeft
, m_captionRect
.top(),
318 m_captionRect
.left() - (r_x
+titleMarginLeft
), m_captionRect
.height() );
319 if (tempRect
.isValid() && region
.contains(tempRect
) ) {
320 painter
.drawTiledPixmap(tempRect
, handler
->pixmap(TitleBarTile
, active
, toolWindow
) );
323 // right to the title
324 tempRect
.setRect(m_captionRect
.right()+1, m_captionRect
.top(),
325 (r_x2
-titleMarginRight
) - m_captionRect
.right(), m_captionRect
.height() );
326 if (tempRect
.isValid() && region
.contains(tempRect
) ) {
327 painter
.drawTiledPixmap(tempRect
, handler
->pixmap(TitleBarTile
, active
, toolWindow
) );
333 if(borderLeft
> 0 && sideHeight
> 0)
335 tempRect
.setCoords(r_x
, titleEdgeBottomBottom
+1, borderLeftRight
, borderBottomTop
-1);
336 if (tempRect
.isValid() && region
.contains(tempRect
) ) {
337 painter
.drawTiledPixmap(tempRect
, handler
->pixmap(BorderLeftTile
, active
, toolWindow
) );
342 if(borderRight
> 0 && sideHeight
> 0)
344 tempRect
.setCoords(borderRightLeft
, titleEdgeBottomBottom
+1, r_x2
, borderBottomTop
-1);
345 if (tempRect
.isValid() && region
.contains(tempRect
) ) {
346 painter
.drawTiledPixmap(tempRect
, handler
->pixmap(BorderRightTile
, active
, toolWindow
) );
356 tempRect
.setRect(r_x
, borderBottomTop
, borderLeft
, borderBottom
);
357 if (tempRect
.isValid() && region
.contains(tempRect
) ) {
358 painter
.drawTiledPixmap(tempRect
, handler
->pixmap(BorderBottomLeft
, active
, toolWindow
) );
359 l
= tempRect
.right()+1;
362 tempRect
.setRect(borderRightLeft
, borderBottomTop
, borderLeft
, borderBottom
);
363 if (tempRect
.isValid() && region
.contains(tempRect
) ) {
364 painter
.drawTiledPixmap(tempRect
, handler
->pixmap(BorderBottomRight
, active
, toolWindow
) );
365 r
= tempRect
.left()-1;
368 tempRect
.setCoords(l
, borderBottomTop
, r
, r_y2
);
369 if (tempRect
.isValid() && region
.contains(tempRect
) ) {
370 painter
.drawTiledPixmap(tempRect
, handler
->pixmap(BorderBottomTile
, active
, toolWindow
) );
375 QRect
PlastikClient::captionRect() const
377 const QPixmap
&caption
= captionPixmap();
378 QRect r
= widget()->rect();
380 const int titleHeight
= layoutMetric(LM_TitleHeight
);
381 const int titleEdgeBottom
= layoutMetric(LM_TitleEdgeBottom
);
382 const int titleEdgeTop
= layoutMetric(LM_TitleEdgeTop
);
383 const int titleEdgeLeft
= layoutMetric(LM_TitleEdgeLeft
);
384 const int marginLeft
= layoutMetric(LM_TitleBorderLeft
);
385 const int marginRight
= layoutMetric(LM_TitleBorderRight
);
387 const int titleLeft
= r
.left() + titleEdgeLeft
+ buttonsLeftWidth() + marginLeft
;
388 const int titleWidth
= r
.width() -
389 titleEdgeLeft
- layoutMetric(LM_TitleEdgeRight
) -
390 buttonsLeftWidth() - buttonsRightWidth() -
391 marginLeft
- marginRight
;
393 Qt::AlignmentFlag a
= Handler()->titleAlign();
395 int tX
, tW
; // position/width of the title buffer
396 if (caption
.width() > titleWidth
) {
399 tW
= caption
.width();
401 if (a
== Qt::AlignLeft
|| (caption
.width() > titleWidth
) ) {
404 } else if (a
== Qt::AlignHCenter
) {
406 tX
= titleLeft
+(titleWidth
- caption
.width() )/2;
409 tX
= titleLeft
+titleWidth
-caption
.width();
412 return QRect(tX
, r
.top()+titleEdgeTop
, tW
, titleHeight
+titleEdgeBottom
);
415 void PlastikClient::updateCaption()
417 QRect oldCaptionRect
= m_captionRect
;
419 if (oldCaption
!= caption() )
420 clearCaptionPixmaps();
422 m_captionRect
= PlastikClient::captionRect();
424 if (oldCaptionRect
.isValid() && m_captionRect
.isValid() )
425 widget()->update(oldCaptionRect
|m_captionRect
);
430 void PlastikClient::reset( unsigned long changed
)
432 if (changed
& SettingColors
)
434 // repaint the whole thing
435 clearCaptionPixmaps();
438 } else if (changed
& SettingFont
) {
439 // font has changed -- update title height and font
440 s_titleFont
= isToolWindow() ? Handler()->titleFontTool() : Handler()->titleFont();
445 clearCaptionPixmaps();
449 KCommonDecoration::reset(changed
);
452 const QPixmap
&PlastikClient::getTitleBarTile(bool active
) const
454 return Handler()->pixmap(TitleBarTile
, active
, isToolWindow() );
457 const QPixmap
&PlastikClient::captionPixmap() const
459 bool active
= isActive();
461 if (m_captionPixmaps
[active
]) {
462 return *m_captionPixmaps
[active
];
465 // not found, create new pixmap...
467 const int maxCaptionLength
= 300; // truncate captions longer than this!
468 QString
c(caption() );
469 if (c
.length() > maxCaptionLength
) {
470 c
.truncate(maxCaptionLength
);
474 QFontMetrics
fm(s_titleFont
);
475 int captionWidth
= fm
.width(c
);
476 int captionHeight
= fm
.height();
478 const int th
= layoutMetric(LM_TitleHeight
, false) + layoutMetric(LM_TitleEdgeBottom
, false);
482 const int thickness
= 2;
484 QPixmap
*captionPixmap
= new QPixmap(captionWidth
+2*thickness
, th
);
486 painter
.begin(captionPixmap
);
487 painter
.drawTiledPixmap(captionPixmap
->rect(),
488 Handler()->pixmap(TitleBarTile
, active
, isToolWindow()) );
490 painter
.setFont(s_titleFont
);
491 QPoint
tp(1, captionHeight
- 3);
492 QColor fontColor
= Handler()->getColor(TitleFont
,active
);
493 if(Handler()->titleShadow())
495 QColor shadowColor
= KColorScheme::shade(fontColor
, KColorScheme::ShadowShade
);
497 painter
.setCompositionMode(QPainter::CompositionMode_SourceOver
);
498 painter
.setPen(alphaColor(shadowColor
, 0.3) );
499 painter
.drawText(tp
+QPoint(1,2), c
);
500 painter
.setPen(alphaColor(shadowColor
, 0.2) );
501 painter
.drawText(tp
+QPoint(2,2), c
);
502 painter
.setPen(alphaColor(shadowColor
, 0.5) );
503 painter
.drawText(tp
+QPoint(1,1), c
);
505 painter
.setPen(fontColor
);
506 painter
.drawText(tp
, c
);
509 m_captionPixmaps
[active
] = captionPixmap
;
510 return *captionPixmap
;
513 void PlastikClient::clearCaptionPixmaps()
515 for (int i
= 0; i
< 2; ++i
) {
516 delete m_captionPixmaps
[i
];
517 m_captionPixmaps
[i
] = 0;
520 oldCaption
= caption();