#include #include "kwmthemeclient.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../../workspace.h" #include "../../options.h" extern "C" { Client *allocate(Workspace *ws, WId w) { return(new KWMThemeClient(ws, w)); } } 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 = NULL; static KPixmap *iTitlePix = NULL; static KPixmapEffect::GradientType grType; static int maxExtent, titleAlign; static bool titleGradient = true; static bool pixmaps_created = false; static bool titleSunken = false; static bool titleTransparent; extern Options *options; static void init_theme() { 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; KIconLoader *ldr = KGlobal::iconLoader(); KConfig *config = KGlobal::config(); config->setGroup("General"); int i; for(i=0; i < 8; ++i){ framePixmaps[i] = new QPixmap(ldr->loadIcon(keys[i])); if(framePixmaps[i]->isNull()) warning("Unable to load frame pixmap for %s", keys[i]); else warning("Loaded pixmap %d", i+1); } 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(); menuPix = new QPixmap(ldr->loadIcon("menu")); iconifyPix = new QPixmap(ldr->loadIcon("iconify")); maxPix = new QPixmap(ldr->loadIcon("maximize")); minmaxPix = new QPixmap(ldr->loadIcon("maximizedown")); closePix = new QPixmap(ldr->loadIcon("close")); pinupPix = new QPixmap(ldr->loadIcon("pinup")); pindownPix = new QPixmap(ldr->loadIcon("pindown")); QString 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", false); titleTransparent = config->readBoolEntry("PixmapUnderTitleText", true); tmpStr = config->readEntry("TitlebarLook"); if(tmpStr == "shadedVertical"){ aTitlePix = new KPixmap; aTitlePix->resize(32, 20); KPixmapEffect::gradient(*aTitlePix, options->color(Options::TitleBar, true), options->color(Options::TitleBlend, true), KPixmapEffect::VerticalGradient); iTitlePix = new KPixmap; iTitlePix->resize(32, 20); KPixmapEffect::gradient(*iTitlePix, options->color(Options::TitleBar, false), options->color(Options::TitleBlend, 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; } void MyButton::drawButtonLabel(QPainter *p) { if(pixmap()){ style().drawItem(p, 0, 0, width(), height(), AlignCenter, colorGroup(), true, pixmap(), QString::null); } } KWMThemeClient::KWMThemeClient( Workspace *ws, WId w, QWidget *parent, const char *name ) : Client( ws, w, parent, name, WResizeNoErase ) { init_theme(); QGridLayout *layout = new QGridLayout(this); layout->addColSpacing(0, maxExtent); layout->addColSpacing(2, maxExtent); layout->addRowSpacing(0, maxExtent); layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Fixed, QSizePolicy::Expanding)); layout->addWidget(windowWrapper(), 2, 1); layout->addRowSpacing(3, maxExtent); layout->setRowStretch(2, 10); layout->setColStretch(1, 10); QHBoxLayout* hb = new QHBoxLayout; 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"){ btn = new MyButton(this, "menu"); btn->setPixmap(*menuPix); hb->addWidget(btn); btn->setFixedSize(20, 20); } else if(val == "Sticky"){ stickyBtn = new MyButton(this, "sticky"); stickyBtn->setPixmap(*pinupPix); connect(stickyBtn, SIGNAL( clicked() ), this, SLOT(toggleSticky())); hb->addWidget(stickyBtn); stickyBtn->setFixedSize(20, 20); } else if(val == "Iconify"){ btn = new MyButton(this, "iconify"); btn->setPixmap(*iconifyPix); connect(btn, SIGNAL(clicked()), this, SLOT(iconify())); hb->addWidget(btn); btn->setFixedSize(20, 20); } else if(val == "Maximize"){ maxBtn = new MyButton(this, "max"); maxBtn->setPixmap(*maxPix); connect(maxBtn, SIGNAL(clicked()), this, SLOT(maximize())); hb->addWidget(maxBtn); maxBtn->setFixedSize(20, 20); } else if(val == "Close"){ btn = new MyButton(this, "close"); btn->setPixmap(*closePix); connect(btn, SIGNAL(clicked()), this, SLOT(closeWindow())); hb->addWidget(btn); btn->setFixedSize(20, 20); } else{ if(val != "Off") warning("KWin: Unrecognized button value: %s", val.latin1()); } } if(titleGradient){ aGradient = new KPixmap; iGradient = new KPixmap; } else{ aGradient = NULL; iGradient = NULL; } } void KWMThemeClient::drawTitle(QPainter &p) { QRect r = titlebar->geometry(); if(titleSunken){ qDrawShadeRect(&p, r, options->colorGroup(Options::Frame, 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(Options::TitleBar, isActive()), options->color(Options::TitleBlend, isActive()), grType); } p.drawTiledPixmap(r, *fill); } else{ p.fillRect(r, options->colorGroup(Options::TitleBar, isActive()). brush(QColorGroup::Button)); } p.setFont(options->font(isActive())); p.setPen(options->color(Options::Font, isActive())); p.drawText(r, titleAlign, caption()); } void KWMThemeClient::resizeEvent( QResizeEvent* e) { Client::resizeEvent( e ); doShape(); if ( isVisibleToTLW() && !testWFlags( WNorthWestGravity )) { QPainter p( this ); QRect t = titlebar->geometry(); t.setTop( 0 ); QRegion r = rect(); r = r.subtract( t ); p.setClipRegion( r ); p.eraseRect( rect() ); } } void KWMThemeClient::captionChange( const QString& ) { repaint( titlebar->geometry(), false ); } void KWMThemeClient::paintEvent( QPaintEvent* ) { QPainter p; p.begin(this); 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]); 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]); 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]); 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]); 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); p.end(); } void KWMThemeClient::doShape() { QBitmap mask(width(), height()); mask.fill(color0); QPainter p; p.begin(&mask); 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; p.drawPixmap(0,0,*(framePixmaps[FrameTopLeft]->mask()), 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]->mask()), 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]->mask()), 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]->mask()), framePixmaps[FrameBottomRight]->width()-w4, framePixmaps[FrameBottomRight]->height()-h4, w4, h4); QPixmap pm; QWMatrix m; int n,s,w; //top 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 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 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 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); p.end(); setMask(mask); } void KWMThemeClient::showEvent(QShowEvent *ev) { Client::showEvent(ev); doShape(); repaint(false); } void KWMThemeClient::windowWrapperShowEvent( QShowEvent* ) { doShape(); } void KWMThemeClient::mouseDoubleClickEvent( QMouseEvent * e ) { if (titlebar->geometry().contains( e->pos() ) ) setShade( !isShade() ); workspace()->requestFocus( this ); } void KWMThemeClient::stickyChange(bool on) { stickyBtn->setPixmap(on ? *pinupPix : *pindownPix); } void KWMThemeClient::maximizeChange(bool m) { maxBtn->setPixmap(m ? *minmaxPix : *maxPix); } void KWMThemeClient::init() { // }