Warning, file /system/qtcurve/qt5/kwin/qtcurveclient.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*****************************************************************************
0002  *   Copyright 2007 - 2010 Craig Drummond <craig.p.drummond@gmail.com>       *
0003  *   Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com>                     *
0004  *                                                                           *
0005  *   This program is free software; you can redistribute it and/or modify    *
0006  *   it under the terms of the GNU Lesser General Public License as          *
0007  *   published by the Free Software Foundation; either version 2.1 of the    *
0008  *   License, or (at your option) version 3, or any later version accepted   *
0009  *   by the membership of KDE e.V. (or its successor approved by the         *
0010  *   membership of KDE e.V.), which shall act as a proxy defined in          *
0011  *   Section 6 of version 3 of the license.                                  *
0012  *                                                                           *
0013  *   This program is distributed in the hope that it will be useful,         *
0014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
0015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
0016  *   Lesser General Public License for more details.                         *
0017  *                                                                           *
0018  *   You should have received a copy of the GNU Lesser General Public        *
0019  *   License along with this library. If not,                                *
0020  *   see <http://www.gnu.org/licenses/>.                                     *
0021  *****************************************************************************/
0022 /*
0023   based on the window decoration "Plastik":
0024   Copyright (C) 2003-2005 Sandro Giessl <sandro@giessl.com>
0025 
0026   based on the window decoration "Web":
0027   Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org>
0028  */
0029 
0030 #include <qtcurve-utils/x11wrap.h>
0031 #include <qtcurve-utils/x11qtc.h>
0032 #include <qtcurve-utils/log.h>
0033 
0034 #define DRAW_INTO_PIXMAPS
0035 #include <KDE/KLocale>
0036 #include <QBitmap>
0037 #include <QDateTime>
0038 #include <QFontMetrics>
0039 #include <QImage>
0040 #include <QLabel>
0041 #include <QLayout>
0042 #include <QPainter>
0043 #include <QPixmap>
0044 #include <QStyleOptionTitleBar>
0045 #include <QStyle>
0046 #include <QPainterPath>
0047 #include <QLinearGradient>
0048 #include <KDE/KColorUtils>
0049 #include <KDE/KWindowInfo>
0050 #include <KDE/KIconEffect>
0051 #include <KDE/KWindowSystem>
0052 #include <qdesktopwidget.h>
0053 #include "qtcurveclient.h"
0054 #include "qtcurvebutton.h"
0055 #include "qtcurvetogglebutton.h"
0056 #include "qtcurvesizegrip.h"
0057 #include "tileset.h"
0058 #include <common/common.h>
0059 
0060 #include <style/qtcurve.h>
0061 
0062 namespace QtCurve {
0063 namespace KWin {
0064 
0065 static const int constTitlePad = 4;
0066 
0067 int getMenubarSizeProperty(WId wId)
0068 {
0069     return qtcX11GetShortProp(wId, qtc_x11_qtc_menubar_size);
0070 }
0071 
0072 int getStatusbarSizeProperty(WId wId)
0073 {
0074     return qtcX11GetShortProp(wId, qtc_x11_qtc_statusbar);
0075 }
0076 
0077 int getOpacityProperty(WId wId)
0078 {
0079     int o = qtcX11GetShortProp(wId, qtc_x11_qtc_opacity);
0080     return o <= 0 || o >= 100 ? 100 : o;
0081 }
0082 
0083 void getBgndSettings(WId wId, EAppearance &app, QColor &col)
0084 {
0085     auto reply = qtcX11GetProperty(0, wId, qtc_x11_qtc_bgnd,
0086                                    XCB_ATOM_CARDINAL, 0, 1);
0087     if (!reply) {
0088         return;
0089     }
0090     if (qtcX11GetPropertyValueLength(reply) > 0) {
0091         uint32_t val = *(int32_t*)qtcX11GetPropertyValue(reply);
0092         app = (EAppearance)(val & 0xFF);
0093         col.setRgb((val & 0xFF000000) >> 24, (val & 0x00FF0000) >> 16,
0094                    (val & 0x0000FF00) >> 8);
0095     }
0096     free(reply);
0097 }
0098 
0099 static QPainterPath createPath(const QRectF &r, double radiusTop, double radiusBot)
0100 {
0101     QPainterPath path;
0102     double       diameterTop(radiusTop*2),
0103                  diameterBot(radiusBot*2);
0104 
0105     if (radiusBot>1.0)
0106         path.moveTo(r.x()+r.width(), r.y()+r.height()-radiusBot);
0107     else
0108         path.moveTo(r.x()+r.width(), r.y()+r.height());
0109 
0110     if (radiusTop>1.0)
0111         path.arcTo(r.x()+r.width()-diameterTop, r.y(), diameterTop, diameterTop, 0, 90);
0112     else
0113         path.lineTo(r.x()+r.width(), r.y());
0114 
0115     if (radiusTop>1.0)
0116         path.arcTo(r.x(), r.y(), diameterTop, diameterTop, 90, 90);
0117     else
0118         path.lineTo(r.x(), r.y());
0119 
0120     if (radiusBot>1.0)
0121         path.arcTo(r.x(), r.y()+r.height()-diameterBot, diameterBot, diameterBot, 180, 90);
0122     else
0123         path.lineTo(r.x(), r.y()+r.height());
0124 
0125     if (radiusBot>1.0)
0126         path.arcTo(r.x()+r.width()-diameterBot, r.y()+r.height()-diameterBot, diameterBot, diameterBot, 270, 90);
0127     else
0128         path.lineTo(r.x()+r.width(), r.y()+r.height());
0129 
0130     return path;
0131 }
0132 
0133 static void drawSunkenBevel(QPainter *p, const QRect &r, const QColor &bgnd, bool circular, int round)
0134 {
0135     double          radius=circular
0136                             ? r.height()/2.0
0137                             : round>ROUND_FULL
0138                                 ? 5.0
0139                                 : round>ROUND_SLIGHT
0140                                     ? 3.0
0141                                     : 2.0;
0142     QPainterPath    path(createPath(QRectF(r), radius, radius));
0143     QLinearGradient g(r.topLeft(), r.bottomLeft());
0144     QColor          black(Qt::black),
0145                     white(Qt::white);
0146 
0147     black.setAlphaF(SUNKEN_BEVEL_DARK_ALPHA(bgnd));
0148     white.setAlphaF(SUNKEN_BEVEL_LIGHT_ALPHA(bgnd));
0149     g.setColorAt(0, black);
0150     g.setColorAt(1, white);
0151     p->fillPath(path, QBrush(g));
0152 }
0153 
0154 static QColor blendColors(const QColor &foreground, const QColor &background, double alpha)
0155 {
0156     return KColorUtils::mix(background, foreground, alpha);
0157 }
0158 
0159 static void drawFadedLine(QPainter *painter, const QRect &r, const QColor &col, bool horiz=false, bool fadeStart=true, bool fadeEnd=true)
0160 {
0161     bool            aa(painter->testRenderHint(QPainter::Antialiasing));
0162     QPointF         start(r.x()+(aa ? 0.5 : 0.0), r.y()+(aa ? 0.5 : 0.0)),
0163                     end(r.x()+(horiz ? r.width()-1 : 0)+(aa ? 0.5 : 0.0),
0164                         r.y()+(horiz ? 0 : r.height()-1)+(aa ? 0.5 : 0.0));
0165     QLinearGradient grad(start, end);
0166     QColor          c(col),
0167                     blank(Qt::white);
0168 
0169     c.setAlphaF(horiz ? 0.6 : 0.3);
0170     blank.setAlphaF(0.0);
0171     grad.setColorAt(0, fadeStart ? blank : c);
0172     grad.setColorAt(FADE_SIZE, c);
0173     grad.setColorAt(1.0-FADE_SIZE, c);
0174     grad.setColorAt(1, fadeEnd ? blank : c);
0175     painter->setPen(QPen(QBrush(grad), 1));
0176     painter->drawLine(start, end);
0177 }
0178 
0179 static void fillBackground(EAppearance app, QPainter &painter, const QColor &col, const QRect &fillRect, const QRect &widgetRect, const QPainterPath path)
0180 {
0181     if (!qtcIsFlatBgnd(app) || !widgetRect.isEmpty()) {
0182         Style::BgndOption opt;
0183         opt.state|=QtC_StateKWin;
0184         opt.rect=fillRect;
0185         opt.widgetRect=widgetRect;
0186         opt.palette.setColor(QPalette::Window, col);
0187         opt.app=app;
0188         opt.path=path;
0189         Handler()->wStyle()->drawPrimitive(QtC_PE_DrawBackground, &opt, &painter, nullptr);
0190     }
0191     else if(path.isEmpty())
0192         painter.fillRect(fillRect, col);
0193     else
0194         painter.fillPath(path, col);
0195 }
0196 
0197 // static inline bool isModified(const QString &title)
0198 // {
0199 //     return title.indexOf(i18n(" [modified] ")) > 3 ||
0200 //            (title.length()>3 && QChar('*')==title[0] && QChar(' ')==title[1]);
0201 // }
0202 
0203 QtCurveClient::QtCurveClient(KDecorationBridge *bridge, QtCurveHandler *factory)
0204     : KCommonDecorationUnstable(bridge, factory),
0205       m_resizeGrip(0L),
0206       m_titleFont(QFont()),
0207       m_menuBarSize(-1),
0208       m_toggleMenuBarButton(0L),
0209       m_toggleStatusBarButton(0L)
0210       // m_hover(false)
0211 {
0212     Handler()->addClient(this);
0213 }
0214 
0215 QtCurveClient::~QtCurveClient()
0216 {
0217     Handler()->removeClient(this);
0218     deleteSizeGrip();
0219 }
0220 
0221 QString QtCurveClient::visibleName() const
0222 {
0223     return i18n("QtCurve");
0224 }
0225 
0226 bool QtCurveClient::decorationBehaviour(DecorationBehaviour behaviour) const
0227 {
0228     switch (behaviour)
0229     {
0230         case DB_MenuClose:
0231             return true;
0232         case DB_WindowMask:
0233             return false;
0234         default:
0235             return KCommonDecoration::decorationBehaviour(behaviour);
0236     }
0237 }
0238 
0239 int QtCurveClient::layoutMetric(LayoutMetric lm, bool respectWindowState,
0240                                 const KCommonDecorationButton *btn) const
0241 {
0242     switch (lm)
0243     {
0244         case LM_BorderLeft:
0245         case LM_BorderRight:
0246         case LM_BorderBottom:
0247             return respectWindowState && isMaximized() ? 0 : Handler()->borderSize(LM_BorderBottom==lm);
0248         case LM_TitleEdgeTop:
0249             return respectWindowState && isMaximized() ? 0 : Handler()->borderEdgeSize();
0250         case LM_TitleEdgeBottom:
0251             return respectWindowState && isMaximized() && Handler()->borderlessMax() ? 0 :  Handler()->borderEdgeSize();
0252         case LM_TitleEdgeLeft:
0253         case LM_TitleEdgeRight:
0254             return respectWindowState && isMaximized() ? 0 : Handler()->borderEdgeSize();
0255         case LM_TitleBorderLeft:
0256         case LM_TitleBorderRight:
0257             return 5;
0258         case LM_ButtonWidth:
0259         case LM_ButtonHeight:
0260         case LM_TitleHeight:
0261             return respectWindowState && isMaximized() && Handler()->borderlessMax()
0262                         ? 0
0263                         : respectWindowState && isToolWindow()
0264                             ? Handler()->titleHeightTool()
0265                             : Handler()->titleHeight();
0266         case LM_ButtonSpacing:
0267             return 0;
0268         case LM_ButtonMarginTop:
0269             return 0;
0270         case LM_OuterPaddingLeft:
0271         case LM_OuterPaddingRight:
0272         case LM_OuterPaddingTop:
0273         case LM_OuterPaddingBottom:
0274             if(Handler()->customShadows())
0275                 return Handler()->shadowCache().shadowSize();
0276         default:
0277             return KCommonDecoration::layoutMetric(lm, respectWindowState, btn);
0278     }
0279 }
0280 
0281 KCommonDecorationButton *QtCurveClient::createButton(ButtonType type)
0282 {
0283     switch (type) {
0284     case MenuButton:
0285     case OnAllDesktopsButton:
0286     case HelpButton:
0287     case MinButton:
0288     case MaxButton:
0289     case CloseButton:
0290     case AboveButton:
0291     case BelowButton:
0292     case ShadeButton:
0293 #if KDE_IS_VERSION(4, 9, 85)
0294     case AppMenuButton:
0295 #endif
0296         return new QtCurveButton(type, this);
0297     default:
0298         return 0;
0299     }
0300 }
0301 
0302 void QtCurveClient::init()
0303 {
0304     m_titleFont=isToolWindow() ? Handler()->titleFontTool() : Handler()->titleFont();
0305 
0306     KCommonDecoration::init();
0307     widget()->setAutoFillBackground(false);
0308     widget()->setAttribute(Qt::WA_OpaquePaintEvent, true);
0309     widget()->setAttribute(Qt::WA_NoSystemBackground);
0310 
0311     if(Handler()->showResizeGrip())
0312         createSizeGrip();
0313     if (isPreview())
0314         m_caption =  isActive() ? i18n("Active Window") : i18n("Inactive Window");
0315     else
0316         captionChange();
0317 }
0318 
0319 void QtCurveClient::maximizeChange()
0320 {
0321     reset(SettingBorder);
0322     if(m_resizeGrip)
0323         m_resizeGrip->setVisible(!(isShade() || isMaximized()));
0324     KCommonDecoration::maximizeChange();
0325 }
0326 
0327 void QtCurveClient::shadeChange()
0328 {
0329     if(m_resizeGrip)
0330         m_resizeGrip->setVisible(!(isShade() || isMaximized()));
0331     KCommonDecoration::shadeChange();
0332 }
0333 
0334 void QtCurveClient::activeChange()
0335 {
0336     if(m_resizeGrip && !(isShade() || isMaximized()))
0337     {
0338         m_resizeGrip->activeChange();
0339         m_resizeGrip->update();
0340     }
0341 
0342     informAppOfActiveChange();
0343     KCommonDecoration::activeChange();
0344 }
0345 
0346 void QtCurveClient::captionChange()
0347 {
0348     m_caption=caption();
0349     widget()->update();
0350 }
0351 
0352 void QtCurveClient::paintEvent(QPaintEvent *e)
0353 {
0354     bool compositing = compositingActive();
0355     QPainter painter(widget());
0356     QRect r(widget()->rect());
0357     QStyleOptionTitleBar opt;
0358     int windowBorder(Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_WindowBorder, 0L, 0L));
0359     bool active(isActive());
0360     bool colorTitleOnly(windowBorder&WINDOW_BORDER_COLOR_TITLEBAR_ONLY);
0361     bool roundBottom(Handler()->roundBottom());
0362     bool preview(isPreview());
0363     bool blend(!preview && Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_BlendMenuAndTitleBar, nullptr, nullptr));
0364     bool menuColor(windowBorder&WINDOW_BORDER_USE_MENUBAR_COLOR_FOR_TITLEBAR);
0365     bool separator(active && windowBorder&WINDOW_BORDER_SEPARATOR);
0366     bool maximized(isMaximized());
0367     QtCurveConfig::Shade outerBorder(Handler()->outerBorder()),
0368                          innerBorder(Handler()->innerBorder());
0369     const int            border(Handler()->borderEdgeSize()),
0370                          titleHeight(layoutMetric(LM_TitleHeight)),
0371                          titleEdgeTop(layoutMetric(LM_TitleEdgeTop)),
0372                          titleEdgeBottom(layoutMetric(LM_TitleEdgeBottom)),
0373                          titleEdgeLeft(layoutMetric(LM_TitleEdgeLeft)),
0374                          titleEdgeRight(layoutMetric(LM_TitleEdgeRight)),
0375                          titleBarHeight(titleHeight+titleEdgeTop+titleEdgeBottom+(isMaximized() ? border : 0)),
0376                          round=Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_Round, nullptr, nullptr),
0377                          buttonFlags=Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_TitleBarButtons, nullptr, nullptr);
0378     int                  rectX, rectY, rectX2, rectY2, shadowSize(0),
0379                          kwinOpacity(compositing ? Handler()->opacity(active) : 100),
0380                          opacity(kwinOpacity);
0381     EAppearance          bgndAppearance=APPEARANCE_FLAT;
0382     QColor               windowCol(widget()->palette().color(QPalette::Window));
0383 
0384     getBgndSettings(windowId(), bgndAppearance, windowCol);
0385 
0386     QColor               col(KDecoration::options()->color(KDecoration::ColorTitleBar, active)),
0387                          fillCol(colorTitleOnly ? windowCol : col);
0388                          // APPEARANCE_RAISED is used to signal flat background, but have background image!
0389                          // In which case we still have a custom background to draw.
0390     bool customBgnd = bgndAppearance != APPEARANCE_FLAT;
0391     bool customShadows = Handler()->customShadows();
0392 
0393     painter.setClipRegion(e->region());
0394 
0395     if(!preview && compositing && 100==opacity)
0396         opacity=getOpacityProperty(windowId());
0397 
0398     if (customShadows) {
0399         shadowSize = Handler()->shadowCache().shadowSize();
0400 
0401         if (compositing) {
0402             TileSet *tileSet=Handler()->shadowCache().tileSet(this, roundBottom);
0403             if (opacity < 100) {
0404                 painter.save();
0405                 painter.setClipRegion(QRegion(r).subtract(getMask(round, r.adjusted(shadowSize, shadowSize, -shadowSize, -shadowSize))), Qt::IntersectClip);
0406             }
0407 
0408             if(!isMaximized())
0409                 tileSet->render(r.adjusted(5, 5, -5, -5), &painter, TileSet::Ring);
0410             else if(isShade())
0411                 tileSet->render(r.adjusted(0, 5, 0, -5), &painter, TileSet::Bottom);
0412             if(opacity<100)
0413                 painter.restore();
0414         }
0415         r.adjust(shadowSize, shadowSize, -shadowSize, -shadowSize);
0416     }
0417 
0418     int   side(layoutMetric(LM_BorderLeft)),
0419           bot(layoutMetric(LM_BorderBottom));
0420     QRect widgetRect(widget()->rect().adjusted(shadowSize+side, shadowSize+titleBarHeight, -(shadowSize+side), -(shadowSize+bot)));
0421 
0422     r.getCoords(&rectX, &rectY, &rectX2, &rectY2);
0423 
0424     if(!preview && (blend||menuColor) && -1==m_menuBarSize)
0425     {
0426         QString wc(windowClass());
0427         if(wc==QLatin1String("W Navigator Firefox browser") ||
0428            wc==QLatin1String("W Navigator Firefox view-source") ||
0429            wc==QLatin1String("W Mail Thunderbird 3pane") ||
0430            wc==QLatin1String("W Mail Thunderbird addressbook") ||
0431            wc==QLatin1String("W Mail Thunderbird messageWindow") ||
0432            wc==QLatin1String("D Calendar Thunderbird EventDialog") ||
0433            wc==QLatin1String("W Msgcompose Thunderbird Msgcompose") ||
0434            wc==QLatin1String("D Msgcompose Thunderbird Msgcompose"))
0435             m_menuBarSize=QFontMetrics(QApplication::font()).height()+8;
0436 
0437         else if(
0438 #if 0 // Currently LibreOffice does not seem to pain menubar backgrounds for KDE - so disable check here...
0439                 wc.startsWith(QLatin1String("W VCLSalFrame libreoffice-")) ||
0440                 wc.startsWith(QLatin1String("W VCLSalFrame.DocumentWindow libreoffice-")) ||
0441                 //wc==QLatin1String("W soffice.bin Soffice.bin") ||
0442 #endif
0443                 wc.startsWith(QLatin1String("W VCLSalFrame.DocumentWindow OpenOffice.org")) ||
0444                 wc.startsWith(QLatin1String("W VCLSalFrame OpenOffice.org")) ||
0445                 wc==QLatin1String("W soffice.bin Soffice.bin"))
0446             m_menuBarSize=QFontMetrics(QApplication::font()).height()+7;
0447         else
0448         {
0449             int val=getMenubarSizeProperty(windowId());
0450             if(val>-1)
0451                 m_menuBarSize=val;
0452         }
0453     }
0454 
0455     if(menuColor && m_menuBarSize>0 &&
0456        (active || !Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_ShadeMenubarOnlyWhenActive, nullptr, nullptr)))
0457         col=QColor(QRgb(Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_MenubarColor, nullptr, nullptr)));
0458 
0459     if(opacity<100)
0460     {
0461         double alpha=opacity/100.0;
0462         col.setAlphaF(alpha);
0463         windowCol.setAlphaF(alpha);
0464         fillCol.setAlphaF(alpha);
0465     }
0466 
0467     opt.init(widget());
0468     opt.state=QStyle::State_Horizontal|QStyle::State_Enabled|QStyle::State_Raised|
0469              (active ? QStyle::State_Active : QStyle::State_None)|QtC_StateKWin;
0470 
0471     int   fillTopAdjust(maximized ? Handler()->borderEdgeSize() : 0),
0472           fillBotAdjust(maximized ? Handler()->borderSize(true) : 0),
0473           fillSideAdjust(maximized ? Handler()->borderSize(false) : 0);
0474     QRect fillRect(r.adjusted(-fillSideAdjust, -fillTopAdjust, fillSideAdjust, fillBotAdjust));
0475     bool  clipRegion((outerBorder || round<=ROUND_SLIGHT) && !maximized);
0476 
0477     painter.setRenderHint(QPainter::Antialiasing, true);
0478     if(clipRegion)
0479     {
0480         painter.save();
0481         painter.setClipRegion(getMask(round, r));
0482     }
0483     else if(maximized)
0484         painter.setClipRect(r, Qt::IntersectClip);
0485 
0486     //
0487     // Fill titlebar and border backgrounds...
0488     //
0489     QPainterPath fillPath(maximized || round<=ROUND_SLIGHT
0490                                 ? QPainterPath()
0491                                 : createPath(QRectF(fillRect),
0492                                              APPEARANCE_NONE==Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_TitleBarApp,
0493                                                                                                &opt, nullptr) ? 6.0 : 8.0,
0494                                              roundBottom ? 6.0 : 1.0));
0495 
0496 
0497     bool fillTitlebar(windowBorder&WINDOW_BORDER_FILL_TITLEBAR),
0498          opaqueBorder(opacity<100 && Handler()->opaqueBorder());
0499 
0500     if(opaqueBorder)
0501     {
0502         QColor fc(fillCol);
0503         fc.setAlphaF(1.0);
0504         if(!clipRegion)
0505             painter.save();
0506         painter.setClipRect(r.adjusted(0, titleBarHeight, 0, 0), Qt::IntersectClip);
0507         fillBackground(bgndAppearance, painter, fc, fillRect, widgetRect, fillPath);
0508         if(fillTitlebar)
0509         {
0510             painter.save();
0511             painter.setClipRect(QRect(r.x(), r.y(), r.width(), titleBarHeight), Qt::IntersectClip);
0512             fillBackground(bgndAppearance, painter, fillCol, fillRect, widgetRect, fillPath);
0513             painter.restore();
0514         }
0515     }
0516     else
0517     {
0518         if(!fillTitlebar)
0519         {
0520             if(!clipRegion)
0521                 painter.save();
0522             if(!compositing)
0523             {
0524                 // Not compositing, so need to fill with background colour...
0525                 if(fillPath.isEmpty())
0526                     painter.fillRect(QRect(r.x(), r.y(), r.width(), titleBarHeight), windowCol);
0527                 else
0528                     painter.fillPath(fillPath, windowCol);
0529             }
0530 
0531             painter.setClipRect(r.adjusted(0, titleBarHeight, 0, 0), Qt::IntersectClip);
0532         }
0533         fillBackground(bgndAppearance, painter, fillCol, fillRect, widgetRect, fillPath);
0534     }
0535 
0536     if(clipRegion || opaqueBorder || !fillTitlebar)
0537         painter.restore();
0538     //
0539     // Titlebar and border backgrounds filled.
0540     //
0541 
0542     if(maximized)
0543         r.adjust(-3, -border, 3, 0);
0544     opt.palette.setColor(QPalette::Button, col);
0545     opt.palette.setColor(QPalette::Window, windowCol);
0546     opt.rect=QRect(r.x(), r.y()+6, r.width(), r.height()-6);
0547 
0548 
0549     if(!roundBottom)
0550         opt.state|=QtC_StateKWinNotFull;
0551 
0552     if(compositing && !preview)
0553         opt.state|=QtC_StateKWinCompositing;
0554 
0555     if (outerBorder) {
0556         if (outerBorder == QtCurveConfig::SHADE_SHADOW && customShadows) {
0557             opt.version = TBAR_BORDER_VERSION_HACK + 2;
0558             opt.palette.setColor(QPalette::Shadow, blendColors(Handler()->shadowCache().color(active), windowCol, active ? 0.75 : 0.4));
0559         } else {
0560             opt.version = (outerBorder == QtCurveConfig::SHADE_LIGHT ? 0 : 1) +
0561                 TBAR_BORDER_VERSION_HACK;
0562         }
0563         painter.save();
0564         painter.setClipRect(r.adjusted(0, titleBarHeight, 0, 0), Qt::IntersectClip);
0565 #ifdef DRAW_INTO_PIXMAPS
0566         if(!compositing && !preview)
0567         {
0568             // For some reason, on Jaunty drawing directly is *hideously* slow on intel graphics card!
0569             QPixmap pix(32, 32);
0570             pix.fill(Qt::transparent);
0571             QPainter p2(&pix);
0572             p2.setRenderHint(QPainter::Antialiasing, true);
0573             opt.rect=QRect(0, 0, pix.width(), pix.height());
0574             Handler()->wStyle()->drawPrimitive(QStyle::PE_FrameWindow, &opt, &p2, widget());
0575             p2.end();
0576             painter.drawTiledPixmap(r.x(), r.y()+10, 2, r.height()-18, pix.copy(0, 8, 2, 16));
0577             painter.drawTiledPixmap(r.x()+r.width()-2, r.y()+8, 2, r.height()-16, pix.copy(pix.width()-2, 8, 2, 16));
0578             painter.drawTiledPixmap(r.x()+8, r.y()+r.height()-2, r.width()-16, 2, pix.copy(8, pix.height()-2, 16, 2));
0579             painter.drawPixmap(r.x(), r.y()+r.height()-8, pix.copy(0, 24, 8, 8));
0580             painter.drawPixmap(r.x()+r.width()-8, r.y()+r.height()-8, pix.copy(24, 24, 8, 8));
0581         }
0582         else
0583 #endif
0584             Handler()->wStyle()->drawPrimitive(QStyle::PE_FrameWindow, &opt, &painter, widget());
0585         painter.restore();
0586     }
0587     else
0588         opt.state|=QtC_StateKWinNoBorder;
0589 
0590     if(kwinOpacity<100 && (blend||menuColor))
0591     {
0592         // Turn off opacity for titlebar...
0593         QColor c(col);
0594         c.setAlphaF(1.0);
0595         opt.palette.setColor(QPalette::Button, c);
0596         c=windowCol;
0597         c.setAlphaF(1.0);
0598         opt.palette.setColor(QPalette::Window, c);
0599     }
0600 
0601     opt.rect=QRect(r.x(), r.y(), r.width(), titleBarHeight);
0602     opt.titleBarState=(active ? QStyle::State_Active : QStyle::State_None)|QtC_StateKWin;
0603 
0604     if(!preview && !isShade() && blend && -1!=m_menuBarSize)
0605         opt.rect.adjust(0, 0, 0, m_menuBarSize);
0606 
0607     // Remove QtC_StateKWinNotFull settings - as its the same value as QtC_StateKWinFillBgnd, and it is not
0608     // used in CC_TitleBar...
0609     if(!roundBottom)
0610         opt.state&=~QtC_StateKWinNotFull;
0611 
0612 #ifdef DRAW_INTO_PIXMAPS
0613     if(!compositing && !preview && !customBgnd)
0614     {
0615         QPixmap  tPix(32, titleBarHeight+(!blend || m_menuBarSize<0 ? 0 : m_menuBarSize));
0616         QPainter tPainter(&tPix);
0617         tPainter.setRenderHint(QPainter::Antialiasing, true);
0618         if(!customBgnd)
0619             opt.state|=QtC_StateKWinFillBgnd;
0620         opt.rect=QRect(0, 0, tPix.width(), tPix.height());
0621         Handler()->wStyle()->drawComplexControl(QStyle::CC_TitleBar, &opt, &tPainter, widget());
0622         tPainter.end();
0623         painter.drawTiledPixmap(r.x()+12, r.y(), r.width()-24, tPix.height(), tPix.copy(8, 0, 16, tPix.height()));
0624         painter.drawPixmap(r.x(), r.y(), tPix.copy(0, 0, 16, tPix.height()));
0625         painter.drawPixmap(r.x()+r.width()-16, r.y(), tPix.copy(tPix.width()-16, 0, 16, tPix.height()));
0626     }
0627     else
0628 #endif
0629         Handler()->wStyle()->drawComplexControl(QStyle::CC_TitleBar, &opt, &painter, widget());
0630 
0631     if(outerBorder && innerBorder)
0632     {
0633         QStyleOptionFrame frameOpt;
0634 
0635         frameOpt.palette=opt.palette;
0636         if (innerBorder == QtCurveConfig::SHADE_SHADOW && customShadows) {
0637             frameOpt.version = 2 + TBAR_BORDER_VERSION_HACK;
0638             frameOpt.palette.setColor(QPalette::Shadow, blendColors(Handler()->shadowCache().color(active), windowCol, active ? 0.75 : 0.4));
0639         } else {
0640             frameOpt.version = (innerBorder == QtCurveConfig::SHADE_LIGHT ? 0 : 1)+TBAR_BORDER_VERSION_HACK;
0641         }
0642         frameOpt.rect=widgetRect.adjusted(-1, -1, 1, 1);
0643         frameOpt.state=(active ? QStyle::State_Active : QStyle::State_None)|QtC_StateKWin;
0644         frameOpt.lineWidth=frameOpt.midLineWidth=1;
0645         Handler()->wStyle()->drawPrimitive(QStyle::PE_Frame, &frameOpt, &painter, widget());
0646     }
0647 
0648     if(buttonFlags&TITLEBAR_BUTTON_SUNKEN_BACKGROUND)
0649     {
0650         int  hOffset=2,
0651              vOffset=hOffset+(outerBorder ? 1 :0),
0652              posAdjust=maximized || outerBorder ? 2 : 0,
0653              edgePad=Handler()->edgePad();
0654         bool menuIcon=TITLEBAR_ICON_MENU_BUTTON==Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_TitleBarIcon, 0L, 0L),
0655              menuOnlyLeft=menuIcon && onlyMenuIcon(true),
0656              menuOnlyRight=menuIcon && !menuOnlyLeft && onlyMenuIcon(false);
0657 
0658         if(!menuOnlyLeft && buttonsLeftWidth()>(titleBarHeight-2*hOffset))
0659             drawSunkenBevel(&painter, QRect(r.left()+hOffset+posAdjust+edgePad+(compositing ? 0 : -1), r.top()+vOffset+edgePad,
0660                                             buttonsLeftWidth()-hOffset+(compositing ? 0 : 2),
0661                                             titleBarHeight-2*(vOffset+edgePad)), col, buttonFlags&TITLEBAR_BUTTON_ROUND, round);
0662         if(!menuOnlyRight && buttonsRightWidth()>(titleBarHeight-2*hOffset))
0663             drawSunkenBevel(&painter, QRect(r.right()-(buttonsRightWidth()+posAdjust+edgePad), r.top()+vOffset+edgePad,
0664                                             buttonsRightWidth(), titleBarHeight-2*(vOffset+edgePad)), col, buttonFlags&TITLEBAR_BUTTON_ROUND, round);
0665     }
0666 
0667     bool showIcon=TITLEBAR_ICON_NEXT_TO_TITLE==Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_TitleBarIcon,  0L, 0L);
0668     int  iconSize=showIcon ? Handler()->wStyle()->pixelMetric(QStyle::PM_SmallIconSize) : 0;
0669 
0670     m_captionRect=captionRect(); // also update m_captionRect!
0671     paintTitle(&painter, m_captionRect, QRect(rectX+titleEdgeLeft, m_captionRect.y(),
0672                                               rectX2-(titleEdgeRight+rectX+titleEdgeLeft),
0673                                               m_captionRect.height()),
0674                m_caption, showIcon ? icon().pixmap(iconSize) : QPixmap(), shadowSize);
0675 
0676     bool hideToggleButtons(true);
0677     int  toggleButtons(Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_ToggleButtons, nullptr, nullptr));
0678 
0679     if(toggleButtons)
0680     {
0681         if(!m_toggleMenuBarButton && toggleButtons&0x01 && (Handler()->wasLastMenu(windowId()) || getMenubarSizeProperty(windowId())>-1))
0682             m_toggleMenuBarButton=createToggleButton(true);
0683         if(!m_toggleStatusBarButton && toggleButtons&0x02 && (Handler()->wasLastStatus(windowId()) || getStatusbarSizeProperty(windowId())>-1))
0684             m_toggleStatusBarButton=createToggleButton(false);
0685 
0686         // if (m_hover)
0687         {
0688             if (active && (m_toggleMenuBarButton||m_toggleStatusBarButton)) {
0689                 if( (buttonsLeftWidth()+buttonsRightWidth()+constTitlePad+
0690                     (m_toggleMenuBarButton ? m_toggleMenuBarButton->width() : 0) +
0691                     (m_toggleStatusBarButton ? m_toggleStatusBarButton->width() : 0)) < r.width())
0692                 {
0693                     int  align(Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_TitleAlignment, 0L, 0L));
0694                     bool onLeft(align&Qt::AlignRight);
0695 
0696                     if(align&Qt::AlignHCenter)
0697                     {
0698                         QString left=options()->customButtonPositions() ? options()->titleButtonsLeft() : defaultButtonsLeft(),
0699                                 right=options()->customButtonPositions() ? options()->titleButtonsRight() : defaultButtonsRight();
0700                         onLeft=left.length()<right.length();
0701                     }
0702 
0703                     int     offset=2,
0704                             posAdjust=maximized ? 2 : 0;
0705                     QRect   cr(onLeft
0706                                 ? r.left()+buttonsLeftWidth()+posAdjust+constTitlePad+2
0707                                 : r.right()-(buttonsRightWidth()+posAdjust+constTitlePad+2+
0708                                             (m_toggleMenuBarButton ? m_toggleMenuBarButton->width() : 0)+
0709                                             (m_toggleStatusBarButton ? m_toggleStatusBarButton->width() : 0)),
0710                             r.top()+offset,
0711                             (m_toggleMenuBarButton ? m_toggleMenuBarButton->width() : 0)+
0712                             (m_toggleStatusBarButton ? m_toggleStatusBarButton->width() : 0),
0713                             titleBarHeight-2*offset);
0714 
0715                     if(m_toggleMenuBarButton)
0716                     {
0717                         m_toggleMenuBarButton->move(cr.x(), r.y()+3+(outerBorder ? 2 : 0));
0718                         m_toggleMenuBarButton->show();
0719                     }
0720                     if(m_toggleStatusBarButton)
0721                     {
0722                         m_toggleStatusBarButton->move(cr.x()+(m_toggleMenuBarButton ? m_toggleMenuBarButton->width()+2 : 0),
0723                                                        r.y()+3+(outerBorder ? 2 : 0));
0724                         m_toggleStatusBarButton->show();
0725                     }
0726                     hideToggleButtons=false;
0727                 }
0728             }
0729         }
0730     }
0731     if(hideToggleButtons)
0732     {
0733         if(m_toggleMenuBarButton)
0734             m_toggleMenuBarButton->hide();
0735         if(m_toggleStatusBarButton)
0736             m_toggleStatusBarButton->hide();
0737     }
0738 
0739     if(separator)
0740     {
0741         QColor        color(KDecoration::options()->color(KDecoration::ColorFont, isActive()));
0742         Qt::Alignment align((Qt::Alignment)Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_TitleAlignment, 0L, 0L));
0743 
0744         r.adjust(16, titleBarHeight-1, -16, 0);
0745         color.setAlphaF(0.5);
0746         drawFadedLine(&painter, r, color, true, align&(Qt::AlignHCenter|Qt::AlignRight), align&(Qt::AlignHCenter|Qt::AlignLeft));
0747     }
0748 
0749     painter.end();
0750 }
0751 
0752 void
0753 QtCurveClient::paintTitle(QPainter *painter, const QRect &capRect,
0754                           const QRect &alignFullRect, const QString &cap,
0755                           const QPixmap &pix, int shadowSize, bool isTab,
0756                           bool isActiveTab)
0757 {
0758     int iconX = capRect.x();
0759     bool showIcon = !pix.isNull() && capRect.width()>pix.width();
0760 
0761     if(!cap.isEmpty())
0762     {
0763         painter->setFont(m_titleFont);
0764 
0765         QFontMetrics  fm(painter->fontMetrics());
0766         QString       str(fm.elidedText(cap, Qt::ElideRight,
0767                             capRect.width()-(showIcon ? pix.width()+constTitlePad : 0), QPalette::WindowText));
0768         Qt::Alignment hAlign((Qt::Alignment)Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_TitleAlignment, 0L, 0L)),
0769                       alignment(Qt::AlignVCenter|hAlign);
0770         bool          alignFull(!isTab && Qt::AlignHCenter==hAlign),
0771                       reverse=Qt::RightToLeft==QApplication::layoutDirection(),
0772                       iconRight((!reverse && alignment&Qt::AlignRight) || (reverse && alignment&Qt::AlignLeft));
0773         QRect         textRect(alignFull ? alignFullRect : capRect);
0774         int           textWidth=alignFull || (showIcon && alignment&Qt::AlignHCenter)
0775                                     ? fm.boundingRect(str).width()+(showIcon ? pix.width()+constTitlePad : 0) : 0;
0776         EEffect       effect((EEffect)(Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_TitleBarEffect)));
0777 
0778         if(alignFull)
0779         {
0780             int halfWidth=(textWidth+(showIcon ? pix.width()+constTitlePad : 0))/2;
0781 
0782             if(capRect.left()>(textRect.x()+(textRect.width()/2)-halfWidth))
0783             {
0784                 alignment=Qt::AlignVCenter|Qt::AlignLeft;
0785                 textRect=capRect;
0786                 hAlign=Qt::AlignLeft;
0787             }
0788             else if (capRect.right()<(textRect.x()+(textRect.width()/2)+halfWidth))
0789             {
0790                 alignment=Qt::AlignVCenter|Qt::AlignRight;
0791                 textRect=capRect;
0792                 hAlign=Qt::AlignRight;
0793             }
0794         }
0795 
0796         if(showIcon)
0797         {
0798             if(alignment&Qt::AlignHCenter)
0799             {
0800                 if(reverse)
0801                 {
0802                     iconX=((textRect.width()-textWidth)/2.0)+0.5+textWidth+pix.width();
0803                     textRect.setX(textRect.x()-(pix.width()+constTitlePad));
0804                 }
0805                 else
0806                 {
0807 //                     iconX=(((textRect.width()-textWidth)/2.0)+0.5)+
0808 //                             (shadowSize ? (Qt::AlignHCenter==hAlign ? shadowSize : capRect.x()) : 0)+
0809 //                             (isTab ? capRect.x() : 0);
0810 
0811                     int adjustment=textRect==capRect ? capRect.x() : 0;
0812 
0813                     iconX=(((textRect.width()-textWidth)/2.0)+0.5)+
0814                             (shadowSize
0815                                 ? (Qt::AlignHCenter==hAlign ? shadowSize : capRect.x())
0816                                 : (isTab ? 0 : adjustment))+
0817                             (isTab ? capRect.x() : 0);
0818                     textRect.setX(iconX+pix.width()+constTitlePad);
0819                     alignment=Qt::AlignVCenter|Qt::AlignLeft;
0820                 }
0821             }
0822             else if((!reverse && alignment&Qt::AlignLeft) || (reverse && alignment&Qt::AlignRight))
0823             {
0824                 iconX=textRect.x();
0825                 textRect.setX(textRect.x()+(pix.width()+constTitlePad));
0826             }
0827             else if((!reverse && alignment&Qt::AlignRight) || (reverse && alignment&Qt::AlignLeft))
0828             {
0829                 if(iconRight)
0830                 {
0831                     iconX=textRect.x()+textRect.width()-pix.width();
0832                     textRect.setWidth(textRect.width()-(pix.width()+constTitlePad));
0833                 }
0834                 else
0835                 {
0836                     iconX=textRect.x()+textRect.width()-(textWidth+constTitlePad);
0837                     if(iconX<textRect.x())
0838                         iconX=textRect.x();
0839                 }
0840             }
0841         }
0842 
0843 //         painter->setClipRect(capRect.adjusted(-2, 0, 2, 0));
0844 
0845         QColor color(KDecoration::options()->color(KDecoration::ColorFont, isActive())),
0846                bgnd(KDecoration::options()->color(KDecoration::ColorTitleBar, isActive()));
0847 
0848         if(isTab && !isActiveTab)
0849             textRect.adjust(0, 1, 0, 1);
0850 
0851         if((!isTab || isActiveTab) && EFFECT_NONE!=effect)
0852         {
0853 //             QColor shadow(WINDOW_SHADOW_COLOR(effect));
0854 //             shadow.setAlphaF(WINDOW_TEXT_SHADOW_ALPHA(effect));
0855 //             painter->setPen(shadow);
0856             painter->setPen(blendColors(WINDOW_SHADOW_COLOR(effect), bgnd, WINDOW_TEXT_SHADOW_ALPHA(effect)));
0857             painter->drawText(EFFECT_SHADOW==effect
0858                                 ? textRect.adjusted(1, 1, 1, 1)
0859                                 : textRect.adjusted(0, 1, 0, 1),
0860                               alignment, str);
0861 
0862             if (!isActive() && DARK_WINDOW_TEXT(color))
0863             {
0864                 //color.setAlpha((color.alpha() * 180) >> 8);
0865                 color=blendColors(color, bgnd, ((255 * 180) >> 8)/256.0);
0866             }
0867         }
0868 
0869 //         if(isTab && !isActiveTab)
0870 //             color.setAlphaF(0.45);
0871 //         painter->setPen(color);
0872         painter->setPen(isTab && !isActiveTab ? blendColors(color, bgnd, 0.45) : color);
0873         painter->drawText(textRect, alignment, str);
0874 //         painter->setClipping(false);
0875     }
0876 
0877     if(showIcon && iconX>=0)
0878     {
0879 //         if(isModified(cap))
0880 //         {
0881 //             QPixmap mod=pix;
0882 //             KIconEffect::semiTransparent(mod);
0883 //             painter->drawPixmap(iconX, capRect.y()+((capRect.height()-pix.height())/2)+1+(isTab && !isActiveTab ? 1 : 0), mod);
0884 //         }
0885 //         else
0886             painter->drawPixmap(iconX, capRect.y()+((capRect.height()-pix.height())/2)+1+(isTab && !isActiveTab ? 1 : 0), pix);
0887     }
0888 }
0889 
0890 void QtCurveClient::updateWindowShape()
0891 {
0892     if (isMaximized()) {
0893         clearMask();
0894     } else {
0895         QRect r(Handler()->customShadows() ?
0896                 widget()->rect()
0897                 .adjusted(layoutMetric(LM_OuterPaddingLeft),
0898                           layoutMetric(LM_OuterPaddingTop),
0899                           -layoutMetric(LM_OuterPaddingRight),
0900                           compositingActive() ? 0 :
0901                           -layoutMetric(LM_OuterPaddingBottom)) :
0902                 widget()->rect());
0903 
0904         setMask(getMask(Handler()->wStyle()->pixelMetric(
0905                             (QStyle::PixelMetric)QtC_Round, nullptr, nullptr), r));
0906     }
0907 }
0908 
0909 QRegion QtCurveClient::getMask(int round, const QRect &r) const
0910 {
0911     int x, y, w, h;
0912 
0913     r.getRect(&x, &y, &w, &h);
0914 
0915     switch(round)
0916     {
0917         case ROUND_NONE:
0918             return  QRegion(x, y, w, h);
0919         case ROUND_SLIGHT:
0920         {
0921             QRegion mask(x+1, y, w-2, h);
0922             mask += QRegion(x, y+1, 1, h-2);
0923             mask += QRegion(x+w-1, y+1, 1, h-2);
0924 
0925             return mask;
0926         }
0927         default: // ROUND_FULL
0928         {
0929             bool    roundBottom=!isShade() && Handler()->roundBottom();
0930 
0931 // #if KDE_IS_VERSION(4, 3, 0)
0932 //             if(!isPreview() && COMPOSITING_ENABLED)
0933 //             {
0934 //                 QRegion mask(x+4, y, w-8, h);
0935 //
0936 //                 if(roundBottom)
0937 //                 {
0938 //                     mask += QRegion(x, y+4, 1, h-8);
0939 //                     mask += QRegion(x+1, y+2, 1, h-4);
0940 //                     mask += QRegion(x+2, y+1, 1, h-2);
0941 //                     mask += QRegion(x+3, y+1, 1, h-2);
0942 //                     mask += QRegion(x+w-1, y+4, 1, h-8);
0943 //                     mask += QRegion(x+w-2, y+2, 1, h-4);
0944 //                     mask += QRegion(x+w-3, y+1, 1, h-2);
0945 //                     mask += QRegion(x+w-4, y+1, 1, h-2);
0946 //                 }
0947 //                 else
0948 //                 {
0949 //                     mask += QRegion(x, y+4, 1, h-4);
0950 //                     mask += QRegion(x+1, y+2, 1, h-1);
0951 //                     mask += QRegion(x+2, y+1, 1, h);
0952 //                     mask += QRegion(x+3, y+1, 1, h);
0953 //                     mask += QRegion(x+w-1, y+4, 1, h-4);
0954 //                     mask += QRegion(x+w-2, y+2, 1, h-1);
0955 //                     mask += QRegion(x+w-3, y+1, 1, h-0);
0956 //                     mask += QRegion(x+w-4, y+1, 1, h-0);
0957 //                 }
0958 //                 return mask;
0959 //             }
0960 //             else
0961 // #endif
0962             {
0963                 QRegion mask(x+5, y, w-10, h);
0964 
0965                 if(roundBottom)
0966                 {
0967                     mask += QRegion(x, y+5, 1, h-10);
0968                     mask += QRegion(x+1, y+3, 1, h-6);
0969                     mask += QRegion(x+2, y+2, 1, h-4);
0970                     mask += QRegion(x+3, y+1, 2, h-2);
0971                     mask += QRegion(x+w-1, y+5, 1, h-10);
0972                     mask += QRegion(x+w-2, y+3, 1, h-6);
0973                     mask += QRegion(x+w-3, y+2, 1, h-4);
0974                     mask += QRegion(x+w-5, y+1, 2, h-2);
0975                 }
0976                 else
0977                 {
0978                     mask += QRegion(x, y+5, 1, h-5);
0979                     mask += QRegion(x+1, y+3, 1, h-3);
0980                     mask += QRegion(x+2, y+2, 1, h-2);
0981                     mask += QRegion(x+3, y+1, 2, h-1);
0982                     mask += QRegion(x+w-1, y+5, 1, h-5);
0983                     mask += QRegion(x+w-2, y+3, 1, h-3);
0984                     mask += QRegion(x+w-3, y+2, 1, h-2);
0985                     mask += QRegion(x+w-5, y+1, 2, h-1);
0986                 }
0987                 return mask;
0988             }
0989         }
0990     }
0991 
0992     return QRegion();
0993 }
0994 
0995 bool QtCurveClient::onlyMenuIcon(bool left) const
0996 {
0997     return QLatin1String("M")==
0998                 (left
0999                     ? (options()->customButtonPositions() ? options()->titleButtonsLeft() : defaultButtonsLeft())
1000                     : (options()->customButtonPositions() ? options()->titleButtonsRight() : defaultButtonsRight()));
1001 }
1002 
1003 QRect QtCurveClient::captionRect() const
1004 {
1005     QRect     r(widget()->rect());
1006     const int titleHeight(layoutMetric(LM_TitleHeight)),
1007               titleEdgeTop(layoutMetric(LM_TitleEdgeTop)),
1008               titleEdgeLeft(layoutMetric(LM_TitleEdgeLeft)),
1009               marginLeft(layoutMetric(LM_TitleBorderLeft)),
1010               marginRight(layoutMetric(LM_TitleBorderRight)),
1011               titleLeft(r.left() + titleEdgeLeft + buttonsLeftWidth() + marginLeft),
1012               titleWidth(r.width() -
1013                            titleEdgeLeft - layoutMetric(LM_TitleEdgeRight) -
1014                            buttonsLeftWidth() - buttonsRightWidth() -
1015                            marginLeft - marginRight);
1016     if (Handler()->customShadows()) {
1017         int shadowSize = Handler()->shadowCache().shadowSize();
1018         return QRect(titleLeft + shadowSize,
1019                      r.top() + titleEdgeTop + shadowSize,
1020                      titleWidth - shadowSize * 2, titleHeight);
1021     }
1022     return QRect(titleLeft, r.top() + titleEdgeTop, titleWidth, titleHeight);
1023 }
1024 
1025 void QtCurveClient::updateCaption()
1026 {
1027     QRect oldCaptionRect(m_captionRect);
1028 
1029     m_captionRect=QtCurveClient::captionRect();
1030 
1031     if (oldCaptionRect.isValid() && m_captionRect.isValid())
1032         widget()->update(oldCaptionRect|m_captionRect);
1033     else
1034         widget()->update();
1035 }
1036 
1037 bool QtCurveClient::eventFilter(QObject *o, QEvent *e)
1038 {
1039     if (e->type() == QEvent::StyleChange) {
1040         Handler()->setStyle();
1041     }
1042 
1043     // if (widget() == o) {
1044     //     if (m_toggleMenuBarButton || m_toggleStatusBarButton)
1045     //         switch (e->type()) {
1046     //         case QEvent::Enter:
1047     //             m_hover = true;
1048     //             widget()->update();
1049     //             break;
1050     //         case QEvent::Leave:
1051     //             m_hover = false;
1052     //             widget()->update();
1053     //         default:
1054     //             break;
1055     //         }
1056     //     return true;
1057     // }
1058 
1059     return KCommonDecoration::eventFilter(o, e);
1060 }
1061 
1062 void QtCurveClient::reset(unsigned long changed)
1063 {
1064     if (changed & (SettingColors | SettingFont | SettingBorder)) {
1065         // Reset button backgrounds...
1066         for(int i=0; i<constNumButtonStates; ++i)
1067            m_buttonBackground[i].pix=QPixmap();
1068     }
1069 
1070     if (changed&SettingBorder)
1071     {
1072         if (maximizeMode()==MaximizeFull)
1073         {
1074             if (!options()->moveResizeMaximizedWindows() && m_resizeGrip)
1075                 m_resizeGrip->hide();
1076         }
1077         else if (m_resizeGrip)
1078                 m_resizeGrip->show();
1079     }
1080 
1081     if (changed&SettingColors)
1082     {
1083         // repaint the whole thing
1084         widget()->update();
1085         updateButtons();
1086     }
1087     else if (changed&SettingFont)
1088     {
1089         // font has changed -- update title height and font
1090         m_titleFont=isToolWindow() ? Handler()->titleFontTool() : Handler()->titleFont();
1091 
1092         updateLayout();
1093         widget()->update();
1094     }
1095 
1096     if(Handler()->showResizeGrip())
1097         createSizeGrip();
1098     else
1099         deleteSizeGrip();
1100 
1101     KCommonDecoration::reset(changed);
1102 }
1103 
1104 void QtCurveClient::createSizeGrip()
1105 {
1106     if(!m_resizeGrip && ((isResizable() && 0!=windowId()) || isPreview()))
1107     {
1108         m_resizeGrip=new QtCurveSizeGrip(this);
1109         m_resizeGrip->setVisible(!(isMaximized() || isShade()));
1110     }
1111 }
1112 
1113 void QtCurveClient::deleteSizeGrip()
1114 {
1115     if(m_resizeGrip)
1116     {
1117         delete m_resizeGrip;
1118         m_resizeGrip=0L;
1119     }
1120 }
1121 
1122 void QtCurveClient::informAppOfBorderSizeChanges()
1123 {
1124     union {
1125         char _buff[32];
1126         xcb_client_message_event_t ev;
1127     } buff;
1128     xcb_client_message_event_t *xev = &buff.ev;
1129     xev->response_type = XCB_CLIENT_MESSAGE;
1130     xev->format = 32;
1131     xev->window = windowId();
1132     xev->type = qtc_x11_qtc_titlebar_size;
1133     xev->data.data32[0] = 0;
1134     qtcX11SendEvent(false, windowId(), XCB_EVENT_MASK_NO_EVENT, xev);
1135     qtcX11Flush();
1136 }
1137 
1138 void QtCurveClient::informAppOfActiveChange()
1139 {
1140     if (Handler()->wStyle()->pixelMetric(
1141             (QStyle::PixelMetric)QtC_ShadeMenubarOnlyWhenActive, nullptr, nullptr)) {
1142         union {
1143             char _buff[32];
1144             xcb_client_message_event_t ev;
1145         } buff;
1146         xcb_client_message_event_t *xev = &buff.ev;
1147         xev->response_type = XCB_CLIENT_MESSAGE;
1148         xev->format = 32;
1149         xev->window = windowId();
1150         xev->type = qtc_x11_qtc_active_window;
1151         xev->data.data32[0] = isActive() ? 1 : 0;
1152         qtcX11SendEvent(false, windowId(), XCB_EVENT_MASK_NO_EVENT, xev);
1153         qtcX11Flush();
1154     }
1155 }
1156 
1157 void QtCurveClient::sendToggleToApp(bool menubar)
1158 {
1159     // if (Handler()->wStyle()->pixelMetric(
1160     //         (QStyle::PixelMetric)QtC_ShadeMenubarOnlyWhenActive, nullptr, nullptr))
1161     {
1162         union {
1163             char _buff[32];
1164             xcb_client_message_event_t ev;
1165         } buff;
1166         xcb_client_message_event_t *xev = &buff.ev;
1167         xev->response_type = XCB_CLIENT_MESSAGE;
1168         xev->format = 32;
1169         xev->window = windowId();
1170         xev->type = (menubar ? qtc_x11_qtc_toggle_menubar :
1171                      qtc_x11_qtc_toggle_statusbar);
1172         xev->data.data32[0] = 0;
1173         qtcX11SendEvent(false, windowId(), XCB_EVENT_MASK_NO_EVENT, xev);
1174         qtcX11Flush();
1175         if (menubar) {
1176             Handler()->emitToggleMenuBar(windowId());
1177         } else {
1178             Handler()->emitToggleStatusBar(windowId());
1179         }
1180     }
1181 }
1182 
1183 const QString & QtCurveClient::windowClass()
1184 {
1185     if (m_windowClass.isEmpty()) {
1186         KWindowInfo info(windowId(), NET::WMWindowType,
1187                          NET::WM2WindowClass | NET::WM2WindowRole);
1188 
1189         switch (info.windowType((int)NET::AllTypesMask)) {
1190             case NET::Dialog:
1191                 m_windowClass="D "+info.windowClassName()+' '+info.windowClassClass()+' '+info.windowRole();
1192                 break;
1193             case NET::Normal:
1194                 m_windowClass="W "+info.windowClassName()+' '+info.windowClassClass()+' '+info.windowRole();
1195                 break;
1196             default:
1197                 m_windowClass="<>";
1198                 break;
1199         }
1200     }
1201 
1202     return m_windowClass;
1203 }
1204 
1205 void QtCurveClient::menuBarSize(int size)
1206 {
1207     m_menuBarSize=size;
1208     if(Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_ToggleButtons, nullptr, nullptr) &0x01)
1209     {
1210         if(!m_toggleMenuBarButton)
1211             m_toggleMenuBarButton=createToggleButton(true);
1212         //if(m_toggleMenuBarButton)
1213         //    m_toggleMenuBarButton->setChecked(m_menuBarSize>0);
1214     }
1215     KCommonDecoration::activeChange();
1216 }
1217 
1218 void QtCurveClient::statusBarState(bool state)
1219 {
1220     Q_UNUSED(state)
1221     if (Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_ToggleButtons, nullptr, nullptr) &0x02) {
1222         if(!m_toggleStatusBarButton)
1223             m_toggleStatusBarButton=createToggleButton(false);
1224         //if(m_toggleStatusBarButton)
1225         //    m_toggleStatusBarButton->setChecked(state);
1226     }
1227     KCommonDecoration::activeChange();
1228 }
1229 
1230 void QtCurveClient::toggleMenuBar()
1231 {
1232     sendToggleToApp(true);
1233 }
1234 
1235 void QtCurveClient::toggleStatusBar()
1236 {
1237     sendToggleToApp(false);
1238 }
1239 
1240 QtCurveToggleButton*
1241 QtCurveClient::createToggleButton(bool menubar)
1242 {
1243     QtCurveToggleButton *button = new QtCurveToggleButton(menubar, this);
1244     int size = layoutMetric(LM_TitleHeight) - 6;
1245 
1246     button->setFixedSize(size, size);
1247     // button->setCheckable(true);
1248     // button->setChecked(false);
1249     connect(button, SIGNAL(clicked()),
1250             menubar ? SLOT(toggleMenuBar()) : SLOT(toggleStatusBar()));
1251     // widget()->setAttribute(Qt::WA_Hover, true);
1252     // widget()->installEventFilter(this);
1253     return button;
1254 }
1255 
1256 }
1257 }