From 6374f08355ef7208ad956c49457cce7635f11ee4 Mon Sep 17 00:00:00 2001 From: Markus Meik Slopianka Date: Sun, 25 Jul 2010 14:19:05 +0000 Subject: [PATCH] revert. sorry svn path=/trunk/KDE/kdebase/workspace/; revision=1154460 --- clients/kde2/CMakeLists.txt | 16 + clients/kde2/config/CMakeLists.txt | 16 + clients/kde2/config/config.cpp | 150 ++ clients/kde2/config/config.h | 64 + clients/kde2/kde2.cpp | 1093 ++++++++++ clients/kde2/kde2.desktop | 91 + clients/kde2/kde2.h | 110 + clients/keramik/CMakeLists.txt | 15 + clients/keramik/config/CMakeLists.txt | 18 + clients/keramik/config/config.cpp | 112 + clients/keramik/config/config.h | 67 + clients/keramik/config/keramikconfig.ui | 61 + clients/keramik/keramik.cpp | 1818 +++++++++++++++++ clients/keramik/keramik.desktop | 91 + clients/keramik/keramik.h | 198 ++ clients/keramik/pics/border-left.png | Bin 0 -> 126 bytes clients/keramik/pics/border-right.png | Bin 0 -> 127 bytes clients/keramik/pics/bottom-center.png | Bin 0 -> 131 bytes clients/keramik/pics/bottom-left.png | Bin 0 -> 134 bytes clients/keramik/pics/bottom-right.png | Bin 0 -> 135 bytes clients/keramik/pics/caption-large-center.png | Bin 0 -> 171 bytes clients/keramik/pics/caption-large-left.png | Bin 0 -> 379 bytes clients/keramik/pics/caption-large-right.png | Bin 0 -> 489 bytes clients/keramik/pics/caption-small-center.png | Bin 0 -> 173 bytes clients/keramik/pics/caption-small-left.png | Bin 0 -> 415 bytes clients/keramik/pics/caption-small-right.png | Bin 0 -> 486 bytes clients/keramik/pics/grabbar-center.png | Bin 0 -> 145 bytes clients/keramik/pics/grabbar-left.png | Bin 0 -> 166 bytes clients/keramik/pics/grabbar-right.png | Bin 0 -> 164 bytes clients/keramik/pics/titlebar-center.png | Bin 0 -> 150 bytes clients/keramik/pics/titlebar-left.png | Bin 0 -> 220 bytes clients/keramik/pics/titlebar-right.png | Bin 0 -> 280 bytes .../keramik/pics/titlebutton-round-huge.png | Bin 0 -> 7386 bytes .../keramik/pics/titlebutton-round-large.png | Bin 0 -> 4178 bytes clients/keramik/pics/titlebutton-round.png | Bin 0 -> 1412 bytes .../keramik/pics/titlebutton-square-huge.png | Bin 0 -> 4339 bytes .../keramik/pics/titlebutton-square-large.png | Bin 0 -> 2610 bytes clients/keramik/pics/titlebutton-square.png | Bin 0 -> 1052 bytes clients/keramik/tiles.qrc | 27 + clients/kwmtheme/CMakeLists.txt | 25 + clients/kwmtheme/cli_installer/CMakeLists.txt | 14 + clients/kwmtheme/cli_installer/main.cpp | 178 ++ clients/kwmtheme/kwmtheme.desktop | 89 + clients/kwmtheme/kwmthemeclient.cpp | 951 +++++++++ clients/kwmtheme/kwmthemeclient.h | 88 + clients/kwmtheme/pics/CMakeLists.txt | 3 + clients/kwmtheme/pics/bluesun.png | Bin 0 -> 1127 bytes clients/kwmtheme/pics/close.png | Bin 0 -> 285 bytes clients/kwmtheme/pics/fog-grey.png | Bin 0 -> 2922 bytes clients/kwmtheme/pics/fog.png | Bin 0 -> 2760 bytes clients/kwmtheme/pics/greenie.dim.png | Bin 0 -> 3892 bytes clients/kwmtheme/pics/greenie.light.png | Bin 0 -> 3837 bytes clients/kwmtheme/pics/iconify.png | Bin 0 -> 262 bytes clients/kwmtheme/pics/maximize.png | Bin 0 -> 269 bytes clients/kwmtheme/pics/maximizedown.png | Bin 0 -> 269 bytes clients/kwmtheme/pics/menu.png | Bin 0 -> 263 bytes clients/kwmtheme/pics/pindown.png | Bin 0 -> 297 bytes clients/kwmtheme/pics/pinup.png | Bin 0 -> 295 bytes clients/kwmtheme/pics/unknown.png | Bin 0 -> 454 bytes clients/modernsystem/CMakeLists.txt | 18 + clients/modernsystem/btnhighcolor.h | 117 ++ clients/modernsystem/buttondata.h | 65 + clients/modernsystem/config/CMakeLists.txt | 16 + clients/modernsystem/config/config.cpp | 157 ++ clients/modernsystem/config/config.h | 70 + clients/modernsystem/modernsys.cpp | 821 ++++++++ clients/modernsystem/modernsys.h | 89 + clients/modernsystem/modernsystem.desktop | 88 + clients/quartz/CMakeLists.txt | 17 + clients/quartz/config/CMakeLists.txt | 16 + clients/quartz/config/config.cpp | 120 ++ clients/quartz/config/config.h | 61 + clients/quartz/quartz.cpp | 849 ++++++++ clients/quartz/quartz.desktop | 89 + clients/quartz/quartz.h | 105 + clients/redmond/CMakeLists.txt | 11 + clients/redmond/redmond.cpp | 711 +++++++ clients/redmond/redmond.desktop | 90 + clients/redmond/redmond.h | 103 + clients/test/CMakeLists.txt | 21 + clients/test/test.cpp | 361 ++++ clients/test/test.desktop | 87 + clients/test/test.h | 67 + clients/web/CMakeLists.txt | 22 + clients/web/Web.cpp | 402 ++++ clients/web/Web.h | 84 + clients/web/WebButton.cpp | 303 +++ clients/web/WebButton.h | 71 + clients/web/web.desktop | 90 + 89 files changed, 10416 insertions(+) create mode 100644 clients/kde2/CMakeLists.txt create mode 100644 clients/kde2/config/CMakeLists.txt create mode 100644 clients/kde2/config/config.cpp create mode 100644 clients/kde2/config/config.h create mode 100644 clients/kde2/kde2.cpp create mode 100644 clients/kde2/kde2.desktop create mode 100644 clients/kde2/kde2.h create mode 100644 clients/keramik/CMakeLists.txt create mode 100644 clients/keramik/config/CMakeLists.txt create mode 100644 clients/keramik/config/config.cpp create mode 100644 clients/keramik/config/config.h create mode 100644 clients/keramik/config/keramikconfig.ui create mode 100644 clients/keramik/keramik.cpp create mode 100644 clients/keramik/keramik.desktop create mode 100644 clients/keramik/keramik.h create mode 100644 clients/keramik/pics/border-left.png create mode 100644 clients/keramik/pics/border-right.png create mode 100644 clients/keramik/pics/bottom-center.png create mode 100644 clients/keramik/pics/bottom-left.png create mode 100644 clients/keramik/pics/bottom-right.png create mode 100644 clients/keramik/pics/caption-large-center.png create mode 100644 clients/keramik/pics/caption-large-left.png create mode 100644 clients/keramik/pics/caption-large-right.png create mode 100644 clients/keramik/pics/caption-small-center.png create mode 100644 clients/keramik/pics/caption-small-left.png create mode 100644 clients/keramik/pics/caption-small-right.png create mode 100644 clients/keramik/pics/grabbar-center.png create mode 100644 clients/keramik/pics/grabbar-left.png create mode 100644 clients/keramik/pics/grabbar-right.png create mode 100644 clients/keramik/pics/titlebar-center.png create mode 100644 clients/keramik/pics/titlebar-left.png create mode 100644 clients/keramik/pics/titlebar-right.png create mode 100644 clients/keramik/pics/titlebutton-round-huge.png create mode 100644 clients/keramik/pics/titlebutton-round-large.png create mode 100644 clients/keramik/pics/titlebutton-round.png create mode 100644 clients/keramik/pics/titlebutton-square-huge.png create mode 100644 clients/keramik/pics/titlebutton-square-large.png create mode 100644 clients/keramik/pics/titlebutton-square.png create mode 100644 clients/keramik/tiles.qrc create mode 100644 clients/kwmtheme/CMakeLists.txt create mode 100644 clients/kwmtheme/cli_installer/CMakeLists.txt create mode 100644 clients/kwmtheme/cli_installer/main.cpp create mode 100644 clients/kwmtheme/kwmtheme.desktop create mode 100644 clients/kwmtheme/kwmthemeclient.cpp create mode 100644 clients/kwmtheme/kwmthemeclient.h create mode 100644 clients/kwmtheme/pics/CMakeLists.txt create mode 100644 clients/kwmtheme/pics/bluesun.png create mode 100644 clients/kwmtheme/pics/close.png create mode 100644 clients/kwmtheme/pics/fog-grey.png create mode 100644 clients/kwmtheme/pics/fog.png create mode 100644 clients/kwmtheme/pics/greenie.dim.png create mode 100644 clients/kwmtheme/pics/greenie.light.png create mode 100644 clients/kwmtheme/pics/iconify.png create mode 100644 clients/kwmtheme/pics/maximize.png create mode 100644 clients/kwmtheme/pics/maximizedown.png create mode 100644 clients/kwmtheme/pics/menu.png create mode 100644 clients/kwmtheme/pics/pindown.png create mode 100644 clients/kwmtheme/pics/pinup.png create mode 100644 clients/kwmtheme/pics/unknown.png create mode 100644 clients/modernsystem/CMakeLists.txt create mode 100644 clients/modernsystem/btnhighcolor.h create mode 100644 clients/modernsystem/buttondata.h create mode 100644 clients/modernsystem/config/CMakeLists.txt create mode 100644 clients/modernsystem/config/config.cpp create mode 100644 clients/modernsystem/config/config.h create mode 100644 clients/modernsystem/modernsys.cpp create mode 100644 clients/modernsystem/modernsys.h create mode 100644 clients/modernsystem/modernsystem.desktop create mode 100644 clients/quartz/CMakeLists.txt create mode 100644 clients/quartz/config/CMakeLists.txt create mode 100644 clients/quartz/config/config.cpp create mode 100644 clients/quartz/config/config.h create mode 100644 clients/quartz/quartz.cpp create mode 100644 clients/quartz/quartz.desktop create mode 100644 clients/quartz/quartz.h create mode 100644 clients/redmond/CMakeLists.txt create mode 100644 clients/redmond/redmond.cpp create mode 100644 clients/redmond/redmond.desktop create mode 100644 clients/redmond/redmond.h create mode 100644 clients/test/CMakeLists.txt create mode 100644 clients/test/test.cpp create mode 100644 clients/test/test.desktop create mode 100644 clients/test/test.h create mode 100644 clients/web/CMakeLists.txt create mode 100644 clients/web/Web.cpp create mode 100644 clients/web/Web.h create mode 100644 clients/web/WebButton.cpp create mode 100644 clients/web/WebButton.h create mode 100644 clients/web/web.desktop diff --git a/clients/kde2/CMakeLists.txt b/clients/kde2/CMakeLists.txt new file mode 100644 index 0000000000..b1d9a5b217 --- /dev/null +++ b/clients/kde2/CMakeLists.txt @@ -0,0 +1,16 @@ + +add_subdirectory( config ) + +########### next target ############### + +set(kwin3_kde2_PART_SRCS kde2.cpp) + + +kde4_add_plugin(kwin3_kde2 ${kwin3_kde2_PART_SRCS}) + +target_link_libraries(kwin3_kde2 kdecorations ${QT_QTGUI_LIBRARY}) + +install(TARGETS kwin3_kde2 DESTINATION ${PLUGIN_INSTALL_DIR}) + +install( FILES kde2.desktop DESTINATION ${DATA_INSTALL_DIR}/kwin/ ) + diff --git a/clients/kde2/config/CMakeLists.txt b/clients/kde2/config/CMakeLists.txt new file mode 100644 index 0000000000..d31c9fc1ab --- /dev/null +++ b/clients/kde2/config/CMakeLists.txt @@ -0,0 +1,16 @@ + + + +########### next target ############### + +set(kwin_kde2_config_PART_SRCS config.cpp ) + + +kde4_add_plugin(kwin_kde2_config ${kwin_kde2_config_PART_SRCS}) + + + +target_link_libraries(kwin_kde2_config ${KDE4_KDEUI_LIBS} ${QT_QTGUI_LIBRARY}) + +install(TARGETS kwin_kde2_config DESTINATION ${PLUGIN_INSTALL_DIR} ) + diff --git a/clients/kde2/config/config.cpp b/clients/kde2/config/config.cpp new file mode 100644 index 0000000000..1844b8d451 --- /dev/null +++ b/clients/kde2/config/config.cpp @@ -0,0 +1,150 @@ +/********************************************************************* + + KDE2 Default configuration widget + + Copyright (c) 2001 + Karol Szwed + http://gallium.n3.net/ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#include "config.h" + +#include +#include + +#include +#include +#include +#include + +extern "C" +{ + KDE_EXPORT QObject* allocate_config( KConfig* conf, QWidget* parent ) + { + return(new KDE2Config(conf, parent)); + } +} + +// NOTE: +// 'conf' is a pointer to the kwindecoration modules open kwin config, +// and is by default set to the "Style" group. +// 'parent' is the parent of the QObject, which is a VBox inside the +// Configure tab in kwindecoration + +KDE2Config::KDE2Config( KConfig* conf, QWidget* parent ) + : QObject( parent ) +{ + Q_UNUSED( conf ); + KGlobal::locale()->insertCatalog("kwin_clients"); + c = new KConfig("kwinKDE2rc"); + highcolor = QPixmap::defaultDepth() > 8; + gb = new KVBox( parent ); + gb->setSpacing( KDialog::spacingHint() ); + + cbShowStipple = new QCheckBox( i18n("Draw titlebar &stipple effect"), gb ); + cbShowStipple->setWhatsThis( + i18n("When selected, active titlebars are drawn " + "with a stipple (dotted) effect; otherwise, they are " + "drawn without the stipple.")); + + cbShowGrabBar = new QCheckBox( i18n("Draw g&rab bar below windows"), gb ); + cbShowGrabBar->setWhatsThis( + i18n("When selected, decorations are drawn with a \"grab bar\" " + "below windows; otherwise, no grab bar is drawn.")); + + // Only show the gradient checkbox for highcolor displays + if (highcolor) + { + cbUseGradients = new QCheckBox( i18n("Draw &gradients"), gb ); + cbUseGradients->setWhatsThis( + i18n("When selected, decorations are drawn with gradients " + "for high-color displays; otherwise, no gradients are drawn.") ); + } + + // Ensure we track user changes properly + connect( cbShowStipple, SIGNAL(clicked()), + this, SLOT(slotSelectionChanged()) ); + connect( cbShowGrabBar, SIGNAL(clicked()), + this, SLOT(slotSelectionChanged()) ); + if (highcolor) + connect( cbUseGradients, SIGNAL(clicked()), + this, SLOT(slotSelectionChanged()) ); + + // Load configuration options + load( KConfigGroup() ); + + // Make the widgets visible in kwindecoration + gb->show(); +} + + +KDE2Config::~KDE2Config() +{ + delete gb; + delete c; +} + + +void KDE2Config::slotSelectionChanged() +{ + emit changed(); +} + + +// Loads the configurable options from the kwinrc config file +// It is passed the open config from kwindecoration to improve efficiency +void KDE2Config::load( const KConfigGroup& ) +{ + KConfigGroup cg(c, "General"); + bool override = cg.readEntry( "ShowTitleBarStipple", true); + cbShowStipple->setChecked( override ); + + override = cg.readEntry( "ShowGrabBar", true); + cbShowGrabBar->setChecked( override ); + + if (highcolor) { + override = cg.readEntry( "UseGradients", true); + cbUseGradients->setChecked( override ); + } +} + + +// Saves the configurable options to the kwinrc config file +void KDE2Config::save( KConfigGroup& ) +{ + KConfigGroup cg(c, "General"); + cg.writeEntry( "ShowTitleBarStipple", cbShowStipple->isChecked() ); + cg.writeEntry( "ShowGrabBar", cbShowGrabBar->isChecked() ); + + if (highcolor) + cg.writeEntry( "UseGradients", cbUseGradients->isChecked() ); + // No need to conf->sync() - kwindecoration will do it for us +} + + +// Sets UI widget defaults which must correspond to style defaults +void KDE2Config::defaults() +{ + cbShowStipple->setChecked( true ); + cbShowGrabBar->setChecked( true ); + + if (highcolor) + cbUseGradients->setChecked( true ); +} + +#include "config.moc" +// vim: ts=4 +// kate: space-indent off; tab-width 4; diff --git a/clients/kde2/config/config.h b/clients/kde2/config/config.h new file mode 100644 index 0000000000..745e65b69d --- /dev/null +++ b/clients/kde2/config/config.h @@ -0,0 +1,64 @@ +/********************************************************************* + + KDE2 Default configuration widget + + Copyright (c) 2001 + Karol Szwed + http://gallium.n3.net/ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#ifndef KDE2_CONFIG_H +#define KDE2_CONFIG_H + +#include +#include +#include + +#include +#include + +class KDE2Config: public QObject +{ + Q_OBJECT + + public: + KDE2Config( KConfig* conf, QWidget* parent ); + ~KDE2Config(); + + // These public signals/slots work similar to KCM modules + signals: + void changed(); + + public slots: + void load( const KConfigGroup& conf ); + void save( KConfigGroup& conf ); + void defaults(); + + protected slots: + void slotSelectionChanged(); // Internal use + + private: + QCheckBox* cbShowStipple; + QCheckBox* cbShowGrabBar; + QCheckBox* cbUseGradients; + KVBox* gb; + KConfig *c; + bool highcolor; +}; + +#endif +// vim: ts=4 +// kate: space-indent off; tab-width 4; diff --git a/clients/kde2/kde2.cpp b/clients/kde2/kde2.cpp new file mode 100644 index 0000000000..33aaafd56c --- /dev/null +++ b/clients/kde2/kde2.cpp @@ -0,0 +1,1093 @@ +/********************************************************************* + + KDE2 Default KWin client + + Copyright (C) 1999, 2001 Daniel Duley + Matthias Ettrich + Karol Szwed + + Draws mini titlebars for tool windows. + Many features are now customizable. + + drawColorBitmaps originally from kdefx: + Copyright (C) 1999 Daniel M. Duley + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#include "kde2.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace KDE2 +{ + +static const unsigned char iconify_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, + 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char close_bits[] = { + 0x00, 0x00, 0x84, 0x00, 0xce, 0x01, 0xfc, 0x00, 0x78, 0x00, 0x78, 0x00, + 0xfc, 0x00, 0xce, 0x01, 0x84, 0x00, 0x00, 0x00}; + +static const unsigned char maximize_bits[] = { + 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, + 0x86, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00}; + +static const unsigned char minmax_bits[] = { + 0x7f, 0x00, 0x7f, 0x00, 0x63, 0x00, 0xfb, 0x03, 0xfb, 0x03, 0x1f, 0x03, + 0x1f, 0x03, 0x18, 0x03, 0xf8, 0x03, 0xf8, 0x03}; + +static const unsigned char question_bits[] = { + 0x00, 0x00, 0x78, 0x00, 0xcc, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00}; + +static const unsigned char above_on_bits[] = { + 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x30, 0x00, 0xfc, 0x00, 0x78, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +static const unsigned char above_off_bits[] = { + 0x30, 0x00, 0x78, 0x00, 0xfc, 0x00, 0x30, 0x00, 0xfe, 0x01, 0xfe, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +static const unsigned char below_on_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x78, 0x00, 0xfc, 0x00, + 0x30, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00 }; + +static const unsigned char below_off_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, + 0x30, 0x00, 0xfc, 0x00, 0x78, 0x00, 0x30, 0x00 }; + +static const unsigned char shade_on_bits[] = { + 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0xfe, 0x01, 0x00, 0x00 }; + +static const unsigned char shade_off_bits[] = { + 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +static const unsigned char pindown_white_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x1f, 0xa0, 0x03, + 0xb0, 0x01, 0x30, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char pindown_gray_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x80, 0x07, 0xc0, 0x03, 0xe0, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char pindown_dgray_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x10, 0x70, 0x20, 0x50, 0x20, + 0x48, 0x30, 0xc8, 0x38, 0x08, 0x1f, 0x08, 0x18, 0x10, 0x1c, 0x10, 0x0e, + 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char pindown_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x1f, 0xf0, 0x3f, 0xf0, 0x3f, + 0xf8, 0x3f, 0xf8, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf0, 0x1f, 0xf0, 0x0f, + 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char pinup_white_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x11, + 0x3f, 0x15, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char pinup_gray_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x0a, 0xbf, 0x0a, 0x80, 0x15, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char pinup_dgray_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x40, 0x31, 0x40, 0x2e, + 0x40, 0x20, 0x40, 0x20, 0x7f, 0x2a, 0x40, 0x3f, 0xc0, 0x31, 0xc0, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char pinup_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0xc0, 0x31, 0xc0, 0x3f, + 0xff, 0x3f, 0xff, 0x3f, 0xff, 0x3f, 0xc0, 0x3f, 0xc0, 0x31, 0xc0, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +void drawColorBitmaps(QPainter *p, const QPalette &pal, int x, int y, int w, int h, + const uchar *lightColor, const uchar *midColor, const uchar *blackColor) +{ + const uchar *data[]={lightColor, midColor, blackColor}; + + QColor colors[]={pal.color(QPalette::Light), pal.color(QPalette::Mid), Qt::black}; + + int i; + QSize s(w,h); + for(i=0; i < 3; ++i){ + QBitmap b = QBitmap::fromData(s, data[i], QImage::Format_MonoLSB ); + b.setMask(b); + p->setPen(colors[i]); + p->drawPixmap(x, y, b); + } +} + +// =========================================================================== + +static QPixmap* titlePix; +static QPixmap* titleBuffer; +static QPixmap* aUpperGradient; +static QPixmap* iUpperGradient; + +static QPixmap* pinDownPix; +static QPixmap* pinUpPix; +static QPixmap* ipinDownPix; +static QPixmap* ipinUpPix; + +static QPixmap* rightBtnUpPix[2]; +static QPixmap* rightBtnDownPix[2]; +static QPixmap* irightBtnUpPix[2]; +static QPixmap* irightBtnDownPix[2]; + +static QPixmap* leftBtnUpPix[2]; +static QPixmap* leftBtnDownPix[2]; +static QPixmap* ileftBtnUpPix[2]; +static QPixmap* ileftBtnDownPix[2]; + +static KDE2Handler* clientHandler; +static int toolTitleHeight; +static int normalTitleHeight; +static int borderWidth; +static int grabBorderWidth; +static bool KDE2_initialized = false; +static bool useGradients; +static bool showGrabBar; +static bool showTitleBarStipple; + + +// =========================================================================== + +KDE2Handler::KDE2Handler() +{ + clientHandler = this; + readConfig( false ); + createPixmaps(); + KDE2_initialized = true; +} + + +KDE2Handler::~KDE2Handler() +{ + KDE2_initialized = false; + freePixmaps(); + clientHandler = NULL; +} + +KDecoration* KDE2Handler::createDecoration( KDecorationBridge* b ) +{ + return ( new KDE2Client( b, this ))->decoration(); +} + +bool KDE2Handler::reset( unsigned long changed ) +{ + KDE2_initialized = false; + changed |= readConfig( true ); + if( changed & SettingColors ) + { // pixmaps need to be recreated + freePixmaps(); + createPixmaps(); + } + KDE2_initialized = true; + // SettingButtons is handled by KCommonDecoration + bool need_recreate = ( changed & ( SettingDecoration | SettingFont | SettingBorder )) != 0; + if( need_recreate ) // something else than colors changed + return true; + resetDecorations( changed ); + return false; +} + + +unsigned long KDE2Handler::readConfig( bool update ) +{ + unsigned long changed = 0; + KConfig c("kwinKDE2rc"); + KConfigGroup conf(&c, "General"); + + bool new_showGrabBar = conf.readEntry("ShowGrabBar", true); + bool new_showTitleBarStipple = conf.readEntry("ShowTitleBarStipple", true); + bool new_useGradients = conf.readEntry("UseGradients", true); + int new_titleHeight = QFontMetrics(options()->font(true)).height() - 2; + int new_toolTitleHeight = QFontMetrics(options()->font(true, true)).height() - 4; + + int new_borderWidth; + switch(options()->preferredBorderSize(this)) { + case BorderLarge: + new_borderWidth = 8; + break; + case BorderVeryLarge: + new_borderWidth = 12; + break; + case BorderHuge: + new_borderWidth = 18; + break; + case BorderVeryHuge: + new_borderWidth = 27; + break; + case BorderOversized: + new_borderWidth = 40; + break; + case BorderTiny: + case BorderNormal: + default: + new_borderWidth = 4; + } + + if (new_titleHeight < 16) new_titleHeight = 16; + if (new_titleHeight < new_borderWidth) new_titleHeight = new_borderWidth; + if (new_toolTitleHeight < 12) new_toolTitleHeight = 12; + if (new_toolTitleHeight < new_borderWidth) new_toolTitleHeight = new_borderWidth; + + if( update ) + { + if( new_showGrabBar != showGrabBar + || new_titleHeight != normalTitleHeight + || new_toolTitleHeight != toolTitleHeight + || new_borderWidth != borderWidth ) + changed |= SettingDecoration; // need recreating the decoration + if( new_showTitleBarStipple != showTitleBarStipple + || new_useGradients != useGradients + || new_titleHeight != normalTitleHeight + || new_toolTitleHeight != toolTitleHeight ) + changed |= SettingColors; // just recreate the pixmaps and repaint + } + + showGrabBar = new_showGrabBar; + showTitleBarStipple = new_showTitleBarStipple; + useGradients = new_useGradients; + normalTitleHeight = new_titleHeight; + toolTitleHeight = new_toolTitleHeight; + borderWidth = new_borderWidth; + grabBorderWidth = (borderWidth > 15) ? borderWidth + 15 : 2*borderWidth; + return changed; +} + +static void gradientFill(QPixmap *pixmap, const QColor &color1, const QColor &color2) +{ + QPainter p(pixmap); + QLinearGradient gradient(0, 0, 0, pixmap->height()); + gradient.setColorAt(0.0, color1); + gradient.setColorAt(1.0, color2); + QBrush brush(gradient); + p.fillRect(pixmap->rect(), brush); +} + +// This paints the button pixmaps upon loading the style. +void KDE2Handler::createPixmaps() +{ + bool highcolor = useGradients && (QPixmap::defaultDepth() > 8); + + // Make the titlebar stipple optional + if (showTitleBarStipple) + { + QPainter p; + QPainter maskPainter; + int i, x, y; + titlePix = new QPixmap(132, normalTitleHeight+2); + titlePix->fill( Qt::transparent ); + + QBitmap mask(132, normalTitleHeight+2); + mask.fill(Qt::color0); + + p.begin(titlePix); + maskPainter.begin(&mask); + maskPainter.setPen(Qt::color1); + for(i=0, y=2; i < 9; ++i, y+=4) + for(x=1; x <= 132; x+=3) + { + p.setPen(options()->color(ColorTitleBar, true).light(150)); + p.drawPoint(x, y); + maskPainter.drawPoint(x, y); + p.setPen(options()->color(ColorTitleBar, true).dark(150)); + p.drawPoint(x+1, y+1); + maskPainter.drawPoint(x+1, y+1); + } + maskPainter.end(); + p.end(); + titlePix->setMask(mask); + } else + titlePix = NULL; + + QColor activeTitleColor1(options()->color(ColorTitleBar, true)); + QColor activeTitleColor2(options()->color(ColorTitleBlend, true)); + + QColor inactiveTitleColor1(options()->color(ColorTitleBar, false)); + QColor inactiveTitleColor2(options()->color(ColorTitleBlend, false)); + + // Create titlebar gradient images if required + aUpperGradient = NULL; + iUpperGradient = NULL; + + if(highcolor) + { + QSize s(128, normalTitleHeight + 2); + // Create the titlebar gradients + if (activeTitleColor1 != activeTitleColor2) + { + + aUpperGradient = new QPixmap(s); + gradientFill(aUpperGradient, activeTitleColor1, activeTitleColor2); + } + + if (inactiveTitleColor1 != inactiveTitleColor2) + { + iUpperGradient = new QPixmap(s); + gradientFill(iUpperGradient, inactiveTitleColor1, inactiveTitleColor2); + } + } + + // Set the sticky pin pixmaps; + QPalette g; + QPainter p; + + // Active pins + g = options()->palette( ColorButtonBg, true ); + QImage pinUpImg = QImage(16, 16, QImage::Format_ARGB32_Premultiplied); + p.begin( &pinUpImg ); + drawColorBitmaps( &p, g, 0, 0, 16, 16, pinup_white_bits, pinup_gray_bits, pinup_dgray_bits ); + p.end(); + pinUpPix = new QPixmap(QPixmap::fromImage(pinUpImg)); + pinUpPix->setMask( QBitmap::fromData(QSize( 16, 16 ), pinup_mask_bits) ); + + QImage pinDownImg = QImage(16, 16, QImage::Format_ARGB32_Premultiplied); + p.begin( &pinDownImg ); + drawColorBitmaps( &p, g, 0, 0, 16, 16, pindown_white_bits, pindown_gray_bits, pindown_dgray_bits ); + p.end(); + pinDownPix = new QPixmap(QPixmap::fromImage(pinDownImg)); + pinDownPix->setMask( QBitmap::fromData(QSize( 16, 16 ), pindown_mask_bits) ); + + // Inactive pins + g = options()->palette( ColorButtonBg, false ); + QImage ipinUpImg = QImage(16, 16, QImage::Format_ARGB32_Premultiplied); + p.begin( &ipinUpImg ); + drawColorBitmaps( &p, g, 0, 0, 16, 16, pinup_white_bits, pinup_gray_bits, pinup_dgray_bits ); + p.end(); + ipinUpPix = new QPixmap(QPixmap::fromImage(ipinUpImg)); + ipinUpPix->setMask( QBitmap::fromData(QSize( 16, 16 ), pinup_mask_bits) ); + + QImage ipinDownImg = QImage(16, 16, QImage::Format_ARGB32_Premultiplied); + p.begin( &ipinDownImg ); + drawColorBitmaps( &p, g, 0, 0, 16, 16, pindown_white_bits, pindown_gray_bits, pindown_dgray_bits ); + p.end(); + ipinDownPix = new QPixmap(QPixmap::fromImage(ipinDownImg)); + ipinDownPix->setMask( QBitmap::fromData(QSize( 16, 16 ), pindown_mask_bits) ); + + // Create a title buffer for flicker-free painting + titleBuffer = new QPixmap(); + + // Cache all possible button states + leftBtnUpPix[true] = new QPixmap(normalTitleHeight, normalTitleHeight); + leftBtnDownPix[true] = new QPixmap(normalTitleHeight, normalTitleHeight); + ileftBtnUpPix[true] = new QPixmap(normalTitleHeight, normalTitleHeight); + ileftBtnDownPix[true] = new QPixmap(normalTitleHeight, normalTitleHeight); + + rightBtnUpPix[true] = new QPixmap(normalTitleHeight, normalTitleHeight); + rightBtnDownPix[true] = new QPixmap(normalTitleHeight, normalTitleHeight); + irightBtnUpPix[true] = new QPixmap(normalTitleHeight, normalTitleHeight); + irightBtnDownPix[true] = new QPixmap(normalTitleHeight, normalTitleHeight); + + leftBtnUpPix[false] = new QPixmap(toolTitleHeight, normalTitleHeight); + leftBtnDownPix[false] = new QPixmap(toolTitleHeight, normalTitleHeight); + ileftBtnUpPix[false] = new QPixmap(normalTitleHeight, normalTitleHeight); + ileftBtnDownPix[false] = new QPixmap(normalTitleHeight, normalTitleHeight); + + rightBtnUpPix[false] = new QPixmap(toolTitleHeight, toolTitleHeight); + rightBtnDownPix[false] = new QPixmap(toolTitleHeight, toolTitleHeight); + irightBtnUpPix[false] = new QPixmap(toolTitleHeight, toolTitleHeight); + irightBtnDownPix[false] = new QPixmap(toolTitleHeight, toolTitleHeight); + + // Draw the button state pixmaps + g = options()->palette( ColorTitleBar, true ); + drawButtonBackground( leftBtnUpPix[true], g, false ); + drawButtonBackground( leftBtnDownPix[true], g, true ); + drawButtonBackground( leftBtnUpPix[false], g, false ); + drawButtonBackground( leftBtnDownPix[false], g, true ); + + g = options()->palette( ColorButtonBg, true ); + drawButtonBackground( rightBtnUpPix[true], g, false ); + drawButtonBackground( rightBtnDownPix[true], g, true ); + drawButtonBackground( rightBtnUpPix[false], g, false ); + drawButtonBackground( rightBtnDownPix[false], g, true ); + + g = options()->palette( ColorTitleBar, false ); + drawButtonBackground( ileftBtnUpPix[true], g, false ); + drawButtonBackground( ileftBtnDownPix[true], g, true ); + drawButtonBackground( ileftBtnUpPix[false], g, false ); + drawButtonBackground( ileftBtnDownPix[false], g, true ); + + g = options()->palette( ColorButtonBg, false ); + drawButtonBackground( irightBtnUpPix[true], g, false ); + drawButtonBackground( irightBtnDownPix[true], g, true ); + drawButtonBackground( irightBtnUpPix[false], g, false ); + drawButtonBackground( irightBtnDownPix[false], g, true ); +} + + +void KDE2Handler::freePixmaps() +{ + // Free button pixmaps + if (rightBtnUpPix[true]) + delete rightBtnUpPix[true]; + if(rightBtnDownPix[true]) + delete rightBtnDownPix[true]; + if (irightBtnUpPix[true]) + delete irightBtnUpPix[true]; + if (irightBtnDownPix[true]) + delete irightBtnDownPix[true]; + + if (leftBtnUpPix[true]) + delete leftBtnUpPix[true]; + if(leftBtnDownPix[true]) + delete leftBtnDownPix[true]; + if (ileftBtnUpPix[true]) + delete ileftBtnUpPix[true]; + if (ileftBtnDownPix[true]) + delete ileftBtnDownPix[true]; + + if (rightBtnUpPix[false]) + delete rightBtnUpPix[false]; + if(rightBtnDownPix[false]) + delete rightBtnDownPix[false]; + if (irightBtnUpPix[false]) + delete irightBtnUpPix[false]; + if (irightBtnDownPix[false]) + delete irightBtnDownPix[false]; + + if (leftBtnUpPix[false]) + delete leftBtnUpPix[false]; + if(leftBtnDownPix[false]) + delete leftBtnDownPix[false]; + if (ileftBtnUpPix[false]) + delete ileftBtnUpPix[false]; + if (ileftBtnDownPix[false]) + delete ileftBtnDownPix[false]; + + // Title images + if (titleBuffer) + delete titleBuffer; + if (titlePix) + delete titlePix; + if (aUpperGradient) + delete aUpperGradient; + if (iUpperGradient) + delete iUpperGradient; + + // Sticky pin images + if (pinUpPix) + delete pinUpPix; + if (ipinUpPix) + delete ipinUpPix; + if (pinDownPix) + delete pinDownPix; + if (ipinDownPix) + delete ipinDownPix; +} + + +void KDE2Handler::drawButtonBackground(QPixmap *pix, + const QPalette &g, bool sunken) +{ + QPainter p; + int w = pix->width(); + int h = pix->height(); + int x2 = w-1; + int y2 = h-1; + + bool highcolor = useGradients && (QPixmap::defaultDepth() > 8); + QColor c = g.color( QPalette::Background ); + + // Fill the background with a gradient if possible + if (highcolor) + gradientFill(pix, c.light(130), c.dark(130)); + else + pix->fill(c); + + p.begin(pix); + // outer frame + p.setPen(g.color( QPalette::Mid )); + p.drawLine(0, 0, x2, 0); + p.drawLine(0, 0, 0, y2); + p.setPen(g.color( QPalette::Light )); + p.drawLine(x2, 0, x2, y2); + p.drawLine(0, x2, y2, x2); + p.setPen(g.color( QPalette::Dark )); + p.drawRect(1, 1, w-3, h-3); + p.setPen(sunken ? g.color( QPalette::Mid ) : g.color( QPalette::Light )); + p.drawLine(2, 2, x2-2, 2); + p.drawLine(2, 2, 2, y2-2); + p.setPen(sunken ? g.color( QPalette::Light ) : g.color( QPalette::Mid )); + p.drawLine(x2-2, 2, x2-2, y2-2); + p.drawLine(2, x2-2, y2-2, x2-2); +} + +QList< KDE2Handler::BorderSize > KDE2Handler::borderSizes() const +{ // the list must be sorted + return QList< BorderSize >() << BorderNormal << BorderLarge << + BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized; +} + +bool KDE2Handler::supports( Ability ability ) const +{ + switch( ability ) + { + // announce + case AbilityAnnounceButtons: + case AbilityAnnounceColors: + // buttons + case AbilityButtonMenu: + case AbilityButtonOnAllDesktops: + case AbilityButtonSpacer: + case AbilityButtonHelp: + case AbilityButtonMinimize: + case AbilityButtonMaximize: + case AbilityButtonClose: + case AbilityButtonAboveOthers: + case AbilityButtonBelowOthers: + case AbilityButtonShade: + // colors + case AbilityColorTitleBack: + case AbilityColorTitleBlend: + case AbilityColorTitleFore: + case AbilityColorFrame: + case AbilityColorButtonBack: + return true; + default: + return false; + }; +} + +// =========================================================================== + +KDE2Button::KDE2Button(ButtonType type, KDE2Client *parent, const char *name) + : KCommonDecorationButton(type, parent) +{ + setObjectName( name ); + setAttribute( Qt::WA_NoSystemBackground ); + + isMouseOver = false; + deco = NULL; + large = !decoration()->isToolWindow(); +} + + +KDE2Button::~KDE2Button() +{ + if (deco) + delete deco; +} + + +void KDE2Button::reset(unsigned long changed) +{ + if (changed&DecorationReset || changed&ManualReset || changed&SizeChange || changed&StateChange) { + switch (type() ) { + case CloseButton: + setBitmap(close_bits); + break; + case HelpButton: + setBitmap(question_bits); + break; + case MinButton: + setBitmap(iconify_bits); + break; + case MaxButton: + setBitmap( isChecked() ? minmax_bits : maximize_bits ); + break; + case OnAllDesktopsButton: + setBitmap(0); + break; + case ShadeButton: + setBitmap( isChecked() ? shade_on_bits : shade_off_bits ); + break; + case AboveButton: + setBitmap( isChecked() ? above_on_bits : above_off_bits ); + break; + case BelowButton: + setBitmap( isChecked() ? below_on_bits : below_off_bits ); + break; + default: + setBitmap(0); + break; + } + + this->update(); + } +} + + +void KDE2Button::setBitmap(const unsigned char *bitmap) +{ + delete deco; + deco = 0; + + if (bitmap) { + deco = new QPainterPath; + deco->addRegion(QRegion( QBitmap::fromData(QSize( 10, 10 ), bitmap) )); +// deco->setMask( *deco ); + } +} + +void KDE2Button::paintEvent(QPaintEvent *) +{ + QPainter p(this); + drawButton(&p); +} + +void KDE2Button::drawButton(QPainter *p) +{ + if (!KDE2_initialized) + return; + + const bool active = decoration()->isActive(); + + if (deco) { + // Fill the button background with an appropriate button image + QPixmap btnbg; + + if (isLeft() ) { + if (isDown()) + btnbg = active ? + *leftBtnDownPix[large] : *ileftBtnDownPix[large]; + else + btnbg = active ? + *leftBtnUpPix[large] : *ileftBtnUpPix[large]; + } else { + if (isDown()) + btnbg = active ? + *rightBtnDownPix[large] : *irightBtnDownPix[large]; + else + btnbg = active ? + *rightBtnUpPix[large] : *irightBtnUpPix[large]; + } + + p->drawPixmap( 0, 0, btnbg ); + + } else if ( isLeft() ) { + + // Fill the button background with an appropriate color/gradient + // This is for sticky and menu buttons + QPixmap* grad = active ? aUpperGradient : iUpperGradient; + if (!grad) { + QColor c = KDecoration::options()->color(KDecoration::ColorTitleBar, active); + p->fillRect(0, 0, width(), height(), c ); + } else + p->drawPixmap( 0, 0, *grad, 0,1, width(), height() ); + + } else { + // Draw a plain background for menus or sticky buttons on RHS + QColor c = KDecoration::options()->color(KDecoration::ColorFrame, active); + p->fillRect(0, 0, width(), height(), c); + } + + + // If we have a decoration bitmap, then draw that + // otherwise we paint a menu button (with mini icon), or a sticky button. + if( deco ) { + // Select the appropriate button decoration color + bool darkDeco = qGray( KDecoration::options()->color( + isLeft() ? KDecoration::ColorTitleBar : KDecoration::ColorButtonBg, + active).rgb() ) > 127; + + p->setPen(Qt::NoPen); + if (isMouseOver) + p->setBrush( darkDeco ? Qt::darkGray : Qt::lightGray ); + else + p->setBrush( darkDeco ? Qt::black : Qt::white ); + + QPoint offset((width()-10)/2, (height()-10)/2); + if (isDown()) + offset += QPoint(1,1); + p->translate(offset); + p->drawPath(*deco); + p->translate(-offset); + + } else { + QPixmap btnpix; + + if (type()==OnAllDesktopsButton) { + if (active) + btnpix = isChecked() ? *pinDownPix : *pinUpPix; + else + btnpix = isChecked() ? *ipinDownPix : *ipinUpPix; + } else + btnpix = decoration()->icon().pixmap( style()->pixelMetric( QStyle::PM_SmallIconSize ), QIcon::Normal ); + + // Intensify the image if required + if (isMouseOver) { + // XXX Find a suitable substitute for this. + // btnpix = KPixmapEffect::intensity(btnpix, 0.8); + } + + // Smooth scale the pixmap for small titlebars + // This is slow, but we assume this isn't done too often + if ( width() < 16 ) { + btnpix = btnpix.scaled(12, 12); + p->drawPixmap( 0, 0, btnpix ); + } + else + p->drawPixmap( width()/2-8, height()/2-8, btnpix ); + } +} + + +void KDE2Button::enterEvent(QEvent *e) +{ + isMouseOver=true; + repaint(); + KCommonDecorationButton::enterEvent(e); +} + + +void KDE2Button::leaveEvent(QEvent *e) +{ + isMouseOver=false; + repaint(); + KCommonDecorationButton::leaveEvent(e); +} + + +// =========================================================================== + +KDE2Client::KDE2Client( KDecorationBridge* b, KDecorationFactory* f ) + : KCommonDecoration( b, f )/*, + m_closing(false)*/ +{ +} + +QString KDE2Client::visibleName() const +{ + return i18n("KDE 2"); +} + +bool KDE2Client::decorationBehaviour(DecorationBehaviour behaviour) const +{ + switch (behaviour) { + case DB_MenuClose: + return true; + case DB_WindowMask: + return true; + case DB_ButtonHide: + return true; + + default: + return KCommonDecoration::decorationBehaviour(behaviour); + } +} + +int KDE2Client::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *btn) const +{ + switch (lm) { + case LM_BorderLeft: + case LM_BorderRight: + return borderWidth; + + case LM_BorderBottom: + return mustDrawHandle() ? grabBorderWidth : borderWidth; + + case LM_TitleEdgeLeft: + case LM_TitleEdgeRight: + return borderWidth; + + case LM_TitleEdgeTop: + return 3; + + case LM_TitleEdgeBottom: + return 1; + + case LM_TitleBorderLeft: + case LM_TitleBorderRight: + return 1; + + case LM_TitleHeight: + return titleHeight; + + case LM_ButtonWidth: + case LM_ButtonHeight: + return titleHeight; + + case LM_ButtonSpacing: + return 0; + + default: + return KCommonDecoration::layoutMetric(lm, respectWindowState, btn); + } +} + +KCommonDecorationButton *KDE2Client::createButton(ButtonType type) +{ + switch (type) { + case MenuButton: + return new KDE2Button(MenuButton, this, "menu"); + case OnAllDesktopsButton: + return new KDE2Button(OnAllDesktopsButton, this, "on_all_desktops"); + case HelpButton: + return new KDE2Button(HelpButton, this, "help"); + case MinButton: + return new KDE2Button(MinButton, this, "minimize"); + case MaxButton: + return new KDE2Button(MaxButton, this, "maximize"); + case CloseButton: + return new KDE2Button(CloseButton, this, "close"); + case AboveButton: + return new KDE2Button(AboveButton, this, "above"); + case BelowButton: + return new KDE2Button(BelowButton, this, "below"); + case ShadeButton: + return new KDE2Button(ShadeButton, this, "shade"); + + default: + return 0; + } +} + +void KDE2Client::init() +{ + // Finally, toolWindows look small + if ( isToolWindow() ) { + titleHeight = toolTitleHeight; + } + else { + titleHeight = normalTitleHeight; + } + + KCommonDecoration::init(); +} + +void KDE2Client::reset( unsigned long changed) +{ + widget()->repaint(); + + KCommonDecoration::reset(changed); +} + +bool KDE2Client::mustDrawHandle() const +{ + bool drawSmallBorders = !options()->moveResizeMaximizedWindows(); + if (drawSmallBorders && (maximizeMode() & MaximizeVertical)) { + return false; + } else { + return showGrabBar && isResizable(); + } +} + +void KDE2Client::paintEvent( QPaintEvent* ) +{ + if (!KDE2_initialized) + return; + + QPalette g; + int offset; + + QPixmap* upperGradient = isActive() ? aUpperGradient : iUpperGradient; + + QPainter p(widget()); + + // Obtain widget bounds. + QRect r(widget()->rect()); + int x = r.x(); + int y = r.y(); + int x2 = r.width() - 1; + int y2 = r.height() - 1; + int w = r.width(); + int h = r.height(); + + // Determine where to place the extended left titlebar + int leftFrameStart = (h > 42) ? y+titleHeight+26: y+titleHeight; + + // Determine where to make the titlebar color transition + r = titleRect(); + int rightOffset = r.x()+r.width()+1; + + // Create a disposable pixmap buffer for the titlebar + // very early before drawing begins so there is no lag + // during painting pixels. + *titleBuffer = QPixmap( rightOffset-3, titleHeight+1 ); + + // Draw an outer black frame + p.setPen(Qt::black); + p.drawRect(x,y,w-1,h-1); + + // Draw part of the frame that is the titlebar color + g = options()->palette(ColorTitleBar, isActive()); + p.setPen(g.color( QPalette::Light )); + p.drawLine(x+1, y+1, rightOffset-1, y+1); + p.drawLine(x+1, y+1, x+1, leftFrameStart+borderWidth-4); + + // Draw titlebar colour separator line + p.setPen(g.color( QPalette::Dark )); + p.drawLine(rightOffset-1, y+1, rightOffset-1, titleHeight+2); + + p.fillRect(x+2, y+titleHeight+3, + borderWidth-4, leftFrameStart+borderWidth-y-titleHeight-8, + options()->color(ColorTitleBar, isActive() )); + + // Finish drawing the titlebar extension + p.setPen(Qt::black); + p.drawLine(x+1, leftFrameStart+borderWidth-4, x+borderWidth-2, leftFrameStart-1); + p.setPen(g.color( QPalette::Mid )); + p.drawLine(x+borderWidth-2, y+titleHeight+3, x+borderWidth-2, leftFrameStart-2); + + // Fill out the border edges + g = options()->palette(ColorFrame, isActive()); + p.setPen(g.color( QPalette::Light )); + p.drawLine(rightOffset, y+1, x2-1, y+1); + p.drawLine(x+1, leftFrameStart+borderWidth-3, x+1, y2-1); + p.setPen(g.color( QPalette::Dark )); + p.drawLine(x2-1, y+1, x2-1, y2-1); + p.drawLine(x+1, y2-1, x2-1, y2-1); + + p.setPen(options()->color(ColorFrame, isActive())); + QPolygon a; + QBrush brush( options()->color(ColorFrame, isActive()), Qt::SolidPattern ); + p.setBrush( brush ); // use solid, yellow brush + a.setPoints( 4, x+2, leftFrameStart+borderWidth-4, + x+borderWidth-2, leftFrameStart, + x+borderWidth-2, y2-2, + x+2, y2-2); + p.drawPolygon( a ); + p.fillRect(x2-borderWidth+2, y+titleHeight+3, + borderWidth-3, y2-y-titleHeight-4, + options()->color(ColorFrame, isActive() )); + + // Draw the bottom handle if required + if (mustDrawHandle()) + { + if(w > 50) + { + qDrawShadePanel(&p, x+1, y2-grabBorderWidth+3, 2*borderWidth+12, grabBorderWidth-3, + g, false, 1, &g.brush(QPalette::Mid)); + qDrawShadePanel(&p, x+2*borderWidth+13, y2-grabBorderWidth+3, w-4*borderWidth-26, grabBorderWidth-3, + g, false, 1, isActive() ? + &g.brush(QPalette::Background) : + &g.brush(QPalette::Mid)); + qDrawShadePanel(&p, x2-2*borderWidth-12, y2-grabBorderWidth+3, 2*borderWidth+12, grabBorderWidth-3, + g, false, 1, &g.brush(QPalette::Mid)); + } else + qDrawShadePanel(&p, x+1, y2-grabBorderWidth+3, w-2, grabBorderWidth-3, + g, false, 1, isActive() ? + &g.brush(QPalette::Background) : + &g.brush(QPalette::Mid)); + offset = grabBorderWidth; + } else + { + p.fillRect(x+2, y2-borderWidth+2, w-4, borderWidth-3, + options()->color(ColorFrame, isActive() )); + offset = borderWidth; + } + + // Draw a frame around the wrapped widget. + p.setPen( g.color( QPalette::Dark ) ); + p.drawRect( x+borderWidth-1, y+titleHeight+3, w-2*borderWidth+1, h-titleHeight-offset-2 ); + + // Draw the title bar. + r = titleRect(); + + // Obtain titlebar blend colours + QColor c1 = options()->color(ColorTitleBar, isActive() ); + QColor c2 = options()->color(ColorFrame, isActive() ); + + // Fill with frame color behind RHS buttons + p.fillRect( rightOffset, y+2, x2-rightOffset-1, titleHeight+1, c2); + + QPainter p2( titleBuffer ); + p2.initFrom( widget()); + + // Draw the titlebar gradient + if (upperGradient) + p2.drawTiledPixmap(0, 0, rightOffset-3, titleHeight+1, *upperGradient); + else + p2.fillRect(0, 0, rightOffset-3, titleHeight+1, c1); + + // Draw the title text on the pixmap, and with a smaller font + // for toolwindows than the default. + QFont fnt = options()->font(true); + + if ( isToolWindow() ) + fnt.setPointSize( fnt.pointSize()-2 ); // Shrink font by 2pt + + p2.setFont( fnt ); + + // Draw the titlebar stipple if active and available + if (isActive() && titlePix) + { + QFontMetrics fm(fnt); + int captionWidth = fm.width(caption()); + if (caption().isRightToLeft()) + p2.drawTiledPixmap( r.x(), 0, r.width()-captionWidth-4, + titleHeight+1, *titlePix ); + else + p2.drawTiledPixmap( r.x()+captionWidth+3, 0, r.width()-captionWidth-4, + titleHeight+1, *titlePix ); + } + + p2.setPen( options()->color(ColorFont, isActive()) ); + p2.drawText(r.x(), 1, r.width()-1, r.height(), + (caption().isRightToLeft() ? Qt::AlignRight : Qt::AlignLeft) | Qt::AlignVCenter, + caption() ); + + p2.end(); + + p.drawPixmap( 2, 2, *titleBuffer ); + + // Ensure a shaded window has no unpainted areas + // Is this still needed? +#if 1 + p.setPen(c2); + p.drawLine(x+borderWidth, y+titleHeight+4, x2-borderWidth, y+titleHeight+4); +#endif +} + +QRegion KDE2Client::cornerShape(WindowCorner corner) +{ + switch (corner) { + case WC_TopLeft: + return QRect(0, 0, 1, 1); + + case WC_TopRight: + return QRect(width()-1, 0, 1, 1); + + case WC_BottomLeft: + return QRect(0, height()-1, 1, 1); + + case WC_BottomRight: + return QRect(width()-1, height()-1, 1, 1); + + default: + return QRegion(); + } +} + +} // namespace + +// Extended KWin plugin interface +extern "C" KDE_EXPORT KDecorationFactory* create_factory() +{ + return new KDE2::KDE2Handler(); +} + +// vim: ts=4 sw=4 +// kate: space-indent off; tab-width 4; diff --git a/clients/kde2/kde2.desktop b/clients/kde2/kde2.desktop new file mode 100644 index 0000000000..52541ac207 --- /dev/null +++ b/clients/kde2/kde2.desktop @@ -0,0 +1,91 @@ +[Desktop Entry] +Name=KDE 2 +Name[af]=KDE 2 +Name[ar]=كدي 2 +Name[as]=KDE 2 +Name[be]=KDE 2 +Name[be@latin]=KDE 2 +Name[bg]=KDE 2 +Name[bn]=কে.ডি.ই. ২ +Name[bn_IN]=KDE 2 +Name[br]=KDE 2 +Name[ca]=KDE 2 +Name[ca@valencia]=KDE 2 +Name[cs]=KDE 2 +Name[csb]=KDE 2 +Name[cy]=KDE 2 +Name[da]=KDE 2 +Name[de]=KDE 2 +Name[el]=KDE 2 +Name[en_GB]=KDE 2 +Name[eo]=KDE 2 +Name[es]=KDE 2 +Name[et]=KDE 2 +Name[eu]=KDE 2 +Name[fa]=KDE ۲ +Name[fi]=KDE 2 +Name[fr]=KDE 2 +Name[fy]=KDE 2 +Name[ga]=KDE 2 +Name[gl]=KDE 2 +Name[gu]=KDE ૨ +Name[he]=KDE 2 +Name[hi]=केडीई 2 +Name[hne]=केडीई 2 +Name[hr]=KDE 2 +Name[hsb]=KDE 2 +Name[hu]=KDE 2 +Name[ia]=KDE 2 +Name[id]=KDE 2 +Name[is]=KDE 2 +Name[it]=KDE 2 +Name[ja]=KDE 2 +Name[ka]=KDE 2 +Name[kk]=KDE 2 +Name[km]=KDE 2 +Name[kn]=ಕೆಡಿಇ ೨ +Name[ko]=KDE 2 +Name[ku]=KDE 2 +Name[lt]=KDE 2 +Name[lv]=KDE 2 +Name[mai]=केडीई 2 +Name[mk]=KDE 2 +Name[ml]=കെഡിഇ 2 +Name[mr]=KDE 2 +Name[ms]=KDE 2 +Name[nb]=KDE 2 +Name[nds]=KDE 2 +Name[ne]=केडीई २ +Name[nl]=KDE 2 +Name[nn]=KDE 2 +Name[oc]=KDE 2 +Name[pa]=KDE 2 +Name[pl]=KDE 2 +Name[pt]=KDE 2 +Name[pt_BR]=KDE 2 +Name[ro]=KDE 2 +Name[ru]=KDE 2 +Name[se]=KDE 2 +Name[si]=KDE 2 +Name[sk]=KDE 2 +Name[sl]=KDE 2 +Name[sr]=КДЕ‑2 +Name[sr@ijekavian]=КДЕ‑2 +Name[sr@ijekavianlatin]=KDE2 +Name[sr@latin]=KDE2 +Name[sv]=KDE 2 +Name[ta]=KDE 2 +Name[te]=కెడిఈ 2 +Name[tg]=KDE 2 +Name[th]=รูปแบบ KDE 2 +Name[tr]=KDE 2 +Name[uk]=KDE 2 +Name[uz]=KDE 2 +Name[uz@cyrillic]=KDE 2 +Name[vi]=KDE 2 +Name[wa]=KDE 2 +Name[xh]=KDE 2 +Name[x-test]=xxKDE 2xx +Name[zh_CN]=KDE 2 +Name[zh_TW]=KDE 2 +X-KDE-Library=kwin3_kde2 diff --git a/clients/kde2/kde2.h b/clients/kde2/kde2.h new file mode 100644 index 0000000000..f306ebffad --- /dev/null +++ b/clients/kde2/kde2.h @@ -0,0 +1,110 @@ +/********************************************************************* + + KDE2 Default KWin client + + Copyright (C) 1999, 2001 Daniel Duley + Matthias Ettrich + Karol Szwed + + Draws mini titlebars for tool windows. + Many features are now customizable. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#ifndef KDE2_H +#define KDE2_H + +#include +#include +#include + +class QPixmap; +class QPainterPath; + +namespace KDE2 { + +class KDE2Client; + +class KDE2Handler: public KDecorationFactory +{ + public: + KDE2Handler(); + ~KDE2Handler(); + KDecoration* createDecoration( KDecorationBridge* b ); + bool reset( unsigned long changed ); + virtual QList< BorderSize > borderSizes() const; + virtual bool supports( Ability ability ) const; + + private: + unsigned long readConfig( bool update ); + void createPixmaps(); + void freePixmaps(); + void drawButtonBackground(QPixmap *pix, + const QPalette &g, bool sunken); +}; + + +class KDE2Button : public KCommonDecorationButton +{ + public: + KDE2Button(ButtonType type, KDE2Client *parent, const char *name); + ~KDE2Button(); + + void reset(unsigned long changed); + + void setBitmap(const unsigned char *bitmap); + + protected: + void enterEvent(QEvent *); + void leaveEvent(QEvent *); + void paintEvent(QPaintEvent *); + void drawButton(QPainter *p); + void drawButtonLabel(QPainter*) {;} + + QPainterPath* deco; + bool large; + bool isMouseOver; +}; + + +class KDE2Client : public KCommonDecoration +{ + public: + KDE2Client( KDecorationBridge* b, KDecorationFactory* f ); + ~KDE2Client() {;} + + virtual QString visibleName() const; + virtual bool decorationBehaviour(DecorationBehaviour behaviour) const; + virtual int layoutMetric(LayoutMetric lm, bool respectWindowState = true, const KCommonDecorationButton * = 0) const; + virtual KCommonDecorationButton *createButton(ButtonType type); + + virtual QRegion cornerShape(WindowCorner corner); + + void init(); + void reset( unsigned long changed ); + + protected: + void paintEvent( QPaintEvent* ); + + private: + bool mustDrawHandle() const; + int titleHeight; +}; + +} + +#endif +// vim: ts=4 +// kate: space-indent off; tab-width 4; diff --git a/clients/keramik/CMakeLists.txt b/clients/keramik/CMakeLists.txt new file mode 100644 index 0000000000..979850334d --- /dev/null +++ b/clients/keramik/CMakeLists.txt @@ -0,0 +1,15 @@ +add_subdirectory( config ) + +set(kwin3_keramik_PART_SRCS keramik.cpp ) + +qt4_add_resources(kwin3_keramik_PART_SRCS tiles.qrc ) + +kde4_add_plugin(kwin3_keramik ${kwin3_keramik_PART_SRCS}) + +target_link_libraries(kwin3_keramik ${KDE4_KDEUI_LIBS} kdecorations) + +install(TARGETS kwin3_keramik DESTINATION ${PLUGIN_INSTALL_DIR} ) + +########### install files ############### + +install( FILES keramik.desktop DESTINATION ${DATA_INSTALL_DIR}/kwin ) diff --git a/clients/keramik/config/CMakeLists.txt b/clients/keramik/config/CMakeLists.txt new file mode 100644 index 0000000000..a35ec5e47c --- /dev/null +++ b/clients/keramik/config/CMakeLists.txt @@ -0,0 +1,18 @@ +include_directories( ${KDEBASE_WORKSPACE_SOURCE_DIR}/kwin/lib ) + + +########### next target ############### + +set(kwin_keramik_config_PART_SRCS config.cpp ) + + +kde4_add_ui_files(kwin_keramik_config_PART_SRCS keramikconfig.ui ) + +kde4_add_plugin(kwin_keramik_config ${kwin_keramik_config_PART_SRCS}) + + + +target_link_libraries(kwin_keramik_config ${KDE4_KDEUI_LIBS} ${QT_QTGUI_LIBRARY}) + +install(TARGETS kwin_keramik_config DESTINATION ${PLUGIN_INSTALL_DIR} ) + diff --git a/clients/keramik/config/config.cpp b/clients/keramik/config/config.cpp new file mode 100644 index 0000000000..921573d492 --- /dev/null +++ b/clients/keramik/config/config.cpp @@ -0,0 +1,112 @@ +/* + * + * Keramik KWin client configuration module + * + * Copyright (C) 2002 Fredrik Höglund + * + * Based on the Quartz configuration module, + * Copyright (c) 2001 Karol Szwed + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the license, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#include +#include + +#include + +#include "config.moc" + +extern "C" +{ + KDE_EXPORT QObject* allocate_config( KConfig* conf, QWidget* parent ) + { + return ( new KeramikConfig( conf, parent ) ); + } +} + + +/* NOTE: + * 'conf' is a pointer to the kwindecoration modules open kwin config, + * and is by default set to the "Style" group. + * + * 'parent' is the parent of the QObject, which is a VBox inside the + * Configure tab in kwindecoration + */ + +KeramikConfig::KeramikConfig( KConfig* conf, QWidget* parent ) + : QObject( parent ) +{ + Q_UNUSED( conf ); + KGlobal::locale()->insertCatalog("kwin_clients"); + c = new KConfig( "kwinkeramikrc" ); + KConfigGroup cg(c, "General"); + ui = new KeramikConfigUI( parent ); + connect( ui->showAppIcons, SIGNAL(clicked()), SIGNAL(changed()) ); + connect( ui->smallCaptions, SIGNAL(clicked()), SIGNAL(changed()) ); + connect( ui->largeGrabBars, SIGNAL(clicked()), SIGNAL(changed()) ); + connect( ui->useShadowedText, SIGNAL(clicked()), SIGNAL(changed()) ); + + load( cg ); + ui->show(); +} + + +KeramikConfig::~KeramikConfig() +{ + delete ui; + delete c; +} + + +// Loads the configurable options from the kwinrc config file +// It is passed the open config from kwindecoration to improve efficiency +void KeramikConfig::load( const KConfigGroup& ) +{ + KConfigGroup cg(c, "General"); + ui->showAppIcons->setChecked( cg.readEntry("ShowAppIcons", true) ); + ui->smallCaptions->setChecked( cg.readEntry("SmallCaptionBubbles", false) ); + ui->largeGrabBars->setChecked( cg.readEntry("LargeGrabBars", true) ); + ui->useShadowedText->setChecked( cg.readEntry("UseShadowedText", true) ); +} + + +// Saves the configurable options to the kwinrc config file +void KeramikConfig::save( KConfigGroup& ) +{ + KConfigGroup cg(c, "General"); + cg.writeEntry( "ShowAppIcons", ui->showAppIcons->isChecked() ); + cg.writeEntry( "SmallCaptionBubbles", ui->smallCaptions->isChecked() ); + cg.writeEntry( "LargeGrabBars", ui->largeGrabBars->isChecked() ); + cg.writeEntry( "UseShadowedText", ui->useShadowedText->isChecked() ); + c->sync(); +} + + +// Sets UI widget defaults which must correspond to style defaults +void KeramikConfig::defaults() +{ + ui->showAppIcons->setChecked( true ); + ui->smallCaptions->setChecked( false ); + ui->largeGrabBars->setChecked( true ); + ui->useShadowedText->setChecked( true ); + + emit changed(); +} + +// vim: set noet ts=4 sw=4: diff --git a/clients/keramik/config/config.h b/clients/keramik/config/config.h new file mode 100644 index 0000000000..de6db138a7 --- /dev/null +++ b/clients/keramik/config/config.h @@ -0,0 +1,67 @@ +/* + * Keramik KWin client configuration module + * + * Copyright (C) 2002 Fredrik Höglund + * + * Based on the Quartz configuration module, + * Copyright (c) 2001 Karol Szwed + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the license, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __KWIN_KERAMIK_CONFIG_H +#define __KWIN_KERAMIK_CONFIG_H + +#include + +#include "ui_keramikconfig.h" + +class KeramikConfigUI : public QWidget, public Ui::KeramikConfigUI +{ +public: + KeramikConfigUI( QWidget *parent ) : QWidget( parent ) { + setupUi( this ); + } +}; + + + +class KeramikConfig: public QObject +{ + Q_OBJECT + + public: + KeramikConfig( KConfig* conf, QWidget* parent ); + ~KeramikConfig(); + + // These public signals/slots work similar to KCM modules + signals: + void changed(); + + public slots: + void load( const KConfigGroup& conf ); + void save( KConfigGroup& conf ); + void defaults(); + + private: + KeramikConfigUI *ui; + KConfig *c; +}; + + +#endif + +// vim: set noet ts=4 sw=4: diff --git a/clients/keramik/config/keramikconfig.ui b/clients/keramik/config/keramikconfig.ui new file mode 100644 index 0000000000..d2509e5126 --- /dev/null +++ b/clients/keramik/config/keramikconfig.ui @@ -0,0 +1,61 @@ + + KeramikConfigUI + + + + 0 + 0 + 287 + 102 + + + + Keramik + + + + 0 + + + + + Display the window &icon in the caption bubble + + + Check this option if you want the window icon to be displayed in the caption bubble next to the titlebar text. + + + + + + + Draw &small caption bubbles on active windows + + + Check this option if you want the caption bubble to have the same size on active windows that it has on inactive ones. This option is useful for laptops or low resolution displays where you want maximize the amount of space available to the window contents. + + + + + + + Draw g&rab bars below windows + + + Check this option if you want a grab bar to be drawn below windows. When this option is not selected only a thin border will be drawn in its place. + + + + + + + Use shadowed &text + + + Check this option if you want the titlebar text to have a 3D look with a shadow behind it. + + + + + + diff --git a/clients/keramik/keramik.cpp b/clients/keramik/keramik.cpp new file mode 100644 index 0000000000..33eabe5fc9 --- /dev/null +++ b/clients/keramik/keramik.cpp @@ -0,0 +1,1818 @@ +/* + * + * Keramik KWin client (version 0.8) + * + * Copyright (C) 2002 Fredrik H�lund + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the license, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "keramik.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "keramik.moc" + +// ------------------------------------------------------------------------------------------- + +static void flip( QPixmap *&pix ) +{ + QPixmap *tmp = new QPixmap( pix->transformed( QMatrix(-1,0,0,1,pix->width(),0) ) ); + delete pix; + pix = tmp; +} + +static void flip( QBitmap *&pix ) +{ + QBitmap *tmp = new QBitmap( pix->transformed( QMatrix(-1,0,0,1,pix->width(),0) ) ); + delete pix; + pix = tmp; +} + +namespace Keramik +{ + + const int buttonMargin = 9; // Margin between the window edge and the buttons + const int buttonSpacing = 4; // Spacing between the titlebar buttons + const int iconSpacing = 5; // Spacing between the icon and the text label + + // Titlebar button bitmaps + const unsigned char menu_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0xf0, 0x07, 0x00, + 0xe0, 0x03, 0x00, 0xc0, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + + const unsigned char on_all_desktops_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0xf0, 0x0f, 0x00, + 0xf0, 0x0f, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + + const unsigned char not_on_all_desktops_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, + 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + + const unsigned char help_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, + 0xf0, 0x07, 0x00, 0x30, 0x06, 0x00, 0x00, 0x07, 0x00, 0x80, 0x03, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + + const unsigned char minimize_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + + const unsigned char maximize_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x01, 0x00, 0xc0, 0x03, 0x00, 0xe0, 0x07, 0x00, 0xf0, 0x0f, 0x00, + 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + + const unsigned char restore_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, + 0xf0, 0x0f, 0x00, 0xe0, 0x07, 0x00, 0xc0, 0x03, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + + const unsigned char close_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x0c, 0x00, 0x70, 0x0e, 0x00, 0xe0, 0x07, 0x00, 0xc0, 0x03, 0x00, + 0xc0, 0x03, 0x00, 0xe0, 0x07, 0x00, 0x70, 0x0e, 0x00, 0x30, 0x0c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00}; + + const unsigned char above_on_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, + 0x80, 0x01, 0x00, 0xe0, 0x07, 0x00, 0xc0, 0x03, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 }; + + const unsigned char above_off_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0xc0, 0x03, 0x00, + 0xe0, 0x07, 0x00, 0x80, 0x01, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 }; + + const unsigned char below_on_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0xc0, 0x03, 0x00, + 0xe0, 0x07, 0x00, 0x80, 0x01, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 }; + + const unsigned char below_off_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, + 0x80, 0x01, 0x00, 0xe0, 0x07, 0x00, 0xc0, 0x03, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 }; + + const unsigned char shade_on_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, + 0x10, 0x08, 0x00, 0x10, 0x08, 0x00, 0x10, 0x08, 0x00, 0x10, 0x08, 0x00, + 0x10, 0x08, 0x00, 0x10, 0x08, 0x00, 0x10, 0x08, 0x00, 0xf0, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 }; + + const unsigned char shade_off_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 }; + + KeramikHandler *clientHandler = NULL; + bool keramik_initialized = false; + + + +// ------------------------------------------------------------------------------------------- + + + +KeramikHandler::KeramikHandler() +{ + for ( int i = 0; i < NumTiles; i++ ) { + activeTiles[i] = NULL; + inactiveTiles[i] = NULL; + } + + settings_cache = NULL; + + // Create the button deco bitmaps + buttonDecos[ Menu ] = new QBitmap( QBitmap::fromData( QSize( 17, 17 ), menu_bits ) ); + buttonDecos[ OnAllDesktops ] = new QBitmap( QBitmap::fromData( QSize( 17, 17 ), on_all_desktops_bits ) ); + buttonDecos[ NotOnAllDesktops ] = new QBitmap( QBitmap::fromData( QSize( 17, 17 ), not_on_all_desktops_bits ) ); + buttonDecos[ Help ] = new QBitmap( QBitmap::fromData( QSize( 17, 17 ), help_bits ) ); + buttonDecos[ Minimize ] = new QBitmap( QBitmap::fromData( QSize( 17, 17 ), minimize_bits ) ); + buttonDecos[ Maximize ] = new QBitmap( QBitmap::fromData( QSize( 17, 17 ), maximize_bits ) ); + buttonDecos[ Restore ] = new QBitmap( QBitmap::fromData( QSize( 17, 17 ), restore_bits ) ); + buttonDecos[ Close ] = new QBitmap( QBitmap::fromData( QSize( 17, 17 ), close_bits ) ); + buttonDecos[ AboveOn ] = new QBitmap( QBitmap::fromData( QSize( 17, 17 ), above_on_bits ) ); + buttonDecos[ AboveOff ] = new QBitmap( QBitmap::fromData( QSize( 17, 17 ), above_off_bits ) ); + buttonDecos[ BelowOn ] = new QBitmap( QBitmap::fromData( QSize( 17, 17 ), below_on_bits ) ); + buttonDecos[ BelowOff ] = new QBitmap( QBitmap::fromData( QSize( 17, 17 ), below_off_bits ) ); + buttonDecos[ ShadeOn ] = new QBitmap( QBitmap::fromData( QSize( 17, 17 ), shade_on_bits ) ); + buttonDecos[ ShadeOff ] = new QBitmap( QBitmap::fromData( QSize( 17, 17 ), shade_off_bits ) ); + + // Selfmask the bitmaps + for ( int i = 0; i < NumButtonDecos; i++ ) + buttonDecos[i]->setMask( *buttonDecos[i] ); + + // Flip the bitmaps horizontally in right-to-left mode + if ( QApplication::isRightToLeft() ) { + for ( int i = 0; i < Help; ++i ) + ::flip( buttonDecos[i] ); + + for ( int i = Help + 1; i < NumButtonDecos; ++i ) + ::flip( buttonDecos[i] ); + } + + readConfig(); + createPixmaps(); + + keramik_initialized = true; +} + + +KeramikHandler::~KeramikHandler() +{ + keramik_initialized = false; + destroyPixmaps(); + + for ( int i = 0; i < NumButtonDecos; i++ ) + delete buttonDecos[i]; + + delete settings_cache; + + clientHandler = NULL; +} + + +void KeramikHandler::createPixmaps() +{ + int heightOffset; + int widthOffset; + switch(options()->preferredBorderSize(this)) { + case BorderLarge: + widthOffset = 4; + heightOffset = 0; + break; + case BorderVeryLarge: + widthOffset = 8; + heightOffset = 0; + break; + case BorderHuge: + widthOffset = 14; + heightOffset = 0; + break; + case BorderVeryHuge: + widthOffset = 23; + heightOffset = 10; + break; + case BorderOversized: + widthOffset = 36; + heightOffset = 25; + break; + case BorderTiny: + case BorderNormal: + default: + widthOffset = 0; + heightOffset = 0; + } + int fontHeight = QFontMetrics(options()->font(true)).height(); + if (fontHeight > heightOffset + 20) + heightOffset = fontHeight - 20; + + QString size = (heightOffset < 8) ? "" : (heightOffset < 20) ? "-large" : "-huge"; + + QColor titleColor, captionColor, buttonColor; + QImage *titleCenter = NULL, *captionLeft = NULL, + *captionRight = NULL, *captionCenter = NULL; + + + // Active tiles + // ------------------------------------------------------------------------- + captionColor = KDecoration::options()->color( ColorTitleBar, true ); + titleColor = KDecoration::options()->color( ColorTitleBlend, true ); + + // Load the titlebar corners. + activeTiles[ TitleLeft ] = loadPixmap( "titlebar-left", titleColor ); + activeTiles[ TitleRight ] = loadPixmap( "titlebar-right", titleColor ); + + // Load the titlebar center tile image (this will be used as + // the background for the caption bubble tiles). + titleCenter = loadImage( "titlebar-center", titleColor ); + + // Load the small version of the caption bubble corner & center images. + captionLeft = loadImage( "caption-small-left", captionColor ); + captionRight = loadImage( "caption-small-right", captionColor ); + captionCenter = loadImage( "caption-small-center", captionColor ); + + // Create the caption bubble tiles (by blending the images onto the titlebar) + activeTiles[ CaptionSmallLeft ] = composite( captionLeft, titleCenter ); + activeTiles[ CaptionSmallRight ] = composite( captionRight, titleCenter ); + activeTiles[ CaptionSmallCenter ] = composite( captionCenter, titleCenter ); + + delete captionLeft; + delete captionRight; + delete captionCenter; + + // Now do the same with the large version + captionLeft = loadImage( "caption-large-left", captionColor ); + captionRight = loadImage( "caption-large-right", captionColor ); + captionCenter = loadImage( "caption-large-center", captionColor ); + + activeTiles[ CaptionLargeLeft ] = composite( captionLeft, titleCenter ); + activeTiles[ CaptionLargeRight ] = composite( captionRight, titleCenter ); + activeTiles[ CaptionLargeCenter ] = composite( captionCenter, titleCenter ); + + delete captionLeft; + delete captionRight; + delete captionCenter; + + // Create the titlebar center tile + activeTiles[ TitleCenter ] = new QPixmap( QPixmap::fromImage( *titleCenter ) ); + + delete titleCenter; + + // Load the left & right border pixmaps + activeTiles[ BorderLeft ] = loadPixmap( "border-left", titleColor ); + activeTiles[ BorderRight ] = loadPixmap( "border-right", titleColor ); + + // Load the bottom grabbar pixmaps + if ( largeGrabBars ) { + activeTiles[ GrabBarLeft ] = loadPixmap( "grabbar-left", titleColor ); + activeTiles[ GrabBarRight ] = loadPixmap( "grabbar-right", titleColor ); + activeTiles[ GrabBarCenter ] = loadPixmap( "grabbar-center", titleColor ); + } else { + activeTiles[ GrabBarLeft ] = loadPixmap( "bottom-left", titleColor ); + activeTiles[ GrabBarRight ] = loadPixmap( "bottom-right", titleColor ); + activeTiles[ GrabBarCenter ] = loadPixmap( "bottom-center", titleColor ); + } + + // Inactive tiles + // ------------------------------------------------------------------------- + captionColor = KDecoration::options()->color( ColorTitleBar, false ); + titleColor = KDecoration::options()->color( ColorTitleBlend, false ); + + inactiveTiles[ TitleLeft ] = loadPixmap( "titlebar-left", titleColor ); + inactiveTiles[ TitleRight ] = loadPixmap( "titlebar-right", titleColor ); + + titleCenter = loadImage( "titlebar-center", titleColor ); + + captionLeft = loadImage( "caption-small-left", captionColor ); + captionRight = loadImage( "caption-small-right", captionColor ); + captionCenter = loadImage( "caption-small-center", captionColor ); + + inactiveTiles[ CaptionSmallLeft ] = composite( captionLeft, titleCenter ); + inactiveTiles[ CaptionSmallRight ] = composite( captionRight, titleCenter ); + inactiveTiles[ CaptionSmallCenter ] = composite( captionCenter, titleCenter ); + + delete captionLeft; + delete captionRight; + delete captionCenter; + + inactiveTiles[ TitleCenter ] = new QPixmap( QPixmap::fromImage( *titleCenter ) ); + + delete titleCenter; + + inactiveTiles[ BorderLeft ] = loadPixmap( "border-left", titleColor ); + inactiveTiles[ BorderRight ] = loadPixmap( "border-right", titleColor ); + + if ( largeGrabBars ) { + inactiveTiles[ GrabBarLeft ] = loadPixmap( "grabbar-left", titleColor ); + inactiveTiles[ GrabBarRight ] = loadPixmap( "grabbar-right", titleColor ); + inactiveTiles[ GrabBarCenter ] = loadPixmap( "grabbar-center", titleColor ); + } else { + inactiveTiles[ GrabBarLeft ] = loadPixmap( "bottom-left", titleColor ); + inactiveTiles[ GrabBarRight ] = loadPixmap( "bottom-right", titleColor ); + inactiveTiles[ GrabBarCenter ] = loadPixmap( "bottom-center", titleColor ); + } + + // Buttons + // ------------------------------------------------------------------------- + buttonColor = QColor(); //KDecoration::options()->color( ButtonBg, true ); + + titleButtonRound = loadPixmap( "titlebutton-round"+size, buttonColor ); + titleButtonSquare = loadPixmap( "titlebutton-square"+size, buttonColor ); + + + // Prepare the tiles for use + // ------------------------------------------------------------------------- + if ( QApplication::isRightToLeft() ) { + + // Fix lighting + flip( activeTiles[CaptionSmallLeft], activeTiles[CaptionSmallRight] ); + flip( inactiveTiles[CaptionSmallLeft], inactiveTiles[CaptionSmallRight] ); + + flip( activeTiles[CaptionLargeLeft], activeTiles[CaptionLargeRight] ); + + flip( activeTiles[TitleLeft], activeTiles[TitleRight] ); + flip( inactiveTiles[TitleLeft], inactiveTiles[TitleRight] ); + + flip( activeTiles[BorderLeft], activeTiles[BorderRight] ); + flip( inactiveTiles[BorderLeft], inactiveTiles[BorderRight] ); + + flip( activeTiles[GrabBarLeft], activeTiles[GrabBarRight] ); + flip( inactiveTiles[GrabBarLeft], inactiveTiles[GrabBarRight] ); + + ::flip( titleButtonRound ); + ::flip( titleButtonSquare ); + } + + // Pretile the center & border tiles for optimal performance + pretile( activeTiles[ CaptionSmallCenter ], 64, Qt::Horizontal ); + pretile( activeTiles[ CaptionLargeCenter ], 64, Qt::Horizontal ); + pretile( activeTiles[ TitleCenter ], 64, Qt::Horizontal ); + pretile( activeTiles[ GrabBarCenter ], 128, Qt::Horizontal ); + pretile( activeTiles[ BorderLeft ], 128, Qt::Vertical ); + pretile( activeTiles[ BorderRight ], 128, Qt::Vertical ); + + pretile( inactiveTiles[ CaptionSmallCenter ], 64, Qt::Horizontal ); + pretile( inactiveTiles[ TitleCenter ], 64, Qt::Horizontal ); + pretile( inactiveTiles[ GrabBarCenter ], 128, Qt::Horizontal ); + pretile( inactiveTiles[ BorderLeft ], 128, Qt::Vertical ); + pretile( inactiveTiles[ BorderRight ], 128, Qt::Vertical ); + + if (heightOffset > 0) { + addHeight (heightOffset, activeTiles[TitleLeft]); + addHeight (heightOffset, activeTiles[TitleCenter]); + addHeight (heightOffset, activeTiles[TitleRight]); + addHeight (heightOffset, activeTiles[CaptionSmallLeft]); + addHeight (heightOffset, activeTiles[CaptionSmallCenter]); + addHeight (heightOffset, activeTiles[CaptionSmallRight]); + addHeight (heightOffset, activeTiles[CaptionLargeLeft]); + addHeight (heightOffset, activeTiles[CaptionLargeCenter]); + addHeight (heightOffset, activeTiles[CaptionLargeRight]); + + addHeight (heightOffset, inactiveTiles[TitleLeft]); + addHeight (heightOffset, inactiveTiles[TitleCenter]); + addHeight (heightOffset, inactiveTiles[TitleRight]); + addHeight (heightOffset, inactiveTiles[CaptionSmallLeft]); + addHeight (heightOffset, inactiveTiles[CaptionSmallCenter]); + addHeight (heightOffset, inactiveTiles[CaptionSmallRight]); + } + + if (widthOffset > 0) { + addWidth (widthOffset, activeTiles[BorderLeft], true, activeTiles[GrabBarCenter]); + addWidth (widthOffset, activeTiles[BorderRight], false, activeTiles[GrabBarCenter]); + addWidth (widthOffset, inactiveTiles[BorderLeft], true, inactiveTiles[GrabBarCenter]); + addWidth (widthOffset, inactiveTiles[BorderRight], false, inactiveTiles[GrabBarCenter]); + + if (largeGrabBars) + widthOffset = widthOffset*3/2; + + addHeight (widthOffset, activeTiles[GrabBarLeft]); + addHeight (widthOffset, activeTiles[GrabBarCenter]); + addHeight (widthOffset, activeTiles[GrabBarRight]); + addHeight (widthOffset, inactiveTiles[GrabBarLeft]); + addHeight (widthOffset, inactiveTiles[GrabBarCenter]); + addHeight (widthOffset, inactiveTiles[GrabBarRight]); + } +} + + + +void KeramikHandler::destroyPixmaps() +{ + for ( int i = 0; i < NumTiles; i++ ) { + delete activeTiles[i]; + delete inactiveTiles[i]; + activeTiles[i] = NULL; + inactiveTiles[i] = NULL; + } + + delete titleButtonRound; + delete titleButtonSquare; +} + + +void KeramikHandler::addWidth (int width, QPixmap *&pix, bool left, QPixmap *bottomPix) { + int w = pix->width()+width; + int h = pix->height(); + + QPixmap *tmp = new QPixmap (w, h); + tmp->fill (); + QPainter p; + p.begin (tmp); + + for (int i = 0; i < h; i++) + p.drawPixmap (0, i, *bottomPix, i%2, 0, w,1); + + if (left) + p.drawPixmap(0, 0, *pix); + else + p.drawPixmap(width, 0, *pix); + + p.end(); + + delete pix; + pix = tmp; +} + + +void KeramikHandler::addHeight (int height, QPixmap *&pix) { + int w = pix->width(); + int h = pix->height()+height; + + QPixmap *tmp = new QPixmap (w, h); + QPainter p; + p.begin (tmp); + if (pix->height() > 10) { + p.drawPixmap(0, 0, *pix, 0, 0, w, 11); + for (int i = 0; i < height; i+=2) + p.drawPixmap(0, 11+i, *pix, 0, 11, w, 2); + p.drawPixmap(0, 11+height, *pix, 0, 11, w, -1); + } + else { + int lines = h-3; + int factor = pix->height()-3; + for (int i = 0; i < lines; i++) + p.drawPixmap(0, i, *pix, 0, i*factor/lines, w, 1); + p.drawPixmap(0, lines, *pix, 0, factor, w, 3); + } + p.end(); + + delete pix; + pix = tmp; +} + + +void KeramikHandler::flip( QPixmap *&pix1, QPixmap *&pix2 ) +{ + // Flip the pixmaps horizontally + QPixmap *tmp = new QPixmap( pix1->transformed( QMatrix(-1,0,0,1,pix1->width(),0) ) ); + + delete pix1; + pix1 = new QPixmap( pix2->transformed( QMatrix(-1,0,0,1,pix2->width(),0) ) ); + + delete pix2; + pix2 = tmp; +} + + +void KeramikHandler::pretile( QPixmap *&pix, int size, Qt::Orientation dir ) +{ + QPixmap *newpix; + QPainter p; + + if ( dir == Qt::Horizontal ) + newpix = new QPixmap( size, pix->height() ); + else + newpix = new QPixmap( pix->width(), size ); + + p.begin( newpix ); + p.drawTiledPixmap( newpix->rect(), *pix ) ; + p.end(); + + delete pix; + pix = newpix; +} + + +void KeramikHandler::readConfig() +{ + KConfig *c = new KConfig( "kwinkeramikrc" ); + KConfigGroup cg(c, "General"); + showIcons = cg.readEntry( "ShowAppIcons", true); + shadowedText = cg.readEntry( "UseShadowedText", true); + smallCaptionBubbles = cg.readEntry( "SmallCaptionBubbles", false); + largeGrabBars = cg.readEntry( "LargeGrabBars", true); + + if ( ! settings_cache ) { + settings_cache = new SettingsCache; + settings_cache->largeGrabBars = largeGrabBars; + settings_cache->smallCaptionBubbles = smallCaptionBubbles; + } + + delete c; +} + + +QPixmap *KeramikHandler::composite( QImage *over, QImage *under ) +{ + QImage dest( over->width(), over->height(), QImage::Format_ARGB32_Premultiplied ); + + QPainter p( &dest ); + p.setCompositionMode( QPainter::CompositionMode_Source ); + p.fillRect( dest.rect(), Qt::transparent ); + p.drawImage( 0, dest.height() - under->height(), *under ); + p.setCompositionMode( QPainter::CompositionMode_SourceOver ); + p.drawImage( 0, 0, *over ); + p.end(); + + // Create the final pixmap and return it + return new QPixmap( QPixmap::fromImage( dest ) ); +} + + +QImage *KeramikHandler::loadImage( const QString &name, const QColor &col ) +{ + if ( col.isValid() ) { + QImage *img = new QImage( ":/pics/" + name + ".png" ); + KIconEffect::colorize( *img, col, 1.0 ); + return img; + } else + return new QImage( ":/pics/" + name + ".png" ); +} + + +QPixmap *KeramikHandler::loadPixmap( const QString &name, const QColor &col ) +{ + QImage *img = loadImage( name, col ); + QPixmap *pix = new QPixmap( QPixmap::fromImage( *img ) ); + delete img; + + return pix; +} + + +bool KeramikHandler::reset( unsigned long changed ) +{ + keramik_initialized = false; + + bool needHardReset = false; + bool pixmapsInvalid = false; + + // Re-read the config file + readConfig(); + + if ( changed & SettingBorder ) + { + pixmapsInvalid = true; + needHardReset = true; + } + if ( changed & SettingFont ) + { + pixmapsInvalid = true; + needHardReset = true; + } + // Check if the color scheme has changed + if ( changed & SettingColors ) + { + pixmapsInvalid = true; + } + // Check if button positions have changed + + if ( changed & SettingButtons ) { + needHardReset = true; + } + + // Check if tooltips options have changed + if ( changed & SettingTooltips ) { + needHardReset = true; + } + + if ( (settings_cache->largeGrabBars != largeGrabBars) ) { + pixmapsInvalid = true; + needHardReset = true; + } + + if ( (settings_cache->smallCaptionBubbles != smallCaptionBubbles) ) { + needHardReset = true; + } + + // Update our config cache + settings_cache->largeGrabBars = largeGrabBars; + settings_cache->smallCaptionBubbles = smallCaptionBubbles; + + // Do we need to recreate the pixmaps? + if ( pixmapsInvalid ) { + destroyPixmaps(); + createPixmaps(); + } + + keramik_initialized = true; + + // Do we need to "hit the wooden hammer" ? + if ( !needHardReset ) + resetDecorations( changed ); + return needHardReset; +} + + +bool KeramikHandler::supports( Ability ability ) const +{ + switch( ability ) + { + // announce + case AbilityAnnounceButtons: + case AbilityAnnounceColors: + // buttons + case AbilityButtonMenu: + case AbilityButtonOnAllDesktops: + case AbilityButtonSpacer: + case AbilityButtonHelp: + case AbilityButtonMinimize: + case AbilityButtonMaximize: + case AbilityButtonClose: + case AbilityButtonAboveOthers: + case AbilityButtonBelowOthers: + case AbilityButtonShade: + // colors + case AbilityColorTitleBack: + case AbilityColorTitleBlend: + case AbilityColorTitleFore: + return true; + default: + return false; + }; +} + + +const QPixmap *KeramikHandler::tile( TilePixmap tilePix, bool active ) const +{ + return ( active ? activeTiles[ tilePix ] : inactiveTiles[ tilePix ] ); +} + +KDecoration* KeramikHandler::createDecoration( KDecorationBridge* bridge ) +{ + return new KeramikClient( bridge, this ); +} + +QList< KeramikHandler::BorderSize > KeramikHandler::borderSizes() const +{ // the list must be sorted + return QList< BorderSize >() << BorderNormal << BorderLarge << + BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized; +} + + +// ------------------------------------------------------------------------------------------- + + + +KeramikButton::KeramikButton( KeramikClient* c, Button btn, const QString &tip, const int realizeBtns ) + : QAbstractButton( c->widget() ), + client( c ), button( btn ), hover( false ), lastbutton( Qt::NoButton ) +{ + realizeButtons = realizeBtns; + + this->setToolTip( tip ); // FRAME + setAttribute( Qt::WA_NoSystemBackground ); + setCursor( Qt::ArrowCursor ); + int size = clientHandler->roundButton()->height(); + setFixedSize( size, size ); + + setCheckable( (button == OnAllDesktopsButton) ); +} + + +KeramikButton::~KeramikButton() +{ + // Empty. +} + + +void KeramikButton::enterEvent( QEvent *e ) +{ + QAbstractButton::enterEvent( e ); + + hover = true; + repaint(); +} + + +void KeramikButton::leaveEvent( QEvent *e ) +{ + QAbstractButton::leaveEvent( e ); + + hover = false; + repaint(); +} + + +void KeramikButton::mousePressEvent( QMouseEvent *e ) +{ + lastbutton = e->button(); + QMouseEvent me( e->type(), e->pos(), e->globalPos(), + (e->button()&realizeButtons)?Qt::LeftButton : Qt::NoButton, + (e->button()&realizeButtons)?Qt::LeftButton : Qt::NoButton, + e->modifiers() ); + QAbstractButton::mousePressEvent( &me ); +} + + +void KeramikButton::mouseReleaseEvent( QMouseEvent *e ) +{ + lastbutton = e->button(); + QMouseEvent me( e->type(), e->pos(), e->globalPos(), + (e->button()&realizeButtons)?Qt::LeftButton : Qt::NoButton, + (e->button()&realizeButtons)?Qt::LeftButton : Qt::NoButton, + e->modifiers() ); + QAbstractButton::mouseReleaseEvent( &me ); +} + + +void KeramikButton::paintEvent( QPaintEvent * ) +{ + const QPixmap *pix; + const QBitmap *deco; + int size = clientHandler->roundButton()->height(); + + QPainter p( this ); + + // Get the bevel from the client handler + if ( button == MenuButton || button == OnAllDesktopsButton || button == HelpButton ) + pix = clientHandler->roundButton(); + else + pix = clientHandler->squareButton(); + + // Draw the button background + const QPixmap *background = clientHandler->tile( TitleCenter, client->isActive() ); + p.drawPixmap( 0, 0, *background, + 0, (background->height()-size+1)/2, size, size ); + + if ( isDown() ) { + // Pressed + p.drawPixmap( QPoint(), *pix, QStyle::visualRect( QApplication::layoutDirection(), pix->rect(), QRect(2*size, 0, size, size) ) ); + p.translate( QApplication::isRightToLeft() ? -1 : 1, 1 ); + } else if ( hover ) + // Mouse over + p.drawPixmap( QPoint(), *pix, QStyle::visualRect( QApplication::layoutDirection(), pix->rect(), QRect(size, 0, size, size) ) ); + else + // Normal + p.drawPixmap( QPoint(), *pix, QStyle::visualRect( QApplication::layoutDirection(), pix->rect(), QRect(0, 0, size, size) ) ); + + + // Draw the button deco on the bevel + switch ( button ) { + case MenuButton: + deco = clientHandler->buttonDeco( Menu ); + break; + + case OnAllDesktopsButton: + deco = clientHandler->buttonDeco( client->isOnAllDesktops() ? NotOnAllDesktops : OnAllDesktops ); + break; + + case HelpButton: + deco = clientHandler->buttonDeco( Help ); + // The '?' won't be flipped around in the ctor, so we need to + // shift it to the right to compensate for the button shadow + // being on the left side of the button in RTL mode. + if ( QApplication::isRightToLeft() ) + p.translate( 2, 0 ); + break; + + case MinButton: + deco = clientHandler->buttonDeco( Minimize ); + break; + + case MaxButton: + deco = clientHandler->buttonDeco( client->maximizeMode() == KeramikClient::MaximizeFull ? Restore : Maximize ); + break; + + case CloseButton: + deco = clientHandler->buttonDeco( Close ); + break; + + case AboveButton: + deco = clientHandler->buttonDeco( client->keepAbove() ? AboveOn : AboveOff ); + break; + + case BelowButton: + deco = clientHandler->buttonDeco( client->keepBelow() ? BelowOn : BelowOff ); + break; + + case ShadeButton: + deco = clientHandler->buttonDeco( client->isSetShade() ? ShadeOn : ShadeOff ); + break; + + default: + deco = NULL; + } + + if (deco) + { + QPainterPath path; + path.addRegion( *deco ); + QPoint offset( (size-17)/2, (size-17)/2 ); + p.translate( offset ); + p.setPen( Qt::NoPen ); + p.setBrush( Qt::black ); + p.drawPath( path ); + } +} + + + +// ------------------------------------------------------------------------------------------ + + + +KeramikClient::KeramikClient( KDecorationBridge* bridge, KDecorationFactory* factory ) + : KDecoration( bridge, factory ), + activeIcon( NULL ), inactiveIcon( NULL ), captionBufferDirty( true ), maskDirty( true ) +{ +} + +void KeramikClient::init() +{ + connect( this, SIGNAL( keepAboveChanged( bool )), SLOT( keepAboveChange( bool ))); + connect( this, SIGNAL( keepBelowChanged( bool )), SLOT( keepBelowChange( bool ))); + + createMainWidget(); + widget()->setAttribute( Qt::WA_StaticContents ); + widget()->installEventFilter( this ); + + // Minimize flicker + widget()->setAttribute( Qt::WA_NoSystemBackground ); + + for ( int i=0; i < NumButtons; i++ ) + button[i] = NULL; + + createLayout(); +} + +void KeramikClient::createLayout() +{ + + QVBoxLayout *mainLayout = new QVBoxLayout( widget() ); + QBoxLayout *titleLayout = new QBoxLayout( QBoxLayout::LeftToRight ); + QHBoxLayout *windowLayout = new QHBoxLayout(); + + mainLayout->setMargin( 0 ); + mainLayout->setSpacing( 0 ); + + titleLayout->setMargin( 0 ); + titleLayout->setSpacing( 0 ); + + windowLayout->setMargin( 0 ); + windowLayout->setSpacing( 0 ); + + largeTitlebar = ( !maximizedVertical() && clientHandler->largeCaptionBubbles() ); + largeCaption = ( isActive() && largeTitlebar ); + + int grabBarHeight = clientHandler->grabBarHeight(); + int topSpacing = ( largeTitlebar ? 4 : 1 ); + int leftBorderWidth = clientHandler->tile( BorderLeft, true )->width(); + int rightBorderWidth = clientHandler->tile( BorderRight, true )->width(); + topSpacer = new QSpacerItem( 10, topSpacing, + QSizePolicy::Expanding, QSizePolicy::Minimum ); + + mainLayout->addItem( topSpacer ); + + mainLayout->addLayout( titleLayout ); // Titlebar + mainLayout->addLayout( windowLayout, 1 ); // Left border + window + right border + mainLayout->addSpacing( grabBarHeight ); // Bottom grab bar + + titleLayout->setSpacing( buttonSpacing ); + + titleLayout->addSpacing( buttonMargin ); // Left button margin + addButtons( titleLayout, options()->customButtonPositions() ? + options()->titleButtonsLeft() : KDecorationOptions::defaultTitleButtonsLeft() ); + + titlebar = new QSpacerItem( 10, clientHandler->titleBarHeight(largeTitlebar) + - topSpacing, QSizePolicy::Expanding, QSizePolicy::Minimum ); + titleLayout->addItem( titlebar ); + + titleLayout->addSpacing( buttonSpacing ); + addButtons( titleLayout, options()->customButtonPositions() ? + options()->titleButtonsRight() : KDecorationOptions::defaultTitleButtonsRight() ); + titleLayout->addSpacing( buttonMargin - 1 ); // Right button margin + + windowLayout->addSpacing( leftBorderWidth ); // Left border + if( isPreview()) + { + QWidget *previewWidget = new QLabel( i18n( "
Keramik preview
" ), widget() ); + previewWidget->setAutoFillBackground( true ); + windowLayout->addWidget( previewWidget ); + } + else + windowLayout->addItem( new QSpacerItem( 0, 0 )); //no widget in the middle + windowLayout->addSpacing( rightBorderWidth ); // Right border +} + + +KeramikClient::~KeramikClient() +{ + delete activeIcon; + delete inactiveIcon; + + activeIcon = inactiveIcon = NULL; +} + + +void KeramikClient::reset( unsigned long ) +{ + if ( clientHandler->largeCaptionBubbles() && !largeTitlebar ) + { + // We're switching from small caption bubbles to large + if ( !maximizedVertical() ) { + topSpacer->changeSize( 10, 4, QSizePolicy::Expanding, QSizePolicy::Minimum ); + largeTitlebar = true; + largeCaption = isActive(); + + widget()->layout()->activate(); + + // Compensate for the titlebar size change + + // TODO This is wrong, this may break size increments (see bug #53784). + // FRAME + widget()->setGeometry( widget()->x(), widget()->y() - 3, width(), height() + 3 ); + } + } + else if ( !clientHandler->largeCaptionBubbles() && largeTitlebar ) + { + // We're switching from large caption bubbles to small + topSpacer->changeSize( 10, 1, QSizePolicy::Expanding, QSizePolicy::Minimum ); + largeTitlebar = largeCaption = false; + + widget()->layout()->activate(); + + // Compensate for the titlebar size change + // FRAME + widget()->setGeometry( widget()->x(), widget()->y() + 3, width(), height() - 3 ); + } + + calculateCaptionRect(); + + captionBufferDirty = maskDirty = true; + + // Only repaint the window if it's visible + // (i.e. not minimized and on the current desktop) + if ( widget()->isVisible() ) { + widget()->repaint(); + + for ( int i = 0; i < NumButtons; i++ ) + if ( button[i] ) button[i]->repaint(); + } +} + + +void KeramikClient::addButtons( QBoxLayout *layout, const QString &s ) +{ + for ( int i=0; i < s.length(); i++ ) + { + switch ( s[i].toLatin1() ) + { + // Menu button + case 'M' : + if ( !button[MenuButton] ) { + button[MenuButton] = new KeramikButton( this, MenuButton, i18n("Menu"), Qt::LeftButton|Qt::RightButton ); + connect( button[MenuButton], SIGNAL( pressed() ), SLOT( menuButtonPressed() ) ); + layout->addWidget( button[MenuButton] ); + } + break; + + // OnAllDesktops button + case 'S' : + if ( !button[OnAllDesktopsButton] ) { + button[OnAllDesktopsButton] = new KeramikButton( this, + OnAllDesktopsButton, isOnAllDesktops()?i18n("Not on all desktops"):i18n("On all desktops") ); + if(isOnAllDesktops()) + button[OnAllDesktopsButton]->toggle(); + connect( button[OnAllDesktopsButton], SIGNAL( clicked() ), SLOT( toggleOnAllDesktops() ) ); + layout->addWidget( button[OnAllDesktopsButton] ); + } + break; + + // Help button + case 'H' : + if ( !button[HelpButton] && providesContextHelp() ) { + button[HelpButton] = new KeramikButton( this, HelpButton, i18n("Help") ); + connect( button[HelpButton], SIGNAL( clicked() ), SLOT( showContextHelp() ) ); + layout->addWidget( button[HelpButton] ); + } + break; + + // Minimize button + case 'I' : + if ( !button[MinButton] && isMinimizable() ) { + button[MinButton] = new KeramikButton( this, MinButton, i18n("Minimize") ); + connect( button[MinButton], SIGNAL( clicked() ), SLOT( minimize() ) ); + layout->addWidget( button[MinButton] ); + } + break; + + // Maximize button + case 'A' : + if ( !button[MaxButton] && isMaximizable() ) { + button[MaxButton] = new KeramikButton( this, MaxButton, i18n("Maximize"), Qt::LeftButton|Qt::MidButton|Qt::RightButton ); + connect( button[MaxButton], SIGNAL( clicked() ), SLOT( slotMaximize() ) ); + layout->addWidget( button[MaxButton] ); + } + break; + + // Close button + case 'X' : + if ( !button[CloseButton] && isCloseable() ) { + button[CloseButton] = new KeramikButton( this, CloseButton, i18n("Close") ); + connect( button[CloseButton], SIGNAL( clicked() ), SLOT( closeWindow() ) ); + layout->addWidget( button[CloseButton] ); + } + break; + + // Above button + case 'F' : + if ( !button[AboveButton]) { + button[AboveButton] = new KeramikButton( this, AboveButton, i18n("Keep Above Others") ); + connect( button[AboveButton], SIGNAL( clicked() ), SLOT( slotAbove() ) ); + layout->addWidget( button[AboveButton] ); + } + break; + + // Below button + case 'B' : + if ( !button[BelowButton]) { + button[BelowButton] = new KeramikButton( this, BelowButton, i18n("Keep Below Others") ); + connect( button[BelowButton], SIGNAL( clicked() ), SLOT( slotBelow() ) ); + layout->addWidget( button[BelowButton] ); + } + break; + + // Shade button + case 'L' : + if ( !button[ShadeButton] && isShadeable() ) { + button[ShadeButton] = new KeramikButton( this, ShadeButton, + isSetShade() ? i18n("Unshade") : i18n( "Shade" )); + connect( button[ShadeButton], SIGNAL( clicked() ), SLOT( slotShade() ) ); + layout->addWidget( button[ShadeButton] ); + } + break; + + // Additional spacing + case '_' : + layout->addSpacing( buttonSpacing ); + break; + } + } +} + + +void KeramikClient::updateMask() +{ + if ( !keramik_initialized ) + return; + + // To maximize performance this code uses precalculated bounding rects + // to set the window mask. This saves us from having to allocate a 1bpp + // pixmap, paint the mask on it and then have the X server iterate + // over the pixels to compute the bounding rects from it. + + QRegion r; + register int w, y = 0; + int nrects; + + if ( QApplication::isRightToLeft() ) { + + // If the caption bubble is visible and extends above the titlebar + if ( largeCaption && captionRect.width() >= 25 ) { + register int x = captionRect.left(); + w = captionRect.width(); + r += QRegion( x + 11, y++, w - 19, 1 ); + r += QRegion( x + 9, y++, w - 15, 1 ); + r += QRegion( x + 7, y++, w - 12, 1 ); + } else { + nrects = 8; + + // Do we have a large titlebar with a retracted caption bubble? + // (i.e. the style is set to use large caption bubbles, we're + // not maximized and not active) + if ( largeTitlebar ) + y = 3; + } + + w = width(); // FRAME + + // The rounded titlebar corners + r += QRegion( 9, y++, w - 17, 1 ); + r += QRegion( 7, y++, w - 13, 1 ); + r += QRegion( 5, y++, w - 9, 1 ); + r += QRegion( 4, y++, w - 7, 1 ); + r += QRegion( 3, y++, w - 5, 1 ); + r += QRegion( 2, y++, w - 4, 1 ); + r += QRegion( 1, y++, w - 2, 2 ); + } else { + + // If the caption bubble is visible and extends above the titlebar + if ( largeCaption && captionRect.width() >= 25 ) { + nrects = 11; + register int x = captionRect.left(); + w = captionRect.width(); + r += QRegion( x + 8, y++, w - 19, 1 ); + r += QRegion( x + 6, y++, w - 15, 1 ); + r += QRegion( x + 5, y++, w - 12, 1 ); + } else { + nrects = 8; + + // Do we have a large titlebar with a retracted caption bubble? + // (i.e. the style is set to use large caption bubbles, we're + // not maximized and not active) + if ( largeTitlebar ) + y = 3; + } + + w = width(); // FRAME + + // The rounded titlebar corners + r += QRegion( 8, y++, w - 17, 1 ); + r += QRegion( 6, y++, w - 13, 1 ); + r += QRegion( 4, y++, w - 9, 1 ); + r += QRegion( 3, y++, w - 7, 1 ); + r += QRegion( 2, y++, w - 5, 1 ); + r += QRegion( 2, y++, w - 4, 1 ); + r += QRegion( 1, y++, w - 2, 2 ); + } + + y++; + + // The part of the window below the titlebar + r += QRegion( 0, y, w, height() - y ); + + setMask( r, YXBanded ); + + maskDirty = false; +} + + +void KeramikClient::updateCaptionBuffer() +{ + if ( !keramik_initialized ) + return; + + bool active = isActive(); + QPixmap *icon = NULL; + + if ( captionBuffer.size() != captionRect.size() ) + captionBuffer = QPixmap( captionRect.size() ); + + if ( captionBuffer.isNull() ) + return; + + QPainter p( &captionBuffer ); + + // Draw the caption bubble + if ( active && largeCaption ) { + p.drawPixmap( 0, 0, *clientHandler->tile( CaptionLargeLeft, true ) ); + p.drawTiledPixmap( 15, 0, captionRect.width() - 30, captionRect.height(), + *clientHandler->tile( CaptionLargeCenter, true ) ); + p.drawPixmap( captionRect.width() - 15, 0, *clientHandler->tile( CaptionLargeRight, true ) ); + } else { + p.drawPixmap( 0, 0, *clientHandler->tile( CaptionSmallLeft, active ) ); + p.drawTiledPixmap( 15, 0, captionRect.width() - 30, captionRect.height(), + *clientHandler->tile( CaptionSmallCenter, active ) ); + p.drawPixmap( captionRect.width() - 15, 0, *clientHandler->tile( CaptionSmallRight, active ) ); + } + + if ( clientHandler->showAppIcons() ) + { + QStyle *style = QApplication::style(); + if ( active ) { + if ( ! activeIcon ) + activeIcon = new QPixmap( this->icon().pixmap( style->pixelMetric( QStyle::PM_SmallIconSize ), QIcon::Normal )); // FRAME + icon = activeIcon; + } else { + if ( ! inactiveIcon ) { + QImage img = this->icon().pixmap( style->pixelMetric( QStyle::PM_SmallIconSize ), QIcon::Normal ).toImage(); + KIconEffect::semiTransparent( img ); + inactiveIcon = new QPixmap( QPixmap::fromImage( img ) ); + } + icon = inactiveIcon; + } + } + + p.setFont( options()->font( active ) ); + int tw = p.fontMetrics().width( caption() ) + + ( clientHandler->showAppIcons() ? 16 + iconSpacing : 0 ); + + int xpos = qMax( (captionRect.width() - tw) / 3, 8 ); + QRect tr = QStyle::visualRect( QApplication::layoutDirection(), captionBuffer.rect(), + QRect(xpos, 1, captionRect.width() - xpos - 10, captionRect.height() - 4) ); + + //p.setPen( Qt::red ); // debug + //p.drawRect( tr ); // debug + + // Application icon + if ( clientHandler->showAppIcons() ) + { + QRect iconRect = QStyle::visualRect( QApplication::layoutDirection(), tr, + QRect(tr.x(), 1 + (captionRect.height() - 4 - 16) / 2, 16, 16) ); + QRect r( icon->rect() ); + r.moveCenter( iconRect.center() ); + + if ( tr.width() > 16 ) { + p.drawPixmap( r, *icon ); + } else { + QRect sr( 0, 0, icon->width(), icon->height() ); + + if ( QApplication::isRightToLeft() ) + sr.adjust( icon->width() - tr.width(), 0, 0, 0 ); + else + sr.adjust( 0, 0, -( icon->width() - tr.width() ), 0 ); + + p.drawPixmap( r.x() + sr.x(), r.y() + sr.y(), *icon, + sr.x(), sr.y(), sr.width(), sr.height() ); + } + + //p.drawRect( r ); // debug + + if ( QApplication::isRightToLeft() ) + tr.adjust( 0, 0, -(16 + iconSpacing), 0 ); + else + tr.adjust( (16 + iconSpacing), 0, 0, 0 ); + } + + // Draw the titlebar text + int flags = Qt::AlignVCenter | Qt::TextSingleLine; + flags |= ( QApplication::isRightToLeft() ? Qt::AlignRight : Qt::AlignLeft ); + + if ( clientHandler->useShadowedText() ) + { + p.translate( QApplication::isRightToLeft() ? -1 : 1, 1 ); + //p.setPen( options()->color(ColorTitleBar, active).dark() ); + if (qGray(options()->color(ColorFont, active).rgb()) < 100) + p.setPen( QColor(200,200,200) ); + else + p.setPen( Qt::black ); + p.drawText( tr, flags, caption() ); + p.translate( QApplication::isRightToLeft() ? 1 : -1, -1 ); + } + + p.setPen( options()->color( ColorFont, active ) ); + p.drawText( tr, flags, caption() ); + + captionBufferDirty = false; +} + + +void KeramikClient::calculateCaptionRect() +{ + QFontMetrics fm( options()->font(isActive()) ); + int cw = fm.width( caption() ) + 95; + int titleBaseY = ( largeTitlebar ? 3 : 0 ); + + if ( clientHandler->showAppIcons() ) + cw += 16 + 4; // icon width + space + + cw = qMin( cw, titlebar->geometry().width() ); + captionRect = QStyle::visualRect( QApplication::layoutDirection(), titlebar->geometry(), + QRect(titlebar->geometry().x(), (largeCaption ? 0 : titleBaseY), + cw, clientHandler->titleBarHeight(largeCaption) ) ); +} + + +void KeramikClient::captionChange() +{ + QRect r( captionRect ); + calculateCaptionRect(); + + if ( r.size() != captionRect.size() ) + maskDirty = true; + + captionBufferDirty = true; + + widget()->repaint( r | captionRect ); +} + + +void KeramikClient::iconChange() +{ + if ( clientHandler->showAppIcons() ) { + + // Force updateCaptionBuffer() to recreate the cached icons + delete activeIcon; + + delete inactiveIcon; + + activeIcon = inactiveIcon = NULL; + + captionBufferDirty = true; + widget()->repaint( captionRect ); + } +} + + +void KeramikClient::activeChange() +{ + bool active = isActive(); + // Note: It's assumed that the same font will always be used for both active + // and inactive windows, since the fonts kcm hasn't supported setting + // different fonts for different window states for some time. + if ( largeTitlebar ) { + largeCaption = ( active && !maximizedVertical() ); + calculateCaptionRect(); + maskDirty = true; + } + + captionBufferDirty = true; + + widget()->repaint(); + + for ( int i=0; i < NumButtons; i++ ) + if ( button[i] ) button[i]->repaint(); +} + + +void KeramikClient::maximizeChange() +{ + if ( clientHandler->largeCaptionBubbles() ) + { + if ( maximizeMode() & MaximizeVertical ) { + // We've been maximized - shrink the titlebar by 3 pixels + topSpacer->changeSize( 10, 1, QSizePolicy::Expanding, QSizePolicy::Minimum ); + largeCaption = largeTitlebar = false; + + calculateCaptionRect(); + captionBufferDirty = maskDirty = true; + + widget()->layout()->activate(); + widget()->repaint(); + } else if (( maximizeMode() & MaximizeVertical ) == 0 && !largeTitlebar ) { + // We've been restored - enlarge the titlebar by 3 pixels + topSpacer->changeSize( 10, 4, QSizePolicy::Expanding, QSizePolicy::Minimum ); + largeCaption = largeTitlebar = true; + + calculateCaptionRect(); + captionBufferDirty = maskDirty = true; + + widget()->layout()->activate(); + widget()->repaint(); + } + } + + if ( button[ MaxButton ] ) { + button[ MaxButton ]->setToolTip( maximizeMode() == MaximizeFull ? i18n("Restore") : i18n("Maximize") ); + button[ MaxButton ]->repaint(); + } +} + + +void KeramikClient::desktopChange() +{ + if ( button[ OnAllDesktopsButton ] ) + { + button[ OnAllDesktopsButton ]->repaint(); + button[ OnAllDesktopsButton ]->setToolTip( isOnAllDesktops() ? i18n("Not on all desktops") : i18n("On all desktops") ); + } +} + + +void KeramikClient::shadeChange() +{ + if ( button[ ShadeButton ] ) + { + button[ ShadeButton ]->repaint(); + button[ ShadeButton ]->setToolTip( isSetShade() ? i18n("Unshade") : i18n("Shade") ); + } +} + + +void KeramikClient::keepAboveChange( bool ) +{ + if ( button[ AboveButton ] ) + button[ AboveButton ]->repaint(); +} + + +void KeramikClient::keepBelowChange( bool ) +{ + if ( button[ BelowButton ] ) + button[ BelowButton ]->repaint(); +} + + +void KeramikClient::menuButtonPressed() +{ + QPoint menuTop ( button[MenuButton]->rect().topLeft() ); + QPoint menuBottom ( button[MenuButton]->rect().bottomRight() ); + menuTop += QPoint(-6, -3); + menuBottom += QPoint(6, 3); + KDecorationFactory* f = factory(); + showWindowMenu( QRect( button[MenuButton]->mapToGlobal( menuTop ), + button[MenuButton]->mapToGlobal( menuBottom )) ); + if( !f->exists( this )) // 'this' was destroyed + return; + button[MenuButton]->setDown(false); +} + + +void KeramikClient::slotMaximize() +{ + maximize( button[ MaxButton ]->lastButton() ); +} + + +void KeramikClient::slotAbove() +{ + setKeepAbove( !keepAbove()); + button[ AboveButton ]->repaint(); +} + + +void KeramikClient::slotBelow() +{ + setKeepBelow( !keepBelow()); + button[ BelowButton ]->repaint(); +} + + +void KeramikClient::slotShade() +{ + setShade( !isSetShade()); + button[ ShadeButton ]->repaint(); +} + + +void KeramikClient::paintEvent( QPaintEvent *e ) +{ + if ( !keramik_initialized ) + return; + + QPainter p( widget()); + QRect updateRect( e->rect() ); + bool active = isActive(); + + int titleBaseY = ( largeTitlebar ? 3 : 0 ); + int titleBarHeight = clientHandler->titleBarHeight( largeTitlebar ); + int grabBarHeight = clientHandler->grabBarHeight(); + int leftBorderWidth = clientHandler->tile( BorderLeft, active )->width(); + int rightBorderWidth = clientHandler->tile( BorderRight, active )->width(); + + if ( maskDirty ) + updateMask(); + + // Titlebar + // ----------------------------------------------------------------------- + if ( updateRect.y() < titleBarHeight ) + { + int titleBarBaseHeight = titleBarHeight - titleBaseY; + + if ( captionBufferDirty ) + updateCaptionBuffer(); + + // Top left corner + if ( updateRect.x() < 15 ) + p.drawPixmap( 0, titleBaseY, + *clientHandler->tile( TitleLeft, active ) ); + + // Space between the top left corner and the caption bubble + if ( updateRect.x() < captionRect.left() && updateRect.right() >= 15 ) { + int x1 = qMax( 15, updateRect.x() ); + int x2 = qMin( captionRect.left(), updateRect.right() ); + + p.drawTiledPixmap( x1, titleBaseY, x2 - x1 + 1, titleBarBaseHeight, + *clientHandler->tile( TitleCenter, active ) ); + } + + // Caption bubble + if ( updateRect.x() <= captionRect.right() && updateRect.right() > 15 ) { + if ( captionRect.width() >= 25 ) + p.drawPixmap( captionRect.left(), active ? 0 : titleBaseY, captionBuffer ); + else + p.drawTiledPixmap( captionRect.x(), titleBaseY, captionRect.width(), + titleBarBaseHeight, *clientHandler->tile( TitleCenter, active ) ); + } + + // Space between the caption bubble and the top right corner + if ( updateRect.right() > captionRect.right() && updateRect.x() < width() - 15 ) { // FRAME + int x1 = qMax( captionRect.right() + 1, updateRect.x() ); + int x2 = qMin( width() - 15, updateRect.right() ); + + p.drawTiledPixmap( x1, titleBaseY, x2 - x1 + 1, titleBarBaseHeight, + *clientHandler->tile( TitleCenter, active ) ); + } + + // Top right corner + if ( updateRect.right() >= width() - 15 ) + p.drawPixmap( width() - 15, titleBaseY, + *clientHandler->tile( TitleRight, active ) ); + } + + // Borders + // ----------------------------------------------------------------------- + if ( updateRect.bottom() >= titleBarHeight && + updateRect.top() < height() - grabBarHeight ) + { + int top = qMax( titleBarHeight, updateRect.top() ); + int bottom = qMin( updateRect.bottom(), height() - grabBarHeight ); + + // Left border + if ( updateRect.x() < leftBorderWidth ) + p.drawTiledPixmap( 0, top, leftBorderWidth, bottom - top + 1, + *clientHandler->tile( BorderLeft, active ) ); + + // Right border + if ( e->rect().right() > width() - rightBorderWidth - 1 ) + p.drawTiledPixmap( width() - rightBorderWidth, top, rightBorderWidth, + bottom - top + 1, *clientHandler->tile( BorderRight, active ) ); + } + + // Bottom grab bar + // ----------------------------------------------------------------------- + if ( updateRect.bottom() >= height() - grabBarHeight ) { + // Bottom left corner + if ( updateRect.x() < 9 ) + p.drawPixmap( 0, height() - grabBarHeight, + *clientHandler->tile( GrabBarLeft, active ) ); + + // Space between the left corner and the right corner + if ( updateRect.x() < width() - 9 ) { + int x1 = qMax( 9, updateRect.x() ); + int x2 = qMin( width() - 9, updateRect.right() ); + + p.drawTiledPixmap( x1, height() - grabBarHeight, x2 - x1 + 1, + grabBarHeight, *clientHandler->tile( GrabBarCenter, active ) ); + } + + // Bottom right corner + if ( updateRect.right() > width() - 9 ) + p.drawPixmap( width() - 9, height() - grabBarHeight, + *clientHandler->tile( GrabBarRight, active ) ); + } + + // Extra drawline for the 1 pixel empty space QLayout leaves when a window is shaded. + p.setPen( options()->color( ColorTitleBlend, active ) ); + p.drawLine( leftBorderWidth, height() - grabBarHeight - 1, + width() - rightBorderWidth - 1, height() - grabBarHeight - 1 ); +} + + +void KeramikClient::resizeEvent( QResizeEvent *e ) +{ +// FRAME Client::resizeEvent( e ); + + QRect r( captionRect ); + calculateCaptionRect(); + + if ( r.size() != captionRect.size() ) + captionBufferDirty = true; + + maskDirty = true; + + if ( widget()->isVisible() ) + { + widget()->update( widget()->rect() ); + int dx = 0; + int dy = 0; + + if ( e->oldSize().width() != width() ) + dx = 32 + qAbs( e->oldSize().width() - width() ); + + if ( e->oldSize().height() != height() ) + dy = 8 + qAbs( e->oldSize().height() - height() ); + + if ( dy ) + widget()->update( 0, height() - dy + 1, width(), dy ); + + if ( dx ) + { + widget()->update( width() - dx + 1, 0, dx, height() ); + widget()->update( QRect( QPoint(4,4), titlebar->geometry().bottomLeft() - QPoint(1,0) ) ); + widget()->update( QRect( titlebar->geometry().topRight(), QPoint( width() - 4, + titlebar->geometry().bottom() ) ) ); + // Titlebar needs no paint event + QApplication::postEvent( this, new QPaintEvent( titlebar->geometry() ) ); + } + } +} + + +void KeramikClient::mouseDoubleClickEvent( QMouseEvent *e ) +{ + if ( e->button() == Qt::LeftButton + && QRect( 0, 0, width(), clientHandler->titleBarHeight( largeTitlebar ) ).contains( e->pos() ) ) + titlebarDblClickOperation(); +} + + +KeramikClient::Position KeramikClient::mousePosition( const QPoint &p ) const +{ + int titleBaseY = (largeTitlebar ? 3 : 0); + + int leftBorder = clientHandler->tile( BorderLeft, true )->width(); + int rightBorder = width() - clientHandler->tile( BorderRight, true )->width() - 1; + int bottomBorder = height() - clientHandler->grabBarHeight() - 1; + int bottomCornerSize = 3*clientHandler->tile( BorderRight, true )->width()/2 + 24; + + // Test if the mouse is over the titlebar area + if ( p.y() < titleBaseY + 11 ) { + // Test for the top left corner + if ( p.x() < leftBorder + 11 ) { + if ( (p.y() < titleBaseY + 3 && p.x() < leftBorder + 11) || + (p.y() < titleBaseY + 6 && p.x() < leftBorder + 6) || + (p.y() < titleBaseY + 11 && p.x() < leftBorder + 3) ) + return PositionTopLeft; + } + + // Test for the top right corner + if ( p.x() > rightBorder - 11 ) { + if ( (p.y() < titleBaseY + 3 && p.x() > rightBorder - 11) || + (p.y() < titleBaseY + 6 && p.x() > rightBorder - 6) || + (p.y() < titleBaseY + 11 && p.x() > rightBorder - 3) ) + return PositionTopRight; + } + + // Test for the top border + if ( p.y() <= 3 || (p.y() <= titleBaseY+3 && + (p.x() < captionRect.left() || p.x() > captionRect.right()) ) ) + return PositionTop; + + // The cursor must be over the center of the titlebar. + return PositionCenter; + } + + // Test the sides + else if ( p.y() < bottomBorder ) { + // Test for the left side + if ( p.x() < leftBorder ) { + if ( p.y() < height() - bottomCornerSize ) + return PositionLeft; + else + return PositionBottomLeft; + } + + // Test for the right side + else if ( p.x() > rightBorder ) { + if ( p.y() < height() - bottomCornerSize ) + return PositionRight; + else + return PositionBottomRight; + } + + // The cursor must be over the center of the window + return PositionCenter; + } + + // Test the grab bar / bottom border + else { + // Test for the bottom left corner + if ( p.x() < bottomCornerSize ) + return PositionBottomLeft; + + // Test for the bottom right corner + else if ( p.x() > width() - bottomCornerSize - 1 ) + return PositionBottomRight; + + // The cursor must be over the bottom border + return PositionBottom; + } + + // We should never get here + return PositionCenter; +} + + +void KeramikClient::resize( const QSize& s ) +{ + widget()->resize( s ); +} + + +void KeramikClient::borders( int& left, int& right, int& top, int& bottom ) const +{ + int titleBarHeight = clientHandler->titleBarHeight( clientHandler->largeCaptionBubbles() ); + int grabBarHeight = clientHandler->grabBarHeight(); + int leftBorderWidth = clientHandler->tile( BorderLeft, isActive() )->width(); + int rightBorderWidth = clientHandler->tile( BorderRight, isActive() )->width(); + + left = leftBorderWidth; + right = rightBorderWidth; + top = titleBarHeight; + bottom = grabBarHeight; + + if ( ( maximizeMode() & MaximizeHorizontal ) && !options()->moveResizeMaximizedWindows()) + left = right = 0; + if( maximizeMode() & MaximizeVertical) + { + top = clientHandler->titleBarHeight( false ); + if( !options()->moveResizeMaximizedWindows()) + bottom = 0; + } +} + + +QSize KeramikClient::minimumSize() const +{ + return widget()->minimumSize(); +} + + +bool KeramikClient::eventFilter( QObject* o, QEvent* e ) +{ + if ( o != widget() ) + return false; + + switch ( e->type() ) + { + case QEvent::Resize: + resizeEvent( static_cast< QResizeEvent* >( e ) ); + return true; + + case QEvent::Paint: + paintEvent( static_cast< QPaintEvent* >( e ) ); + return true; + + case QEvent::MouseButtonDblClick: + mouseDoubleClickEvent( static_cast< QMouseEvent* >( e ) ); + return true; + + case QEvent::MouseButtonPress: + processMousePressEvent( static_cast< QMouseEvent* >( e ) ); + return true; + + default: + return false; + } +} + +} // namespace Keramik + + + +// ------------------------------------------------------------------------------------------- + + + +extern "C" +{ + KDE_EXPORT KDecorationFactory *create_factory() + { + Keramik::clientHandler = new Keramik::KeramikHandler(); + return Keramik::clientHandler; + } +} + + + +// vim: set noet ts=4 sw=4: diff --git a/clients/keramik/keramik.desktop b/clients/keramik/keramik.desktop new file mode 100644 index 0000000000..97a6fd19ec --- /dev/null +++ b/clients/keramik/keramik.desktop @@ -0,0 +1,91 @@ +[Desktop Entry] +Name=Keramik +Name[af]=Keramik +Name[ar]=كيراميك +Name[be]=Keramik +Name[be@latin]=Keramik +Name[bg]=Keramik +Name[bn]=কেরামিক +Name[bn_IN]=Keramik +Name[br]=Keramik +Name[ca]=Keramik +Name[ca@valencia]=Keramik +Name[cs]=Keramika +Name[csb]=Keramik +Name[cy]=Keramik +Name[da]=Keramik +Name[de]=Keramik +Name[el]=Keramik +Name[en_GB]=Keramik +Name[eo]=Keramik +Name[es]=Keramik +Name[et]=Keramik +Name[eu]=Keramik +Name[fa]=کرامیک +Name[fi]=Keramik +Name[fr]=Keramik +Name[fy]=Keramyk +Name[ga]=Keramik +Name[gl]=Keramik +Name[gu]=કેરામિક +Name[he]=Keramik +Name[hi]=केरामिक +Name[hne]=केरामिक +Name[hr]=Keramik +Name[hsb]=Keramik +Name[hu]=Keramik +Name[ia]=Keramik +Name[id]=Keramik +Name[is]=Keramík +Name[it]=Ceramica +Name[ja]=Keramik +Name[ka]=Keramik +Name[kk]=Керамика +Name[km]=Keramik +Name[kn]=ಕೆರಾಮಿಕ್ +Name[ko]=Keramik +Name[ku]=Keramik +Name[lt]=Keramik +Name[lv]=Keramik +Name[mai]=केरामिक +Name[mk]=Керамик +Name[ml]=കെരാമിക് +Name[mr]=केरामिक +Name[ms]=Keramik +Name[nb]=Keramik +Name[nds]=Keramik +Name[ne]=केरामिक +Name[nl]=Keramik +Name[nn]=Keramikk +Name[oc]=Keramik +Name[or]=Keramik +Name[pa]=ਕੀਰਾਮਿਕ +Name[pl]=Keramik +Name[pt]=Keramik +Name[pt_BR]=Keramik +Name[ro]=Keramik +Name[ru]=Керамика +Name[se]=Bálseduodji +Name[si]=Keramik +Name[sk]=Keramik +Name[sl]=Keramik +Name[sr]=Керамика +Name[sr@ijekavian]=Керамика +Name[sr@ijekavianlatin]=Keramika +Name[sr@latin]=Keramika +Name[sv]=Keramik +Name[ta]=கெராமிக் +Name[te]=కెరామిక్ +Name[tg]=Keramik +Name[th]=รูปแบบเครามิก +Name[tr]=Keramik +Name[uk]=Керамік +Name[uz]=Keramika +Name[uz@cyrillic]=Керамика +Name[vi]=Gốm +Name[wa]=Keramik +Name[xh]=Keramik +Name[x-test]=xxKeramikxx +Name[zh_CN]=Keramik +Name[zh_TW]=Keramik +X-KDE-Library=kwin3_keramik diff --git a/clients/keramik/keramik.h b/clients/keramik/keramik.h new file mode 100644 index 0000000000..9cf1b9321f --- /dev/null +++ b/clients/keramik/keramik.h @@ -0,0 +1,198 @@ +/* + * + * Keramik KWin client (version 0.8) + * + * Copyright (C) 2002 Fredrik Höglund + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the license, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __KERAMIK_H +#define __KERAMIK_H + +#include +#include +#include + +class QSpacerItem; +class QBoxLayout; + +namespace Keramik { + + enum TilePixmap { TitleLeft=0, TitleCenter, TitleRight, + CaptionSmallLeft, CaptionSmallCenter, CaptionSmallRight, + CaptionLargeLeft, CaptionLargeCenter, CaptionLargeRight, + GrabBarLeft, GrabBarCenter, GrabBarRight, + BorderLeft, BorderRight, NumTiles }; + + enum Button { MenuButton=0, OnAllDesktopsButton, HelpButton, MinButton, + MaxButton, CloseButton, AboveButton, BelowButton, ShadeButton, + NumButtons }; + + enum ButtonDeco { Menu=0, OnAllDesktops, NotOnAllDesktops, Help, Minimize, Maximize, + Restore, Close, AboveOn, AboveOff, BelowOn, BelowOff, ShadeOn, ShadeOff, + NumButtonDecos }; + + struct SettingsCache + { + bool largeGrabBars:1; + bool smallCaptionBubbles:1; + }; + + class KeramikHandler : public KDecorationFactory + { + public: + KeramikHandler(); + ~KeramikHandler(); + + virtual QList< BorderSize > borderSizes() const; + virtual bool reset( unsigned long changed ); + virtual KDecoration* createDecoration( KDecorationBridge* ); + virtual bool supports( Ability ability ) const; + + bool showAppIcons() const { return showIcons; } + bool useShadowedText() const { return shadowedText; } + bool largeCaptionBubbles() const { return !smallCaptionBubbles; } + + int titleBarHeight( bool large ) const { + return ( large ? activeTiles[CaptionLargeCenter]->height() + : activeTiles[CaptionSmallCenter]->height() ); + } + + int grabBarHeight() const + { return activeTiles[GrabBarCenter]->height(); } + + const QPixmap *roundButton() const { return titleButtonRound; } + const QPixmap *squareButton() const { return titleButtonSquare; } + const QBitmap *buttonDeco( ButtonDeco deco ) const + { return buttonDecos[ deco ]; } + + inline const QPixmap *tile( TilePixmap tilePix, bool active ) const; + + private: + void readConfig(); + void createPixmaps(); + void destroyPixmaps(); + + void addWidth (int width, QPixmap *&pix, bool left, QPixmap *bottomPix); + void addHeight (int height, QPixmap *&pix); + void flip( QPixmap *&, QPixmap *& ); + void pretile( QPixmap *&, int, Qt::Orientation ); + QPixmap *composite( QImage *, QImage * ); + QImage *loadImage( const QString &, const QColor & ); + QPixmap *loadPixmap( const QString &, const QColor & ); + + bool showIcons:1, shadowedText:1, + smallCaptionBubbles:1, largeGrabBars:1; + SettingsCache *settings_cache; + + QPixmap *activeTiles[ NumTiles ]; + QPixmap *inactiveTiles[ NumTiles ]; + QBitmap *buttonDecos[ NumButtonDecos ]; + + QPixmap *titleButtonRound, *titleButtonSquare; + + }; // class KeramikHandler + + class KeramikClient; + class KeramikButton : public QAbstractButton + { + public: + KeramikButton( KeramikClient *, Button, const QString &, const int realizeBtns = Qt::LeftButton ); + ~KeramikButton(); + + Qt::MouseButtons lastButton() const { return lastbutton; } + + private: + void enterEvent( QEvent * ); + void leaveEvent( QEvent * ); + void mousePressEvent( QMouseEvent * ); + void mouseReleaseEvent( QMouseEvent * ); + void paintEvent( QPaintEvent * ); + + private: + KeramikClient *client; + Button button; + bool hover; + Qt::MouseButtons lastbutton; + int realizeButtons; + }; // class KeramikButton + + + class KeramikClient : public KDecoration + { + Q_OBJECT + + public: + + KeramikClient( KDecorationBridge* bridge, KDecorationFactory* factory ); + ~KeramikClient(); + virtual void init(); + virtual void reset( unsigned long changed ); + virtual Position mousePosition( const QPoint& p ) const; + virtual void borders( int& left, int& right, int& top, int& bottom ) const; + virtual void resize( const QSize& s ); + virtual QSize minimumSize() const; + virtual bool eventFilter( QObject* o, QEvent* e ); + virtual void activeChange(); + virtual void captionChange(); + virtual void maximizeChange(); + virtual void desktopChange(); + virtual void shadeChange(); + + private: + void createLayout(); + void addButtons( QBoxLayout*, const QString & ); + void updateMask(); // FRAME + void updateCaptionBuffer(); + void iconChange(); + void resizeEvent( QResizeEvent *); // FRAME + void paintEvent( QPaintEvent *); // FRAME + void mouseDoubleClickEvent( QMouseEvent * ); // FRAME + int width() const { return widget()->width(); } + int height() const { return widget()->height(); } + + void calculateCaptionRect(); + + inline bool maximizedVertical() const { + return ( maximizeMode() & MaximizeVertical ); + } + + private slots: + void menuButtonPressed(); + void slotMaximize(); + void slotAbove(); + void slotBelow(); + void slotShade(); + void keepAboveChange( bool ); + void keepBelowChange( bool ); + + private: + QSpacerItem *topSpacer, *titlebar; + KeramikButton *button[ NumButtons ]; + QRect captionRect; + QPixmap captionBuffer; + QPixmap *activeIcon, *inactiveIcon; + bool captionBufferDirty:1, maskDirty:1; + bool largeCaption:1, largeTitlebar:1; + }; // class KeramikClient + +} // namespace Keramik + +#endif // ___KERAMIK_H + +// vim: set noet ts=4 sw=4: diff --git a/clients/keramik/pics/border-left.png b/clients/keramik/pics/border-left.png new file mode 100644 index 0000000000000000000000000000000000000000..121e850e4f9a7c65216bfe674aa35ea34afe40d8 GIT binary patch literal 126 zcmeAS@N?(olHy`uVBq!ia0vp^%s?!_0VEi{G0qADQk(@Ik;M!Q+&m!6Xz!qO0w~B{ z;_2(keu;-sP)^q6Ec-&B5L1%3y9>kr_Wm>bfjoXs7sn8ZsmXWFZ=hoY literal 0 HcmV?d00001 diff --git a/clients/keramik/pics/border-right.png b/clients/keramik/pics/border-right.png new file mode 100644 index 0000000000000000000000000000000000000000..8384374f9167fd7c6e5d993211e992aa6ff3c9e5 GIT binary patch literal 127 zcmeAS@N?(olHy`uVBq!ia0vp^EI=&40VEhi?l$TJDb50q$YKTtZXOV3w0BTC0Tg5} z@$_|Nzr@2RC~x*L>-++s5L1%3y9>kr_Wm>bfjj|E7sn8ZsmW(J(`Fp=uw`Nh^A%0x TIG?i%D97OG>gTe~DWM4f{hb|f literal 0 HcmV?d00001 diff --git a/clients/keramik/pics/bottom-center.png b/clients/keramik/pics/bottom-center.png new file mode 100644 index 0000000000000000000000000000000000000000..67c6bc161a3e310b69e7ff2de9b296cb12ef5c39 GIT binary patch literal 131 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~d0VEg}-G5*Jq&N#aB8wRqxcNbtaneubr9eUU z5>H=O_DejBf(m?%+hUo3LQF~C?k)`f+xyS#2l7NbT^vIsrY6rh-oPdCU08&}RhWSx Xx0R`EVP9elP@cil)z4*}Q$iB}yHp;0 literal 0 HcmV?d00001 diff --git a/clients/keramik/pics/bottom-left.png b/clients/keramik/pics/bottom-left.png new file mode 100644 index 0000000000000000000000000000000000000000..9c73d863578815411904fd8b16d42cb45d5d0e89 GIT binary patch literal 134 zcmeAS@N?(olHy`uVBq!ia0vp^oIuRN0VEhIQ@n&g0tFtC#S9GG{2`sfB_2jWMgI4zVy*&(n3BBRT^Rni_n+Ahzf2y2>!JBqQl`st+ a28Ji0VoD)K%!`0Z7(8A5T-G@yGywqX1|M7i literal 0 HcmV?d00001 diff --git a/clients/keramik/pics/bottom-right.png b/clients/keramik/pics/bottom-right.png new file mode 100644 index 0000000000000000000000000000000000000000..01f091f5fec94d49e961f66d91e488a4f7f57cf2 GIT binary patch literal 135 zcmeAS@N?(olHy`uVBq!ia0vp^oIuRN0VEhIQ@n&g0tFtC#S9GGd?3u|u{XE z)7O>#5)Y%GqN<7DRA!(MQXQ&dbqRDnliF#`iPP!Ts5<9_F~V4xs- ziKnkC`z1CpCN|abQ@$sFLQF~C?k)`f+xyS#2l8w@T^vI+&L{u;Kc7)QAyI)L!b~ve z!~6+N^;^sz>L2C$$IB$#*4}hbAaaVff#MQ{h6zpC)|?s_&K+9M!0@6~dU~UjTMW<~ N22WQ%mvv4FO#tAZFQotg literal 0 HcmV?d00001 diff --git a/clients/keramik/pics/caption-large-left.png b/clients/keramik/pics/caption-large-left.png new file mode 100644 index 0000000000000000000000000000000000000000..39287262d904fa8e310bc0f7f3aeb48e60937f8f GIT binary patch literal 379 zcmV->0fhdEP)z>%2XskIMF-Lb76J${^OLkY00002VoOIv0RM-N%)bBt0Srk*K~#9! zozSsM!$25@@#m7*3Mv#-gt$0~9b6oRZ0_A${g=8qTM!f%7rTn+tWZIbx+x{;Qf!S% zZSJ#!VD6gB;PZ_?-WyI~Bp~E6SOhC&?lcKKQikX}OM`P5amT=1|6!L$GO$^e=@8ye zdA0y(683naC?#venl>pEt{d>m5F8xA3%ZPBGAFOYd&xS0Z*Ve@mGFc>{{Q%hC7-c_ zJszM&<~WaQ*eKyPYy!IQJax&{3U%iiTCm4LAu9kmWk2DF53GK literal 0 HcmV?d00001 diff --git a/clients/keramik/pics/caption-large-right.png b/clients/keramik/pics/caption-large-right.png new file mode 100644 index 0000000000000000000000000000000000000000..a1773e8c9dbc25caa1f394b0d7e578c43939ed93 GIT binary patch literal 489 zcmVz>%2XskIMF-Lb76J$=dG>wR00002VoOIv0RM-N%)bBt0eVS9K~#9! zZIekWg<%+mZ&Rd1gd7=DR%F4#!omjmH?ok-B~oN4Wj@MqPKj_*Vu6q$Sr`fnvc`f^ z=G)!tIKFdU&$Yas@0s2{@Hg;p&>6N~;u^Pk$>;ww7WspZS4MwrJ-Zxwfq!iBiR8yB z!UKAqPJE`xt2>Y|$6(g@N%Ew?pWtOE*V2z3L?cXkhM_D=zuY1o5z|n`bQdzsj5=DA|6lZ})WHAE+HxCFi+B+zn01C2~ zc>21sUt$wu;$nPW^Gp;d#FXUi?!xfDz5mR9AkWUz#W6(VeDcr#^BMIM5)~LC$^?Tx z^e3^_XXGD>@A6#`bMU?6gSPlB+aKw__1&PjM4@3qQ?@my#)Wf-)-y1OWlMC2Et~ia PXcB{`tDnm{r-UW|y-qW; literal 0 HcmV?d00001 diff --git a/clients/keramik/pics/caption-small-left.png b/clients/keramik/pics/caption-small-left.png new file mode 100644 index 0000000000000000000000000000000000000000..e824b6a2c47d9db1adb940c0c5655b6ba349a109 GIT binary patch literal 415 zcmV;Q0bu@#P)z>%2XskIMF-Lb76J)31M47900002VoOIv0RM-N%)bBt0We8KK~#9! zb<#acLQx#Y@qaorMS+791igXwR$oEyp`oQQXb1`#BGADgD8iuV0gRw0(2yD=2;?Gx z1@?eJ6b(@%N^ymI&-tboL%p7UpYeM*(_cDAm?@IvaWo2-&X@r3LQ^Y^kp+j(mm(JD zWITUy95mlpoONi6uh|SKpGFMvrgP_h_|01_fn&{vzM7}X*@P)z>%2XskIMF-Lb76J({osYHb00002VoOIv0RM-N%)bBt0e4A6K~#9! zZIa6?L~#_yzuu)}B4m(9%F1NH!op%U$bX|LBGeRFOhOjqHM3BZBuQql!6*xq*G8f7 zDBF?o9P{-pTzBquKFiNJ=Xbu{3zByXbC7QQS8;waAygY|vgr_adB7XKs7>Xw=yiUx z$y>&$J=-y-Nw4vbea6%f4M`0vl`y~M#D0b+2IGtliHt#MOwMnd~_aJNReKk zm33u!jUX3k(sQ))MAF}+c_2VLTF*TXaS#Yo2(?OaL+ zhfs=44AahomQQq|Ovm|XWrXiKt-1wHWMF_+wlsTvjz$zJxtGcG^HH-4Q*gnd%X^v3 zp=Pfx(26Q#D|a`|ge1u>FX~aCSU?AV>7phjXZ&!Z0-BZfP)IE^`YW4J^YcM~Fi#ob zn^Zz?w)ep;nWso8razU6vNWrM8niaokih=@>gZ%oU7K>cbZvp&Op`RKQvKy9K@l8M c>1G9d0Rob;KuCmrY5)KL07*qoM6N<$g6@vgr2qf` literal 0 HcmV?d00001 diff --git a/clients/keramik/pics/grabbar-center.png b/clients/keramik/pics/grabbar-center.png new file mode 100644 index 0000000000000000000000000000000000000000..ebd76025faad49a52165e99fcda94f0f64b5816c GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~c0VEi%$|`sRDb50q$YKTtZlEG=F2?=NX~952 z_7YEDSN6-y+`_7?ergOGfkI44-tI08|J(b|><99cJY5_^B&H_MIorS`@q972j)VAt n3r3Q$3%Fww>~}e6%wk~3k78M`xAxa`plSwBS3j3^P6{XE z)7O>#GBdZZD)VyJr7b`qrX+877l!}s{b%+AdFGxjjv*YftOpk|HW&!7Y`7!tmU8bq z2g|xywo#L|a4xCMTC1BYmA-9@c`45&xs_A4%vRu?!2N*z{|CM`ujKY90*zqsboFyt I=akR{0Q871fdBvi literal 0 HcmV?d00001 diff --git a/clients/keramik/pics/grabbar-right.png b/clients/keramik/pics/grabbar-right.png new file mode 100644 index 0000000000000000000000000000000000000000..5a6acdd2ec57124d6ca3e952682e79fda4637ef2 GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^oIuRM0VEjsmUU%<1PVMNiy0WWxj~pQm!)MpP>{XE z)7O>#GBdZZDubQR7dxO3Q#}E!#)`N|l4Gugk8*JunwrE`4 zHCxLgdh(qI1*!92Hs-|IPVf)q|D<=d*(RIOlCg;K&zq$pQex&0a)Aagc)I$ztaD0e F0sw{hEXe=> literal 0 HcmV?d00001 diff --git a/clients/keramik/pics/titlebar-center.png b/clients/keramik/pics/titlebar-center.png new file mode 100644 index 0000000000000000000000000000000000000000..79c1548ecdf475b6fe31b23ec9bc4a5792259006 GIT binary patch literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRq0VEh^GdJG`Qk(@Ik;M!Q+&~F#0mik;drN_W z>?NMQuI!iC#F%(QSO1y%4k*NwMT)nj@+XJYD!PC{xWt~$(696F3Drx`# literal 0 HcmV?d00001 diff --git a/clients/keramik/pics/titlebar-left.png b/clients/keramik/pics/titlebar-left.png new file mode 100644 index 0000000000000000000000000000000000000000..ec4d36196e20a97d1b1749b53bdae7adbe83e6ff GIT binary patch literal 220 zcmeAS@N?(olHy`uVBq!ia0vp^{6H+l!2%=?9Xa4nJa04Z{`57nuWL^ps zWH0gbb!ETA!zifE80T><1SrImwlcDFvQ^b|`6rzF%x3w`KK19ee@AAePk+Mg7wEiq8<(XS P&|(HpS3j3^P64nJaPxvN<6HIvIzU18 z5>H=O_DejBg6bMFzx*tKLQF~C?k)`f+xyS#2l7^Wx;TbZ+&X*4){iMs#O>kp**83# zyi=WXlVVy+-n6T3kg?Wo>hzv*k`wci}C=}0}V9_dn$>(wPsp9j#g144FxgJ&f zQ^l5jJ1=v2m4XQ80*=J=mv_&wdz{KBecRrAX*JjPIHk+HV$aGXX1cAD-nVDv#}uKR zc@e*lDDSX56)u&OBY!mToLejV>eHs&wYJsItdoCX-90@cZ=kU?Bi;}%AcT2Eg1-Rb1&QSii9Y~8 z0AXRC5JHxWUwOf+ur*`PjA!X(YR`R%j6LFB&Uf$4h^%Z^*VJeX$e}qMnX#Vu&bQqg zS;MSPu>@g4s|K(RYyexpCg1_CfekRA1PUMo=G9sw=(HPHf4+<1*8%o`-6fvfKs~2f zOY=Dc@+E!~pbvh1>(^*;u5fG%xDDI~9vXCjHJ}MJjL3<>=@L#1j+8NfHOnUOMc^yM z(ZB_qN@NXTM4lV;fMehZ@HX%(6_}jy^IG7Hmmc#%1Rr+CmN7`fphfT;`Dj@tSxyeq&yTtKFy2rDfUG`XdEHEdttbujdS*8&e(md?^T(_2rNwmOQ{8x60l?+-;TlWX(_}{lQe&a z_~D=`^MGIaIf~1HCc$uTSB_}78VG|7NSBZ-0D;A4jbIztHYx8e@P$&yd#n`umgILh zlN+|pHifWUh~}13I#?4J45NgG;r8&I1h^w1CcY10NQkR&V9*8npCPJU6QPd{zdMBx zcUWoNb}ajb?XY#*=KgZzO2(8k3#sClcs8VvHom(;igj?^D@#F6@pZ%P6T|h%XOC** zkY<_8V{3D*>6$Wfi|lH!wIsR^c$KiGbgbYE=pOf{8F?##7C7R?0{`@bBU~&mbA6|ZoTk@JZ5cZPFWcmgImMWn*j^QLaHZ`$*IZuR^#KYh^ z*!(_@TPJ70u^H~2lI?%<@tty&;0iw*{9N$c@;&DvD7;Dhh$pVSE46W4($eNj$%(iU zG+ibHRziA`2@f3F*o1TC7qI_T92{cXdjbGYAEF1iH#uMqe#K`H);4emQJQyr*WL%m zS2cI*bqb{O<&IHCj4gts5+V;JE@=VabO>$@WWvG(Mqwa;^0EkS0NZI++%8J-7H<9) zguaQ?w`((dn^~+y#$z17nsc3TR8U9(Fo5i-HdNh=)>%@t@4$FAuDwoFURHL1`{4Hw&h#ed>i<0B)}Q? zdxDo%Q55>r?rBQiGYEvc7S~$!~`~b0vkRxea)GP>Iv>!*$>WmUSNtq7_33w z1Zf__fN$aR?}9+fv8ApHN>{7^7}O|7g_k}OWW8p(=n12+kV@cdAh->~-3LKzlAAar zz!5W`c$vUBm_#FEJ;vuZasC_d*Ehh!cP)pbWH2})fudLOTV3S2&VwS_I3x#z;FPXe zN!f?pD@u76Jey#-I3vAO;5yT+I^|tcPQHZuJ%(Uk5KK}wgL#<^zRd7rCfhJ7f5ZpJ zHYF1zuEcjjfzQuyIN^QZUEsqD>{kmsj}tOri^#w@uOkgoC~_SiQR_G)s;wi} zHreH(g|CP$3F;r^6wGlQSWwtbY1`npljg;vB+aIHu4mOS>+;1m4Pa*$CSL{bH^A`` zGR+;=<~PA}8@6qLJ0rf>UvpBW#DtUCK%u9jO90Hpw(Al`FN?B~<>fBY^=*L$aUrEa zc}`#)NY`#r(YIkhbfvqT7Gp40D{M&}@n*Xg*;Wxes^%M$DX6oGACgjM}s(Um0?~!WUvA4d>TTf86_~l;CK!oEr`33 z<;8;}%Vwe!KdLWLbG)QUy-S$}&-^}@Pf=hwj2bGcxhP{?MK8x%_XeM8Tv%}yb!n-33%Z``N?JFtVW$+YWg1pT^}^tEG-uM|w&mHj zSYsSC$SL#k)hNl1abS+6M@`{!1g`_Pv!Z+ma{FAcTX^J_xqn?(wYKNhY{_D*O4ZB~ zHXyk=uLK0Zq&^1F56Fuaw(MbFkQd^Cr zv2_$M!20wH@rIp=7ZoqXk(lW zIAD|{$%hCQ#m`Byg6h@=b*Fh*KJuk~2gbXmJ*A4+>f%-~2^^(YfTY^Je z-BMS_$ttBQp&K}@fnB%IU81oO4@lfR&y)uuYP2__)1(HlV3^E+o?WI+PkVzzvL~A{ieX)k=XHl;FEWkF4nDHmb=Ybj z{CA=-a4+Z=n!s+7=KIJkufPevfFriCc5P=l)37UN8q@bE$l7jjLb5~Y!4t3H1`^Ty zN}89C*4EaEW1r&-H87jNLv&*gaL#7KTNqFIk$&*HS;D%8sJ>T}Od7757DGmhU?xMV zrpq{yhkNgW!#*0W?Jx|L0ss7uew$Hq1%qt>_w&5G$02spb1e@X>ERgX%E^SF>t9V^ zZbT-2rs*SoSPSB(xM^XSSAbuV7W?3_GY=!D3No|Mxklhyi1b%+9rQ73@?@LF=qhr# zt@tu_b%8lRoJuV+pxQ#{F-GU{`ZQpms!aE*!}8JJzBxWHerk;$&+crT60` zrGDYi!BBuMKmux-LB_!ZaCHVq2B! zjlhTy*XA^zP4~Z?)DWfvTme zo!G{0eb0kIT(Tq5G-lxPqA{DzoCQBXnqeGWtW5&LZm-kSX+sN45oRV{i0fy|G!n42 zz$S`?+G|G0x-&=9iG5qJ**$=UoehVG83$?PAP;gVJ5@@pQ!$Au09m6l$%;A6elxQ{ zV1&BuH`gVBT|Gfz!*NYJ&AzUNALS z52xzwxDiDO8Gz$@6d^4%TYelx3xOFjO!bT;u(~f>b|e$Ij8#$0D?(QhdNsG}`#26Y zTDn|;AIq|w*A7@8on$H#()M*2e1{y?#fgsY^6MG1rE+3jHPe`ST#9kz@!Q;~*=$qb-s0>li}uE>+~bHP+iAW@yi=!en$^HN;PO0m8yumDP^Uc%61 zL~=Xx!16_r8Nj9Xs+IVa^;%=4>tPGWFpWY{2&!KK-D!@-AW7r6jN^#YrA-7^HU~dT z^HW?5C##NPLDy79xVp$d#m{`Fd(l`tiZd%pQW*o_$6_roKQC|gZeEBcOzIPtMGY1}fe3-Xl9&3;(sC*^1{5%$?ufYn zh^!j#%6guD_434J+jujFsi4&G4$%_K#wZM+UNnpkof-JI)8N-6MiQp>^ z+~ums>bknr*;I!)!*>r6?BrTtPMxVG_0-!bKA&PRzcUJ=jdsJcT1~$e&O|RgG$)d# z*g;&17UPY}Ij4?gY1Nxe!&OB{h+$d~Cn8Re_~IylxM`Lql`dvBs{o<|J}?UtcQgy# zjSi(HSHJ6%>>R(sOqtTc*~KESG_%GDYapRn^C-a(D3tRkEWxh;KbdD~W#ScqB~YSq zED$R;9MKkL+|K~4wd1Jqwx-TkIbJE_5KrB>;f7=&3X~#2#Kh#8*ySWTLgv5;KA#3r z+8E8E4HB`{@U2>5UECRiz=A0#dQ81GuSBiu4X|p$Y6eE5fB_>CI7(o=IEkV#NTYcM zf%S!q;qZmXMi>)E5V#F~E{VI=Zjz9u6fl+YS;?`DxU$OA`D!GuzAmh-W-^yP7b3y= zAaD>#Ol}D9E3+sR*)J0~TM-xp;B2<)nki&;6Ntr>l2Y>$rse0KvXeHlo_`iumy#GF z#&Mb;U^3c85lriV2E{Put?4}8?TrF8z~5e%Rn&o|ndzwoX3R_ua9#xf+jb!f+pest{qC>?~*8%2DL3&B{f}-CWNM8Y(*d)Q!<3gk#TK$fz9>XY7gX!Grjb_CZ zOE?*Jvp5LyBrX?M$a5G@JK#Z*UUKSs&Aqu^^Cem@ z4)1E`BVUy!)uUVyH>*3CCc$iW8cjzZfL||*=Q&+!HAQ0!8MT+@_F;s+VmJ#sHjPhx zpC)GX38u*^OsV5S@qcMKsl}~HGjlLBpv~mB1#os0fDmd!tF% z6Qu}l?yP(BIQ1|a!yNOjRjM3gY8?}ZUS>R=LpX}?sta8;XFXW2nhZrs_Q!MUY%s|t zlj&qW?w%G&G|khfSj-Zc8axI*f3xuXRoidEN{^-n24j(OU{)zyc$_t9>sO9P;V$o%@vtYL}@z6vh3qDO^zvs9CJ

b~-mUy3M_vjW*j}CxT{TUsmH>9mz~vh*j?pmzbIeH^NpBvQ)#P zd6-HVusrFGqseGI2#3eVWuA_UG|E=q2ls)u(KxuhJimi9w2vRNHMj8U>&DIoySBNe zUq5nt(OFg*@NV;#Lo7Ljk zY#!e_wYh9J8`kx$4*D6-a4!)*w2B%Lf|>!@O03^`ooR2=FQ!$j)R$z>lB`AEuSW+>&bxXCp&7=1M9`O)7Fhu z?P2xMs2)BkaTBT;^GKWxruk8K7=``*aD4DCdEEraRwATNKqR?X|3+q89@9#*{{W zasS@^?~EpIcfbFwzq6bl{^MV$lOKNLugEeX)w(ou-aj2qchW*UMjBP!V4qFn$`Hlv*ueRY~VX(-;5CLFbQ5yKr$pFGu_o3>&rjn1a5zn);5bjB(J$k-GV_&?z^LCo>fuLW6o1g$TDx)F zn`~o$V{;w+U_-{~V7vOMu@Kxeh|JjbB@JOc{v~Hr(Hlgu9E@k;;B2_yWs$h&e{`3` zEz@hWdpo=)u#7LV9{j`rlIxxWN3Zx zN!R+t^RCq!43bg5JB)*IkGfMD3SDGC!%qn;%3}MdH|`9AnBHMmvqO}oTfSo^5vdNF znhK%$a)(S97^^#z8g1S4tkYBwdKo^Zpj#0sf z_`HuYBG=cNZEo`hO((W>fN0yPOe6H{Tgi2F+UI$)6>%39m#WO=I@^Siq(=4NbgBTLf`(pGD*weB~4*J=PXl=3}CrAH6sCCKH( zR??aXlzJi~N|8bW@ySUqeRkB#4o>><;c+jSO~+^Pbaa>p!)F-b_LmG;tP;i0iJXY` zA0jO@g86(CHF@*cWxJNhH!+N9OlP4z*xlrnj#%z9&g|8tKJUTktyoS{3-MYTRsp$eoHPqV#*4yCM z^wq0B>dKMUi60PK{YeOZGis#dv*(B6*}+i}2h(ma89oQU!%O+CEJdDC?Wg^8{LgXi zTl2K|3fV%Ca{*LN8m^8n7I#Byv5p$|w_#1MA>yWIa6^SRWtusoV|G zc>X62{Wfp{#4iZk``$lUhIHK6|E`fI~co-sl}aew6h%r2*<%BD6VaGTo}=X z@oYk;)j-tv+;waiFP8~`F0uqfe>^L@=#Z z_7vuLj?DFB8m3RnvgE$Yn^3=z<++Dw_L@GLL%=hckVYzkG9kd!>sZ|-QyIzt^a(2C zJUQ$ZPY$}pGt|(JkB5`)X#O@Okq`duZ@+iR-zFK-WnM~5`%1nR+=CMIrL%JeW?V!)`YpA9iu= zkw}7}ERul~Ii=c z4q$tp2jh7R{HSgLg-nxJq)7tAGjQyO!E87kb;rfzbS!Xfh2qChPm|v`imLh-B0`HqcS=8acRcJp?R?5WcTq|f9?8&xvepC zn|CbRzhgPxCbPXwL{J;iL~kY>DT~w+MT*tjDv~*bm_mdx3^tGvqIP<8M%Of$0%P+z zFa|6Eagn%$^ynuP$z5}9A9$YbJm`))Hw)&qZScDWeggbF@N>b>20xYfz)ymo1%4&? z736H-cOc@)!RNrw3J>3*m6$*OF$o;Czx<8&7+-S;5OeF!3LOYcCEa8@*m*9ZezrYxoTx z`OtMK<2dv>3Mh~U^CV6)r1c?e{VrmNnyAol`Vi>8^DlpGT~S~oa&1H*!+{X#Jcg)e zi$AOa+6E1Px-1u#rb$aq76%Fd5iO{Li}5v7g4BqBq&6OKxwy3h)&j>efs2><8TkDS z_v|QsQZ{jD3u_;158FJ&PeN!AQXB>N$s&UA(dWp|a<9KC?e;aR7(EY>I5OO7j{Eh? zM(5xt*z0kxHRf*PHWJ@0=6KuO@iv(4O3H+s+qOi!>NrL&wHwu7N|S4PGB_kQ-!6>(W46@DBcRZsy$oD}GnZHYJc5ZbyJ` z;27Ae{0vHSPXDSmXIDD5hJ67PIRmL+2wnhrSycR*@MD$O|I5q&0L#WX_w#kuZ~y=R M07*qoM6N<$f?Adg6#xJL literal 0 HcmV?d00001 diff --git a/clients/keramik/pics/titlebutton-round-large.png b/clients/keramik/pics/titlebutton-round-large.png new file mode 100644 index 0000000000000000000000000000000000000000..68e6ba7391eda376da65ea8164a13431ccfeeef6 GIT binary patch literal 4178 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 literal 0 HcmV?d00001 diff --git a/clients/keramik/tiles.qrc b/clients/keramik/tiles.qrc new file mode 100644 index 0000000000..e6a12e4169 --- /dev/null +++ b/clients/keramik/tiles.qrc @@ -0,0 +1,27 @@ + + + pics/border-left.png + pics/border-right.png + pics/bottom-center.png + pics/bottom-left.png + pics/bottom-right.png + pics/caption-large-center.png + pics/caption-large-left.png + pics/caption-large-right.png + pics/caption-small-center.png + pics/caption-small-left.png + pics/caption-small-right.png + pics/grabbar-center.png + pics/grabbar-left.png + pics/grabbar-right.png + pics/titlebar-center.png + pics/titlebar-left.png + pics/titlebar-right.png + pics/titlebutton-round-huge.png + pics/titlebutton-round-large.png + pics/titlebutton-round.png + pics/titlebutton-square-huge.png + pics/titlebutton-square-large.png + pics/titlebutton-square.png + + diff --git a/clients/kwmtheme/CMakeLists.txt b/clients/kwmtheme/CMakeLists.txt new file mode 100644 index 0000000000..8b601112a7 --- /dev/null +++ b/clients/kwmtheme/CMakeLists.txt @@ -0,0 +1,25 @@ + +add_subdirectory( cli_installer ) +add_subdirectory( pics ) + + + + +########### next target ############### + +set(kwin3_kwmtheme_PART_SRCS kwmthemeclient.cpp ) + + +kde4_add_plugin(kwin3_kwmtheme ${kwin3_kwmtheme_PART_SRCS}) + + + +target_link_libraries(kwin3_kwmtheme ${KDE4_KDECORE_LIBS} kdecorations ) + +install(TARGETS kwin3_kwmtheme DESTINATION ${PLUGIN_INSTALL_DIR} ) + + +########### install files ############### + +install( FILES kwmtheme.desktop DESTINATION ${DATA_INSTALL_DIR}/kwin ) + diff --git a/clients/kwmtheme/cli_installer/CMakeLists.txt b/clients/kwmtheme/cli_installer/CMakeLists.txt new file mode 100644 index 0000000000..96116a8da7 --- /dev/null +++ b/clients/kwmtheme/cli_installer/CMakeLists.txt @@ -0,0 +1,14 @@ + + + +########### next target ############### + +set(kwmtheme_SRCS main.cpp ) + + +kde4_add_executable(kwmtheme ${kwmtheme_SRCS}) + +target_link_libraries(kwmtheme ${KDE4_KDECORE_LIBS} ) + +install(TARGETS kwmtheme ${INSTALL_TARGETS_DEFAULT_ARGS}) + diff --git a/clients/kwmtheme/cli_installer/main.cpp b/clients/kwmtheme/cli_installer/main.cpp new file mode 100644 index 0000000000..58f7f245be --- /dev/null +++ b/clients/kwmtheme/cli_installer/main.cpp @@ -0,0 +1,178 @@ +/******************************************************************** +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const char description[] = + I18N_NOOP("Installs a KWM theme"); + +void copy(const QString &src, const QString &dest) +{ + QFile copyInput(src); + QFile copyOutput(dest); + if(!copyInput.open(QIODevice::ReadOnly)){ + kWarning(1212) << "Couldn't open " << src ; + return; + } + if(!copyOutput.open(QIODevice::WriteOnly)){ + kWarning(1212) << "Couldn't open " << dest ; + copyInput.close(); + return; + } + while(!copyInput.atEnd()){ + copyOutput.putch(copyInput.getch()); + } + copyInput.close(); + copyOutput.close(); +} + +int main(int argc, char **argv) +{ + KCmdLineArgs::init(argc, argv, "kwmtheme", description, "0.1"); + + KCmdLineOptions options; + options.add("+[file]", ki18n("Path to a theme config file")); + KCmdLineArgs::addCmdLineOptions( options ); + KApplication app(argc, argv); + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + if(!args->count()){ + kWarning(1212) << "You need to specify the path to a theme config file!" ; + return(1); + } + + QString srcStr = QString(args->arg(0)); + QFile f(srcStr); + QString tmpStr; + + if(!f.exists()){ + kWarning(1212) << "Specified theme config file doesn't exist!" ; + return(2); + } + + QStringList appDirs = KGlobal::dirs()->findDirs("data", "kwin"); + QString localDirStr = *(appDirs.end()); + if(localDirStr.isEmpty()){ + localDirStr = KGlobal::dirs()->saveLocation("data", "kwin"); + } + localDirStr += "/pics/"; + if(!QFile::exists(localDirStr)) + QDir().mkdir(localDirStr); + + QFileInfo fi(f); + KSimpleConfig input(fi.absoluteFilePath()); + srcStr = fi.dirPath(true) + '/'; + KSharedConfig::Ptr output = KGlobal::config(); + input.setGroup("Window Border"); + output->setGroup("General"); + + tmpStr = input.readEntry("shapePixmapTop"); + if(!tmpStr.isEmpty()){ + copy(srcStr+tmpStr, localDirStr+tmpStr); + } + output->writeEntry("wm_top", tmpStr, KConfig::Normal|KConfig::Global); + tmpStr = input.readEntry("shapePixmapBottom"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_bottom", tmpStr, KConfig::Normal|KConfig::Global); + tmpStr = input.readEntry("shapePixmapLeft"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_left", tmpStr, KConfig::Normal|KConfig::Global); + tmpStr = input.readEntry("shapePixmapRight"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_right", tmpStr, KConfig::Normal|KConfig::Global); + tmpStr = input.readEntry("shapePixmapTopLeft"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_topleft", tmpStr, KConfig::Normal|KConfig::Global); + tmpStr = input.readEntry("shapePixmapTopRight"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_topright", tmpStr, KConfig::Normal|KConfig::Global); + tmpStr = input.readEntry("shapePixmapBottomLeft"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_bottomleft", tmpStr, KConfig::Normal|KConfig::Global); + tmpStr = input.readEntry("shapePixmapBottomRight"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_bottomright", tmpStr, KConfig::Normal|KConfig::Global); + + + input.setGroup("Window Titlebar"); + output->writeEntry("TitleAlignment", input.readEntry("TitleAlignment"), KConfig::Normal|KConfig::Global); + output->writeEntry("PixmapUnderTitleText", input.readEntry("PixmapUnderTitleText"), KConfig::Normal|KConfig::Global); + output->writeEntry("TitleFrameShaded", input.readEntry("TitleFrameShaded"), KConfig::Normal|KConfig::Global); + + tmpStr = input.readEntry("MenuButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("menu", tmpStr, KConfig::Normal|KConfig::Global); + tmpStr = input.readEntry("PinUpButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("pinup", tmpStr, KConfig::Normal|KConfig::Global); + tmpStr = input.readEntry("PinDownButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("pindown", tmpStr, KConfig::Normal|KConfig::Global); + tmpStr = input.readEntry("CloseButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("close", tmpStr, KConfig::Normal|KConfig::Global); + tmpStr = input.readEntry("MaximizeButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("maximize", tmpStr, KConfig::Normal|KConfig::Global); + tmpStr = input.readEntry("MaximizeDownButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("maximizedown", tmpStr, KConfig::Normal|KConfig::Global); + tmpStr = input.readEntry("MinimizeButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("iconify", tmpStr, KConfig::Normal|KConfig::Global); + tmpStr = input.readEntry("TitlebarPixmapActive"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("TitlebarPixmapActive", tmpStr, KConfig::Normal|KConfig::Global); + tmpStr = input.readEntry("TitlebarPixmapInactive"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("TitlebarPixmapInactive", tmpStr, KConfig::Normal|KConfig::Global); + + input.setGroup("Window Button Layout"); + output->setGroup("Buttons"); + output->writeEntry("ButtonA", input.readEntry("ButtonA"), KConfig::Normal|KConfig::Global); + output->writeEntry("ButtonB", input.readEntry("ButtonB"), KConfig::Normal|KConfig::Global); + output->writeEntry("ButtonC", input.readEntry("ButtonC"), KConfig::Normal|KConfig::Global); + output->writeEntry("ButtonD", input.readEntry("ButtonD"), KConfig::Normal|KConfig::Global); + output->writeEntry("ButtonE", input.readEntry("ButtonE"), KConfig::Normal|KConfig::Global); + output->writeEntry("ButtonF", input.readEntry("ButtonF"), KConfig::Normal|KConfig::Global); + + output->sync(); + + return(0); +} + diff --git a/clients/kwmtheme/kwmtheme.desktop b/clients/kwmtheme/kwmtheme.desktop new file mode 100644 index 0000000000..a7d71c7712 --- /dev/null +++ b/clients/kwmtheme/kwmtheme.desktop @@ -0,0 +1,89 @@ +[Desktop Entry] +Name=KWM Theme +Name[af]=KWM Tema +Name[ar]=سمة KWM +Name[be]=Тэма KWM +Name[be@latin]=Matyŭ „KWM” +Name[bg]=Тема KWM +Name[bn]=KWM থীম +Name[bn_IN]=KWM থিম +Name[br]=Gwiskad KWM +Name[ca]=Tema KWM +Name[ca@valencia]=Tema KWM +Name[cs]=Téma KWM +Name[csb]=Témë KWM +Name[cy]=Thema KWM +Name[da]=KWM-tema +Name[de]=KWM-Design +Name[el]=Θέμα KWM +Name[en_GB]=KWM Theme +Name[eo]=KWM-etoso +Name[es]=Tema de KWM +Name[et]=KWM teema +Name[eu]=KWM gaia +Name[fa]=چهره KWM +Name[fi]=KWM-teema +Name[fr]=Thème KWM +Name[fy]=KWM-tema +Name[ga]=Téama KWM +Name[gl]=Tema do KWM +Name[gu]=KWM થીમ +Name[he]=ערכת KWM +Name[hi]=केडबल्यूएम प्रसंग +Name[hne]=केडबल्यूएम प्रसंग +Name[hr]=KWM tema +Name[hsb]=KWM-tema +Name[hu]=KWM téma +Name[ia]=Thema KWM +Name[id]=Tema KWM +Name[is]=KWM þema +Name[it]=Tema KWM +Name[ja]=KWM テーマ +Name[ka]=KWM სტილი +Name[kk]=KWM нақышы +Name[km]=ស្បែក KWM +Name[kn]=KWM ಪರಿಸರವಿನ್ಯಾಸ (ಥೀಮ್) +Name[ko]=KWM 테마 +Name[ku]=Dirbê KWM +Name[lt]=KWM tema +Name[lv]=KWM tēma +Name[mai]=केडबल्यूएम प्रसंग +Name[mk]=KWM тема +Name[ml]=കെഡബ്ല്യൂഎം പ്രമേയം +Name[mr]=केडबल्यूएम सुत्रयोजना +Name[ms]=Temas KWM +Name[nb]=KWM-tema +Name[nds]=KWM-Muster +Name[ne]=KWM विषयवस्तु +Name[nl]=KWM-thema +Name[nn]=KWM-tema +Name[pa]=KWM ਥੀਮ +Name[pl]=Motyw KWM +Name[pt]=Tema KWM +Name[pt_BR]=Tema KWM +Name[ro]=Tematică KWM +Name[ru]=Стиль KWM +Name[se]=KWM-fáddá +Name[si]=KWM තේමාව +Name[sk]=Téma KWM +Name[sl]=Tema KWM +Name[sr]=КВМ‑ова тема +Name[sr@ijekavian]=КВМ‑ова тема +Name[sr@ijekavianlatin]=KWM‑ova tema +Name[sr@latin]=KWM‑ova tema +Name[sv]=KWM-tema +Name[ta]=KWM தலைப்பு +Name[te]=KWM థీమ్ +Name[tg]=Мавзӯъи KWM +Name[th]=รูปแบบชุดตกแต่ง KWM +Name[tr]=KWM Teması +Name[uk]=Тема KWM +Name[uz]=KWM mavzusi +Name[uz@cyrillic]=KWM мавзуси +Name[vi]=Sắc thái KWM +Name[wa]=Tinme KWM +Name[xh]=Umxholo we KWM +Name[x-test]=xxKWM Themexx +Name[zh_CN]=KWM 主题 +Name[zh_TW]=KWM 主題 +X-KDE-Library=kwin3_kwmtheme diff --git a/clients/kwmtheme/kwmthemeclient.cpp b/clients/kwmtheme/kwmthemeclient.cpp new file mode 100644 index 0000000000..7b120a54c7 --- /dev/null +++ b/clients/kwmtheme/kwmthemeclient.cpp @@ -0,0 +1,951 @@ +/******************************************************************** +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#include "kwmthemeclient.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace KWMTheme { + + +/* static QPixmap stretchPixmap(QPixmap& src, bool stretchVert){ + QPixmap dest; + QBitmap *srcMask, *destMask; + int w, h, w2, h2; + QPainter p; + + if (src.isNull()) return src; + + w = src.width(); + h = src.height(); + + if (stretchVert){ + w2 = w; + for (h2=h; h2<100; h2=h2<<1) + ; + } + else{ + h2 = h; + for (w2=w; w2<100; w2=w2<<1) + ; + } + if (w2==w && h2==h) return src; + + dest = src; + dest.resize(w2, h2); + + p.begin(&dest); + p.drawTiledPixmap(0, 0, w2, h2, src); + p.end(); + + srcMask = (QBitmap*)src.mask(); + if (srcMask){ + destMask = (QBitmap*)dest.mask(); + p.begin(destMask); + p.drawTiledPixmap(0, 0, w2, h2, *srcMask); + p.end(); + } + return dest; +} */ + + +inline const KDecorationOptions* options() { return KDecoration::options(); } + +enum FramePixmap{FrameTop=0, FrameBottom, FrameLeft, FrameRight, FrameTopLeft, + FrameTopRight, FrameBottomLeft, FrameBottomRight}; + +static QPixmap *framePixmaps[8]; +static QPixmap *menuPix, *iconifyPix, *closePix, *maxPix, *minmaxPix, + *pinupPix, *pindownPix; +static QPixmap *aTitlePix = 0; +static QPixmap *iTitlePix = 0; +static KPixmapEffect::GradientType grType; +static int maxExtent, titleAlign; +static bool titleGradient = true; +static bool pixmaps_created = false; +static bool titleSunken = false; +static bool titleTransparent; + +static void create_pixmaps() +{ + const char * const keys[] = {"wm_top", "wm_bottom", "wm_left", "wm_right", + "wm_topleft", "wm_topright", "wm_bottomleft", "wm_bottomright"}; + + if(pixmaps_created) + return; + pixmaps_created = true; + + KSharedConfig::Ptr _config = KGlobal::config(); + KConfigGroup config(_config, "General"); + + QString tmpStr; + + for(int i=0; i < 8; ++i) + { + framePixmaps[i] = new QPixmap(locate("data", + "kwin/pics/"+config.readEntry(keys[i], " "))); + if(framePixmaps[i]->isNull()) + kWarning(1212) << "Unable to load frame pixmap for " << keys[i] ; + } +/* + *framePixmaps[FrameTop] = stretchPixmap(*framePixmaps[FrameTop], false); + *framePixmaps[FrameBottom] = stretchPixmap(*framePixmaps[FrameBottom], false); + *framePixmaps[FrameLeft] = stretchPixmap(*framePixmaps[FrameLeft], true); + *framePixmaps[FrameRight] = stretchPixmap(*framePixmaps[FrameRight], true); +*/ + maxExtent = framePixmaps[FrameTop]->height(); + if(framePixmaps[FrameBottom]->height() > maxExtent) + maxExtent = framePixmaps[FrameBottom]->height(); + if(framePixmaps[FrameLeft]->width() > maxExtent) + maxExtent = framePixmaps[FrameLeft]->width(); + if(framePixmaps[FrameRight]->width() > maxExtent) + maxExtent = framePixmaps[FrameRight]->width(); + + maxExtent++; + + menuPix = new QPixmap(locate("data", + "kwin/pics/"+config.readEntry("menu", " "))); + iconifyPix = new QPixmap(locate("data", + "kwin/pics/"+config.readEntry("iconify", " "))); + maxPix = new QPixmap(locate("appdata", + "pics/"+config.readEntry("maximize", " "))); + minmaxPix = new QPixmap(locate("data", + "kwin/pics/"+config.readEntry("maximizedown", " "))); + closePix = new QPixmap(locate("data", + "kwin/pics/"+config.readEntry("close", " "))); + pinupPix = new QPixmap(locate("data", + "kwin/pics/"+config.readEntry("pinup", " "))); + pindownPix = new QPixmap(locate("data", + "kwin/pics/"+config.readEntry("pindown", " "))); + if(menuPix->isNull()) + menuPix->load(locate("data", "kwin/pics/menu.png")); + if(iconifyPix->isNull()) + iconifyPix->load(locate("data", "kwin/pics/iconify.png")); + if(maxPix->isNull()) + maxPix->load(locate("data", "kwin/pics/maximize.png")); + if(minmaxPix->isNull()) + minmaxPix->load(locate("data", "kwin/pics/maximizedown.png")); + if(closePix->isNull()) + closePix->load(locate("data", "kwin/pics/close.png")); + if(pinupPix->isNull()) + pinupPix->load(locate("data", "kwin/pics/pinup.png")); + if(pindownPix->isNull()) + pindownPix->load(locate("data", "kwin/pics/pindown.png")); + + tmpStr = config.readEntry("TitleAlignment"); + if(tmpStr == "right") + titleAlign = Qt::AlignRight | Qt::AlignVCenter; + else if(tmpStr == "middle") + titleAlign = Qt::AlignCenter; + else + titleAlign = Qt::AlignLeft | Qt::AlignVCenter; + titleSunken = config.readEntry("TitleFrameShaded", true ); + // titleSunken = true; // is this fixed? + titleTransparent = config.readEntry("PixmapUnderTitleText", true); + + tmpStr = config.readEntry("TitlebarLook"); + if(tmpStr == "shadedVertical"){ + aTitlePix = new QPixmap; + aTitlePix->resize(32, 20); + KPixmapEffect::gradient(*aTitlePix, + options()->color(KDecorationOptions::ColorTitleBar, true), + options()->color(KDecorationOptions::ColorTitleBlend, true), + KPixmapEffect::VerticalGradient); + iTitlePix = new QPixmap; + iTitlePix->resize(32, 20); + KPixmapEffect::gradient(*iTitlePix, + options()->color(KDecorationOptions::ColorTitleBar, false), + options()->color(KDecorationOptions::ColorTitleBlend, false), + KPixmapEffect::VerticalGradient); + titleGradient = false; // we can just tile this + + } + else if(tmpStr == "shadedHorizontal") + grType = KPixmapEffect::HorizontalGradient; + else if(tmpStr == "shadedDiagonal") + grType = KPixmapEffect::DiagonalGradient; + else if(tmpStr == "shadedCrossDiagonal") + grType = KPixmapEffect::CrossDiagonalGradient; + else if(tmpStr == "shadedPyramid") + grType = KPixmapEffect::PyramidGradient; + else if(tmpStr == "shadedRectangle") + grType = KPixmapEffect::RectangleGradient; + else if(tmpStr == "shadedPipeCross") + grType = KPixmapEffect::PipeCrossGradient; + else if(tmpStr == "shadedElliptic") + grType = KPixmapEffect::EllipticGradient; + else{ + titleGradient = false; + tmpStr = config.readEntry("TitlebarPixmapActive", ""); + if(!tmpStr.isEmpty()){ + aTitlePix = new QPixmap; + aTitlePix->load(locate("data", "kwin/pics/" + tmpStr)); + } + else + aTitlePix = NULL; + tmpStr = config.readEntry("TitlebarPixmapInactive", ""); + if(!tmpStr.isEmpty()){ + iTitlePix = new QPixmap; + iTitlePix->load(locate("data", "kwin/pics/" + tmpStr)); + } + else + iTitlePix = NULL; + } +} + +static void delete_pixmaps() +{ + for(int i=0; i < 8; ++i) + delete framePixmaps[i]; + + delete menuPix; + delete iconifyPix; + delete closePix; + delete maxPix; + delete minmaxPix; + delete pinupPix; + delete pindownPix; + delete aTitlePix; + aTitlePix = 0; + delete iTitlePix; + iTitlePix = 0; + + titleGradient = true; + pixmaps_created = false; + titleSunken = false; +} + +void MyButton::drawButtonLabel(QPainter *p) +{ + if(pixmap()){ + // If we have a theme who's button covers the entire width or + // entire height, we shift down/right by 1 pixel so we have + // some visual notification of button presses. i.e. for MGBriezh + int offset = (isDown() && ((pixmap()->width() >= width()) || + (pixmap()->height() >= height()))) ? 1 : 0; + style().drawItem(p, QRect( offset, offset, width(), height() ), + AlignCenter, colorGroup(), + true, pixmap(), QString()); + } +} + +KWMThemeClient::KWMThemeClient( KDecorationBridge* b, KDecorationFactory* f ) + : KDecoration( b, f ) +{ +} + +void KWMThemeClient::init() +{ + createMainWidget( WResizeNoErase | WStaticContents ); + widget()->installEventFilter( this ); + + stickyBtn = maxBtn = mnuBtn = 0; + layout = new QGridLayout(widget()); + layout->addColSpacing(0, maxExtent); + layout->addColSpacing(2, maxExtent); + + layout->addRowSpacing(0, maxExtent); + + layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Fixed, + QSizePolicy::Expanding)); + + if( isPreview()) + layout->addWidget( new QLabel( i18n( "

KWMTheme
" ), widget()), 2, 1); + else + layout->addItem( new QSpacerItem( 0, 0 ), 2, 1); + + // Without the next line, shading flickers + layout->addItem( new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding) ); + layout->addRowSpacing(3, maxExtent); + layout->setRowStretch(2, 10); + layout->setColumnStretch(1, 10); + + QBoxLayout* hb = new QBoxLayout(0, QBoxLayout::LeftToRight, 0, 0, 0); + layout->addLayout( hb, 1, 1 ); + + KSharedConfig::Ptr _config = KGlobal::config(); + KConfigGroup config(_config, "Buttons"); + QString val; + MyButton *btn; + int i; + static const char * const defaultButtons[]={"Menu","Sticky","Off","Iconify", + "Maximize","Close"}; + static const char keyOffsets[]={"ABCDEF"}; + for(i=0; i < 6; ++i){ + if(i == 3){ + titlebar = new QSpacerItem(10, 20, QSizePolicy::Expanding, + QSizePolicy::Minimum ); + hb->addItem( titlebar ); + } + QString key("Button"); + key += QChar(keyOffsets[i]); + val = config.readEntry(key, defaultButtons[i]); + if(val == "Menu"){ + mnuBtn = new MyButton(widget(), "menu"); + mnuBtn->setToolTip( i18n("Menu")); + iconChange(); + hb->addWidget(mnuBtn); + mnuBtn->setFixedSize(20, 20); + connect(mnuBtn, SIGNAL(pressed()), this, + SLOT(menuButtonPressed())); + } + else if(val == "Sticky"){ + stickyBtn = new MyButton(widget(), "sticky"); + stickyBtn->setToolTip( i18n("Sticky")); + if (isOnAllDesktops()) + stickyBtn->setPixmap(*pindownPix); + else + stickyBtn->setPixmap(*pinupPix); + connect(stickyBtn, SIGNAL( clicked() ), this, SLOT(toggleOnAllDesktops())); + hb->addWidget(stickyBtn); + stickyBtn->setFixedSize(20, 20); + } + else if((val == "Iconify") && isMinimizable()){ + btn = new MyButton(widget(), "iconify"); + btn->setToolTip( i18n("Minimize")); + btn->setPixmap(*iconifyPix); + connect(btn, SIGNAL(clicked()), this, SLOT(minimize())); + hb->addWidget(btn); + btn->setFixedSize(20, 20); + } + else if((val == "Maximize") && isMaximizable()){ + maxBtn = new MyButton(widget(), "max"); + maxBtn->setToolTip( i18n("Maximize")); + maxBtn->setPixmap(*maxPix); + connect(maxBtn, SIGNAL(clicked()), this, SLOT(maximize())); + hb->addWidget(maxBtn); + maxBtn->setFixedSize(20, 20); + } + else if((val == "Close") && isCloseable()){ + btn = new MyButton(widget(), "close"); + btn->setToolTip( i18n("Close")); + btn->setPixmap(*closePix); + connect(btn, SIGNAL(clicked()), this, SLOT(closeWindow())); + hb->addWidget(btn); + btn->setFixedSize(20, 20); + } + else{ + if((val != "Off") && + ((val == "Iconify") && !isMinimizable()) && + ((val == "Maximize") && !isMaximizable())) + kWarning(1212) << "KWin: Unrecognized button value: " << val ; + + } + } + if(titleGradient){ + aGradient = new QPixmap; + iGradient = new QPixmap; + } + else{ + aGradient = 0; + iGradient = 0; + } + widget()->setBackgroundMode(NoBackground); +} + +void KWMThemeClient::drawTitle(QPainter &dest) +{ + QRect titleRect = titlebar->geometry(); + QRect r(0, 0, titleRect.width(), titleRect.height()); + QPixmap buffer; + + if(buffer.width() == r.width()) + return; + + buffer.resize(r.size()); + QPainter p; + p.begin(&buffer); + + if(titleSunken){ + qDrawShadeRect(&p, r, options()->palette(KDecorationOptions::ColorFrame, isActive()).active(), + true, 1, 0); + r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2); + } + + QPixmap *fill = isActive() ? aTitlePix : iTitlePix; + if(fill) + p.drawTiledPixmap(r, *fill); + else if(titleGradient){ + fill = isActive() ? aGradient : iGradient; + if(fill->width() != r.width()){ + fill->resize(r.width(), 20); + KPixmapEffect::gradient(*fill, + options()->color(KDecorationOptions::ColorTitleBar, isActive()), + options()->color(KDecorationOptions::ColorTitleBlend, isActive()), + grType); + } + p.drawTiledPixmap(r, *fill); + } + else{ + p.fillRect(r, options()->palette(KDecorationOptions::ColorTitleBar, isActive()).active(). + brush(QPalette::Button)); + } + p.setFont(options()->font(isActive())); + p.setPen(options()->color(KDecorationOptions::ColorFont, isActive())); + // Add left & right margin + r.setLeft(r.left()+5); + r.setRight(r.right()-5); + p.drawText(r, titleAlign, caption()); + p.end(); + + dest.drawPixmap(titleRect.x(), titleRect.y(), buffer); +} + + +void KWMThemeClient::resizeEvent( QResizeEvent* ) +{ + doShape(); + widget()->repaint(); +} + +void KWMThemeClient::captionChange() +{ + widget()->repaint( titlebar->geometry(), false ); +} + +void KWMThemeClient::paintEvent( QPaintEvent *) +{ + QPainter p; + p.begin(widget()); + int x,y; + // first the corners + int w1 = framePixmaps[FrameTopLeft]->width(); + int h1 = framePixmaps[FrameTopLeft]->height(); + if (w1 > width()/2) w1 = width()/2; + if (h1 > height()/2) h1 = height()/2; + p.drawPixmap(0,0,*framePixmaps[FrameTopLeft], + 0,0,w1, h1); + int w2 = framePixmaps[FrameTopRight]->width(); + int h2 = framePixmaps[FrameTopRight]->height(); + if (w2 > width()/2) w2 = width()/2; + if (h2 > height()/2) h2 = height()/2; + p.drawPixmap(width()-w2,0,*framePixmaps[FrameTopRight], + framePixmaps[FrameTopRight]->width()-w2,0,w2, h2); + + int w3 = framePixmaps[FrameBottomLeft]->width(); + int h3 = framePixmaps[FrameBottomLeft]->height(); + if (w3 > width()/2) w3 = width()/2; + if (h3 > height()/2) h3 = height()/2; + p.drawPixmap(0,height()-h3,*framePixmaps[FrameBottomLeft], + 0,framePixmaps[FrameBottomLeft]->height()-h3,w3, h3); + + int w4 = framePixmaps[FrameBottomRight]->width(); + int h4 = framePixmaps[FrameBottomRight]->height(); + if (w4 > width()/2) w4 = width()/2; + if (h4 > height()/2) h4 = height()/2; + p.drawPixmap(width()-w4,height()-h4,*(framePixmaps[FrameBottomRight]), + framePixmaps[FrameBottomRight]->width()-w4, + framePixmaps[FrameBottomRight]->height()-h4, + w4, h4); + + QPixmap pm; + QMatrix m; + int n,s,w; + //top + pm = *framePixmaps[FrameTop]; + + if (pm.width() > 0){ + s = width()-w2-w1; + n = s/pm.width(); + w = n>0?s/n:s; + m.reset(); + m.scale(w/(float)pm.width(), 1); + pm = pm.transformed(m); + + x = w1; + while (1){ + if (pm.width() < width()-w2-x){ + p.drawPixmap(x,maxExtent-pm.height()-1, + pm); + x += pm.width(); + } + else { + p.drawPixmap(x,maxExtent-pm.height()-1, + pm, + 0,0,width()-w2-x,pm.height()); + break; + } + } + } + + //bottom + pm = *framePixmaps[FrameBottom]; + + if (pm.width() > 0){ + s = width()-w4-w3; + n = s/pm.width(); + w = n>0?s/n:s; + m.reset(); + m.scale(w/(float)pm.width(), 1); + pm = pm.transformed(m); + + x = w3; + while (1){ + if (pm.width() < width()-w4-x){ + p.drawPixmap(x,height()-maxExtent+1,pm); + x += pm.width(); + } + else { + p.drawPixmap(x,height()-maxExtent+1,pm, + 0,0,width()-w4-x,pm.height()); + break; + } + } + } + + //left + pm = *framePixmaps[FrameLeft]; + + if (pm.height() > 0){ + s = height()-h3-h1; + n = s/pm.height(); + w = n>0?s/n:s; + m.reset(); + m.scale(1, w/(float)pm.height()); + pm = pm.transformed(m); + + y = h1; + while (1){ + if (pm.height() < height()-h3-y){ + p.drawPixmap(maxExtent-pm.width()-1, y, + pm); + y += pm.height(); + } + else { + p.drawPixmap(maxExtent-pm.width()-1, y, + pm, + 0,0, pm.width(), + height()-h3-y); + break; + } + } + } + + //right + pm = *framePixmaps[FrameRight]; + + if (pm.height() > 0){ + s = height()-h4-h2; + n = s/pm.height(); + w = n>0?s/n:s; + m.reset(); + m.scale(1, w/(float)pm.height()); + pm = pm.transformed(m); + + y = h2; + while (1){ + if (pm.height() < height()-h4-y){ + p.drawPixmap(width()-maxExtent+1, y, + pm); + y += pm.height(); + } + else { + p.drawPixmap(width()-maxExtent+1, y, + pm, + 0,0, pm.width(), + height()-h4-y); + break; + } + } + } + drawTitle(p); + + QColor c = widget()->colorGroup().background(); + + // KWM evidently had a 1 pixel border around the client window. We + // emulate it here, but should be removed at some point in order to + // seamlessly mesh widget themes + p.setPen(c); + p.drawRect(maxExtent-1, maxExtent-1, width()-(maxExtent-1)*2, + height()-(maxExtent-1)*2); + + // We fill the area behind the wrapped widget to ensure that + // shading animation is drawn as smoothly as possible + QRect r(layout->cellGeometry(2, 1)); + p.fillRect( r.x(), r.y(), r.width(), r.height(), c); + p.end(); +} + +void KWMThemeClient::doShape() +{ + + QBitmap shapemask(width(), height()); + shapemask.fill(color0); + QPainter p; + p.begin(&shapemask); + p.setBrush(color1); + p.setPen(color1); + int x,y; + // first the corners + int w1 = framePixmaps[FrameTopLeft]->width(); + int h1 = framePixmaps[FrameTopLeft]->height(); + if (w1 > width()/2) w1 = width()/2; + if (h1 > height()/2) h1 = height()/2; + if (framePixmaps[FrameTopLeft]->mask()) + p.drawPixmap(0,0,*framePixmaps[FrameTopLeft]->mask(), + 0,0,w1, h1); + else + p.fillRect(0,0,w1,h1,color1); + int w2 = framePixmaps[FrameTopRight]->width(); + int h2 = framePixmaps[FrameTopRight]->height(); + if (w2 > width()/2) w2 = width()/2; + if (h2 > height()/2) h2 = height()/2; + if (framePixmaps[FrameTopRight]->mask()) + p.drawPixmap(width()-w2,0,*framePixmaps[FrameTopRight]->mask(), + framePixmaps[FrameTopRight]->width()-w2,0,w2, h2); + else + p.fillRect(width()-w2,0,w2, h2,color1); + + int w3 = framePixmaps[FrameBottomLeft]->width(); + int h3 = framePixmaps[FrameBottomLeft]->height(); + if (w3 > width()/2) w3 = width()/2; + if (h3 > height()/2) h3 = height()/2; + if (framePixmaps[FrameBottomLeft]->mask()) + p.drawPixmap(0,height()-h3,*framePixmaps[FrameBottomLeft]->mask(), + 0,framePixmaps[FrameBottomLeft]->height()-h3,w3, h3); + else + p.fillRect(0,height()-h3,w3,h3,color1); + + int w4 = framePixmaps[FrameBottomRight]->width(); + int h4 = framePixmaps[FrameBottomRight]->height(); + if (w4 > width()/2) w4 = width()/2; + if (h4 > height()/2) h4 = height()/2; + if (framePixmaps[FrameBottomRight]->mask()) + p.drawPixmap(width()-w4,height()-h4,*framePixmaps[FrameBottomRight]->mask(), + framePixmaps[FrameBottomRight]->width()-w4, + framePixmaps[FrameBottomRight]->height()-h4, + w4, h4); + else + p.fillRect(width()-w4,height()-h4,w4,h4,color1); + + QPixmap pm; + QMatrix m; + int n,s,w; + //top + if (framePixmaps[FrameTop]->mask()) + { + pm = *framePixmaps[FrameTop]->mask(); + + s = width()-w2-w1; + n = s/pm.width(); + w = n>0?s/n:s; + m.reset(); + m.scale(w/(float)pm.width(), 1); + pm = pm.transformed(m); + + x = w1; + while (1){ + if (pm.width() < width()-w2-x){ + p.drawPixmap(x,maxExtent-pm.height()-1, + pm); + x += pm.width(); + } + else { + p.drawPixmap(x,maxExtent-pm.height()-1, + pm, + 0,0,width()-w2-x,pm.height()); + break; + } + } + } + + //bottom + if (framePixmaps[FrameBottom]->mask()) + { + pm = *framePixmaps[FrameBottom]->mask(); + + s = width()-w4-w3; + n = s/pm.width(); + w = n>0?s/n:s; + m.reset(); + m.scale(w/(float)pm.width(), 1); + pm = pm.transformed(m); + + x = w3; + while (1){ + if (pm.width() < width()-w4-x){ + p.drawPixmap(x,height()-maxExtent+1,pm); + x += pm.width(); + } + else { + p.drawPixmap(x,height()-maxExtent+1,pm, + 0,0,width()-w4-x,pm.height()); + break; + } + } + } + + //left + if (framePixmaps[FrameLeft]->mask()) + { + pm = *framePixmaps[FrameLeft]->mask(); + + s = height()-h3-h1; + n = s/pm.height(); + w = n>0?s/n:s; + m.reset(); + m.scale(1, w/(float)pm.height()); + pm = pm.transformed(m); + + y = h1; + while (1){ + if (pm.height() < height()-h3-y){ + p.drawPixmap(maxExtent-pm.width()-1, y, + pm); + y += pm.height(); + } + else { + p.drawPixmap(maxExtent-pm.width()-1, y, + pm, + 0,0, pm.width(), + height()-h3-y); + break; + } + } + } + + //right + if (framePixmaps[FrameRight]->mask()) + { + pm = *framePixmaps[FrameRight]->mask(); + + s = height()-h4-h2; + n = s/pm.height(); + w = n>0?s/n:s; + m.reset(); + m.scale(1, w/(float)pm.height()); + pm = pm.transformed(m); + + y = h2; + while (1){ + if (pm.height() < height()-h4-y){ + p.drawPixmap(width()-maxExtent+1, y, + pm); + y += pm.height(); + } + else { + p.drawPixmap(width()-maxExtent+1, y, + pm, + 0,0, pm.width(), + height()-h4-y); + break; + } + } + } + p.fillRect(maxExtent-1, maxExtent-1, width()-2*maxExtent+2, height()-2*maxExtent+2, color1); + setMask(shapemask); +} + + +void KWMThemeClient::showEvent(QShowEvent *) +{ + doShape(); + widget()->repaint(false); +} + +void KWMThemeClient::mouseDoubleClickEvent( QMouseEvent * e ) +{ + if (e->button() == LeftButton && titlebar->geometry().contains( e->pos() ) ) + titlebarDblClickOperation(); +} + +void KWMThemeClient::desktopChange() +{ + if (stickyBtn) { + bool on = isOnAllDesktops(); + stickyBtn->setPixmap(on ? *pindownPix : *pinupPix); + stickyBtn->setToolTip( on ? i18n("Unsticky") : i18n("Sticky") ); + } +} + +void KWMThemeClient::maximizeChange() +{ + if (maxBtn) { + bool m = maximizeMode() == MaximizeFull; + maxBtn->setPixmap(m ? *minmaxPix : *maxPix); + maxBtn->setToolTip( m ? i18n("Restore") : i18n("Maximize")); + } +} + +void KWMThemeClient::slotMaximize() +{ + maximize( maximizeMode() == MaximizeFull ? MaximizeRestore : MaximizeFull ); +} + +void KWMThemeClient::activeChange() +{ + widget()->update(); +} + +KDecoration::Position KWMThemeClient::mousePosition(const QPoint &p) const +{ + Position m = KDecoration::mousePosition(p); + // corners + if(p.y() < framePixmaps[FrameTop]->height() && + p.x() < framePixmaps[FrameLeft]->width()){ + m = PositionTopLeft; + } + else if(p.y() < framePixmaps[FrameTop]->height() && + p.x() > width()-framePixmaps[FrameRight]->width()){ + m = PositionTopRight; + } + else if(p.y() > height()-framePixmaps[FrameBottom]->height() && + p.x() < framePixmaps[FrameLeft]->width()){ + m = PositionBottomLeft; + } + else if(p.y() > height()-framePixmaps[FrameBottom]->height() && + p.x() > width()-framePixmaps[FrameRight]->width()){ + m = PositionBottomRight; + } // edges + else if(p.y() < framePixmaps[FrameTop]->height()) + m = PositionTop; + else if(p.y() > height()-framePixmaps[FrameBottom]->height()) + m = PositionBottom; + else if(p.x() < framePixmaps[FrameLeft]->width()) + m = PositionLeft; + else if(p.x() > width()-framePixmaps[FrameRight]->width()) + m = PositionRight; + return(m); +} + +void KWMThemeClient::menuButtonPressed() +{ + mnuBtn->setDown(false); // will stay down if I don't do this + QPoint pos = mnuBtn->mapToGlobal(mnuBtn->rect().bottomLeft()); + showWindowMenu( pos ); +} + +void KWMThemeClient::iconChange() +{ + if(mnuBtn){ + if( icon().pixmap( QIcon::Small, QIcon::Normal ).isNull()){ + mnuBtn->setPixmap(*menuPix); + } + else{ + mnuBtn->setPixmap(icon().pixmap( QIcon::Small, QIcon::Normal )); + } + } +} + +bool KWMThemeClient::eventFilter( QObject* o, QEvent* e ) +{ + if ( o != widget() ) + return false; + + switch ( e->type() ) + { + case QEvent::Resize: + resizeEvent( static_cast< QResizeEvent* >( e ) ); + return true; + + case QEvent::Paint: + paintEvent( static_cast< QPaintEvent* >( e ) ); + return true; + + case QEvent::MouseButtonDblClick: + mouseDoubleClickEvent( static_cast< QMouseEvent* >( e ) ); + return true; + + case QEvent::MouseButtonPress: + processMousePressEvent( static_cast< QMouseEvent* >( e ) ); + return true; + + case QEvent::Show: + showEvent( static_cast< QShowEvent* >( e ) ); + return true; + + default: + return false; + } +} + +QSize KWMThemeClient::minimumSize() const +{ + return widget()->minimumSize().expandedTo( QSize( 100, 50 )); +} + +void KWMThemeClient::resize( const QSize& s ) +{ + widget()->resize( s ); +} + +void KWMThemeClient::borders( int& left, int& right, int& top, int& bottom ) const +{ + left = + right = + top = + bottom = + +TODO +} + +KWMThemeFactory::KWMThemeFactory() +{ + create_pixmaps(); +} + +KWMThemeFactory::~KWMThemeFactory() +{ + delete_pixmaps(); +} + +KDecoration* KWMThemeFactory::createDecoration( KDecorationBridge* b ) +{ + return new KWMThemeClient( b, this ); +} + +bool KWMThemeFactory::reset( unsigned long mask ) +{ + bool needHardReset = false; + +TODO + + // doesn't obey the Border size setting + if( mask & ( SettingFont | SettingButtons )) + needHardReset = true; + + if( mask & ( SettingFont | SettingColors )) { + KWMTheme::delete_pixmaps(); + KWMTheme::create_pixmaps(); + } + + if( !needHardReset ) + resetDecorations( mask ); + return needHardReset; +} + +} + +extern "C" +{ + KDE_EXPORT KDecorationFactory *create_factory() + { + return new KWMTheme::KWMThemeFactory(); + } +} + +#include "kwmthemeclient.moc" diff --git a/clients/kwmtheme/kwmthemeclient.h b/clients/kwmtheme/kwmthemeclient.h new file mode 100644 index 0000000000..69e6d3844b --- /dev/null +++ b/clients/kwmtheme/kwmthemeclient.h @@ -0,0 +1,88 @@ +/******************************************************************** +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#ifndef __KWMTHEMECLIENT_H +#define __KWMTHEMECLIENT_H + +#include +#include +#include +#include +#include + +class QSpacerItem; +class QGridLayout; + +namespace KWMTheme { + +class MyButton : public QToolButton +{ +public: + explicit MyButton(QWidget *parent=0, const char *name=0) + : QToolButton(parent, name){setAutoRaise(true);setCursor( arrowCursor ); } +protected: + void drawButtonLabel(QPainter *p); +}; + +class KWMThemeClient : public KDecoration +{ + Q_OBJECT +public: + KWMThemeClient( KDecorationBridge* b, KDecorationFactory* f ); + ~KWMThemeClient(){;} + void init(); + void resize( const QSize& s ); + QSize minimumSize() const; + void borders( int& left, int& right, int& top, int& bottom ) const; +protected: + void doShape(); + void drawTitle(QPainter &p); + void resizeEvent( QResizeEvent* ); + void paintEvent( QPaintEvent* ); + void showEvent( QShowEvent* ); + void mouseDoubleClickEvent( QMouseEvent * ); + bool eventFilter( QObject* o, QEvent* e ); + void captionChange(); + void desktopChange(); + void maximizeChange(); + void iconChange(); + void activeChange(); + void shadeChange() {}; + Position mousePosition(const QPoint &) const; +protected slots: + //void slotReset(); + void menuButtonPressed(); + void slotMaximize(); +private: + QPixmap buffer; + KPixmap *aGradient, *iGradient; + MyButton *maxBtn, *stickyBtn, *mnuBtn; + QSpacerItem *titlebar; + QGridLayout* layout; +}; + +class KWMThemeFactory : public KDecorationFactory +{ +public: + KWMThemeFactory(); + ~KWMThemeFactory(); + KDecoration* createDecoration( KDecorationBridge* b ); + bool reset( unsigned long mask ); +}; + +} + +#endif + diff --git a/clients/kwmtheme/pics/CMakeLists.txt b/clients/kwmtheme/pics/CMakeLists.txt new file mode 100644 index 0000000000..cd0e702950 --- /dev/null +++ b/clients/kwmtheme/pics/CMakeLists.txt @@ -0,0 +1,3 @@ + +install( FILES close.png maximize.png maximizedown.png menu.png iconify.png pindown.png pinup.png unknown.png fog.png fog-grey.png bluesun.png greenie.light.png greenie.dim.png DESTINATION ${DATA_INSTALL_DIR}/kwin/pics ) + diff --git a/clients/kwmtheme/pics/bluesun.png b/clients/kwmtheme/pics/bluesun.png new file mode 100644 index 0000000000000000000000000000000000000000..bcd8c091ff2e38740cdb77d3e91b6c6dfd5e7ba3 GIT binary patch literal 1127 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 dc|+iiyDOIv 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 U_=~Zav8{GM^`N^qP?+cb3;v*f&j0`b literal 0 HcmV?d00001 diff --git a/clients/kwmtheme/pics/greenie.light.png b/clients/kwmtheme/pics/greenie.light.png new file mode 100644 index 0000000000000000000000000000000000000000..44fadcae0b72a1261bab43676321281b47a2d8ef GIT binary patch literal 3837 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 literal 0 HcmV?d00001 diff --git a/clients/kwmtheme/pics/maximize.png b/clients/kwmtheme/pics/maximize.png new file mode 100644 index 0000000000000000000000000000000000000000..ff96561bbfb6a215582c5d72695842b2c087de60 GIT binary patch literal 269 zcmeAS@N?(olHy`uVBq!ia0vp^0wBx*Bp9q_EZ7UAm`Z~Df*BafCZDwc@shmVT^RPt z$G%|(@)SK?977~7CnqQ{{c⪙lL-L1z)*3k_(H(7FK2vx{J;A8ocB2wW^mE?l5yCEEmzD9u9_Q!c<7zd z(OX$^Vy%weNuO)py4Solbx)kvzUY1KJS)SOLZQZ72~TC9xyE2~Gt=`DOG+UIdmDM1 z7;ZQ5HQVfC=56d_xN(btzu#7aO$M8NOuY=veV7>fzjJIhPUJWQ)Xw1P>gTe~DWM4f DkoH){ literal 0 HcmV?d00001 diff --git a/clients/kwmtheme/pics/maximizedown.png b/clients/kwmtheme/pics/maximizedown.png new file mode 100644 index 0000000000000000000000000000000000000000..089c679204c8f7c0722b0e21675274ac9c683384 GIT binary patch literal 269 zcmeAS@N?(olHy`uVBq!ia0vp^0wBx*Bp9q_EZ7UAm`Z~Df*BafCZDwc@shmVT^RPt z$G%|(@)SK?977~7CnqQ{i6}6HJg}EJz#s zR+gMttD|?)=bE?fHE&Jb6X&%rdY?Pb%J8L7s4-WEmy*T?^>ug`g(b72M-jV~F8ZP;?f+~BIYL5PRmDIL9)B`4PE z=$-Vr=B<0pTT}PMdF_kd=gzY-d?^%a%$4v|2AXROHa9apFR`Q)VzBYX4F(%b%)O1x w49zx}82T7)HSqND-eR)R#LvudlZQ7OLv25Ya zZb)PIc;oQ$&?3Gay1zc`;lfi(4<=~V(syAP{?rCq@KjEvOgiFypW_#X4cN8|PQkoJh zaFrn@>f8>&Z)|(^{{Og?`^Y1m#``SHoj_xJszM@4g7ec#$`gxH85k;V6<-Lr_T`MP zkN;O+pYuNF!VE4NUosBcu;q%m!BumE5D&dmI(jQhPOR0@JLz-HTlbo`rtXRJ+84dg zoo8kEQYh4zE8(dOG}jnxZf1I3Vo52)U}NvC1_qvfz9xnne7p?}&5aE_jSNjTZZR-2 f^E5LxH)Le!ZsOqlW8bq7sGY&n)z4*}Q$iB}LF8w| literal 0 HcmV?d00001 diff --git a/clients/kwmtheme/pics/unknown.png b/clients/kwmtheme/pics/unknown.png new file mode 100644 index 0000000000000000000000000000000000000000..48601d1c6736cca23590ea4780b9e7c55fe0b298 GIT binary patch literal 454 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy5&=FTu0R?H92^`1E2m{nTi4Lg zaNxj!|Ns9-yuVfrlwd3g@(X5gcy=QV#7XjYcVXyYmGuB}c6hothE&|D?RVrmpuoW* z%JT33<6VMHy0>gSF3r@v#V2{j=9X>GA5EFe`kfN1ULUc@4cvV4%C#A8PZPGeaZGi0 zT4BRlTfB%r{qm*u)MneXq8F3%V!Y*(AOF2@{1>Bq41X=hYwn7-%Ndq_F;s9-vHWEh zB#^6QW!YFMZ>>?0f6H0$eej%rT>(da?^CMOxcPkMlXW?@O%H4~zi + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#ifndef __BTNHIGHCOLOR_H +#define __BTNHIGHCOLOR_H + +/* XPM */ +static const char * const btnhighcolor_xpm[] = { +"14 15 75 1", +" c None", +". c #6E6E6E", +"+ c #757575", +"@ c #878787", +"# c #7D7D7D", +"$ c #9E9E9E", +"% c #B9B9B9", +"& c #C6C6C6", +"* c #BABABA", +"= c #A5A5A5", +"- c #7F7F7F", +"; c #848484", +"> c #A7A7A7", +", c #BFBFBF", +"' c #D1D1D1", +") c #D7D7D7", +"! c #DADADA", +"~ c #CBCBCB", +"{ c #ABABAB", +"] c #B3B3B3", +"^ c #C2C2C2", +"/ c #CACACA", +"( c #C9C9C9", +"_ c #B6B6B6", +": c #9A9A9A", +"< c #999999", +"[ c #B0B0B0", +"} c #C4C4C4", +"| c #C3C3C3", +"1 c #C0C0C0", +"2 c #AEAEAE", +"3 c #969696", +"4 c #C1C1C1", +"5 c #CCCCCC", +"6 c #C5C5C5", +"7 c #BEBEBE", +"8 c #AAAAAA", +"9 c #CECECE", +"0 c #D4D4D4", +"a c #DBDBDB", +"b c #DEDEDE", +"c c #D5D5D5", +"d c #D3D3D3", +"e c #BCBCBC", +"f c #CDCDCD", +"g c #E0E0E0", +"h c #E4E4E4", +"i c #E8E8E8", +"j c #EBEBEB", +"k c #E9E9E9", +"l c #E6E6E6", +"m c #DDDDDD", +"n c #E1E1E1", +"o c #EDEDED", +"p c #F1F1F1", +"q c #F5F5F5", +"r c #F8F8F8", +"s c #F6F6F6", +"t c #F3F3F3", +"u c #EEEEEE", +"v c #E5E5E5", +"w c #DCDCDC", +"x c #B7B7B7", +"y c #E2E2E2", +"z c #FDFDFD", +"A c #FFFFFF", +"B c #FCFCFC", +"C c #F7F7F7", +"D c #B5B5B5", +"E c #F2F2F2", +"F c #FAFAFA", +"G c #9B9B9B", +"H c #FBFBFB", +"I c #A9A9A9", +"J c #747474", +" .... ", +" ..+@@+.. ", +" .#$%&&*=-. ", +" .;>,')!)~{#. ", +" .$]^///(&_:. ", +".<[*^}||11*23.", +".[4&5555~(678.", +".,90!aba)cd~e.", +".faghijklhm06.", +".'nopqrstuvw/.", +".xyprzAzBCunD.", +" .'EzAAAAFpf. ", +" .GcHAAAAF0<. ", +" ..I5kk5I.. ", +" J..... "}; + +#endif // __BTNHIGHCOLOR_H diff --git a/clients/modernsystem/buttondata.h b/clients/modernsystem/buttondata.h new file mode 100644 index 0000000000..e4fa86c68f --- /dev/null +++ b/clients/modernsystem/buttondata.h @@ -0,0 +1,65 @@ +/* + Copyright (C) 1999 Daniel M. Duley + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#ifndef __BUTTONDATA_H +#define __BUTTONDATA_H + +/* Image bits processed by KPixmap2Bitmaps */ + +#define lowcolor_mask_width 14 +#define lowcolor_mask_height 15 +static const unsigned char lowcolor_mask_bits[] = { + 0xf0,0x03,0xf8,0x07,0xfc,0xcf,0xfe,0x1f,0xfe,0x1f,0xff,0xff,0xff,0xff,0xff, + 0x3f,0xff,0x3f,0xff,0xbf,0xfe,0xdf,0xfe,0x9f,0xfc,0x0f,0xf8,0x07,0xf0,0x03, + 0x00,0x40,0x80,0x00,0x00,0x00,0x29,0x00,0x00,0x00,0x7c,0xfe,0x87,0x40,0x00, + 0x00,0x64,0x00,0x20,0x00,0x64,0x00,0x86,0xfe,0x87,0x40,0x00,0x00,0x65,0x00 }; + +#define lowcolor_6a696a_width 14 +#define lowcolor_6a696a_height 15 +static const unsigned char lowcolor_6a696a_bits[] = { + 0xf0,0x03,0x18,0x06,0x04,0xcc,0x06,0x18,0x02,0x10,0x00,0xc0,0x00,0xc0,0x00, + 0x00,0x00,0x00,0x00,0xc0,0x00,0xc0,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x80,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03, + 0x00,0x00,0x00,0x80,0x24,0x0e,0x08,0x61,0x00,0x00,0x00,0xf0,0xd9,0x0c,0x08 }; + +#define lowcolor_949194_width 14 +#define lowcolor_949194_height 15 +static const unsigned char lowcolor_949194_bits[] = { + 0x00,0x40,0xe0,0x01,0x08,0x02,0x00,0x04,0x04,0x08,0x07,0x78,0x03,0xf0,0x01, + 0xe0,0x01,0x60,0x01,0x20,0x00,0xc0,0x02,0x90,0x04,0x08,0x08,0x04,0xf0,0x03, + 0x00,0x40,0x80,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0xc8,0x51,0x0c,0x08,0x0e, + 0x01,0x00,0x00,0x37,0x00,0x00,0x00,0x58,0x5f,0x49,0x6d,0x61,0x67,0x65,0x54 }; + +#define lowcolor_b4b6b4_width 14 +#define lowcolor_b4b6b4_height 15 +static const unsigned char lowcolor_b4b6b4_bits[] = { + 0x00,0x40,0x00,0x00,0x10,0x00,0x08,0x02,0x18,0x06,0xb8,0x47,0x0c,0xce,0x0e, + 0xd8,0x06,0x58,0x02,0x10,0x02,0xd0,0x00,0x80,0x00,0x00,0x10,0x02,0x00,0x00, + 0x00,0x40,0x80,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01, + 0x00,0x08,0x00,0x02,0x00,0x00,0x00,0x61,0x00,0x00,0x00,0x38,0x5b,0x0c,0x08 }; + +#define lowcolor_e6e6e6_width 14 +#define lowcolor_e6e6e6_height 15 +static const unsigned char lowcolor_e6e6e6_bits[] = { + 0x00,0x40,0x00,0x00,0x00,0x00,0xe0,0x01,0x00,0x00,0x00,0x40,0x00,0xc0,0x00, + 0xc0,0x00,0x40,0xe0,0xc0,0xe0,0xc1,0xe0,0x81,0xf0,0x03,0xc0,0x00,0x00,0x00, + 0x00,0x40,0x80,0x00,0x00,0x00,0x39,0x00,0x00,0x00,0x08,0x19,0x0d,0x08,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00 }; + +#endif // __BUTTONDATA_H diff --git a/clients/modernsystem/config/CMakeLists.txt b/clients/modernsystem/config/CMakeLists.txt new file mode 100644 index 0000000000..612318e188 --- /dev/null +++ b/clients/modernsystem/config/CMakeLists.txt @@ -0,0 +1,16 @@ + + + +########### next target ############### + +set(kwin_modernsys_config_PART_SRCS config.cpp ) + + +kde4_add_plugin(kwin_modernsys_config ${kwin_modernsys_config_PART_SRCS}) + + + +target_link_libraries(kwin_modernsys_config ${KDE4_KDEUI_LIBS} ${QT_QTGUI_LIBRARY}) + +install(TARGETS kwin_modernsys_config DESTINATION ${PLUGIN_INSTALL_DIR} ) + diff --git a/clients/modernsystem/config/config.cpp b/clients/modernsystem/config/config.cpp new file mode 100644 index 0000000000..6a61def8fd --- /dev/null +++ b/clients/modernsystem/config/config.cpp @@ -0,0 +1,157 @@ +/******************************************************************** +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +// Melchior FRANZ -- 2001-04-22 + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +//Added by qt3to4: +#include +#include +#include +#include + + +extern "C" +{ + KDE_EXPORT QObject* allocate_config(KConfig* conf, QWidget* parent) + { + return(new ModernSysConfig(conf, parent)); + } +} + + +// 'conf' is a pointer to the kwindecoration modules open kwin config, +// and is by default set to the "Style" group. +// +// 'parent' is the parent of the QObject, which is a VBox inside the +// Configure tab in kwindecoration + +ModernSysConfig::ModernSysConfig(KConfig* conf, QWidget* parent) : QObject(parent) +{ + clientrc = new KConfig("kwinmodernsysrc"); + KGlobal::locale()->insertCatalog("kwin_clients"); + mainw = new QWidget(parent); + vbox = new QVBoxLayout(mainw); + vbox->setSpacing(6); + vbox->setMargin(0); + + handleBox = new QWidget(mainw); + QGridLayout* layout = new QGridLayout(handleBox ); + layout->setSpacing( KDialog::spacingHint() ); + + cbShowHandle = new QCheckBox(i18n("&Show window resize handle"), handleBox); + cbShowHandle->setWhatsThis( + i18n("When selected, all windows are drawn with a resize " + "handle at the lower right corner. This makes window resizing " + "easier, especially for trackballs and other mouse replacements " + "on laptops.")); + layout->addWidget(cbShowHandle, 0, 0, 1, 2 ); + connect(cbShowHandle, SIGNAL(clicked()), this, SLOT(slotSelectionChanged())); + + sliderBox = new KVBox(handleBox); + //handleSizeSlider = new QSlider(0, 4, 1, 0, Qt::Horizontal, sliderBox); + handleSizeSlider = new QSlider(Qt::Horizontal, sliderBox); + handleSizeSlider->setMinimum(0); + handleSizeSlider->setMaximum(4); + handleSizeSlider->setPageStep(1); + handleSizeSlider->setWhatsThis( + i18n("Here you can change the size of the resize handle.")); + handleSizeSlider->setTickInterval(1); + handleSizeSlider->setTickPosition(QSlider::TicksBelow); + connect(handleSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(slotSelectionChanged())); + + hbox = new KHBox(sliderBox); + hbox->setSpacing(6); + + bool rtl = kapp->layoutDirection() == Qt::RightToLeft; + label1 = new QLabel(i18n("Small"), hbox); + label1->setAlignment(rtl ? Qt::AlignRight : Qt::AlignLeft); + label2 = new QLabel(i18n("Medium"), hbox); + label2->setAlignment( Qt::AlignHCenter ); + label3 = new QLabel(i18n("Large"), hbox); + label3->setAlignment(rtl ? Qt::AlignLeft : Qt::AlignRight); + + vbox->addWidget(handleBox); + vbox->addStretch(1); + +// layout->setColumnMinimumWidth(0, 30); + layout->addItem(new QSpacerItem(30, 10, QSizePolicy::Fixed, QSizePolicy::Fixed), 1, 0); + layout->addWidget(sliderBox, 1, 1); + + KConfigGroup group(conf,"General"); + load(group); + mainw->show(); +} + + +ModernSysConfig::~ModernSysConfig() +{ + delete mainw; + delete clientrc; +} + + +void ModernSysConfig::slotSelectionChanged() +{ + bool i = cbShowHandle->isChecked(); + if (i != hbox->isEnabled()) { + hbox->setEnabled(i); + handleSizeSlider->setEnabled(i); + } + emit changed(); +} + + +void ModernSysConfig::load(const KConfigGroup& /*conf*/) +{ + KConfigGroup cg(clientrc, "General"); + bool i = cg.readEntry("ShowHandle", true); + cbShowHandle->setChecked(i); + hbox->setEnabled(i); + handleSizeSlider->setEnabled(i); + handleWidth = cg.readEntry("HandleWidth", 6); + handleSize = cg.readEntry("HandleSize", 30); + handleSizeSlider->setValue(qMin((handleWidth - 6) / 2, (uint)4)); + +} + + +void ModernSysConfig::save(KConfigGroup& /*conf*/) +{ + KConfigGroup cg(clientrc, "General"); + cg.writeEntry("ShowHandle", cbShowHandle->isChecked()); + cg.writeEntry("HandleWidth", 6 + 2 * handleSizeSlider->value()); + cg.writeEntry("HandleSize", 30 + 4 * handleSizeSlider->value()); + clientrc->sync(); +} + + +void ModernSysConfig::defaults() +{ + cbShowHandle->setChecked(true); + hbox->setEnabled(true); + handleSizeSlider->setEnabled(true); + handleSizeSlider->setValue(0); +} + +#include "config.moc" diff --git a/clients/modernsystem/config/config.h b/clients/modernsystem/config/config.h new file mode 100644 index 0000000000..743b12dbf8 --- /dev/null +++ b/clients/modernsystem/config/config.h @@ -0,0 +1,70 @@ +/******************************************************************** +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#ifndef __KDE_MODSYSTEMCONFIG_H +#define __KDE_MODSYSTEMCONFIG_H + +#include +#include + +#include +#include +//Added by qt3to4: +#include +#include + +class KConfig; +class KConfigGroup; + +class ModernSysConfig : public QObject +{ + Q_OBJECT + + public: + ModernSysConfig(KConfig* conf, QWidget* parent); + ~ModernSysConfig(); + + // These public signals/slots work similar to KCM modules + signals: + void changed(); + + public slots: + void load(const KConfigGroup& conf); + void save(KConfigGroup& conf); + void defaults(); + + protected slots: + void slotSelectionChanged(); // Internal use + + private: + KConfig *clientrc; + QWidget *mainw; + QVBoxLayout *vbox; + QWidget *handleBox; + QCheckBox *cbShowHandle; + KVBox *sliderBox; + QSlider *handleSizeSlider; + KHBox *hbox; + QLabel *label1; + QLabel *label2; + QLabel *label3; + + unsigned handleWidth; + unsigned handleSize; + +}; + + +#endif diff --git a/clients/modernsystem/modernsys.cpp b/clients/modernsystem/modernsys.cpp new file mode 100644 index 0000000000..c254a9d605 --- /dev/null +++ b/clients/modernsystem/modernsys.cpp @@ -0,0 +1,821 @@ +/* + Copyright (C) 1999 Daniel M. Duley + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +// Daniel M. DULEY original work +// Melchior FRANZ configuration options + +#include "modernsys.h" + +#include +#include +#include +#include +#include +//Added by qt3to4: +#include +#include +#include +#include + +#include +#include + +#include "buttondata.h" +#include "btnhighcolor.h" +#include + +namespace ModernSystem { + +static unsigned char iconify_bits[] = { + 0x00, 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00}; + +static unsigned char close_bits[] = { + 0x00, 0x66, 0x7e, 0x3c, 0x3c, 0x7e, 0x66, 0x00}; + +static unsigned char maximize_bits[] = { + 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00}; + +static unsigned char r_minmax_bits[] = { + 0x0c, 0x18, 0x33, 0x67, 0xcf, 0x9f, 0x3f, 0x3f}; + +static unsigned char l_minmax_bits[] = { + 0x30, 0x18, 0xcc, 0xe6, 0xf3, 0xf9, 0xfc, 0xfc}; + +static unsigned char unsticky_bits[] = { + 0x3c, 0x42, 0x99, 0xbd, 0xbd, 0x99, 0x42, 0x3c}; + +static unsigned char sticky_bits[] = { + 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c}; + +static unsigned char question_bits[] = { + 0x3c, 0x66, 0x60, 0x30, 0x18, 0x00, 0x18, 0x18}; + +static unsigned char above_on_bits[] = { + 0x7e, 0x00, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00}; + +static unsigned char above_off_bits[] = { + 0x18, 0x3c, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00}; + +static unsigned char below_off_bits[] = { + 0x00, 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x3c, 0x18}; + +static unsigned char below_on_bits[] = { + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x00, 0x7e}; + +static unsigned char shade_off_bits[] = { + 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static unsigned char shade_on_bits[] = { + 0x00, 0x7e, 0x7e, 0x42, 0x42, 0x42, 0x7e, 0x00}; + +static unsigned char menu_bits[] = { + 0xff, 0x81, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff}; + +static unsigned char btnhighcolor_mask_bits[] = { + 0xe0,0x41,0xf8,0x07,0xfc,0x0f,0xfe,0xdf,0xfe,0x1f,0xff,0x3f,0xff,0xff,0xff, + 0x3f,0xff,0x3f,0xff,0xff,0xff,0xff,0xfe,0x9f,0xfe,0x1f,0xfc,0x0f,0xf0,0x03, + 0x00,0x40,0x80,0x00,0x00,0x00,0x39,0x00,0x00,0x00,0x20,0x99,0x0f,0x08,0xc4, + 0x00,0x00,0x00,0x67,0x00,0x00,0x00,0x58,0x5f,0x43,0x68,0x61,0x6e,0x67,0x65 }; + +static QPixmap *aUpperGradient=0; +static QPixmap *iUpperGradient=0; +static QPixmap *buttonPix=0; +static QPixmap *buttonPixDown=0; +static QPixmap *iButtonPix=0; +static QPixmap *iButtonPixDown=0; + +static QColor *buttonFg; +static bool pixmaps_created = false; + +static QBitmap lcDark1; +static QBitmap lcDark2; +static QBitmap lcDark3; +static QBitmap lcLight1; +static QImage *btnSource; + +static bool show_handle; +static int handle_size; +static int handle_width; +static int border_width; +static int title_height; + +static inline const KDecorationOptions* options() +{ + return KDecoration::options(); +} + +static void make_button_fx(const QPalette &g, QPixmap *pix, bool light=false) +{ + pix->fill(g.background().color()); + + if(QPixmap::defaultDepth() > 8){ + int i, destH, destS, destV, srcH, srcS, srcV; + QColor btnColor = g.background().color(); + + // TODO: This seems to have been broken from the port to Qt4 + if(btnSource->depth() < 32) + *btnSource = btnSource->convertToFormat(QImage::Format_RGB32); + if(light) + btnColor = btnColor.light(120); + btnColor.getHsv(&destH, &destS, &destV); + QImage btnDest(14, 15, QImage::Format_RGB32); + + unsigned int *srcData = (unsigned int *)btnSource->bits(); + unsigned int *destData = (unsigned int *)btnDest.bits(); + QColor srcColor; + for(i=0; i < btnSource->width()*btnSource->height(); ++i){ + srcColor.setRgb(srcData[i]); + srcColor.getHsv(&srcH, &srcS, &srcV); + srcColor.setHsv(destH, destS, srcV); + destData[i] = srcColor.rgb(); + } + *pix = QPixmap::fromImage(btnDest); + + } + else{ + QPainter p(pix); + if(!lcDark1.mask()){ + lcDark1.setMask(lcDark1); + lcDark2.setMask(lcDark2); + lcDark3.setMask(lcDark3); + lcLight1.setMask(lcLight1); + } + p.setPen(g.dark().color()); + p.drawPixmap(0, 0, lcDark2); + p.drawPixmap(0, 0, lcDark1); + p.setPen(g.mid().color()); + p.drawPixmap(0, 0, lcDark3); + p.setPen(g.light().color()); + p.drawPixmap(0, 0, lcLight1); + } +} + +static void gradientFill(QPixmap *pixmap, const QColor &color1, const QColor &color2) +{ + QPainter p(pixmap); + QLinearGradient gradient(0, 0, 0, pixmap->height()); + gradient.setColorAt(0.0, color1); + gradient.setColorAt(1.0, color2); + QBrush brush(gradient); + p.fillRect(pixmap->rect(), brush); +} + +static void create_pixmaps() +{ + if(pixmaps_created) + return; + pixmaps_created = true; + + lcDark1 = QBitmap::fromData(QSize(14, 15), lowcolor_6a696a_bits, QImage::Format_Mono); + lcDark2 = QBitmap::fromData(QSize(14, 15), lowcolor_949194_bits, QImage::Format_Mono); + lcDark3 = QBitmap::fromData(QSize(14, 15), lowcolor_b4b6b4_bits, QImage::Format_Mono); + lcLight1 = QBitmap::fromData(QSize(14, 15), lowcolor_e6e6e6_bits, QImage::Format_Mono); + btnSource = new QImage(btnhighcolor_xpm); + + if(QPixmap::defaultDepth() > 8){ + aUpperGradient = new QPixmap( 32, title_height+2 ); + iUpperGradient = new QPixmap( 32, title_height+2);; + gradientFill(aUpperGradient, + options()->color(KDecoration::ColorTitleBar, true).light(130), + options()->color(KDecoration::ColorTitleBlend, true)); + gradientFill(iUpperGradient, + options()->color(KDecoration::ColorTitleBar, false).light(130), + options()->color(KDecoration::ColorTitleBlend, false)); + } + // buttons + QPalette btnColor(options()->palette(KDecoration::ColorButtonBg, true) ); + btnColor.setCurrentColorGroup(QPalette::Active); + buttonPix = new QPixmap(14, 15); + make_button_fx(btnColor, buttonPix); + buttonPixDown = new QPixmap(14, 15); + make_button_fx(btnColor, buttonPixDown, true); + + btnColor = options()->palette(KDecoration::ColorButtonBg, false); + btnColor.setCurrentColorGroup(QPalette::Active); + iButtonPix = new QPixmap(14, 15); + make_button_fx(btnColor, iButtonPix); + iButtonPixDown = new QPixmap(14, 15); + make_button_fx(btnColor, iButtonPixDown, true); + + + if(qGray(btnColor.background().color().rgb()) < 150) + buttonFg = new QColor(Qt::white); + else + buttonFg = new QColor(Qt::black); + + delete btnSource; +} + +static void delete_pixmaps() +{ + if(aUpperGradient){ + delete aUpperGradient; + delete iUpperGradient; + } + delete buttonPix; + delete buttonPixDown; + delete iButtonPix; + delete iButtonPixDown; + + delete buttonFg; + + pixmaps_created = false; +} + +static void draw_button(QPainter &p, int x, int y, int w, int h, const QPalette &pal) +{ + if (w > 16 && h > 16){ + int x2 = x+w, y2 = y+h; + QPen oldPen = p.pen(); + QPolygon hPntArray, lPntArray; + hPntArray.putPoints(0, 12, x+4,y+1, x+5,y+1, // top left + x+3,y+2, x+2,y+3, x+1,y+4, x+1,y+5, + x+1,y2-5, x+1,y2-4, x+2,y2-3, // half corners + x2-5,y+1, x2-4,y+1, x2-3,y+2); + + lPntArray.putPoints(0, 17, x2-5,y2-1, x2-4,y2-1, // btm right + x2-3,y2-2, x2-2,y2-3, x2-1,y2-5, x2-1,y2-4, + + x+3,y2-2, x+4,y2-1, x+5,y2-1, //half corners + x2-2,y+3, x2-1,y+4, x2-1,y+5, + + x2-5,y2-2, x2-4,y2-2, // testing + x2-3,y2-3, + x2-2,y2-5, x2-2,y2-4); + + p.setPen(pal.color(QPalette::Light)); + p.drawLine(x+6, y, x2-6, y); + p.drawLine(0, y+6, 0, y2-6); + p.drawPoints(hPntArray); + + p.setPen(pal.color(QPalette::Dark)); + p.drawLine(x+6, y2, x2-6, y2); + p.drawLine(x+6, y2-1, x2-6, y2-1); + p.drawLine(x2, y+6, x2, y2-6); + p.drawLine(x2-1, y+6, x2-1, y2-6); + p.drawPoints(lPntArray); + p.setPen(oldPen); + } + else + qDrawWinPanel(&p, x, y, w, h, pal, false); +} + +void ModernSysFactory::read_config() +{ + bool showh; + int hsize, hwidth, bwidth, theight; + + KConfig _c( "kwinmodernsysrc" ); + KConfigGroup c(&_c, "General"); + showh = c.readEntry("ShowHandle", true); + + hwidth = c.readEntry("HandleWidth", 6); + hsize = c.readEntry("HandleSize", 30); + if (!(showh && hsize && hwidth)) { + showh = false; + hwidth = hsize = 0; + } + + switch(options()->preferredBorderSize( this )) { + case BorderLarge: + bwidth = 8; + hwidth = hwidth * 7/5; + hsize = hsize * 7/5; + break; + case BorderVeryLarge: + bwidth = 12; + hwidth = hwidth * 17/10 + 2; + hsize = hsize * 17/10; + break; + case BorderHuge: + bwidth = 18; + hwidth = hwidth * 2 + 6; + hsize = hsize * 2; + break; + /* + // If we allow these large sizes we need to change the + // correlation between the border width and the handle size. + case BorderVeryHuge: + bwidth = 27; + hwidth = hwidth * 5/2 + 15; + hsize = hsize * 5/2; + break; + case BorderOversized: + bwidth = 40; + hwidth = hwidth * 3 + 22; + hsize = hsize * 3; + break; + */ + case BorderNormal: + default: + bwidth = 4; + } + + theight = QFontMetrics(options()->font(true)).height(); + if (theight < 16) + theight = 16; + if (theight < bwidth) + theight = bwidth; + + show_handle = showh; + handle_width = hwidth; + handle_size = hsize; + border_width = bwidth; + title_height = theight; +} + +QList< ModernSysFactory::BorderSize > ModernSysFactory::borderSizes() const +{ // the list must be sorted + return QList< BorderSize >() << BorderNormal << BorderLarge << + BorderVeryLarge << BorderHuge; + // as long as the buttons don't scale don't offer the largest two sizes. + // BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized; +} + +ModernButton::ModernButton(ButtonType type, ModernSys *parent, const char *name) + : KCommonDecorationButton(type, parent) +{ + setObjectName( name ); + setAttribute(Qt::WA_NoSystemBackground, true); + + QBitmap mask = QBitmap::fromData( QSize(14, 15), QPixmap::defaultDepth() > 8 ? btnhighcolor_mask_bits : lowcolor_mask_bits); + resize(14, 15); + + setMask(mask); +} + +void ModernButton::reset(unsigned long changed) +{ + if (changed&DecorationReset || changed&ManualReset || changed&SizeChange || changed&StateChange) { + switch (type() ) { + case CloseButton: + setBitmap(close_bits); + break; + case HelpButton: + setBitmap(question_bits); + break; + case MinButton: + setBitmap(iconify_bits); + break; + case MaxButton: + setBitmap( isChecked() ? (isLeft()?l_minmax_bits:r_minmax_bits) : maximize_bits ); + break; + case OnAllDesktopsButton: + setBitmap( isChecked() ? unsticky_bits : sticky_bits ); + break; + case ShadeButton: + setBitmap( isChecked() ? shade_on_bits : shade_off_bits ); + break; + case AboveButton: + setBitmap( isChecked() ? above_on_bits : above_off_bits ); + break; + case BelowButton: + setBitmap( isChecked() ? below_on_bits : below_off_bits ); + break; + case MenuButton: + setBitmap(menu_bits); + break; + default: + setBitmap(0); + break; + } + + this->update(); + } +} + +void ModernButton::setBitmap(const unsigned char *bitmap) +{ + if (bitmap) + deco = QBitmap::fromData( QSize(8, 8), bitmap); + else { + deco = QBitmap(8,8); + deco.fill(Qt::color0); + } + deco.setMask(deco); +} + +void ModernButton::paintEvent(QPaintEvent *) +{ + QPainter p(this); + drawButton(&p); +} + +void ModernButton::drawButton(QPainter *p) +{ + if(decoration()->isActive()){ + if(buttonPix) + p->drawPixmap(0, 0, isDown() ? *buttonPixDown : *buttonPix); + } + else{ + if(iButtonPix) + p->drawPixmap(0, 0, isDown() ? *iButtonPixDown : *iButtonPix); + } + if(!deco.isNull()){ + QPainterPath path; + path.addRegion( deco ); + p->setBrush(*buttonFg); + p->setPen( Qt::NoPen ); + p->translate( isDown() ? QPoint( 4, 5 ):QPoint( 3, 4 ) ); + p->drawPath( path ); + } +} + +void ModernSys::reset( unsigned long changed) +{ + KCommonDecoration::reset(changed); + + titleBuffer = QPixmap(); + recalcTitleBuffer(); + resetButtons(); + widget()->update(); +} + +ModernSys::ModernSys( KDecorationBridge* b, KDecorationFactory* f ) + : KCommonDecoration( b, f ) +{ +} + +QString ModernSys::visibleName() const +{ + return i18n("Modern System"); +} + +QString ModernSys::defaultButtonsLeft() const +{ + return "X"; +} + +QString ModernSys::defaultButtonsRight() const +{ + return "HSIA"; +} + +bool ModernSys::decorationBehaviour(DecorationBehaviour behaviour) const +{ + switch (behaviour) { + case DB_MenuClose: + return false; + + case DB_WindowMask: + return true; + + case DB_ButtonHide: + return true; + + default: + return KCommonDecoration::decorationBehaviour(behaviour); + } +} + +int ModernSys::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *btn) const +{ + // bool maximized = maximizeMode()==MaximizeFull && !options()->moveResizeMaximizedWindows(); + + switch (lm) { + case LM_BorderLeft: + return border_width + (reverse ? handle_width : 0); + + case LM_BorderRight: + return border_width + (reverse ? 0 : handle_width); + + case LM_BorderBottom: + return border_width + handle_width; + + case LM_TitleEdgeLeft: + return layoutMetric(LM_BorderLeft,respectWindowState)+3; + case LM_TitleEdgeRight: + return layoutMetric(LM_BorderRight,respectWindowState)+3; + + case LM_TitleEdgeTop: + return 2; + + case LM_TitleEdgeBottom: + return 2; + + case LM_TitleBorderLeft: + case LM_TitleBorderRight: + return 4; + + case LM_TitleHeight: + return title_height; + + case LM_ButtonWidth: + return 14; + case LM_ButtonHeight: + return 15; + + case LM_ButtonSpacing: + return 1; + + default: + return KCommonDecoration::layoutMetric(lm, respectWindowState, btn); + } +} + +KCommonDecorationButton *ModernSys::createButton(ButtonType type) +{ + switch (type) { + case MenuButton: + return new ModernButton(MenuButton, this, "menu"); + + case OnAllDesktopsButton: + return new ModernButton(OnAllDesktopsButton, this, "on_all_desktops"); + + case HelpButton: + return new ModernButton(HelpButton, this, "help"); + + case MinButton: + return new ModernButton(MinButton, this, "minimize"); + + case MaxButton: + return new ModernButton(MaxButton, this, "maximize"); + + case CloseButton: + return new ModernButton(CloseButton, this, "close"); + + case AboveButton: + return new ModernButton(AboveButton, this, "above"); + + case BelowButton: + return new ModernButton(BelowButton, this, "below"); + + case ShadeButton: + return new ModernButton(ShadeButton, this, "shade"); + + default: + return 0; + } +} + +void ModernSys::init() +{ + reverse = QApplication::isRightToLeft(); + + KCommonDecoration::init(); + + recalcTitleBuffer(); +} + +void ModernSys::recalcTitleBuffer() +{ + if(oldTitle == caption() && width() == titleBuffer.width()) + return; + + QFontMetrics fm(options()->font(true)); + titleBuffer = QPixmap(width(), title_height+2); + QPainter p; + p.begin(&titleBuffer); + + QPalette pt = options()->palette(ColorTitleBar, true); + pt.setCurrentColorGroup( QPalette::Active ); + if(aUpperGradient) + p.drawTiledPixmap(0, 0, width(), title_height+2, *aUpperGradient); + else + p.fillRect(0, 0, width(), title_height+2, + pt.brush(QPalette::Button)); + + QRect t = titleRect(); // titlebar->geometry(); + t.setTop( 2 ); + t.setLeft( t.left() ); + t.setRight( t.right() - 2 ); + + QRegion r(t.x(), 0, t.width(), title_height+2); + r -= QRect(t.x()+((t.width()-fm.width(caption()))/2)-4, + 0, fm.width(caption())+8, title_height+2); + p.setClipRegion(r); + int i, ly; + ly = (title_height % 3 == 0) ? 3 : 4; + for(i=0; i < (title_height-2)/3; ++i, ly+=3){ + p.setPen(options()->color(ColorTitleBar, true).light(150)); + p.drawLine(0, ly, width()-1, ly); + p.setPen(options()->color(ColorTitleBar, true).dark(120)); + p.drawLine(0, ly+1, width()-1, ly+1); + } + p.setClipRect(t); + p.setPen(options()->color(ColorFont, true)); + p.setFont(options()->font(true)); + + p.drawText(t.x()+((t.width()-fm.width(caption()))/2)-4, + 0, fm.width(caption())+8, title_height+2, Qt::AlignCenter, caption()); + p.setClipping(false); + p.end(); + oldTitle = caption(); +} + +void ModernSys::updateCaption() +{ + widget()->update(titleRect() ); +} + +void ModernSys::drawRoundFrame(QPainter &p, int x, int y, int w, int h) +{ + QPalette pt = options()->palette(ColorFrame, isActive()); + pt.setCurrentColorGroup( QPalette::Active ); + draw_button(p, x, y, w, h, pt); + +} + +void ModernSys::paintEvent( QPaintEvent* ) +{ + // update title buffer... + if (oldTitle != caption() || width() != titleBuffer.width() ) + recalcTitleBuffer(); + + int hs = handle_size; + int hw = handle_width; + + QPainter p( widget() ); + QRect t = titleRect(); // titlebar->geometry(); + + QPalette pt = options()->palette(ColorFrame, isActive()); + pt.setCurrentColorGroup( QPalette::Active ); + QBrush fillBrush(!widget()->palette().brush(QPalette::Background).texture().isNull() ? + widget()->palette().brush(QPalette::Background) : + pt.brush(QPalette::Button)); + + p.fillRect(1, title_height+3, width()-2, height()-(title_height+3), fillBrush); + p.fillRect(width()-6, 0, width()-1, height(), fillBrush); + + t.setTop( 2 ); + t.setLeft( t.left() ); + t.setRight( t.right() - 2 ); + + int w = width() - hw; // exclude handle + int h = height() - hw; + + // titlebar + QPalette g = options()->palette(ColorTitleBar, isActive()); + g.setCurrentColorGroup( QPalette::Active ); + if(isActive()){ + p.drawPixmap(1, 1, titleBuffer, 0, 0, w-2, title_height+2); + } + else{ + if(iUpperGradient) + p.drawTiledPixmap(1, 1, w-2, title_height+2, *iUpperGradient); + else + p.fillRect(1, 1, w-2, title_height+2, fillBrush); + p.setPen(options()->color(ColorFont, isActive())); + p.setFont(options()->font(isActive())); + p.drawText(t, Qt::AlignCenter, caption() ); + } + + // titlebar highlight + p.setPen(g.light().color()); + p.drawLine(1, 1, 1, title_height+3); + p.drawLine(1, 1, w-3, 1); + p.setPen(g.dark().color()); + p.drawLine(w-2, 1, w-2, title_height+3); + p.drawLine(0, title_height+2, w-2, title_height+2); + + // frame + g = options()->palette(ColorFrame, isActive()); + g.setCurrentColorGroup(QPalette::Active); + p.setPen(g.light().color()); + p.drawLine(1, title_height+3, 1, h-2); + p.setPen(g.dark().color()); + p.drawLine(2, h-2, w-2, h-2); + p.drawLine(w-2, title_height+3, w-2, h-2); + //p.drawPoint(w-3, title_height+3); + //p.drawPoint(2, title_height+3); + + qDrawShadePanel(&p, border_width-1, title_height+3, w-2*border_width+2, h-title_height-border_width-2, g, true); + + if (show_handle) { + p.setPen(g.dark().color()); + p.drawLine(width()-3, height()-hs-1, width()-3, height()-3); + p.drawLine(width()-hs-1, height()-3, width()-3, height()-3); + + p.setPen(g.light().color()); + p.drawLine(width()-hw, height()-hs-1, width()-hw, height()-hw); + p.drawLine(width()-hs-1, height()-hw, width()-hw, height()-hw); + p.drawLine(width()-hw, height()-hs-1, width()-4, height()-hs-1); + p.drawLine(width()-hs-1, height()-hw, width()-hs-1, height()-4); + + p.setPen(Qt::black); + p.drawRect(0, 0, w-1, h-1); + + // handle outline + p.drawLine(width()-hw, height()-hs, width(), height()-hs); + p.drawLine(width()-2, height()-hs, width()-2, height()-2); + p.drawLine(width()-hs, height()-2, width()-2, height()-2); + p.drawLine(width()-hs, height()-hw, width()-hs, height()-2); + } else { + p.setPen(Qt::black); + p.drawRect(0, 0, w-1, h-1); + } +} + +void ModernSys::updateWindowShape() +{ + int hs = handle_size; + int hw = handle_width; + QRegion mask; + mask += QRect(0, 0, width()-hw, height()-hw); + //single points + mask -= QRect(0, 0, 1, 1); + mask -= QRect(width()-hw-1, 0, 1, 1); + mask -= QRect(0, height()-hw-1, 1, 1); + + if (show_handle) { + mask += QRect(width()-hs, height()-hs, hs-1, hs-1); + mask -= QRect(width()-2, height()-2, 1, 1); + mask -= QRect(width()-2, height()-hs, 1, 1); + mask -= QRect(width()-hs, height()-2, 1, 1); + } else + mask -= QRect(width()-1, height()-1, 1, 1); + + setMask(mask); +} + +ModernSysFactory::ModernSysFactory() +{ + read_config(); + create_pixmaps(); +} + +ModernSysFactory::~ModernSysFactory() +{ + ModernSystem::delete_pixmaps(); +} + +KDecoration* ModernSysFactory::createDecoration( KDecorationBridge* b ) +{ + return(new ModernSys(b, this))->decoration(); +} + +bool ModernSysFactory::reset( unsigned long changed ) +{ + read_config(); + + bool needHardReset = true; + if( changed & (SettingColors | SettingBorder | SettingFont) ) + { + delete_pixmaps(); + create_pixmaps(); + } + if( ( changed & ~(SettingColors | SettingBorder | SettingFont | SettingButtons)) == 0 ) + needHardReset = false; + + if( needHardReset ) + return true; + else + { + resetDecorations( changed ); + return false; // no recreating of decorations + } +} + +bool ModernSysFactory::supports( Ability ability ) const +{ + switch( ability ) + { + // announce + case AbilityAnnounceButtons: + case AbilityAnnounceColors: + // buttons + case AbilityButtonOnAllDesktops: + case AbilityButtonSpacer: + case AbilityButtonHelp: + case AbilityButtonMinimize: + case AbilityButtonMaximize: + case AbilityButtonClose: + case AbilityButtonAboveOthers: + case AbilityButtonBelowOthers: + case AbilityButtonShade: + case AbilityButtonMenu: + // colors + case AbilityColorTitleBack: + case AbilityColorTitleBlend: + case AbilityColorTitleFore: + return true; + default: + return false; + }; +} + +} + +// KWin extended plugin interface +extern "C" KDE_EXPORT KDecorationFactory* create_factory() +{ + return new ModernSystem::ModernSysFactory(); +} + +// vim:ts=4:sw=4 diff --git a/clients/modernsystem/modernsys.h b/clients/modernsystem/modernsys.h new file mode 100644 index 0000000000..1a68e4de46 --- /dev/null +++ b/clients/modernsystem/modernsys.h @@ -0,0 +1,89 @@ +/* + Copyright (C) 1999 Daniel M. Duley + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#ifndef __MODERNSYS_H +#define __MODERNSYS_H + +#include +#include +#include + +namespace ModernSystem { + +class ModernSys; + +class ModernButton : public KCommonDecorationButton +{ +public: + ModernButton(ButtonType type, ModernSys *parent, const char *name); + void setBitmap(const unsigned char *bitmap); + virtual void reset(unsigned long changed); +protected: + void paintEvent(QPaintEvent *); + virtual void drawButton(QPainter *p); + void drawButtonLabel(QPainter *){;} + QBitmap deco; +}; + +class ModernSys : public KCommonDecoration +{ +public: + ModernSys( KDecorationBridge* b, KDecorationFactory* f ); + ~ModernSys(){;} + + virtual QString visibleName() const; + virtual QString defaultButtonsLeft() const; + virtual QString defaultButtonsRight() const; + virtual bool decorationBehaviour(DecorationBehaviour behaviour) const; + virtual int layoutMetric(LayoutMetric lm, bool respectWindowState = true, const KCommonDecorationButton * = 0) const; + virtual KCommonDecorationButton *createButton(ButtonType type); + + virtual void updateWindowShape(); + virtual void updateCaption(); + + void init(); +protected: + void drawRoundFrame(QPainter &p, int x, int y, int w, int h); + void paintEvent( QPaintEvent* ); + void recalcTitleBuffer(); + void reset( unsigned long ); +private: + QPixmap titleBuffer; + QString oldTitle; + bool reverse; +}; + +class ModernSysFactory : public QObject, public KDecorationFactory +{ + Q_OBJECT + +public: + ModernSysFactory(); + virtual ~ModernSysFactory(); + virtual KDecoration* createDecoration( KDecorationBridge* ); + virtual bool reset( unsigned long changed ); + virtual bool supports( Ability ability ) const; + QList< BorderSize > borderSizes() const; +private: + void read_config(); +}; + +} + +#endif // __MODERNSYS_H diff --git a/clients/modernsystem/modernsystem.desktop b/clients/modernsystem/modernsystem.desktop new file mode 100644 index 0000000000..db47cd6b0b --- /dev/null +++ b/clients/modernsystem/modernsystem.desktop @@ -0,0 +1,88 @@ +[Desktop Entry] +Name=Modern System +Name[af]=Moderne Stelsel +Name[ar]=نظام عصري +Name[be]=Сучасная сістэма +Name[be@latin]=Sučasnaja systema +Name[bg]=Модерна система +Name[bn]=মডার্ন সিস্টেম +Name[bn_IN]=আধুনিক সিস্টেম +Name[br]=Reizhiad Nevez +Name[ca]=Sistema modern +Name[ca@valencia]=Sistema modern +Name[cs]=Moderní systém +Name[csb]=Mòdernô systema +Name[cy]=Cysawd Cyfoes +Name[da]=Moderne system +Name[de]=Modern System +Name[el]=Μοντέρνο σύστημα +Name[en_GB]=Modern System +Name[eo]=Moderna sistemo +Name[es]=Sistema moderno +Name[et]=Modern System +Name[eu]=Sistema modernoa +Name[fa]=سیستم نوین +Name[fi]=Moderni järjestelmä +Name[fr]=Système Moderne +Name[fy]=Modern systeem +Name[ga]=Córas Nua-Aimseartha +Name[gl]=Sistema moderno +Name[gu]=મોર્ડન સિસ્ટમ +Name[he]=מערכת מודרנית +Name[hi]=आधुनिक तंत्र +Name[hne]=आधुनिक तंत्र +Name[hr]=Suvremeni sustav +Name[hsb]=Moderny system +Name[hu]=Modern System +Name[ia]=Systema Moderne +Name[id]=Sistem Modern +Name[is]=Nútímalegt kerfi +Name[it]=Sistema moderno +Name[ja]=モダンシステム +Name[ka]=თანამედროვე სისტემა +Name[kk]=Заманауи жүйе +Name[km]=ប្រព័ន្ធ​ទំនើប +Name[kn]=ಆಧುನಿಕ ವ್ಯವಸ್ಥೆ +Name[ko]=모던 시스템 +Name[ku]=Modern System +Name[lt]=Moderni sistema +Name[lv]=Moderna sistēma +Name[mai]=आधुनिक तंत्र +Name[mk]=Модерен систем +Name[ml]=മോഡേര്‍ണ്‍ സിസ്റ്റം +Name[mr]=आधुनिक प्रणाली +Name[ms]=Sistem Moden +Name[nb]=Moderne System +Name[nds]=Modeern Systeem +Name[ne]=आधुनिक प्रणाली +Name[nl]=Modern systeem +Name[nn]=Moderne System +Name[pa]=ਮਾਡਰਨ ਸਿਸਟਮ +Name[pl]=Nowoczesny system +Name[pt]=Sistema Moderno +Name[pt_BR]=Sistema moderno +Name[ro]=Sistem modern +Name[ru]=Современная система +Name[se]=Áigeguovdilis vuogádat +Name[si]=නවතම පද්ධති +Name[sk]=Moderný systém +Name[sl]=Moderni sistem +Name[sr]=Модеран систем +Name[sr@ijekavian]=Модеран систем +Name[sr@ijekavianlatin]=Moderan sistem +Name[sr@latin]=Moderan sistem +Name[sv]=Modernt system +Name[ta]=நவீன அமைப்பு +Name[te]=ఆధునిక సిస్టమ్ +Name[tg]=Системаи ҳозира +Name[th]=รูปแบบระบบทันสมัย +Name[tr]=Modern Sistem +Name[uk]=Сучасна система +Name[uz]=Zamonaviy tizim +Name[uz@cyrillic]=Замонавий тизим +Name[vi]=Hệ thống Hiện đại +Name[wa]=Sistinme modiene +Name[x-test]=xxModern Systemxx +Name[zh_CN]=现代系统 +Name[zh_TW]=現代系統 +X-KDE-Library=kwin3_modernsys diff --git a/clients/quartz/CMakeLists.txt b/clients/quartz/CMakeLists.txt new file mode 100644 index 0000000000..0bf29dbf30 --- /dev/null +++ b/clients/quartz/CMakeLists.txt @@ -0,0 +1,17 @@ +add_subdirectory( config ) + +########### next target ############### + +set(kwin3_quartz_PART_SRCS quartz.cpp ) + +kde4_add_plugin(kwin3_quartz ${kwin3_quartz_PART_SRCS}) + +target_link_libraries(kwin3_quartz kdecorations) + +install(TARGETS kwin3_quartz DESTINATION ${PLUGIN_INSTALL_DIR} ) + +########### install files ############### + +install( FILES quartz.desktop DESTINATION ${DATA_INSTALL_DIR}/kwin/ ) + + diff --git a/clients/quartz/config/CMakeLists.txt b/clients/quartz/config/CMakeLists.txt new file mode 100644 index 0000000000..708efe5f93 --- /dev/null +++ b/clients/quartz/config/CMakeLists.txt @@ -0,0 +1,16 @@ + + + +########### next target ############### + +set(kwin_quartz_config_PART_SRCS config.cpp ) + + +kde4_add_plugin(kwin_quartz_config ${kwin_quartz_config_PART_SRCS}) + + + +target_link_libraries(kwin_quartz_config ${KDE4_KDEUI_LIBS} ${QT_QTGUI_LIBRARY}) + +install(TARGETS kwin_quartz_config DESTINATION ${PLUGIN_INSTALL_DIR} ) + diff --git a/clients/quartz/config/config.cpp b/clients/quartz/config/config.cpp new file mode 100644 index 0000000000..e8d7db8948 --- /dev/null +++ b/clients/quartz/config/config.cpp @@ -0,0 +1,120 @@ +/******************************************************************** + + This file contains the quartz configuration widget + + Copyright (c) 2001 + Karol Szwed + http://gallium.n3.net/ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#include "config.h" +#include +#include +#include +#include + + +extern "C" +{ + KDE_EXPORT QObject* allocate_config( KConfig* conf, QWidget* parent ) + { + return(new QuartzConfig(conf, parent)); + } +} + + +/* NOTE: + * 'conf' is a pointer to the kwindecoration modules open kwin config, + * and is by default set to the "Style" group. + * + * 'parent' is the parent of the QObject, which is a VBox inside the + * Configure tab in kwindecoration + */ + +QuartzConfig::QuartzConfig( KConfig* conf, QWidget* parent ) + : QObject( parent ) +{ + Q_UNUSED( conf ); + quartzConfig = new KConfig("kwinquartzrc"); + KConfigGroup cg(quartzConfig, "General"); + KGlobal::locale()->insertCatalog("kwin_clients"); + gb = new KVBox( parent ); + cbColorBorder = new QCheckBox( + i18n("Draw window frames using &titlebar colors"), gb ); + cbColorBorder->setWhatsThis( + i18n("When selected, the window decoration borders " + "are drawn using the titlebar colors; otherwise, they are " + "drawn using normal border colors instead.") ); + cbExtraSmall = new QCheckBox( i18n("Quartz &extra slim"), gb ); + cbExtraSmall->setWhatsThis( + i18n("Quartz window decorations with extra-small title bar.") ); + // Load configuration options + load( cg ); + + // Ensure we track user changes properly + connect( cbColorBorder, SIGNAL(clicked()), this, SLOT(slotSelectionChanged()) ); + connect( cbExtraSmall, SIGNAL(clicked()), this, SLOT(slotSelectionChanged()) ); + + // Make the widgets visible in kwindecoration + gb->show(); +} + + +QuartzConfig::~QuartzConfig() +{ + delete gb; + delete quartzConfig; +} + + +void QuartzConfig::slotSelectionChanged() +{ + emit changed(); +} + + +// Loads the configurable options from the kwinrc config file +// It is passed the open config from kwindecoration to improve efficiency +void QuartzConfig::load( const KConfigGroup& /*conf*/ ) +{ + KConfigGroup cg(quartzConfig, "General"); + bool override = cg.readEntry( "UseTitleBarBorderColors", true); + cbColorBorder->setChecked( override ); + override = cg.readEntry( "UseQuartzExtraSlim", false); + cbExtraSmall->setChecked( override ); +} + + +// Saves the configurable options to the kwinrc config file +void QuartzConfig::save( KConfigGroup& /*conf*/ ) +{ + KConfigGroup cg(quartzConfig, "General"); + cg.writeEntry( "UseTitleBarBorderColors", cbColorBorder->isChecked() ); + cg.writeEntry( "UseQuartzExtraSlim", cbExtraSmall->isChecked() ); + // Ensure others trying to read this config get updated + quartzConfig->sync(); +} + + +// Sets UI widget defaults which must correspond to style defaults +void QuartzConfig::defaults() +{ + cbColorBorder->setChecked( true ); + cbExtraSmall->setChecked( false ); +} + +#include "config.moc" +// vim: ts=4 diff --git a/clients/quartz/config/config.h b/clients/quartz/config/config.h new file mode 100644 index 0000000000..f58263858a --- /dev/null +++ b/clients/quartz/config/config.h @@ -0,0 +1,61 @@ +/******************************************************************** + + This file contains the quartz configuration widget + + Copyright (c) 2001 + Karol Szwed + http://gallium.n3.net/ + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#ifndef __KDE_QUARTZCONFIG_H +#define __KDE_QUARTZCONFIG_H + +#include + +#include +#include + +class QuartzConfig: public QObject +{ + Q_OBJECT + + public: + QuartzConfig( KConfig* conf, QWidget* parent ); + ~QuartzConfig(); + + // These public signals/slots work similar to KCM modules + signals: + void changed(); + + public slots: + void load( const KConfigGroup& conf ); + void save( KConfigGroup& conf ); + void defaults(); + + protected slots: + void slotSelectionChanged(); // Internal use + + private: + KConfig* quartzConfig; + QCheckBox* cbColorBorder; + QCheckBox* cbExtraSmall; + KVBox* gb; +}; + + +#endif + +// vim: ts=4 diff --git a/clients/quartz/quartz.cpp b/clients/quartz/quartz.cpp new file mode 100644 index 0000000000..8898d78b8b --- /dev/null +++ b/clients/quartz/quartz.cpp @@ -0,0 +1,849 @@ +/******************************************************************** + + Gallium-Quartz KWin client + + Copyright (C) 2005 Sandro Giessl + Copyright 2001 + Karol Szwed + http://gallium.n3.net/ + + Based on the KDE default client. + + Includes mini titlebars for ToolWindow Support. + Button positions are now customizable. + + drawColorBitmaps originally from kdefx: + Copyright (C) 1999 Daniel M. Duley + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "quartz.h" + + +namespace Quartz { + +static const unsigned char iconify_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00 }; + +static const unsigned char close_bits[] = { + 0x00, 0x00, 0x86, 0x01, 0xcc, 0x00, 0x78, 0x00, 0x30, 0x00, 0x78, 0x00, + 0xcc, 0x00, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char maximize_bits[] = { + 0xff, 0x01, 0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0xff, 0x01, 0x00, 0x00}; + +static const unsigned char minmax_bits[] = { + 0xfc, 0x00, 0xfc, 0x00, 0x84, 0x00, 0xbf, 0x00, 0xbf, 0x00, 0xe1, 0x00, + 0x21, 0x00, 0x21, 0x00, 0x3f, 0x00, 0x00, 0x00}; + +static const unsigned char question_bits[] = { + 0x00, 0x00, 0x3c, 0x00, 0x66, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00}; + +static const unsigned char pindown_white_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x1f, 0xa0, 0x03, + 0xb0, 0x01, 0x30, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char pindown_gray_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x80, 0x07, 0xc0, 0x03, 0xe0, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char pindown_dgray_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x10, 0x70, 0x20, 0x50, 0x20, + 0x48, 0x30, 0xc8, 0x38, 0x08, 0x1f, 0x08, 0x18, 0x10, 0x1c, 0x10, 0x0e, + 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char pinup_white_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x11, + 0x3f, 0x15, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char pinup_gray_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x0a, 0xbf, 0x0a, 0x80, 0x15, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char pinup_dgray_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x40, 0x31, 0x40, 0x2e, + 0x40, 0x20, 0x40, 0x20, 0x7f, 0x2a, 0x40, 0x3f, 0xc0, 0x31, 0xc0, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char above_on_bits[] = { + 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x30, 0x00, 0xfc, 0x00, 0x78, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char above_off_bits[] = { + 0x30, 0x00, 0x78, 0x00, 0xfc, 0x00, 0x30, 0x00, 0xfe, 0x01, 0xfe, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const unsigned char below_on_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x78, 0x00, 0xfc, 0x00, + 0x30, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00}; + +static const unsigned char below_off_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, + 0x30, 0x00, 0xfc, 0x00, 0x78, 0x00, 0x30, 0x00}; + +static const unsigned char shade_on_bits[] = { + 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0xfe, 0x01, 0x00, 0x00}; + +static const unsigned char shade_off_bits[] = { + 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +void drawColorBitmaps(QPainter *p, const QPalette &pal, int x, int y, int w, int h, + const uchar *lightColor, const uchar *midColor, const uchar *blackColor) +{ + const uchar *data[]={lightColor, midColor, blackColor}; + + QColor colors[]={pal.color(QPalette::Light), pal.color(QPalette::Mid), Qt::black}; + + int i; + QSize s(w,h); + for(i=0; i < 3; ++i){ + QBitmap b = QBitmap::fromData(s, data[i], QImage::Format_MonoLSB ); + b.setMask(b); + p->setPen(colors[i]); + p->drawPixmap(x, y, b); + } +} + +/////////////////////////////////////////////////////////////////////////// + +// Titlebar button positions +bool onAllDesktopsButtonOnLeft = true; +bool coloredFrame = true; +bool extraSlim = false; + +QPixmap* titleBlocks = NULL; +QPixmap* ititleBlocks = NULL; +QPixmap* pinDownPix = NULL; +QPixmap* pinUpPix = NULL; +QPixmap* ipinDownPix = NULL; +QPixmap* ipinUpPix = NULL; +static int normalTitleHeight; +static int toolTitleHeight; +static int borderWidth; + +bool quartz_initialized = false; +QuartzHandler* clientHandler; + +/////////////////////////////////////////////////////////////////////////// + + +QuartzHandler::QuartzHandler() +{ + quartz_initialized = false; + readConfig(); + createPixmaps(); + quartz_initialized = true; +} + + +QuartzHandler::~QuartzHandler() +{ + quartz_initialized = false; + freePixmaps(); +} + + +KDecoration* QuartzHandler::createDecoration( KDecorationBridge* bridge ) +{ + return ( new QuartzClient( bridge, this ))->decoration(); +} + + +bool QuartzHandler::reset(unsigned long changed) +{ + quartz_initialized = false; + freePixmaps(); + readConfig(); + createPixmaps(); + quartz_initialized = true; + + // Do we need to "hit the wooden hammer" ? + bool needHardReset = true; + if ((changed & ~(SettingColors | SettingButtons)) == 0) + { + needHardReset = false; + } + + if (needHardReset) { + return true; + } else { + resetDecorations(changed); + return false; + } + return true; +} + + +bool QuartzHandler::supports( Ability ability ) const +{ + switch( ability ) + { + // announce + case AbilityAnnounceButtons: + case AbilityAnnounceColors: + // buttons + case AbilityButtonMenu: + case AbilityButtonOnAllDesktops: + case AbilityButtonHelp: + case AbilityButtonMinimize: + case AbilityButtonMaximize: + case AbilityButtonClose: + case AbilityButtonAboveOthers: + case AbilityButtonBelowOthers: + case AbilityButtonShade: + case AbilityButtonSpacer: + // colors + case AbilityColorTitleBack: + case AbilityColorTitleBlend: + case AbilityColorTitleFore: + case AbilityColorButtonBack: + return true; + default: + return false; + }; +} + + +void QuartzHandler::readConfig() +{ + KConfig configFile("kwinquartzrc"); + KConfigGroup conf( &configFile, "General"); + coloredFrame = conf.readEntry( "UseTitleBarBorderColors", true); + extraSlim = conf.readEntry( "UseQuartzExtraSlim", false); + + // A small hack to make the on all desktops button look nicer + onAllDesktopsButtonOnLeft = KDecoration::options()->titleButtonsLeft().contains( 'S' ); + if ( QApplication::isRightToLeft() ) + onAllDesktopsButtonOnLeft = !onAllDesktopsButtonOnLeft; + switch(options()->preferredBorderSize(this)) { + case BorderLarge: + borderWidth = 8; + break; + case BorderVeryLarge: + borderWidth = 12; + break; + case BorderHuge: + borderWidth = 18; + break; + case BorderVeryHuge: + borderWidth = 27; + break; + case BorderOversized: + borderWidth = 40; + break; + case BorderTiny: + case BorderNormal: + default: + borderWidth = extraSlim?2:4; + } + + normalTitleHeight = QFontMetrics(options()->font(true)).height() - 2; + int nTH_limit=extraSlim?14:18; + normalTitleHeight = QFontMetrics(options()->font(true)).height()-(extraSlim?1:0); + if (normalTitleHeight < nTH_limit) normalTitleHeight = nTH_limit; + if (normalTitleHeight < borderWidth) normalTitleHeight = borderWidth; + + toolTitleHeight = QFontMetrics(options()->font(true, true)).height() - 2; + if (toolTitleHeight < 12) toolTitleHeight = 12; + if (toolTitleHeight < borderWidth) toolTitleHeight = borderWidth; +} + + +// This does the colour transition magic. (You say "Oh, is that it?") +// This may be made configurable at a later stage +void QuartzHandler::drawBlocks( QPixmap *pi, QPixmap &p, const QColor &c1, const QColor &c2 ) +{ + // Draw a background gradient first + QPainter gp; + gp.begin(&p); + QLinearGradient grad(0, 0, p.width(), 0); + grad.setColorAt(0.0, c1); + grad.setColorAt(1.0, c2); + gp.setPen(Qt::NoPen); + gp.setBrush(grad); + gp.drawRect(p.rect()); + gp.end(); + + QPainter px; + + px.begin( pi ); + + int factor = (pi->height()-2)/4; + int square = factor - (factor+2)/4; + + int x = pi->width() - 5*factor - square; + int y = (pi->height() - 4*factor)/2; + + px.fillRect( x, y, square, square, c1.light(120) ); + px.fillRect( x, y+factor, square, square, c1 ); + px.fillRect( x, y+2*factor, square, square, c1.light(110) ); + px.fillRect( x, y+3*factor, square, square, c1 ); + + px.fillRect( x+factor, y, square, square, c1.light(110) ); + px.fillRect( x+factor, y+factor, square, square, c2.light(110) ); + px.fillRect( x+factor, y+2*factor, square, square, c1.light(120) ); + px.fillRect( x+factor, y+3*factor, square, square, c2.light(130) ); + + px.fillRect( x+2*factor, y+factor, square, square, c1.light(110) ); + px.fillRect( x+2*factor, y+2*factor, square, square, c2.light(120) ); + px.fillRect( x+2*factor, y+3*factor, square, square, c2.light(150) ); + + px.fillRect( x+3*factor, y, square, square, c1.dark(110) ); + px.fillRect( x+3*factor, y+2*factor, square, square, c2.light(120) ); + px.fillRect( x+3*factor, y+3*factor, square, square, c1.dark(120) ); + + px.fillRect( x+4*factor, y+factor, square, square, c1.light(110) ); + px.fillRect( x+4*factor, y+3*factor, square, square, c1.dark(110) ); + + px.fillRect( x+5*factor, y+2*factor, square, square, c2.light(120)); + px.fillRect( x+5*factor, y+3*factor, square, square, c2.light(110) ); +} + + +// This paints the button pixmaps upon loading the style. +void QuartzHandler::createPixmaps() +{ + // Obtain titlebar blend colours, and create the block stuff on pixmaps. + QPalette g2 = options()->palette(ColorTitleBlend, true); + g2.setCurrentColorGroup( QPalette::Active ); + QColor c2 = g2.color( QPalette::Background ); + g2 = options()->palette(ColorTitleBar, true ); + g2.setCurrentColorGroup( QPalette::Active ); + QColor c = g2.color(QPalette::Background).light(130); + + titleBlocks = new QPixmap( normalTitleHeight*25/18, normalTitleHeight ); + drawBlocks( titleBlocks, *titleBlocks, c, c2 ); + + g2 = options()->palette(ColorTitleBlend, false); + g2.setCurrentColorGroup( QPalette::Active ); + c2 = g2.color( QPalette::Background ); + g2 = options()->palette(ColorTitleBar, false ); + g2.setCurrentColorGroup( QPalette::Active ); + c = g2.color(QPalette::Background).light(130); + + ititleBlocks = new QPixmap( normalTitleHeight*25/18, normalTitleHeight ); + drawBlocks( ititleBlocks, *ititleBlocks, c, c2 ); + + // Set the on all desktops pin pixmaps; + QPalette g; + QPainter p; + + g = options()->palette( onAllDesktopsButtonOnLeft ? ColorTitleBar : ColorTitleBlend, true ); + g.setCurrentColorGroup( QPalette::Active ); + c = onAllDesktopsButtonOnLeft ? g.color(QPalette::Background).light(130) : g.color(QPalette::Background); + g2 = options()->palette( ColorButtonBg, true ); + g2.setCurrentColorGroup( QPalette::Active ); + + QImage pinImg = QImage(16, 16, QImage::Format_ARGB32_Premultiplied); + p.begin(&pinImg); + p.fillRect( 0, 0, 16, 16, c); + drawColorBitmaps( &p, g2, 0, 1, 16, 16, pinup_white_bits, pinup_gray_bits, pinup_dgray_bits ); + p.end(); + pinUpPix = new QPixmap(QPixmap::fromImage(pinImg)); + + p.begin(&pinImg); + p.fillRect( 0, 0, 16, 16, c); + drawColorBitmaps( &p, g2, 0, 1, 16, 16, pindown_white_bits, pindown_gray_bits, pindown_dgray_bits ); + p.end(); + pinDownPix = new QPixmap(QPixmap::fromImage(pinImg)); + + // Inactive pins + g = options()->palette( onAllDesktopsButtonOnLeft ? ColorTitleBar : ColorTitleBlend, false ); + g.setCurrentColorGroup( QPalette::Active ); + c = onAllDesktopsButtonOnLeft ? g.color(QPalette::Background).light(130) : g.color( QPalette::Background ); + g2 = options()->palette( ColorButtonBg, false ); + g2.setCurrentColorGroup( QPalette::Active ); + + p.begin(&pinImg); + p.fillRect( 0, 0, 16, 16, c); + drawColorBitmaps( &p, g2, 0, 1, 16, 16, pinup_white_bits, pinup_gray_bits, pinup_dgray_bits ); + p.end(); + ipinUpPix = new QPixmap(QPixmap::fromImage(pinImg)); + + p.begin(&pinImg); + p.fillRect( 0, 0, 16, 16, c); + drawColorBitmaps( &p, g2, 0, 1, 16, 16, pindown_white_bits, pindown_gray_bits, pindown_dgray_bits ); + p.end(); + ipinDownPix = new QPixmap(QPixmap::fromImage(pinImg)); +} + + +void QuartzHandler::freePixmaps() +{ + delete titleBlocks; + delete ititleBlocks; + + // On all desktops pin images + delete pinUpPix; + delete ipinUpPix; + delete pinDownPix; + delete ipinDownPix; +} + + +QList< QuartzHandler::BorderSize > QuartzHandler::borderSizes() const +{ // the list must be sorted + return QList< BorderSize >() << BorderNormal << BorderLarge << + BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized; +} + + +QuartzButton::QuartzButton(ButtonType type, QuartzClient *parent, const char *name) + : KCommonDecorationButton(type, parent) +{ + setObjectName( name ); + // Eliminate any possible background flicker + setAttribute(Qt::WA_NoSystemBackground, false); + + deco = 0; +} + + +QuartzButton::~QuartzButton() +{ + delete deco; +} + +void QuartzButton::reset(unsigned long changed) +{ + if (changed&DecorationReset || changed&ManualReset || changed&SizeChange || changed&StateChange) { + switch (type() ) { + case CloseButton: + setBitmap(close_bits); + break; + case HelpButton: + setBitmap(question_bits); + break; + case MinButton: + setBitmap(iconify_bits); + break; + case MaxButton: + setBitmap( isChecked() ? minmax_bits : maximize_bits ); + break; + case OnAllDesktopsButton: + setBitmap(0); + break; + case ShadeButton: + setBitmap( isChecked() ? shade_on_bits : shade_off_bits ); + break; + case AboveButton: + setBitmap( isChecked() ? above_on_bits : above_off_bits ); + break; + case BelowButton: + setBitmap( isChecked() ? below_on_bits : below_off_bits ); + break; + default: + setBitmap(0); + break; + } + + this->update(); + } +} + +void QuartzButton::setBitmap(const unsigned char *bitmap) +{ + delete deco; + deco = 0; + + if (bitmap) { + deco = new QBitmap(QBitmap::fromData(QSize(10, 10), bitmap)); + deco->setMask( *deco ); + repaint( ); + } +} + +void QuartzButton::paintEvent(QPaintEvent *) +{ + QPainter p(this); + drawButton(&p); +} + +void QuartzButton::drawButton(QPainter *p) +{ + // Never paint if the pixmaps have not been created + if (!quartz_initialized) + return; + + QColor c; + + if (isLeft() ) + c = KDecoration::options()->color(KDecoration::ColorTitleBar, decoration()->isActive()).light(130); + else + c = KDecoration::options()->color(KDecoration::ColorTitleBlend, decoration()->isActive()); + + // Fill the button background with an appropriate color + p->fillRect(0, 0, width(), height(), c ); + + // If we have a decoration bitmap, then draw that + // otherwise we paint a menu button (with mini icon), or a onAllDesktops button. + if( deco ) + { + int xOff = (width()-10)/2; + int yOff = (height()-10)/2; + QPainterPath path; + path.addRegion( *deco ); + + p->setPen( Qt::NoPen ); + p->setBrush( Qt::black ); + p->translate( isDown() ? QPoint( xOff+2, yOff+2 ) : QPoint( xOff+1, yOff+1 ) ); + p->drawPath( path ); + + p->setBrush( KDecoration::options()->color(KDecoration::ColorButtonBg, decoration()->isActive()).light(150) ); + p->translate( QPoint( -1, -1 ) ); + p->drawPath( path ); + + } else + { + QPixmap btnpix; + int Offset = 0; + + if (type() == OnAllDesktopsButton) + { + if (isDown()) + Offset = 1; + + // Select the right onAllDesktops button to paint + if (decoration()->isActive()) + btnpix = isChecked() ? *pinDownPix : *pinUpPix; + else + btnpix = isChecked() ? *ipinDownPix : *ipinUpPix; + + } else + btnpix = decoration()->icon().pixmap( QSize(10,10), QIcon::Normal); + + // Shrink the miniIcon for tiny titlebars. + if ( height() < 16) + { + // Smooth scale the image + QPixmap tmpPix = btnpix.scaled(height(), height(), Qt::IgnoreAspectRatio,Qt::SmoothTransformation); + p->drawPixmap( 0, 0, tmpPix ); + } else { + Offset += (height() - 16)/2; + p->drawPixmap( Offset, Offset, btnpix ); + } + } +} + +/////////////////////////////////////////////////////////////////////////// + +QuartzClient::QuartzClient(KDecorationBridge* bridge, KDecorationFactory* factory) + : KCommonDecoration (bridge, factory) +{ +} + +QString QuartzClient::visibleName() const +{ + return i18n("Quartz"); +} + +QString QuartzClient::defaultButtonsLeft() const +{ + return "M"; +} + +QString QuartzClient::defaultButtonsRight() const +{ + return "HIA__X"; +} + +bool QuartzClient::decorationBehaviour(DecorationBehaviour behaviour) const +{ + switch (behaviour) { + case DB_MenuClose: + return false; + + case DB_WindowMask: + return false; + + case DB_ButtonHide: + return true; + + default: + return KCommonDecoration::decorationBehaviour(behaviour); + } +} + +int QuartzClient::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *btn) const +{ + bool maximized = maximizeMode()==MaximizeFull && !options()->moveResizeMaximizedWindows(); + + switch (lm) { + case LM_BorderLeft: + case LM_BorderRight: + case LM_BorderBottom: + case LM_TitleEdgeLeft: + case LM_TitleEdgeRight: + { + if (respectWindowState && maximized) { + return 0; + } else { + return borderSize; + } + } + + case LM_TitleEdgeTop: + return borderSize-1; + + case LM_TitleEdgeBottom: + return 1; + + case LM_TitleBorderLeft: + case LM_TitleBorderRight: + return 5; + + case LM_TitleHeight: + return titleHeight; + + case LM_ButtonWidth: + case LM_ButtonHeight: + return titleHeight-2; + + case LM_ButtonSpacing: + return 1; + + default: + return KCommonDecoration::layoutMetric(lm, respectWindowState, btn); + } +} + +KCommonDecorationButton *QuartzClient::createButton(ButtonType type) +{ + switch (type) { + case MenuButton: + return new QuartzButton(MenuButton, this, "menu"); + + case OnAllDesktopsButton: + return new QuartzButton(OnAllDesktopsButton, this, "on_all_desktops"); + + case HelpButton: + return new QuartzButton(HelpButton, this, "help"); + + case MinButton: + return new QuartzButton(MinButton, this, "minimize"); + + case MaxButton: + return new QuartzButton(MaxButton, this, "maximize"); + + case CloseButton: + return new QuartzButton(CloseButton, this, "close"); + + case AboveButton: + return new QuartzButton(AboveButton, this, "above"); + + case BelowButton: + return new QuartzButton(BelowButton, this, "below"); + + case ShadeButton: + return new QuartzButton(ShadeButton, this, "shade"); + + default: + return 0; + } +} + + +void QuartzClient::init() +{ + // Finally, toolWindows look small + if ( isToolWindow() ) { + titleHeight = toolTitleHeight; + largeButtons = false; + } + else { + titleHeight = normalTitleHeight; + largeButtons = true; + } + + borderSize = borderWidth; + + KCommonDecoration::init(); +} + +void QuartzClient::reset( unsigned long changed ) +{ + if (changed & SettingColors || changed & SettingFont) + { + // repaint the whole thing + widget()->repaint(); + } + + KCommonDecoration::reset(changed); +} + + +// Quartz Paint magic goes here. +void QuartzClient::paintEvent( QPaintEvent* ) +{ + // Never paint if the pixmaps have not been created + if (!quartz_initialized) + return; + + const bool maxFull = (maximizeMode()==MaximizeFull) && !options()->moveResizeMaximizedWindows(); + + QPalette g; + QPainter p(widget()); + + // Obtain widget bounds. + QRect r(widget()->rect()); + int x = r.x(); + int y = r.y(); + int x2 = r.width() - 1; + int y2 = r.height() - 1; + int w = r.width(); + int h = r.height(); + + // Draw part of the frame that is the title color + + if( coloredFrame ) + g = options()->palette(ColorTitleBar, isActive()); + else + g = options()->palette(ColorFrame, isActive()); + g.setCurrentColorGroup( QPalette::Active ); + + // Draw outer highlights and lowlights + p.setPen( g.color(QPalette::Light).light(120) ); + p.drawLine( x, y, x2-1, y ); + p.drawLine( x, y+1, x, y2-1 ); + p.setPen( g.color(QPalette::Dark).light(120) ); + p.drawLine( x2, y, x2, y2 ); + p.drawLine( x, y2, x2, y2 ); + + // Fill out the border edges + QColor frameColor; + if ( coloredFrame) + frameColor = g.color(QPalette::Background).light(130); + else + frameColor = g.color( QPalette::Background ); + if (borderSize > 2) { + p.fillRect(x+1, y+1, w-2, borderSize-2, frameColor); // top + if (!maxFull) { + p.fillRect(x+1, y+h-(borderSize), w-2, borderSize-1, frameColor); // bottom + p.fillRect(x+1, y+borderSize-1, borderSize-1, h-2*(borderSize-1), frameColor); // left + p.fillRect(x+w-(borderSize), y+borderSize-1, borderSize-1, h-2*(borderSize-1), frameColor); // right + } + } + + // Draw a frame around the wrapped widget. + p.setPen( g.color(QPalette::Background) ); + if (maxFull) { + p.drawLine(x+1, y+titleHeight+(borderSize-1), w-2, y+titleHeight+(borderSize-1)); + } else { + p.drawRect( x+(borderSize-1), y+titleHeight+(borderSize-1), w-2*(borderSize-1)-1, h-titleHeight-2*(borderSize-1)-1 ); + } + + // Drawing this extra line removes non-drawn areas when shaded + p.drawLine( x+borderSize, y2-borderSize, x2-borderSize, y2-borderSize); + + // Highlight top corner + p.setPen( g.color(QPalette::Light).light(160) ); + p.drawPoint( x, y ); + p.setPen( g.color(QPalette::Light).light(140) ); + p.drawPoint( x+1, y ); + p.drawPoint( x, y+1 ); + + // Draw the title bar. + // =================== + int r_x, r_y, r_x2, r_y2; + widget()->rect().getCoords(&r_x, &r_y, &r_x2, &r_y2); + const int titleEdgeLeft = layoutMetric(LM_TitleEdgeLeft); + const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop); + const int titleEdgeRight = layoutMetric(LM_TitleEdgeRight); + const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom); + const int ttlHeight = layoutMetric(LM_TitleHeight); + const int titleEdgeBottomBottom = r_y+titleEdgeTop+ttlHeight+titleEdgeBottom-1; + r = QRect(r_x+titleEdgeLeft+buttonsLeftWidth(), r_y+titleEdgeTop, + r_x2-titleEdgeRight-buttonsRightWidth()-(r_x+titleEdgeLeft+buttonsLeftWidth()), + titleEdgeBottomBottom-(r_y+titleEdgeTop) ); + + // Obtain titlebar blend colours + QColor c1 = options()->color(ColorTitleBar, isActive() ).light(130); + QColor c2 = options()->color(ColorTitleBlend, isActive() ); + + // Create a disposable pixmap buffer for the titlebar + QPixmap* titleBuffer = new QPixmap( maxFull?w-2:(w-2*(borderSize-1)), titleHeight ); + + QPainter p2( titleBuffer ); + + // subtract titleBlocks pixmap width and some + int rightoffset = r.x()+r.width()-titleBlocks->width()-borderSize; + + p2.fillRect( 0, 0, w, r.height(), c1 ); + p2.fillRect( rightoffset, 0, maxFull?w-rightoffset:w-rightoffset-2*(borderSize-1), r.height(), c2 ); + + // 8 bit displays will be a bit dithered, but they still look ok. + if ( isActive() ) + p2.drawPixmap( rightoffset, 0, *titleBlocks ); + else + p2.drawPixmap( rightoffset, 0, *ititleBlocks ); + + // Draw the title text on the pixmap, and with a smaller font + // for toolwindows than the default. + QFont fnt; + if ( largeButtons ) { + fnt = options()->font(true, false); // font not small + } else { + fnt = options()->font(true, true); // font small + fnt.setWeight( QFont::Normal ); // and disable bold + } + p2.setFont( fnt ); + + p2.setPen( options()->color(ColorFont, isActive() )); + p2.drawText(r.x()+4-borderSize, 0, r.width()-3, r.height(), + Qt::AlignLeft | Qt::AlignVCenter, caption() ); + p2.end(); + + p.drawPixmap( maxFull?1:borderSize-1, borderSize-1, *titleBuffer ); + + delete titleBuffer; +} + +} + +// Extended KWin plugin interface +///////////////////////////////// +extern "C" +{ + KDE_EXPORT KDecorationFactory *create_factory() + { + Quartz::clientHandler = new Quartz::QuartzHandler(); + return Quartz::clientHandler; + } +} + + + +#include "quartz.moc" +// vim: ts=4 +// kate: space-indent off; tab-width 4; diff --git a/clients/quartz/quartz.desktop b/clients/quartz/quartz.desktop new file mode 100644 index 0000000000..ba0b113210 --- /dev/null +++ b/clients/quartz/quartz.desktop @@ -0,0 +1,89 @@ +[Desktop Entry] +Name=Quartz +Name[af]=Quartz +Name[ar]=كوارتز +Name[be]=Quartz +Name[be@latin]=Quartz +Name[bg]=Кварц +Name[bn]=কোয়ার্ট্‌জ +Name[bn_IN]=Quartz (কোয়ার্টজ) +Name[br]=Quartz +Name[ca]=Quartz +Name[ca@valencia]=Quartz +Name[cs]=Quartz +Name[csb]=Kwarc +Name[cy]=Cwarts +Name[da]=Quartz +Name[de]=Quartz +Name[el]=Quartz +Name[en_GB]=Quartz +Name[eo]=Quartz +Name[es]=Cuarzo +Name[et]=Quartz +Name[eu]=Kuartzoa +Name[fa]=کوارتز +Name[fi]=Quartz +Name[fr]=Quartz +Name[fy]=Quartz +Name[ga]=Grianchloch +Name[gl]=Quartz +Name[gu]=ક્વાર્ટઝ +Name[he]=Quartz +Name[hi]=क्वार्ट्ज +Name[hne]=क्वार्ट्ज +Name[hr]=Kvarc +Name[hsb]=Quartz +Name[hu]=Quartz +Name[ia]=Quartz +Name[id]=Quartz +Name[is]=Kvartz +Name[it]=Quarzo +Name[ja]=Quartz +Name[ka]=კვარცი +Name[kk]=Кварц +Name[km]=Quartz +Name[kn]=ಕ್ವಾರ್ಟ್ಜ +Name[ko]=수정 +Name[ku]=Quartz +Name[lt]=Quartz +Name[lv]=Quartz +Name[mai]=क्वार्ट्ज +Name[mk]=Кварц +Name[ml]=ക്വാര്‍ട്ട്സ് +Name[mr]=क्वार्ट्ज +Name[ms]=Quartz +Name[nb]=Quartz +Name[nds]=Quartz +Name[ne]=क्वार्ज +Name[nl]=Quartz +Name[nn]=Quartz +Name[pa]=Quartz +Name[pl]=Kwarc +Name[pt]=Quartz +Name[pt_BR]=Quartzo +Name[ro]=Cuarț +Name[ru]=Кварц +Name[se]=Quartz +Name[si]=Quartz +Name[sk]=Quartz +Name[sl]=Quartz +Name[sr]=Кварц +Name[sr@ijekavian]=Кварц +Name[sr@ijekavianlatin]=Kvarc +Name[sr@latin]=Kvarc +Name[sv]=Quartz +Name[ta]=குவார்ட்ஸ் +Name[te]=ఖ్వార్‍ట్జ్ +Name[tg]=Квартс +Name[th]=รูปแบบควอทซ์ +Name[tr]=Kuartz +Name[uk]=Кварц +Name[uz]=Chaqmoqtosh +Name[uz@cyrillic]=Чақмоқтош +Name[vi]=Thạch anh +Name[wa]=Blanc cayô +Name[xh]=Quartz +Name[x-test]=xxQuartzxx +Name[zh_CN]=Quartz +Name[zh_TW]=石英 +X-KDE-Library=kwin3_quartz diff --git a/clients/quartz/quartz.h b/clients/quartz/quartz.h new file mode 100644 index 0000000000..2e113749d2 --- /dev/null +++ b/clients/quartz/quartz.h @@ -0,0 +1,105 @@ +/******************************************************************** + Gallium-Quartz KWin client + + Copyright (C) 2005 Sandro Giessl + Copyright 2001 + Karol Szwed + http://gallium.n3.net/ + + Based on the KDE default client. + + Includes mini titlebars for ToolWindow Support. + Button positions are now customizable. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#ifndef __KDEGALLIUM_QUARTZ_H +#define __KDEGALLIUM_QUARTZ_H + +#include +#include "../../lib/kcommondecoration.h" +#include "../../lib/kdecorationfactory.h" + + +namespace Quartz { + +class QuartzClient; + +class QuartzHandler: public QObject, public KDecorationFactory +{ + Q_OBJECT + public: + QuartzHandler(); + ~QuartzHandler(); + + virtual KDecoration* createDecoration( KDecorationBridge* ); + virtual bool reset(unsigned long changed); + virtual bool supports( Ability ability ) const; + virtual QList< BorderSize > borderSizes() const; + + private: + void readConfig(); + void createPixmaps(); + void freePixmaps(); + void drawBlocks(QPixmap* pi, QPixmap &p, const QColor &c1, const QColor &c2); +}; + + +class QuartzButton : public KCommonDecorationButton +{ + public: + QuartzButton(ButtonType type, QuartzClient *parent, const char *name); + ~QuartzButton(); + void setBitmap(const unsigned char *bitmap); + + void reset(unsigned long changed); + + protected: + void paintEvent(QPaintEvent *); + void drawButton(QPainter *p); + + QBitmap* deco; +}; + + +class QuartzClient : public KCommonDecoration +{ + public: + QuartzClient(KDecorationBridge* bridge, KDecorationFactory* factory); + ~QuartzClient() {;} + + virtual QString visibleName() const; + virtual QString defaultButtonsLeft() const; + virtual QString defaultButtonsRight() const; + virtual bool decorationBehaviour(DecorationBehaviour behaviour) const; + virtual int layoutMetric(LayoutMetric lm, bool respectWindowState = true, const KCommonDecorationButton * = 0) const; + virtual KCommonDecorationButton *createButton(ButtonType type); + + virtual void init(); + + protected: + virtual void reset( unsigned long changed ); + void paintEvent( QPaintEvent* ); + + private: + int titleHeight, borderSize; + bool largeButtons; +}; + +} + +#endif +// vim: ts=4 +// kate: space-indent off; tab-width 4; diff --git a/clients/redmond/CMakeLists.txt b/clients/redmond/CMakeLists.txt new file mode 100644 index 0000000000..c484a8b5b3 --- /dev/null +++ b/clients/redmond/CMakeLists.txt @@ -0,0 +1,11 @@ +set(kwin3_redmond_PART_SRCS redmond.cpp) + +kde4_add_plugin(kwin3_redmond ${kwin3_redmond_PART_SRCS}) + +target_link_libraries(kwin3_redmond kdecorations) + +install(TARGETS kwin3_redmond DESTINATION ${PLUGIN_INSTALL_DIR}) + +########### install files ############### + +install( FILES redmond.desktop DESTINATION ${DATA_INSTALL_DIR}/kwin ) diff --git a/clients/redmond/redmond.cpp b/clients/redmond/redmond.cpp new file mode 100644 index 0000000000..2487664609 --- /dev/null +++ b/clients/redmond/redmond.cpp @@ -0,0 +1,711 @@ +/******************************************************************** + + Redmond KWin client + + Copyright 2001 + Karol Szwed + http://gallium.n3.net/ + + Based on the default KWin client. + + Updated to support toolwindows 3/2001 (KS) + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#include "redmond.h" + +#include +#include +//Added by qt3to4: +#include +#include +#include + +#include +#include +#include +#include + +namespace Redmond { + +static const char * const kdelogo[] = { +/* columns rows colors chars-per-pixel */ +"16 16 8 1", +" c None", +". c #000000", +"+ c #A0A0A4", +"@ c #FFFFFF", +"# c #585858", +"$ c #C0C0C0", +"% c #808080", +"& c #DCDCDC", +" ", +" .. .. ", +" .+@. .@#. ", +" .@@@. .@@@# ", +" .@@@..$@@$. ", +" .@@@.@@@$. ", +" .@@@%@@$. ", +" .@@@&@@. ", +" .@@@@@@. ", +" .@@@$@@&. ", +" .@@@.@@@. ", +" .@@@.+@@@. ", +" .@@@..$@@&. ", +" .@@%. .@@@. ", +" .... ... ", +" "}; + +static unsigned char iconify_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00}; + +static unsigned char close_bits[] = { + 0x00, 0x00, 0x86, 0x01, 0xcc, 0x00, 0x78, 0x00, 0x30, 0x00, 0x78, 0x00, + 0xcc, 0x00, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00}; + +static unsigned char maximize_bits[] = { + 0xff, 0x01, 0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0xff, 0x01, 0x00, 0x00}; + +static unsigned char minmax_bits[] = { + 0xfc, 0x00, 0xfc, 0x00, 0x84, 0x00, 0xbf, 0x00, 0xbf, 0x00, 0xe1, 0x00, + 0x21, 0x00, 0x21, 0x00, 0x3f, 0x00, 0x00, 0x00}; + +static unsigned char question_bits[] = { + 0x00, 0x00, 0x3c, 0x00, 0x66, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00}; + + +// Up / Down titlebar button images +static QPixmap *btnPix1; +static QPixmap *iBtnPix1; +static QPixmap *btnDownPix1; +static QPixmap *iBtnDownPix1; + +static QPixmap *miniBtnPix1; +static QPixmap *iMiniBtnPix1; +static QPixmap *miniBtnDownPix1; +static QPixmap *iMiniBtnDownPix1; + +static QPixmap *defaultMenuPix; +static QColor *btnForeground; +static bool pixmaps_created = false; + +static int toolTitleHeight; +static int normalTitleHeight; +static int borderWidth; + +static inline const KDecorationOptions *options() +{ + return KDecoration::options(); +} + +static void drawButtonFrame( QPixmap *pix, const QPalette &g, bool sunken ) +{ + QPainter p; + int x2 = pix->width() - 3; + int y2 = pix->height() - 3; + p.begin(pix); + + // titlebar button frame + p.setPen( sunken ? g.color(QPalette::Dark).dark(155) : g.color(QPalette::Light)); + p.drawLine(0, 0, x2, 0); + p.drawLine(0, 0, 0, y2); + + if (sunken) + { + p.setPen( g.color(QPalette::Mid).dark(135) ); + p.drawLine(1, 1, x2-1, 1); + p.drawLine(1, 1, 1, y2-1); + } + + p.setPen( sunken ? g.color(QPalette::Light) : g.color(QPalette::Mid).dark(135)); + p.drawLine(1, y2-1, x2-1, y2-1); + p.drawLine(x2-1, 1, x2-1, y2-1); + + p.setPen( sunken ? g.color(QPalette::Light) : g.color(QPalette::Dark).dark(155)); + p.drawLine(0, y2, x2, y2); + p.drawLine(x2, 0, x2, y2); +} + +static void gradientFill(QPixmap *pixmap, + const QColor &color1, const QColor &color2, bool horizontal = false) +{ + QPainter p(pixmap); + QLinearGradient gradient(0, 0, + horizontal ? pixmap->width() : 0, + horizontal ? 0 : pixmap->height()); + gradient.setColorAt(0.0, color1); + gradient.setColorAt(1.0, color2); + QBrush brush(gradient); + p.fillRect(pixmap->rect(), brush); +} + +static void create_pixmaps () +{ + if (pixmaps_created) + return; + + pixmaps_created = true; + + bool highcolor = QPixmap::defaultDepth() > 8; + + btnPix1 = new QPixmap; + btnDownPix1 = new QPixmap; + iBtnPix1 = new QPixmap; + iBtnDownPix1 = new QPixmap; + miniBtnPix1 = new QPixmap; + miniBtnDownPix1 = new QPixmap; + iMiniBtnPix1 = new QPixmap; + iMiniBtnDownPix1 = new QPixmap; + defaultMenuPix = new QPixmap(kdelogo); + + // buttons (active/inactive, sunken/unsunken) + QPalette g = options()->palette(KDecoration::ColorButtonBg, true); + QColor c = g.button().color(); + *btnPix1 = QPixmap(normalTitleHeight, normalTitleHeight-2); + *btnDownPix1 = QPixmap(normalTitleHeight, normalTitleHeight-2); + *iBtnPix1 = QPixmap(normalTitleHeight, normalTitleHeight-2); + *iBtnDownPix1 = QPixmap(normalTitleHeight, normalTitleHeight-2); + + *miniBtnPix1 = QPixmap(toolTitleHeight, toolTitleHeight); + *miniBtnDownPix1 = QPixmap(toolTitleHeight, toolTitleHeight); + *iMiniBtnPix1 = QPixmap(toolTitleHeight, toolTitleHeight); + *iMiniBtnDownPix1 = QPixmap(toolTitleHeight, toolTitleHeight); + + if (highcolor && false) { + gradientFill(btnPix1, c.light(130), c.dark(130)); + gradientFill(btnDownPix1, c.dark(130), c.light(130)); + gradientFill(miniBtnPix1, c.light(130), c.dark(130)); + gradientFill(miniBtnDownPix1, c.dark(130), c.light(130)); + + g = options()->palette(KDecoration::ColorButtonBg, false); + c = g.button().color(); + gradientFill(iBtnPix1, c.light(130), c.dark(130)); + gradientFill(iBtnDownPix1, c.dark(130), c.light(130)); + gradientFill(iMiniBtnPix1, c.light(130), c.dark(130)); + gradientFill(iMiniBtnDownPix1, c.dark(130), c.light(130)); + } else { + btnPix1->fill(c.rgb()); + btnDownPix1->fill(c.rgb()); + miniBtnPix1->fill(c.rgb()); + miniBtnDownPix1->fill(c.rgb()); + + g = options()->palette(KDecoration::ColorButtonBg, false); + c = g.button().color(); + iBtnPix1->fill(c.rgb()); + iBtnDownPix1->fill(c.rgb()); + iMiniBtnPix1->fill(c.rgb()); + iMiniBtnDownPix1->fill(c.rgb()); + } + + g = options()->palette(KDecoration::ColorButtonBg, true); + drawButtonFrame(btnPix1, g, false); + drawButtonFrame(btnDownPix1, g, true); + drawButtonFrame(miniBtnPix1, g, false); + drawButtonFrame(miniBtnDownPix1, g, true); + + g = options()->palette(KDecoration::ColorButtonBg, false); + drawButtonFrame(iBtnPix1, g, false); + drawButtonFrame(iBtnDownPix1, g, true); + drawButtonFrame(iMiniBtnPix1, g, false); + drawButtonFrame(iMiniBtnDownPix1, g, true); + + // Make sure button pixmaps contrast with the current colour scheme. + if (qGray(options()->color(KDecoration::ColorButtonBg, true).rgb()) > 127) + btnForeground = new QColor(Qt::black); + else + btnForeground = new QColor(Qt::white); +} + +void delete_pixmaps() +{ + delete btnPix1; + delete btnDownPix1; + delete iBtnPix1; + delete iBtnDownPix1; + delete miniBtnPix1; + delete miniBtnDownPix1; + delete iMiniBtnPix1; + delete iMiniBtnDownPix1; + delete defaultMenuPix; + delete btnForeground; + pixmaps_created = false; +} + +RedmondButton::RedmondButton(ButtonType type, RedmondDeco *parent) + : KCommonDecorationButton(type, parent) +{ + // Eliminate background flicker + setAttribute(Qt::WA_NoSystemBackground, true); + + miniBtn = decoration()->isToolWindow(); +} + +void RedmondButton::reset(unsigned long changed) +{ + if (changed&DecorationReset || changed&ManualReset || changed&SizeChange || changed&StateChange) { + switch (type() ) { + case CloseButton: + setBitmap(close_bits); + break; + case HelpButton: + setBitmap(question_bits); + break; + case MinButton: + setBitmap(iconify_bits); + break; + case MaxButton: + setBitmap( isChecked() ? minmax_bits : maximize_bits ); + break; + case MenuButton: + { + QPixmap miniIcon = decoration()->icon().pixmap(QSize(16, 16), QIcon::Normal, QIcon::On); + if (!miniIcon.isNull()) { + setPixmap(miniIcon); + } else { + setPixmap(*defaultMenuPix); + } + break; + } + default: + setBitmap(0); + break; + } + + this->update(); + } +} + + +void RedmondButton::setBitmap(const unsigned char *bitmap) +{ + pix = QPixmap(); + + if (bitmap) + deco = QBitmap::fromData( QSize(10, 10), bitmap); + else { + deco = QBitmap(10,10); + deco.fill(Qt::color0); + } + deco.setMask(deco); +} + + +void RedmondButton::setPixmap( const QPixmap &p ) +{ + deco = QPixmap(); + pix = p; + + repaint(); +} + +void RedmondButton::paintEvent(QPaintEvent *) +{ + QPainter p(this); + drawButton(&p); +} + +void RedmondButton::drawButton(QPainter *p) +{ + if ( pix.isNull() ) { + if ( decoration()->isActive() ) { + if ( isDown() ) + p->drawPixmap(0, 0, miniBtn ? *miniBtnDownPix1 : *btnDownPix1); + else + p->drawPixmap(0, 0, miniBtn ? *miniBtnPix1 : *btnPix1); + } else { + if ( isDown() ) + p->drawPixmap(0, 0, miniBtn ? *iMiniBtnDownPix1 : *iBtnDownPix1); + else + p->drawPixmap(0, 0, miniBtn ? *iMiniBtnPix1 : *iBtnPix1); + } + + QPainterPath path; + path.addRegion( deco ); + p->setPen( Qt::NoPen ); + p->setBrush( *btnForeground ); + QPoint offset( ( width() - 10 )/2, ( height() - 10 )/2 ); + if( isDown() ) offset += QPoint( 1, 1 ); + p->translate( offset ); + p->drawPath( path ); + + } else { + if (isLeft() ) { + p->fillRect(0, 0, width(), height(), + options()->color(KDecoration::ColorTitleBar, decoration()->isActive())); + } else { + p->fillRect(0, 0, width(), height(), + options()->color(KDecoration::ColorTitleBlend, decoration()->isActive())); + } + + if ( type()==MenuButton && height() < 16) { + + // Smooth scale the menu button pixmap + QPixmap tmpPix = QPixmap::fromImage( + pix.toImage().scaled( height(), height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation )); + + p->drawPixmap( 0, 0, tmpPix ); + } else { + int xOff = (width() -pix.width() )/2; + int yOff = (height()-pix.height())/2; + p->drawPixmap(xOff, yOff, pix ); + } + } +} + + +RedmondDeco::RedmondDeco(KDecorationBridge *b, KDecorationFactory *f) + : KCommonDecoration(b, f) +{ +} + +QString RedmondDeco::visibleName() const +{ + return i18n("Redmond"); +} + +QString RedmondDeco::defaultButtonsLeft() const +{ + return "M"; +} + +QString RedmondDeco::defaultButtonsRight() const +{ + return "HIA_X"; +} + +bool RedmondDeco::decorationBehaviour(DecorationBehaviour behaviour) const +{ + switch (behaviour) { + case DB_MenuClose: + return true; + + case DB_WindowMask: + return false; + + case DB_ButtonHide: + return true; + + default: + return KCommonDecoration::decorationBehaviour(behaviour); + } +} + +int RedmondDeco::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *btn) const +{ + bool border = !(maximizeMode()==MaximizeFull && !options()->moveResizeMaximizedWindows()); + + switch (lm) { + case LM_BorderLeft: + case LM_BorderRight: + case LM_BorderBottom: + return border ? borderWidth : 0; + + case LM_TitleEdgeLeft: + case LM_TitleEdgeRight: + return border ? borderWidth+2 : 0; + + case LM_TitleEdgeTop: + return border ? borderWidth+2 : 0; + + case LM_TitleEdgeBottom: + return border ? 1 : 0; + + case LM_TitleBorderLeft: + case LM_TitleBorderRight: + return border ? 1 : 0; + + case LM_TitleHeight: + return titleHeight-2; + + case LM_ButtonWidth: + return titleHeight-2; + case LM_ButtonHeight: + if (isToolWindow() || (btn && btn->type()==MenuButton) ) { + return titleHeight-2; + } else { + return titleHeight-2-2; + } + + case LM_ButtonSpacing: + return 0; + + default: + return KCommonDecoration::layoutMetric(lm, respectWindowState, btn); + } +} + +KCommonDecorationButton *RedmondDeco::createButton(ButtonType type) +{ + switch (type) { + case MenuButton: + return new RedmondButton(MenuButton, this); + case HelpButton: + return new RedmondButton(HelpButton, this); + case MinButton: + return new RedmondButton(MinButton, this); + case MaxButton: + return new RedmondButton(MaxButton, this); + case CloseButton: + return new RedmondButton(CloseButton, this); + + default: + return 0; + } +} + +void RedmondDeco::init() +{ +// Finally, toolwindows look small + if ( isToolWindow() ) { + titleHeight = toolTitleHeight; + } else { + titleHeight = normalTitleHeight; + } + + KCommonDecoration::init(); +} + +void RedmondDeco::reset( unsigned long changed ) +{ + KCommonDecoration::reset(changed); +} + +void RedmondDeco::paintEvent( QPaintEvent* ) +{ + bool hicolor = QPixmap::defaultDepth() > 8; + int fontoffset = 1; + + // Modify borderWith used by titlebar to 0, when maximized and not move or resize able + bool border = !(maximizeMode()==MaximizeFull && !options()->moveResizeMaximizedWindows()); + int modBorderWidth = border ? borderWidth : 0; + + QPainter p(widget()); + + // Obtain widget bounds. + QRect r(widget()->rect()); + int x = r.x(); + int y = r.y(); + int x2 = r.width()-1; + int y2 = r.height()-1; + int w = r.width(); + //int h = r.height(); + + // Draw part of the frame that is the frame color + // ============================================== + QPalette g = options()->palette(KDecoration::ColorFrame, isActive()); + g.setCurrentColorGroup( QPalette::Active ); + p.setPen( g.background().color() ); + p.drawLine( x, y, x2-1, y ); + p.drawLine( x, y, x, y2-1 ); + + // Draw line under title bar + p.drawLine( x+borderWidth, y+titleHeight+borderWidth, x2-borderWidth, y+titleHeight+borderWidth ); + // Draw a hidden line that appears during shading + p.drawLine( x+borderWidth, y2-borderWidth, x2-borderWidth, y2-borderWidth ); + + // Fill out the border edges + for (int i = 1; i < borderWidth; i++) + p.drawRect( x+i, y+i, x2-2*i, y2-2*i ); + + // Draw highlights and lowlights + p.setPen(g.color( QPalette::Light )); + for (int i = 1; i <= borderWidth/3; i++) { + p.drawLine( x+i, y+i, x2-i-1, y+i); + p.drawLine( x+i, y+i, x+i, y2-i-1); + } + + p.setPen(g.color(QPalette::Dark).dark(135)); + for (int i = 1; i <= borderWidth/3; i++) { + p.drawLine( x2-i, y+i+1, x2-i, y2-i); + p.drawLine( x+i+1, y2-i, x2-i, y2-i); + } + + // Draw black edges + p.setPen( g.color(QPalette::Dark).dark(155) ); + p.drawLine(x2, y, x2, y2); + p.drawLine(x, y2, x2, y2); + + // Draw the title bar. + // =================== + r = titleRect(); +// QFontMetrics fm(options()->font(true)); + + // Obtain blend colours. + QColor c1 = options()->color(KDecoration::ColorTitleBar, isActive() ); + QColor c2 = options()->color(KDecoration::ColorTitleBlend, isActive() ); + + QFont fnt = options()->font(true, isToolWindow() ); + if (isToolWindow() ) { + fnt.setWeight( QFont::Normal ); + fontoffset = 0; + } + + // Paint without a buffer if the colours are the same to + // improve performance, and only draw gradients on hicolor displays. + if ((c1 != c2) && hicolor) { + // KS - Add gradient caching if needed at a later stage. + + // Create a disposable pixmap buffer for the title blend + QPixmap* titleBuffer = new QPixmap; + *titleBuffer = QPixmap(w-2*modBorderWidth, titleHeight); + + if (titleBuffer->depth() > 16) { + gradientFill(titleBuffer, c1, c2, true); + } + + QPainter p2( titleBuffer ); + + // Since drawing the gradient is (relatively) slow, it is best + // to draw the title text on the pixmap. + + p2.setFont( fnt ); + p2.setPen( options()->color(KDecoration::ColorFont, isActive() )); + p2.drawText( r.x(), fontoffset, r.width()-3, r.height()-1, + Qt::AlignLeft | Qt::AlignVCenter, caption() ); + p2.end(); + + p.drawPixmap( modBorderWidth, modBorderWidth, *titleBuffer ); + + delete titleBuffer; + + } else { + // Assume lower ended hardware, so don't use buffers. + // Don't draw a gradient either. + p.fillRect( modBorderWidth, modBorderWidth, w-2*modBorderWidth, titleHeight, c1 ); + + // Draw the title text. + p.setFont( fnt ); + p.setPen(options()->color(KDecoration::ColorFont, isActive() )); + p.drawText(r.x()+4, r.y()+fontoffset-2, r.width()-3, r.height()-1, + Qt::AlignLeft | Qt::AlignVCenter, caption() ); + } + +} + +void RedmondDecoFactory::readConfig() { + normalTitleHeight = QFontMetrics(options()->font(true)).height(); + QFont toolFont = options()->font(true, true); + toolFont.setWeight(QFont::Normal); + toolTitleHeight = QFontMetrics(toolFont).height(); + switch(options()->preferredBorderSize(this)) { + case BorderLarge: + borderWidth = 8; + if (normalTitleHeight < 20) normalTitleHeight = 20; + if (toolTitleHeight < 20) toolTitleHeight = 20; + break; + case BorderVeryLarge: + borderWidth = 12; + if (normalTitleHeight < 24) normalTitleHeight = 24; + if (toolTitleHeight < 24) toolTitleHeight = 24; + break; + case BorderHuge: + borderWidth = 18; + if (normalTitleHeight < 28) normalTitleHeight = 28; + if (toolTitleHeight < 28) toolTitleHeight = 28; + break; + case BorderVeryHuge: + borderWidth = 27; + if (normalTitleHeight < 33) normalTitleHeight = 33; + if (toolTitleHeight < 33) toolTitleHeight = 33; + break; + case BorderOversized: + borderWidth = 40; + if (normalTitleHeight < 40) normalTitleHeight = 40; + if (toolTitleHeight < 40) toolTitleHeight = 40; + break; + case BorderTiny: + case BorderNormal: + default: + borderWidth = 4; + if (normalTitleHeight < 16) normalTitleHeight = 16; + if (toolTitleHeight < 16) toolTitleHeight = 16; + } +} + +RedmondDecoFactory::RedmondDecoFactory() +{ + readConfig(); + create_pixmaps(); +} + +RedmondDecoFactory::~RedmondDecoFactory() +{ + Redmond::delete_pixmaps(); +} + +KDecoration *RedmondDecoFactory::createDecoration( KDecorationBridge *b ) +{ + return (new RedmondDeco(b, this))->decoration(); +} + +bool RedmondDecoFactory::reset( unsigned long changed ) +{ + // SettingButtons is handled by KCommonDecoration + if ( changed & ( SettingFont | SettingBorder | SettingColors | SettingButtons ) ) { + delete_pixmaps(); + readConfig(); + create_pixmaps(); + resetDecorations(changed); + return true; + } else { + resetDecorations(changed); + return false; + } +} + +bool RedmondDecoFactory::supports( Ability ability ) const +{ + switch( ability ) + { + // announce + case AbilityAnnounceButtons: + case AbilityAnnounceColors: + // buttons + case AbilityButtonMenu: + case AbilityButtonHelp: + case AbilityButtonMinimize: + case AbilityButtonMaximize: + case AbilityButtonClose: + case AbilityButtonSpacer: + // colors + case AbilityColorTitleBack: + case AbilityColorTitleBlend: + case AbilityColorTitleFore: + return true; + default: + return false; + } +} + +QList< RedmondDecoFactory::BorderSize > RedmondDecoFactory::borderSizes() const +{ // the list must be sorted + return QList< BorderSize >() << BorderNormal << BorderLarge << + BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized; +} + +} + +extern "C" KDE_EXPORT KDecorationFactory *create_factory() +{ + return new Redmond::RedmondDecoFactory(); +} + + +#include "redmond.moc" +// vim: ts=4 sw=4 +// kate: space-indent off; tab-width 4; diff --git a/clients/redmond/redmond.desktop b/clients/redmond/redmond.desktop new file mode 100644 index 0000000000..a808c3536e --- /dev/null +++ b/clients/redmond/redmond.desktop @@ -0,0 +1,90 @@ +[Desktop Entry] +Name=Redmond +Name[af]=Redmond +Name[ar]=ريدموند +Name[be]=Redmond +Name[be@latin]=Redmond +Name[bg]=Редмънд +Name[bn]=রেডমন্ড +Name[bn_IN]=Redmond (রেডমন্ড) +Name[br]=Redmond +Name[ca]=Redmond +Name[ca@valencia]=Redmond +Name[cs]=Redmond +Name[csb]=Redmond +Name[cy]=Redmond +Name[da]=Redmond +Name[de]=Redmond +Name[el]=Redmond +Name[en_GB]=Redmond +Name[eo]=Redmondo +Name[es]=Redmond +Name[et]=Redmond +Name[eu]=Redmond +Name[fa]=ردموند +Name[fi]=Redmond +Name[fr]=Redmond +Name[fy]=Redmond +Name[ga]=Redmond +Name[gl]=Redmond +Name[gu]=રેડમન્ડ +Name[he]=Redmond +Name[hi]=रेडमण्ड +Name[hne]=रेडमन्ड +Name[hr]=Redmond +Name[hsb]=Redmond +Name[hu]=Redmond +Name[ia]=Redmond +Name[id]=Redmond +Name[is]=Redmond +Name[it]=Redmond +Name[ja]=Redmond +Name[ka]=რედმონდი +Name[kk]=Redmond +Name[km]=Redmond +Name[kn]=ರೆಡ್ಮಂಡ್ +Name[ko]=레드몬드 +Name[ku]=Redmond +Name[lt]=Redmond +Name[lv]=Redmond +Name[mai]=रेडमंड +Name[mk]=Редмонд +Name[ml]=റെഡ്മണ്ട് +Name[mr]=रेडमंड +Name[ms]=Redmond +Name[nb]=Redmond +Name[nds]=Redmond +Name[ne]=रेडमोन्ड +Name[nl]=Redmond +Name[nn]=Redmond +Name[oc]=Redmond +Name[pa]=ਰੀਡਮੋਂਡ +Name[pl]=Redmond +Name[pt]=Redmond +Name[pt_BR]=Redmond +Name[ro]=Redmond +Name[ru]=Редмонд +Name[se]=Redmond +Name[si]=Redmond +Name[sk]=Redmond +Name[sl]=Redmond +Name[sr]=Редмонд +Name[sr@ijekavian]=Редмонд +Name[sr@ijekavianlatin]=Redmond +Name[sr@latin]=Redmond +Name[sv]=Redmond +Name[ta]=ரெட்மான்ட் +Name[te]=రెడ్‌మాండ్ +Name[tg]=Редмонд +Name[th]=รูปแบบเรดมอนด์ +Name[tr]=Redmond +Name[uk]=Редмонд +Name[uz]=Redmond +Name[uz@cyrillic]=Редмонд +Name[vi]=Redmond +Name[wa]=Redmond +Name[xh]=Redmond +Name[x-test]=xxRedmondxx +Name[zh_CN]=Redmond +Name[zh_TW]=Redmond +X-KDE-Library=kwin3_redmond diff --git a/clients/redmond/redmond.h b/clients/redmond/redmond.h new file mode 100644 index 0000000000..9bc46ebde3 --- /dev/null +++ b/clients/redmond/redmond.h @@ -0,0 +1,103 @@ +/******************************************************************** + + Redmond KWin client + + Copyright 2001-2003 + Ported to kwin_iii by Chris Lee + Karol Szwed + http://gallium.n3.net/ + + Based on the default KWin client. + + Updated to support the new API 9/2003 (CL) + Updated to emulate More Accurately 9/2003 (CL) + Updated to support toolwindows 3/2001 (KS) + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#ifndef __KDE_REDMOND_H +#define __KDE_REDMOND_H + +#include +#include +#include + +namespace Redmond { + +class RedmondDeco; + +class RedmondButton : public KCommonDecorationButton +{ + Q_OBJECT +public: + RedmondButton(ButtonType type, RedmondDeco *parent); + void setBitmap(const unsigned char *bitmap); + void setPixmap(const QPixmap &p); + void reset(unsigned long changed); + +protected: + void paintEvent(QPaintEvent *); + virtual void drawButton(QPainter *p); + void drawButtonLabel(QPainter *){;} + + QBitmap deco; + QPixmap pix; + bool miniBtn; +}; + + +class RedmondDeco : public KCommonDecoration +{ +public: + RedmondDeco(KDecorationBridge *, KDecorationFactory *); + ~RedmondDeco() {;} + + virtual QString visibleName() const; + virtual QString defaultButtonsLeft() const; + virtual QString defaultButtonsRight() const; + virtual bool decorationBehaviour(DecorationBehaviour behaviour) const; + virtual int layoutMetric(LayoutMetric lm, bool respectWindowState = true, const KCommonDecorationButton * = 0) const; + virtual KCommonDecorationButton *createButton(ButtonType type); + + void init(); + +protected: + virtual void reset( unsigned long changed ); + + void paintEvent(QPaintEvent*); + +private: + int titleHeight; +}; + +class RedmondDecoFactory : public QObject, public KDecorationFactory +{ + Q_OBJECT +public: + RedmondDecoFactory(); + virtual ~RedmondDecoFactory(); + virtual KDecoration *createDecoration(KDecorationBridge *); + virtual bool reset(unsigned long); + virtual bool supports( Ability ability ) const; + virtual QList< BorderSize > borderSizes() const; +private: + void readConfig(); +}; + +} + +#endif +// vim: ts=4 +// kate: space-indent off; tab-width 4; diff --git a/clients/test/CMakeLists.txt b/clients/test/CMakeLists.txt new file mode 100644 index 0000000000..050e71c48e --- /dev/null +++ b/clients/test/CMakeLists.txt @@ -0,0 +1,21 @@ + + + + +########### next target ############### + +set(kwin3_test_PART_SRCS test.cpp ) + + +kde4_add_plugin(kwin3_test ${kwin3_test_PART_SRCS}) + + + +target_link_libraries(kwin3_test ${KDE4_KDEUI_LIBS} kdecorations ) + +install(TARGETS kwin3_test DESTINATION ${PLUGIN_INSTALL_DIR} ) + + +########### install files ############### + +install( FILES test.desktop DESTINATION ${DATA_INSTALL_DIR}/kwin ) diff --git a/clients/test/test.cpp b/clients/test/test.cpp new file mode 100644 index 0000000000..34439a4af7 --- /dev/null +++ b/clients/test/test.cpp @@ -0,0 +1,361 @@ +/******************************************************************** + +Copyright (C) 2003 Lubos Lunak + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#include "test.h" + + +#include +#include + +namespace KWinTest +{ + +Decoration::Decoration( KDecorationBridge* bridge, KDecorationFactory* factory ) + : KDecoration( bridge, factory ), + button( NULL ) + { + } + +void Decoration::init() + { + createMainWidget(); + widget()->setEraseColor( red ); + widget()->installEventFilter( this ); + if( isCloseable()) + { + button = new QPushButton( widget()); + button->show(); + button->setCursor( arrowCursor ); + button->move( 0, 0 ); + connect( button, SIGNAL( clicked()), SLOT( closeWindow())); + button->setToolTip( "Zelva Mana" ); + } + } + +Decoration::MousePosition Decoration::mousePosition( const QPoint& p ) const + { + const int range = 16; + const int border = 4; + + MousePosition m = Nowhere; + + int width = widget()->width(); + int height = widget()->height(); + if ( ( p.x() > border && p.x() < width - border ) + && ( p.y() > border && p.y() < height - border ) ) + return Center; + + if ( p.y() <= range && p.x() <= range) + m = TopLeft2; + else if ( p.y() >= height-range && p.x() >= width-range) + m = BottomRight2; + else if ( p.y() >= height-range && p.x() <= range) + m = BottomLeft2; + else if ( p.y() <= range && p.x() >= width-range) + m = TopRight2; + else if ( p.y() <= border ) + m = Top; + else if ( p.y() >= height-border ) + m = Bottom; + else if ( p.x() <= border ) + m = Left; + else if ( p.x() >= width-border ) + m = Right; + else + m = Center; + return m; + } + +void Decoration::borders( int& left, int& right, int& top, int& bottom ) const + { + if( options()->preferredBorderSize( factory()) == BorderTiny ) + { + left = right = bottom = 1; + top = 5; + } + else + { + left = right = options()->preferredBorderSize( factory()) * 5; + top = options()->preferredBorderSize( factory()) * 10; + bottom = options()->preferredBorderSize( factory()) * 2; + } + if( isShade()) + bottom = 0; + if( ( maximizeMode() & MaximizeHorizontal ) && !options()->moveResizeMaximizedWindows()) + left = right = 0; + if( ( maximizeMode() & MaximizeVertical ) && !options()->moveResizeMaximizedWindows()) + bottom = 0; + } + +void Decoration::reset( unsigned long ) + { + } + +void Decoration::resize( const QSize& s ) + { + widget()->resize( s ); + } + +QSize Decoration::minimumSize() const + { + return QSize( 100, 50 ); + } + +bool Decoration::eventFilter( QObject* o, QEvent* e ) + { + if( o == widget()) + { + switch( e->type()) + { + case QEvent::MouseButtonPress: + { // FRAME + processMousePressEvent( static_cast< QMouseEvent* >( e )); + return true; + } + case QEvent::Show: + break; + case QEvent::Hide: + break; + default: + break; + } + } + return false; + } + +} +#include +#include +#include +#include +#include +namespace KWinTest +{ + +// taken from riscos +bool Decoration::animateMinimize(bool iconify) +{ + int style = 1; + switch (style) { + + case 1: + { + // Double twisting double back, with pike ;) + + if (!iconify) // No animation for restore. + return true; + + // Go away quick. + helperShowHide( false ); + qApp->syncX(); + + QRect r = iconGeometry(); + + if (!r.isValid()) + return true; + + // Algorithm taken from Window Maker (http://www.windowmaker.org) + + int sx = geometry().x(); + int sy = geometry().y(); + int sw = width(); + int sh = height(); + int dx = r.x(); + int dy = r.y(); + int dw = r.width(); + int dh = r.height(); + + double steps = 12; + + double xstep = double((dx-sx)/steps); + double ystep = double((dy-sy)/steps); + double wstep = double((dw-sw)/steps); + double hstep = double((dh-sh)/steps); + + double cx = sx; + double cy = sy; + double cw = sw; + double ch = sh; + + double finalAngle = 3.14159265358979323846; + + double delta = finalAngle / steps; + + QPainter p( workspaceWidget()); + p.setRasterOp(Qt::NotROP); + + for (double angle = 0; ; angle += delta) { + + if (angle > finalAngle) + angle = finalAngle; + + double dx = (cw / 10) - ((cw / 5) * sin(angle)); + double dch = (ch / 2) * cos(angle); + double midy = cy + (ch / 2); + + QPoint p1(int(cx + dx), int(midy - dch)); + QPoint p2(int(cx + cw - dx), p1.y()); + QPoint p3(int(cx + dw + dx), int(midy + dch)); + QPoint p4(int(cx - dx), p3.y()); + + grabXServer(); + + p.drawLine(p1, p2); + p.drawLine(p2, p3); + p.drawLine(p3, p4); + p.drawLine(p4, p1); + + p.flush(); + + usleep(500); + + p.drawLine(p1, p2); + p.drawLine(p2, p3); + p.drawLine(p3, p4); + p.drawLine(p4, p1); + + ungrabXServer(); + +// FRAME qApp->processEvents(); // FRAME ??? + + cx += xstep; + cy += ystep; + cw += wstep; + ch += hstep; + + if (angle >= finalAngle) + break; + } + } + break; + + case 2: + { + // KVirc style ? Maybe. For qwertz. + + if (!iconify) // No animation for restore. + return true; + + // Go away quick. + helperShowHide( false ); + + qApp->syncX(); + + int stepCount = 12; + + QRect r(geometry()); + + int dx = r.width() / (stepCount * 2); + int dy = r.height() / (stepCount * 2); + + QPainter p( workspaceWidget()); + p.setRasterOp(Qt::NotROP); + + for (int step = 0; step < stepCount; step++) { + + r.translate(dx, dy); + r.setWidth(r.width() - 2 * dx); + r.setHeight(r.height() - 2 * dy); + + grabXServer(); + + p.drawRect(r); + p.flush(); + usleep(200); + p.drawRect(r); + + ungrabXServer(); + +// FRAME qApp->processEvents(); + } + } + break; + + + default: + { + QRect icongeom = iconGeometry(); + + if (!icongeom.isValid()) + return true; + + QRect wingeom = geometry(); + + QPainter p( workspaceWidget()); + + p.setRasterOp(Qt::NotROP); + +#if 0 + if (iconify) + p.setClipRegion( + QRegion( workspaceWidget()->rect()) - wingeom + ); +#endif + + grabXServer(); + + p.drawLine(wingeom.bottomRight(), icongeom.bottomRight()); + p.drawLine(wingeom.bottomLeft(), icongeom.bottomLeft()); + p.drawLine(wingeom.topLeft(), icongeom.topLeft()); + p.drawLine(wingeom.topRight(), icongeom.topRight()); + + p.flush(); + + qApp->syncX(); + + usleep(30000); + + p.drawLine(wingeom.bottomRight(), icongeom.bottomRight()); + p.drawLine(wingeom.bottomLeft(), icongeom.bottomLeft()); + p.drawLine(wingeom.topLeft(), icongeom.topLeft()); + p.drawLine(wingeom.topRight(), icongeom.topRight()); + + ungrabXServer(); + } + break; + } + return true; +} + +KDecoration* Factory::createDecoration( KDecorationBridge* bridge ) + { + NET::WindowType type = windowType( SUPPORTED_WINDOW_TYPES_MASK, bridge ); + if( type == NET::Dialog ) + ; + return new Decoration( bridge, this ); + } + +bool Factory::reset( unsigned long changed ) + { + resetDecorations( changed ); + return false; + } + +} // namespace + +extern "C" +{ + +KDE_EXPORT KDecorationFactory *create_factory() + { + return new KWinTest::Factory(); + } + +} + +#include "test.moc" diff --git a/clients/test/test.desktop b/clients/test/test.desktop new file mode 100644 index 0000000000..2452bacaf8 --- /dev/null +++ b/clients/test/test.desktop @@ -0,0 +1,87 @@ +[Desktop Entry] +Name=KWin test +Name[af]=KWin toets +Name[ar]=اختبار كوين +Name[be]=Тэст KWin +Name[be@latin]=Test dla akońnika „KWin” +Name[bg]=Тест KWin +Name[bn]=Kwin পরীক্ষা +Name[bn_IN]=KWin পরীক্ষা +Name[ca]=Test de KWin +Name[ca@valencia]=Test de KWin +Name[cs]=KWin test +Name[csb]=Test KWin +Name[cy]=arbrawf KWin +Name[da]=KWin-test +Name[de]=KWin-Test +Name[el]=KWin τεστ +Name[en_GB]=KWin test +Name[eo]=Testo de KDE-fenestroadministrilo +Name[es]=Prueba de KWin +Name[et]=KWin test +Name[eu]=KWin froga +Name[fa]=آزمون KWin +Name[fi]=KWin-testi +Name[fr]=Test de KWin +Name[fy]=KWin test +Name[ga]=Tástáil KWin +Name[gl]=Proba de KWin +Name[gu]=KWin ચકાસણી +Name[he]=בדיקה של KWin +Name[hi]=के-विन जांच +Name[hne]=के-विन जांच +Name[hr]=KWina proba +Name[hsb]=KWin-test +Name[hu]=KWin-teszt +Name[ia]=prova de KWin +Name[id]=Tes KWIN +Name[is]=KWin prófun +Name[it]=Prova di KWin +Name[ja]=KWin テスト +Name[ka]=KWin შემოწმება +Name[kk]=KWin сынауы +Name[km]=សាកល្បង KWin +Name[kn]=ಕೆವಿನ್ ಪರೀಕ್ಷೆ +Name[ko]=KWin 테스트 +Name[ku]=KWin test +Name[lt]=KWin patikrinimas +Name[lv]=KWin tests +Name[mai]=के-विन जांच +Name[mk]=Тест за KWin +Name[ml]=കെവിന്‍ ടെസ്റ്റ് +Name[mr]=केविन जांच +Name[ms]=Ujian KWin +Name[nb]=KWin test +Name[nds]=KWin-Test +Name[ne]=केडीई विन परीक्षण +Name[nl]=KWin test +Name[nn]=KWin-test +Name[pa]=KWin ਟੈਸਟ +Name[pl]=Test KWin +Name[pt]=Teste do KWin +Name[pt_BR]=Teste do KWin +Name[ro]=Test KWin +Name[ru]=Проверка KWin +Name[se]=KWin-geahččaleapmi +Name[si]=KWin පරික්‍ෂණය +Name[sk]=Test KWin +Name[sl]=Preizkus KWin +Name[sr]=Проба К‑вина +Name[sr@ijekavian]=Проба К‑вина +Name[sr@ijekavianlatin]=Proba KWina +Name[sr@latin]=Proba KWina +Name[sv]=Kwin-test +Name[ta]=KWin சோதனை +Name[te]=KWin పరిశీలన +Name[tg]=Санҷиши KWin +Name[th]=ทดสอบ KWin +Name[tr]=KWin testi +Name[uk]=Тест KWin +Name[uz]=KWin sinash +Name[uz@cyrillic]=KWin синаш +Name[vi]=Thử KWin +Name[wa]=Saye KWin +Name[x-test]=xxKWin testxx +Name[zh_CN]=KWin 测试 +Name[zh_TW]=KWin 測試 +X-KDE-Library=kwin3_test diff --git a/clients/test/test.h b/clients/test/test.h new file mode 100644 index 0000000000..a383716e8a --- /dev/null +++ b/clients/test/test.h @@ -0,0 +1,67 @@ +/******************************************************************** + +Copyright (C) 2003 Lubos Lunak + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#ifndef KWIN_TEST +#define KWIN_TEST + +#include +#include +#include + +namespace KWinTest +{ + +const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask + | NET::ToolbarMask | NET::MenuMask | NET::DialogMask /*| NET::OverrideMask*/ | NET::TopMenuMask + | NET::UtilityMask | NET::SplashMask; + +class Decoration + : public KDecoration + { + Q_OBJECT + public: + Decoration( KDecorationBridge* bridge, KDecorationFactory* factory ); + virtual void init(); + virtual MousePosition mousePosition( const QPoint& p ) const; + virtual void borders( int& left, int& right, int& top, int& bottom ) const; + virtual void resize( const QSize& s ); + virtual QSize minimumSize() const; + virtual void activeChange() {}; + virtual void captionChange() {}; + virtual void maximizeChange() {}; + virtual void desktopChange() {}; + virtual void shadeChange() {}; + virtual void iconChange() {}; + virtual bool eventFilter( QObject* o, QEvent* e ); + virtual void reset( unsigned long changed ); + virtual bool animateMinimize( bool minimize ); + private: + QPushButton* button; + }; + +class Factory + : public KDecorationFactory + { + public: + virtual KDecoration* createDecoration( KDecorationBridge* ); + virtual bool reset( unsigned long changed ); + }; + +} // namespace + +#endif diff --git a/clients/web/CMakeLists.txt b/clients/web/CMakeLists.txt new file mode 100644 index 0000000000..af8ba67a5c --- /dev/null +++ b/clients/web/CMakeLists.txt @@ -0,0 +1,22 @@ + + + + +########### next target ############### + +set(kwin3_web_PART_SRCS Web.cpp WebButton.cpp ) + + +kde4_add_plugin(kwin3_web ${kwin3_web_PART_SRCS}) + + + +target_link_libraries(kwin3_web ${KDE4_KDEUI_LIBS} kdecorations ) + +install(TARGETS kwin3_web DESTINATION ${PLUGIN_INSTALL_DIR} ) + + +########### install files ############### + +install( FILES web.desktop DESTINATION ${DATA_INSTALL_DIR}/kwin/ ) + diff --git a/clients/web/Web.cpp b/clients/web/Web.cpp new file mode 100644 index 0000000000..a39248eaa0 --- /dev/null +++ b/clients/web/Web.cpp @@ -0,0 +1,402 @@ +/* + 'Web' kwin client + + Copyright (C) 2005 Sandro Giessl + Copyright (C) 2001 Rik Hemsley (rikkus) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "Web.h" + +#include +//Added by qt3to4: +#include + +#include + +#include "WebButton.h" + +extern "C" +{ + KDE_EXPORT KDecorationFactory *create_factory() + { + return new Web::WebFactory(); + } +} + +namespace Web { + +WebClient::WebClient(KDecorationBridge* bridge, KDecorationFactory* factory) + : KCommonDecoration(bridge, factory) +{ + // Empty. +} + +WebClient::~WebClient() +{ + // Empty. +} + +QString WebClient::visibleName() const +{ + return i18n("Web"); +} + +QString WebClient::defaultButtonsLeft() const +{ + return "S"; +} + +QString WebClient::defaultButtonsRight() const +{ + return "HIA__X"; +} + +bool WebClient::decorationBehaviour(DecorationBehaviour behaviour) const +{ + switch (behaviour) { + case DB_MenuClose: + return false; + + case DB_WindowMask: + return true; + + case DB_ButtonHide: + return true; + + default: + return KCommonDecoration::decorationBehaviour(behaviour); + } +} + +int WebClient::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *btn) const +{ +// bool maximized = maximizeMode()==MaximizeFull && !options()->moveResizeMaximizedWindows(); + + switch (lm) { + case LM_BorderLeft: + case LM_BorderRight: + case LM_BorderBottom: + return borderSize_; + + case LM_TitleEdgeLeft: + case LM_TitleEdgeRight: + case LM_TitleEdgeTop: + case LM_TitleEdgeBottom: + return 0; + + case LM_TitleBorderLeft: + case LM_TitleBorderRight: + return 0; + + case LM_TitleHeight: + case LM_ButtonWidth: + case LM_ButtonHeight: + return titleHeight_; + + case LM_ButtonSpacing: + return 0; + + default: + return KCommonDecoration::layoutMetric(lm, respectWindowState, btn); + } +} + +KCommonDecorationButton *WebClient::createButton(ButtonType type) +{ + switch (type) { + case MenuButton: + return new WebButton(MenuButton, this, shape_); + + case OnAllDesktopsButton: + return new WebButton(OnAllDesktopsButton, this, shape_); + + case HelpButton: + return new WebButton(HelpButton, this, shape_); + + case MinButton: + return new WebButton(MinButton, this, shape_); + + case MaxButton: + return new WebButton(MaxButton, this, shape_); + + case CloseButton: + return new WebButton(CloseButton, this, shape_); + + case AboveButton: + return new WebButton(AboveButton, this, shape_); + + case BelowButton: + return new WebButton(BelowButton, this, shape_); + + case ShadeButton: + return new WebButton(ShadeButton, this, shape_); + + default: + return 0; + } +} + + void +WebClient::init() +{ + // title height + const int textVMargin = 2; + QFontMetrics fm(options()->font(isActive(), isToolWindow())); + + // border size + switch(options()->preferredBorderSize( factory())) { + case BorderLarge: + borderSize_ = 8; + break; + case BorderVeryLarge: + borderSize_ = 12; + break; + case BorderHuge: + borderSize_ = 18; + break; + case BorderVeryHuge: + borderSize_ = 27; + break; + case BorderOversized: + borderSize_ = 40; + break; + case BorderNormal: + default: + borderSize_ = 4; + } + titleHeight_ = qMax(qMax(14, fm.height() + textVMargin * 2), borderSize_); + if (0 != titleHeight_ % 2) + titleHeight_ += 1; + + KConfig c("kwinwebrc"); + shape_ = c.group("General").readEntry("Shape", true); + + KCommonDecoration::init(); +} + + void +WebClient::reset( unsigned long changed ) +{ + if (changed & SettingColors) + { + // repaint the whole thing + widget()->repaint(); + } else if (changed & SettingFont) { + // font has changed -- update title height + // title height + const int textVMargin = 2; + QFontMetrics fm(options()->font(isActive(), isToolWindow())); + titleHeight_ = qMax(qMax(14, fm.height() + textVMargin * 2), borderSize_); + if (0 != titleHeight_ % 2) + titleHeight_ += 1; + + widget()->repaint(); + } + + KCommonDecoration::reset(changed); +} + + void +WebClient::paintEvent(QPaintEvent * pe) +{ + int r_x, r_y, r_x2, r_y2; + widget()->rect().getCoords(&r_x, &r_y, &r_x2, &r_y2); + const int titleEdgeLeft = layoutMetric(LM_TitleEdgeLeft); + const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop); + const int titleEdgeRight = layoutMetric(LM_TitleEdgeRight); + const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom); + const int ttlHeight = layoutMetric(LM_TitleHeight); + const int titleEdgeBottomBottom = r_y+titleEdgeTop+ttlHeight+titleEdgeBottom-1; + QRect titleRect = QRect(r_x+titleEdgeLeft+buttonsLeftWidth()+1, r_y+titleEdgeTop, + r_x2-titleEdgeRight-buttonsRightWidth()-(r_x+titleEdgeLeft+buttonsLeftWidth()+1), + titleEdgeBottomBottom-(r_y+titleEdgeTop) ); + titleRect.setTop(1); + + QRegion mask( calcMask() ); + + QPainter p(widget()); + + p.setPen(Qt::black); + QPalette pal = options()->palette(ColorFrame, isActive()); + pal.setCurrentColorGroup( QPalette::Active ); + p.setBrush( pal.background() ); + + p.setClipRegion(pe->region() - titleRect); + if( isPreview() && shape_ ) p.setClipRegion( mask, Qt::IntersectClip ); + + + QRect r(widget()->rect()); + r.adjust(0, 0, -1, -1); + p.drawRect(r); + + p.setClipRegion(pe->region()); + if( isPreview() && shape_ ) p.setClipRegion( mask, Qt::IntersectClip ); + p.fillRect(titleRect, options()->color(ColorTitleBar, isActive())); + + if (shape_) + { + int r(width()); + int b(height()); + + // Draw edge of top-left corner inside the area removed by the mask. + + p.drawPoint(3, 1); + p.drawPoint(4, 1); + p.drawPoint(2, 2); + p.drawPoint(1, 3); + p.drawPoint(1, 4); + + // Draw edge of top-right corner inside the area removed by the mask. + + p.drawPoint(r - 5, 1); + p.drawPoint(r - 4, 1); + p.drawPoint(r - 3, 2); + p.drawPoint(r - 2, 3); + p.drawPoint(r - 2, 4); + + // Draw edge of bottom-left corner inside the area removed by the mask. + + p.drawPoint(1, b - 5); + p.drawPoint(1, b - 4); + p.drawPoint(2, b - 3); + p.drawPoint(3, b - 2); + p.drawPoint(4, b - 2); + + // Draw edge of bottom-right corner inside the area removed by the mask. + + p.drawPoint(r - 2, b - 5); + p.drawPoint(r - 2, b - 4); + p.drawPoint(r - 3, b - 3); + p.drawPoint(r - 4, b - 2); + p.drawPoint(r - 5, b - 2); + } + + p.setFont(options()->font(isActive(), isToolWindow())); + + p.setPen(options()->color(ColorFont, isActive())); + + p.drawText(titleRect, Qt::AlignCenter, caption()); +} + +QRegion WebClient::calcMask(void) const +{ + QRegion mask(0, 0, width(), height()); + + if (maximizeMode() == MaximizeFull) + return mask; + + int r(width()); + int b(height()); + + // Remove top-left corner. + + mask -= QRegion(0, 0, 5, 1); + mask -= QRegion(0, 1, 3, 1); + mask -= QRegion(0, 2, 2, 1); + mask -= QRegion(0, 3, 1, 2); + + // Remove top-right corner. + + mask -= QRegion(r - 5, 0, 5, 1); + mask -= QRegion(r - 3, 1, 3, 1); + mask -= QRegion(r - 2, 2, 2, 1); + mask -= QRegion(r - 1, 3, 1, 2); + + // Remove bottom-left corner. + + mask -= QRegion(0, b - 5, 1, 3); + mask -= QRegion(0, b - 3, 2, 1); + mask -= QRegion(0, b - 2, 3, 1); + mask -= QRegion(0, b - 1, 5, 1); + + // Remove bottom-right corner. + + mask -= QRegion(r - 5, b - 1, 5, 1); + mask -= QRegion(r - 3, b - 2, 3, 1); + mask -= QRegion(r - 2, b - 3, 2, 1); + mask -= QRegion(r - 1, b - 5, 1, 2); + return mask; +} + +void WebClient::updateWindowShape() +{ + if (!shape_) + return; + setMask(calcMask()); +} + +KDecoration* WebFactory::createDecoration( KDecorationBridge* b ) +{ + return(new WebClient(b, this))->decoration(); +} + +bool WebFactory::reset(unsigned long changed) +{ + // Do we need to "hit the wooden hammer" ? + bool needHardReset = true; + if ((changed & ~(SettingColors | SettingFont | SettingButtons)) == 0 ) + { + needHardReset = false; + } + + if (needHardReset) { + return true; + } else { + resetDecorations(changed); + return false; + } +} + +bool WebFactory::supports( Ability ability ) const +{ + switch( ability ) + { + // announce + case AbilityAnnounceButtons: + case AbilityAnnounceColors: + // buttons + case AbilityButtonOnAllDesktops: + case AbilityButtonHelp: + case AbilityButtonMinimize: + case AbilityButtonMaximize: + case AbilityButtonClose: + case AbilityButtonMenu: + case AbilityButtonAboveOthers: + case AbilityButtonBelowOthers: + case AbilityButtonShade: + case AbilityButtonSpacer: + // colors: + case AbilityColorTitleBack: + case AbilityColorTitleFore: + return true; + default: + return false; + }; +} + +QList< WebFactory::BorderSize > WebFactory::borderSizes() const +{ // the list must be sorted + return QList< BorderSize >() << BorderNormal << BorderLarge << + BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized; +} + +} + +#include "Web.moc" +// vim:ts=2:sw=2:tw=78:set et: +// kate: indent-width 2; replace-tabs on; tab-width 2; space-indent on; diff --git a/clients/web/Web.h b/clients/web/Web.h new file mode 100644 index 0000000000..54d90b3fd8 --- /dev/null +++ b/clients/web/Web.h @@ -0,0 +1,84 @@ +/* + 'Web' kwin client + + Copyright (C) 2005 Sandro Giessl + Copyright (C) 2001 Rik Hemsley (rikkus) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KWIN_WEB_H +#define KWIN_WEB_H + +#include "../../lib/kcommondecoration.h" +#include "../../lib/kdecorationfactory.h" + + +namespace Web +{ + + + class WebClient : public KCommonDecoration + { + public: + + WebClient(KDecorationBridge* bridge, KDecorationFactory* factory); + ~WebClient(); + + virtual QString visibleName() const; + virtual QString defaultButtonsLeft() const; + virtual QString defaultButtonsRight() const; + virtual bool decorationBehaviour(DecorationBehaviour behaviour) const; + virtual int layoutMetric(LayoutMetric lm, bool respectWindowState = true, const KCommonDecorationButton * = 0) const; + virtual KCommonDecorationButton *createButton(ButtonType type); + + virtual QRegion calcMask( void ) const; + virtual void updateWindowShape(); + + virtual void init(); + + protected: + virtual void reset( unsigned long changed ); + + virtual void paintEvent(QPaintEvent *); + + private: + + int titleHeight_, borderSize_; + + bool shape_; + + QBitmap _buttonBitmap(ButtonType t) const; + }; + + class WebFactory : public QObject, public KDecorationFactory + { + Q_OBJECT + + public: + + WebFactory() {} + virtual ~WebFactory() {} + virtual KDecoration* createDecoration( KDecorationBridge* ); + virtual bool reset( unsigned long changed ); + virtual bool supports( Ability ability ) const; + virtual QList< BorderSize > borderSizes() const; + }; +} + +#endif +// vim:ts=2:sw=2:tw=78:set et: +// kate: indent-width 2; replace-tabs on; tab-width 2; space-indent on; diff --git a/clients/web/WebButton.cpp b/clients/web/WebButton.cpp new file mode 100644 index 0000000000..9a9c7e3f97 --- /dev/null +++ b/clients/web/WebButton.cpp @@ -0,0 +1,303 @@ +/* + 'Web' kwin client + + Copyright (C) 2001 Rik Hemsley (rikkus) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "WebButton.h" +#include +//Added by qt3to4: +#include + +#include "Web.h" + +namespace Web { + + static unsigned char close_bits[] = { + 0x42, 0xe7, 0x7e, 0x3c, 0x3c, 0x7e, 0xe7, 0x42 + }; + static unsigned char iconify_bits[] = { + 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x3c, 0x18, 0x00 + }; + static unsigned char maximize_bits[] = { + 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00 + }; + static unsigned char unmaximize_bits[] = { + 0x00, 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f + }; + static unsigned char sticky_bits[] = { + 0x20, 0x70, 0xfa, 0x7e, 0x3c, 0x1c, 0x32, 0x01 + }; + static unsigned char unsticky_bits[] = { + 0x1c, 0x1c, 0x1c, 0x3e, 0x7f, 0x08, 0x08, 0x08 + }; + static unsigned char help_bits[] = { + 0x18, 0x18, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x3c + }; + static unsigned char shade_on_bits[] = { + 0xff, 0xff, 0x81, 0x81, 0x99, 0xbd, 0x81, 0xff + }; + static unsigned char shade_off_bits[] = { + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + static unsigned char above_on_bits[] = { + 0xff, 0x7e, 0x3c, 0x18, 0x00, 0xff, 0xff, 0x00 + }; + static unsigned char above_off_bits[] = { + 0x18, 0x3c, 0x7e, 0xff, 0x00, 0xff, 0xff, 0x00 + }; + static unsigned char below_on_bits[] = { + 0x00, 0xff, 0xff, 0x00, 0x18, 0x3c, 0x7e, 0xff + }; + static unsigned char below_off_bits[] = { + 0x00, 0xff, 0xff, 0x00, 0xff, 0x7e, 0x3c, 0x18 + }; + static unsigned char menu_bits[] = { + 0xff, 0x81, 0x81, 0xff, 0x81, 0xff, 0x81, 0xff + }; + +WebButton::WebButton(ButtonType type, WebClient *parent, bool shape) + : KCommonDecorationButton (type, parent), + mouseOver_ (false), + shape_ (shape), + deco_ (parent) +{ + setAttribute(Qt::WA_NoSystemBackground, true); +} + +WebButton::~WebButton() +{ + // Empty. +} + +void WebButton::reset(unsigned long changed) +{ + if (changed&DecorationReset || changed&ManualReset || changed&SizeChange || changed&StateChange) { + switch (type() ) { + case CloseButton: + setBitmap(close_bits); + break; + case HelpButton: + setBitmap(help_bits); + break; + case MinButton: + setBitmap(iconify_bits); + break; + case MaxButton: + setBitmap( isChecked() ? unmaximize_bits : maximize_bits ); + break; + case OnAllDesktopsButton: + setBitmap( isChecked() ? unsticky_bits : sticky_bits ); + break; + case ShadeButton: + setBitmap( isChecked() ? shade_on_bits : shade_off_bits ); + break; + case AboveButton: + setBitmap( isChecked() ? above_on_bits : above_off_bits ); + break; + case BelowButton: + setBitmap( isChecked() ? below_on_bits : below_off_bits ); + break; + case MenuButton: + setBitmap(menu_bits); + break; + default: + setBitmap(0); + break; + } + + this->update(); + } +} + + void +WebButton::enterEvent(QEvent * e) +{ + mouseOver_ = true; + repaint(); + QAbstractButton::enterEvent(e); +} + + void +WebButton::leaveEvent(QEvent * e) +{ + mouseOver_ = false; + repaint(); + QAbstractButton::leaveEvent(e); +} + +void WebButton::paintEvent(QPaintEvent *) +{ + QPainter p(this); + drawButton(&p); +} + + void +WebButton::drawButton(QPainter *p) +{ + QPen highlightPen; + + if (isDown() ) + highlightPen = QPen( palette().color( QPalette::Light )); + + else + { + if (mouseOver_) + highlightPen = QPen( palette().color( QPalette::Highlight )); + else + highlightPen = QPen(Qt::NoPen); + } + + p->fillRect(rect(), palette().color( QPalette::Background ) ); + + Position position_; + if (0 == mapToParent(rect().topLeft() ).x() ) + position_ = Left; + else if (deco_->width()-1 == mapToParent(rect().topRight() ).x() ) + position_ = Right; + else + position_ = Mid; + + if( deco_->isPreview() && shape_ ) + { + QRegion mask( deco_->calcMask().translated( -mapToParent(rect().topLeft()) ) ); + p->setClipRegion( mask, Qt::IntersectClip ); + } + + switch ( position_ ) + { + case Left: + { + + // Draw edge. + p->setPen(Qt::black); + + p->drawLine(0, 0, width(), 0); + p->drawLine(0, 1, 0, height() - 1); + if (shape_) + { + p->drawPoint(3, 1); + p->drawPoint(4, 1); + p->drawPoint(2, 2); + p->drawPoint(1, 3); + p->drawPoint(1, 4); + } + // Draw highlight. + + p->setBrush(Qt::NoBrush); + p->setPen(highlightPen); + + if (shape_) + p->setClipRegion(QRegion(rect()) - QRect(0, 0, 6, 6)); + + p->drawRect(2, 2, width() - 4, height() - 4); + if (shape_) + { + p->setClipRect(rect()); + p->drawPoint(4, 3); + p->drawPoint(5, 3); + p->drawPoint(3, 4); + p->drawPoint(3, 5); + } + } + + break; + + case Right: + { + // Draw edge. + p->setPen(Qt::black); + p->drawLine(0, 0, width(), 0); + p->drawLine(width() - 1, 1, width() - 1, height() - 1); + if (shape_) + { + p->drawPoint(width() - 5, 1); + p->drawPoint(width() - 4, 1); + p->drawPoint(width() - 3, 2); + p->drawPoint(width() - 2, 3); + p->drawPoint(width() - 2, 4); + } + // Draw highlight. + + p->setBrush(Qt::NoBrush); + p->setPen(highlightPen); + + if (shape_) + p->setClipRegion(QRegion(rect()) - QRect(width() - 6, 0, 6, 6)); + + p->drawRect(2, 2, width() - 4, height() - 4); + if (shape_) + { + p->setClipRect(rect()); + p->drawPoint(width() - 5, 3); + p->drawPoint(width() - 6, 3); + p->drawPoint(width() - 4, 4); + p->drawPoint(width() - 4, 5); + } + } + + break; + + case Mid: + default: + { + // Draw edge. + + p->setPen(Qt::black); + p->drawLine(0, 0, width(), 0); + + // Draw highlight. + + p->setBrush(Qt::NoBrush); + p->setPen(highlightPen); + + p->drawRect(2, 2, width() - 4, height() - 4); + } + + break; + } + + // Draw icon. + + QPoint center(rect().center()); + + QPainterPath path; + path.addRegion( bitmap_ ); + int bwby2(bitmap_.width() / 2); // Bitmap Width BY 2 + int bhby2(bitmap_.height() / 2); // Bitmap Height BY 2 + p->setPen( Qt::NoPen ); + p->setBrush(Qt::black); + p->translate( center.x() - bwby2 + 1, center.y() - bhby2 + 1 ); + p->drawPath( path ); + +} + + void +WebButton::setBitmap(const unsigned char *bitmap) +{ + if (bitmap) + bitmap_ = QBitmap::fromData( QSize(8, 8), bitmap); + else + bitmap_ = QBitmap(8,8); + bitmap_.setMask(bitmap_); +} + +} + +// vim:ts=2:sw=2:tw=78:set et: +// kate: indent-width 2; replace-tabs on; tab-width 2; space-indent on; diff --git a/clients/web/WebButton.h b/clients/web/WebButton.h new file mode 100644 index 0000000000..49551e1ce2 --- /dev/null +++ b/clients/web/WebButton.h @@ -0,0 +1,71 @@ +/* + 'Web' kwin client + + Copyright (C) 2001 Rik Hemsley (rikkus) + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KWIN_WEB_BUTTON_H +#define KWIN_WEB_BUTTON_H + +#include +#include +#include + +#include "../../lib/kcommondecoration.h" + +namespace Web +{ + class WebClient; + + class WebButton : public KCommonDecorationButton + { + public: + + enum Position + { + Left, Mid, Right + }; + + WebButton(ButtonType type, WebClient *parent, bool shape); + + virtual ~WebButton(); + + virtual void reset(unsigned long changed); + + protected: + void setBitmap(const unsigned char *bitmap); + + void enterEvent(QEvent *); + void leaveEvent(QEvent *); + void paintEvent(QPaintEvent *); + void drawButton(QPainter *p); + + private: + QBitmap bitmap_; + + bool mouseOver_; + + bool shape_; + WebClient* deco_; + }; +} + +#endif + +// vim:ts=2:sw=2:tw=78:set et: +// kate: indent-width 2; replace-tabs on; tab-width 2; space-indent on; diff --git a/clients/web/web.desktop b/clients/web/web.desktop new file mode 100644 index 0000000000..699299b4fe --- /dev/null +++ b/clients/web/web.desktop @@ -0,0 +1,90 @@ +[Desktop Entry] +Name=Web +Name[af]=Web +Name[ar]=انترنت +Name[be]=Сеціва +Name[be@latin]=Web +Name[bg]=Уеб +Name[bn]=ওয়েব +Name[bn_IN]=ওয়েব +Name[br]=Gwiad +Name[ca]=Web +Name[ca@valencia]=Web +Name[cs]=Web +Name[csb]=Web +Name[cy]=Gwe +Name[da]=Net +Name[de]=Web +Name[el]=Ιστός +Name[en_GB]=Web +Name[eo]=TTT +Name[es]=Web +Name[et]=Veeb +Name[eu]=Web +Name[fa]=وب +Name[fi]=Web +Name[fr]=Web +Name[fy]=Web +Name[ga]=Gréasán +Name[gl]=Web +Name[gu]=વેબ +Name[he]=רשת +Name[hi]=वेब +Name[hne]=वेब +Name[hr]=Internet +Name[hsb]=Web +Name[hu]=Web +Name[ia]=Web +Name[id]=Web +Name[is]=Vefur +Name[it]=Web +Name[ja]=Web +Name[ka]=Web +Name[kk]=Веб +Name[km]=បណ្ដាញ +Name[kn]=ಜಾಲ +Name[ko]=웹 +Name[ku]=Tor +Name[lt]=Žiniatinklis +Name[lv]=Tīmeklis +Name[mai]=वेब +Name[mk]=Веб +Name[ml]=വെബ് +Name[mr]=वेब +Name[ms]=Web +Name[nb]=Nett +Name[nds]=Web +Name[ne]=वेब +Name[nl]=Web +Name[nn]=Vev +Name[oc]=Web +Name[pa]=ਵੈੱਬ +Name[pl]=Sieć +Name[pt]=Web +Name[pt_BR]=Web +Name[ro]=Web +Name[ru]=Веб +Name[se]=Fierpmádat +Name[si]=වෙබ් +Name[sk]=Web +Name[sl]=Splet +Name[sr]=Веб +Name[sr@ijekavian]=Веб +Name[sr@ijekavianlatin]=Web +Name[sr@latin]=Web +Name[sv]=Webb +Name[ta]=வலை +Name[te]=వెబ్ +Name[tg]=Интернет +Name[th]=รูปแบบเว็บ +Name[tr]=Web +Name[uk]=Тенета +Name[uz]=Veb +Name[uz@cyrillic]=Веб +Name[vi]=Mạng +Name[wa]=Waibe +Name[xh]=Web +Name[x-test]=xxWebxx +Name[zh_CN]=网页 +Name[zh_TW]=網頁 +X-KDE-Library=kwin3_web