diff options
Diffstat (limited to 'kwin/clients/kwmtheme')
-rw-r--r-- | kwin/clients/kwmtheme/Makefile.am | 15 | ||||
-rw-r--r-- | kwin/clients/kwmtheme/cli_installer/Makefile.am | 18 | ||||
-rw-r--r-- | kwin/clients/kwmtheme/cli_installer/main.cpp | 166 | ||||
-rw-r--r-- | kwin/clients/kwmtheme/kwmtheme.desktop | 81 | ||||
-rw-r--r-- | kwin/clients/kwmtheme/kwmthemeclient.cpp | 936 | ||||
-rw-r--r-- | kwin/clients/kwmtheme/kwmthemeclient.h | 74 |
6 files changed, 1290 insertions, 0 deletions
diff --git a/kwin/clients/kwmtheme/Makefile.am b/kwin/clients/kwmtheme/Makefile.am new file mode 100644 index 000000000..f6c611180 --- /dev/null +++ b/kwin/clients/kwmtheme/Makefile.am @@ -0,0 +1,15 @@ +SUBDIRS=cli_installer +INCLUDES = $(all_includes) + +kde_module_LTLIBRARIES = kwin3_kwmtheme.la + +kwin3_kwmtheme_la_SOURCES = kwmthemeclient.cpp +kwin3_kwmtheme_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module +kwin3_kwmtheme_la_LIBADD = -lkdecorations + +METASOURCES = AUTO +noinst_HEADERS = kwmthemeclient.h + +lnkdir = $(kde_datadir)/kwin +lnk_DATA = kwmtheme.desktop + diff --git a/kwin/clients/kwmtheme/cli_installer/Makefile.am b/kwin/clients/kwmtheme/cli_installer/Makefile.am new file mode 100644 index 000000000..feb31c424 --- /dev/null +++ b/kwin/clients/kwmtheme/cli_installer/Makefile.am @@ -0,0 +1,18 @@ + +# set the include path for X, qt and KDE +INCLUDES= $(all_includes) + +####### This part is very kwmtheme specific +# you can add here more. This one gets installed +bin_PROGRAMS = kwmtheme + +# Which sources should be compiled for kwmtheme. +kwmtheme_SOURCES = main.cpp + +# the library search path. +kwmtheme_LDFLAGS = $(all_libraries) $(KDE_RPATH) + +# the libraries to link against. Be aware of the order. First the libraries, +# that depend on the following ones. +kwmtheme_LDADD = $(LIB_KDECORE) + diff --git a/kwin/clients/kwmtheme/cli_installer/main.cpp b/kwin/clients/kwmtheme/cli_installer/main.cpp new file mode 100644 index 000000000..bdc04a1de --- /dev/null +++ b/kwin/clients/kwmtheme/cli_installer/main.cpp @@ -0,0 +1,166 @@ +#include <qfile.h> +#include <qdir.h> +#include <kapplication.h> +#include <ksimpleconfig.h> +#include <kglobal.h> +#include <kdebug.h> +#include <kstandarddirs.h> +#include <kcmdlineargs.h> +#include <klocale.h> + +static const char description[] = + I18N_NOOP("Installs a KWM theme"); + +static KCmdLineOptions options[] = +{ + { "+[file]", I18N_NOOP("Path to a theme config file"), 0 }, + KCmdLineLastOption +}; + +void copy(const QString &src, const QString &dest) +{ + QFile copyInput(src); + QFile copyOutput(dest); + if(!copyInput.open(IO_ReadOnly)){ + kdWarning() << "Couldn't open " << src << endl; + return; + } + if(!copyOutput.open(IO_WriteOnly)){ + kdWarning() << "Couldn't open " << dest << endl; + 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"); + KCmdLineArgs::addCmdLineOptions( options ); + KApplication app(argc, argv); + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + if(!args->count()){ + kdWarning() << "You need to specify the path to a theme config file!" << endl; + return(1); + } + + QString srcStr = QString(QFile::decodeName(args->arg(0))); + QFile f(srcStr); + QString tmpStr; + + if(!f.exists()){ + kdWarning() << "Specified theme config file doesn't exist!" << endl; + 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.absFilePath()); + srcStr = fi.dirPath(true) + "/"; + KConfig *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, true, true); + tmpStr = input.readEntry("shapePixmapBottom"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_bottom", tmpStr, true, true); + tmpStr = input.readEntry("shapePixmapLeft"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_left", tmpStr, true, true); + tmpStr = input.readEntry("shapePixmapRight"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_right", tmpStr, true, true); + tmpStr = input.readEntry("shapePixmapTopLeft"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_topleft", tmpStr, true, true); + tmpStr = input.readEntry("shapePixmapTopRight"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_topright", tmpStr, true, true); + tmpStr = input.readEntry("shapePixmapBottomLeft"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_bottomleft", tmpStr, true, true); + tmpStr = input.readEntry("shapePixmapBottomRight"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("wm_bottomright", tmpStr, true, true); + + + input.setGroup("Window Titlebar"); + output->writeEntry("TitleAlignment", input.readEntry("TitleAlignment"), true, true); + output->writeEntry("PixmapUnderTitleText", input.readEntry("PixmapUnderTitleText"), true, true); + output->writeEntry("TitleFrameShaded", input.readEntry("TitleFrameShaded"), true, true); + + tmpStr = input.readEntry("MenuButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("menu", tmpStr, true, true); + tmpStr = input.readEntry("PinUpButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("pinup", tmpStr, true, true); + tmpStr = input.readEntry("PinDownButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("pindown", tmpStr, true, true); + tmpStr = input.readEntry("CloseButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("close", tmpStr, true, true); + tmpStr = input.readEntry("MaximizeButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("maximize", tmpStr, true, true); + tmpStr = input.readEntry("MaximizeDownButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("maximizedown", tmpStr, true, true); + tmpStr = input.readEntry("MinimizeButton"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("iconify", tmpStr, true, true); + tmpStr = input.readEntry("TitlebarPixmapActive"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("TitlebarPixmapActive", tmpStr, true, true); + tmpStr = input.readEntry("TitlebarPixmapInactive"); + if(!tmpStr.isEmpty()) + copy(srcStr+tmpStr, localDirStr+tmpStr); + output->writeEntry("TitlebarPixmapInactive", tmpStr, true, true); + + input.setGroup("Window Button Layout"); + output->setGroup("Buttons"); + output->writeEntry("ButtonA", input.readEntry("ButtonA"), true, true); + output->writeEntry("ButtonB", input.readEntry("ButtonB"), true, true); + output->writeEntry("ButtonC", input.readEntry("ButtonC"), true, true); + output->writeEntry("ButtonD", input.readEntry("ButtonD"), true, true); + output->writeEntry("ButtonE", input.readEntry("ButtonE"), true, true); + output->writeEntry("ButtonF", input.readEntry("ButtonF"), true, true); + + output->sync(); + + return(0); +} + diff --git a/kwin/clients/kwmtheme/kwmtheme.desktop b/kwin/clients/kwmtheme/kwmtheme.desktop new file mode 100644 index 000000000..caa8a6ea8 --- /dev/null +++ b/kwin/clients/kwmtheme/kwmtheme.desktop @@ -0,0 +1,81 @@ +[Desktop Entry] +Name=KWM Theme +Name[af]=KWM Tema +Name[ar]=سمة KWM +Name[az]=KWM Örtüsü +Name[be]=Тэма KWM +Name[bn]=KWM থীম +Name[br]=Gwiskad KWM +Name[bs]=KWM Tema +Name[ca]=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[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[hi]=केडबल्यूएम प्रसंग +Name[hr]=KWM tema +Name[hu]=KWM téma +Name[id]=Theme KWM +Name[is]=KWM þema +Name[it]=Tema KWM +Name[ja]=KWM テーマ +Name[ka]=KWM სტილი +Name[kk]=KWM нақышы +Name[km]=ស្បែក KWM +Name[ko]=KWM 테마 +Name[lo]=ແບບຕົວຈັດການຫນ້າຕ່າງ KWM +Name[lt]=KWM tema +Name[lv]=KWM Tēma +Name[mk]=KWM тема +Name[mn]=KWM-Хэлбэр +Name[ms]=Temas KWM +Name[mt]=Tema KWM +Name[nb]=KWM-tema +Name[nds]=KWM-Muster +Name[ne]=KWM विषयवस्तु +Name[nl]=KWM-thema +Name[nn]=KWM-tema +Name[nso]=Molaetsa wa KWM +Name[oc]=Tema KWM +Name[pa]=KWM ਸਰੂਪ +Name[pl]=Motyw KWM +Name[pt]=Tema KWM +Name[pt_BR]=Tema KWM +Name[ro]=Tematică KWM +Name[ru]=Стиль KWM +Name[rw]=Insanganyamatsiko KWM +Name[se]=KWM-fáddá +Name[sk]=Téma KWM +Name[sl]=Tema KWM +Name[sr]=KWM тема +Name[sr@Latn]=KWM tema +Name[ss]=Indzikimba ye KWM +Name[sv]=KWM-tema +Name[ta]=KWM தலைப்பு +Name[tg]=Услуби KWM +Name[th]=ชุดตกแต่งหน้าต่าง KWM +Name[tr]=KWM Teması +Name[tt]=KWM Tışlaw +Name[uk]=Тема KWM +Name[uz]=KWM mavzusi +Name[uz@cyrillic]=KWM мавзуси +Name[ven]=Thero ya KWM +Name[vi]=Sắc thái KWM +Name[wa]=Tinme KWM +Name[xh]=Umxholo we KWM +Name[zh_CN]=KWM 主题 +Name[zh_TW]=KWM 主題 +Name[zu]=Ingqikithi ye-KWM +X-KDE-Library=kwin3_kwmtheme diff --git a/kwin/clients/kwmtheme/kwmthemeclient.cpp b/kwin/clients/kwmtheme/kwmthemeclient.cpp new file mode 100644 index 000000000..a422f31fb --- /dev/null +++ b/kwin/clients/kwmtheme/kwmthemeclient.cpp @@ -0,0 +1,936 @@ +#include <kconfig.h> +#include "kwmthemeclient.h" +#include <kglobal.h> +#include <qlayout.h> +#include <qdrawutil.h> +#include <qpainter.h> +#include <kpixmapeffect.h> +#include <kstandarddirs.h> +#include <kdebug.h> +#include <klocale.h> +#include <qbitmap.h> +#include <qstyle.h> +#include <qlabel.h> +#include <qtooltip.h> + +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 KPixmap *aTitlePix = 0; +static KPixmap *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 *keys[] = {"wm_top", "wm_bottom", "wm_left", "wm_right", + "wm_topleft", "wm_topright", "wm_bottomleft", "wm_bottomright"}; + + if(pixmaps_created) + return; + pixmaps_created = true; + + KConfig *config = KGlobal::config(); + config->setGroup("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()) + kdWarning() << "Unable to load frame pixmap for " << keys[i] << endl; + } +/* + *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->readBoolEntry("TitleFrameShaded", true); + // titleSunken = true; // is this fixed? + titleTransparent = config->readBoolEntry("PixmapUnderTitleText", true); + + tmpStr = config->readEntry("TitlebarLook"); + if(tmpStr == "shadedVertical"){ + aTitlePix = new KPixmap; + aTitlePix->resize(32, 20); + KPixmapEffect::gradient(*aTitlePix, + options()->color(KDecorationOptions::ColorTitleBar, true), + options()->color(KDecorationOptions::ColorTitleBlend, true), + KPixmapEffect::VerticalGradient); + iTitlePix = new KPixmap; + 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 KPixmap; + aTitlePix->load(locate("data", "kwin/pics/" + tmpStr)); + } + else + aTitlePix = NULL; + tmpStr = config->readEntry("TitlebarPixmapInactive", ""); + if(!tmpStr.isEmpty()){ + iTitlePix = new KPixmap; + 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::null); + } +} + +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( "<center><b>KWMTheme</b></center>" ), 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->setColStretch(1, 10); + + QBoxLayout* hb = new QBoxLayout(0, QBoxLayout::LeftToRight, 0, 0, 0); + layout->addLayout( hb, 1, 1 ); + + KConfig *config = KGlobal::config(); + config->setGroup("Buttons"); + QString val; + MyButton *btn; + int i; + static const char *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"); + QToolTip::add( mnuBtn, 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"); + QToolTip::add( stickyBtn, 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"); + QToolTip::add( btn, 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"); + QToolTip::add( maxBtn, 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"); + QToolTip::add( btn, 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())) + kdWarning() << "KWin: Unrecognized button value: " << val << endl; + + } + } + if(titleGradient){ + aGradient = new KPixmap; + iGradient = new KPixmap; + } + 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()->colorGroup(KDecorationOptions::ColorFrame, isActive()), + true, 1, 0); + r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2); + } + + KPixmap *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()->colorGroup(KDecorationOptions::ColorTitleBar, isActive()). + brush(QColorGroup::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; + QWMatrix 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.xForm(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.xForm(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.xForm(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.xForm(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; + QWMatrix 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.xForm(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.xForm(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.xForm(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.xForm(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); + QToolTip::remove( stickyBtn ); + QToolTip::add( stickyBtn, on ? i18n("Unsticky") : i18n("Sticky") ); + } +} + +void KWMThemeClient::maximizeChange() +{ + if (maxBtn) { + bool m = maximizeMode() == MaximizeFull; + maxBtn->setPixmap(m ? *minmaxPix : *maxPix); + QToolTip::remove( maxBtn ); + QToolTip::add( maxBtn, 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( QIconSet::Small, QIconSet::Normal ).isNull()){ + mnuBtn->setPixmap(*menuPix); + } + else{ + mnuBtn->setPixmap(icon().pixmap( QIconSet::Small, QIconSet::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/kwin/clients/kwmtheme/kwmthemeclient.h b/kwin/clients/kwmtheme/kwmthemeclient.h new file mode 100644 index 000000000..b1d623965 --- /dev/null +++ b/kwin/clients/kwmtheme/kwmthemeclient.h @@ -0,0 +1,74 @@ +#ifndef __KWMTHEMECLIENT_H +#define __KWMTHEMECLIENT_H + +#include <qbutton.h> +#include <qtoolbutton.h> +#include <kpixmap.h> +#include <kdecoration.h> +#include <kdecorationfactory.h> + +class QLabel; +class QSpacerItem; +class QGridLayout; + +namespace KWMTheme { + +class MyButton : public QToolButton +{ +public: + 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 + |