File indexing completed on 2024-05-19 09:43:12
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(nullptr), 0206 m_titleFont(QFont()), 0207 m_menuBarSize(-1), 0208 m_toggleMenuBarButton(nullptr), 0209 m_toggleStatusBarButton(nullptr) 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, nullptr, nullptr)); 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, nullptr, nullptr), 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, nullptr, nullptr); 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, nullptr, nullptr)); 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, nullptr, nullptr)); 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, nullptr, nullptr)), 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 delete m_resizeGrip; 1117 m_resizeGrip = nullptr; 1118 } 1119 } 1120 1121 void QtCurveClient::informAppOfBorderSizeChanges() 1122 { 1123 union { 1124 char _buff[32]; 1125 xcb_client_message_event_t ev; 1126 } buff; 1127 xcb_client_message_event_t *xev = &buff.ev; 1128 xev->response_type = XCB_CLIENT_MESSAGE; 1129 xev->format = 32; 1130 xev->window = windowId(); 1131 xev->type = qtc_x11_qtc_titlebar_size; 1132 xev->data.data32[0] = 0; 1133 qtcX11SendEvent(false, windowId(), XCB_EVENT_MASK_NO_EVENT, xev); 1134 qtcX11Flush(); 1135 } 1136 1137 void QtCurveClient::informAppOfActiveChange() 1138 { 1139 if (Handler()->wStyle()->pixelMetric( 1140 (QStyle::PixelMetric)QtC_ShadeMenubarOnlyWhenActive, nullptr, nullptr)) { 1141 union { 1142 char _buff[32]; 1143 xcb_client_message_event_t ev; 1144 } buff; 1145 xcb_client_message_event_t *xev = &buff.ev; 1146 xev->response_type = XCB_CLIENT_MESSAGE; 1147 xev->format = 32; 1148 xev->window = windowId(); 1149 xev->type = qtc_x11_qtc_active_window; 1150 xev->data.data32[0] = isActive() ? 1 : 0; 1151 qtcX11SendEvent(false, windowId(), XCB_EVENT_MASK_NO_EVENT, xev); 1152 qtcX11Flush(); 1153 } 1154 } 1155 1156 void QtCurveClient::sendToggleToApp(bool menubar) 1157 { 1158 // if (Handler()->wStyle()->pixelMetric( 1159 // (QStyle::PixelMetric)QtC_ShadeMenubarOnlyWhenActive, nullptr, nullptr)) 1160 { 1161 union { 1162 char _buff[32]; 1163 xcb_client_message_event_t ev; 1164 } buff; 1165 xcb_client_message_event_t *xev = &buff.ev; 1166 xev->response_type = XCB_CLIENT_MESSAGE; 1167 xev->format = 32; 1168 xev->window = windowId(); 1169 xev->type = (menubar ? qtc_x11_qtc_toggle_menubar : 1170 qtc_x11_qtc_toggle_statusbar); 1171 xev->data.data32[0] = 0; 1172 qtcX11SendEvent(false, windowId(), XCB_EVENT_MASK_NO_EVENT, xev); 1173 qtcX11Flush(); 1174 if (menubar) { 1175 Handler()->emitToggleMenuBar(windowId()); 1176 } else { 1177 Handler()->emitToggleStatusBar(windowId()); 1178 } 1179 } 1180 } 1181 1182 const QString & QtCurveClient::windowClass() 1183 { 1184 if (m_windowClass.isEmpty()) { 1185 KWindowInfo info(windowId(), NET::WMWindowType, 1186 NET::WM2WindowClass | NET::WM2WindowRole); 1187 1188 switch (info.windowType((int)NET::AllTypesMask)) { 1189 case NET::Dialog: 1190 m_windowClass="D "+info.windowClassName()+' '+info.windowClassClass()+' '+info.windowRole(); 1191 break; 1192 case NET::Normal: 1193 m_windowClass="W "+info.windowClassName()+' '+info.windowClassClass()+' '+info.windowRole(); 1194 break; 1195 default: 1196 m_windowClass="<>"; 1197 break; 1198 } 1199 } 1200 1201 return m_windowClass; 1202 } 1203 1204 void QtCurveClient::menuBarSize(int size) 1205 { 1206 m_menuBarSize=size; 1207 if(Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_ToggleButtons, nullptr, nullptr) &0x01) 1208 { 1209 if(!m_toggleMenuBarButton) 1210 m_toggleMenuBarButton=createToggleButton(true); 1211 //if(m_toggleMenuBarButton) 1212 // m_toggleMenuBarButton->setChecked(m_menuBarSize>0); 1213 } 1214 KCommonDecoration::activeChange(); 1215 } 1216 1217 void QtCurveClient::statusBarState(bool state) 1218 { 1219 Q_UNUSED(state) 1220 if(Handler()->wStyle()->pixelMetric((QStyle::PixelMetric)QtC_ToggleButtons, nullptr, nullptr) &0x02) 1221 { 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 }