diff --git a/clients/b2/Makefile.am b/clients/b2/Makefile.am new file mode 100644 index 0000000000..049d88d20a --- /dev/null +++ b/clients/b2/Makefile.am @@ -0,0 +1,21 @@ + +INCLUDES = $(all_includes) + +kde_module_LTLIBRARIES = libkwinb2.la + +libkwinb2_la_SOURCES = b2client.cpp +libkwinb2_la_LIBADD = ../../kwin.la +libkwinb2_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) + +METASOURCES = AUTO +noinst_HEADERS = b2client.h + +lnkdir = $(kde_datadir)/kwin/ +lnk_DATA = b2.desktop + +EXTRA_DIST = $(lnk_DATA) + + +###KMAKE-start (don't edit or delete this block) + +###KMAKE-end diff --git a/clients/b2/b2.desktop b/clients/b2/b2.desktop new file mode 100644 index 0000000000..475f13111b --- /dev/null +++ b/clients/b2/b2.desktop @@ -0,0 +1,3 @@ +[Desktop Entry] +Name=B II +X-KDE-Library=libkwinb2 diff --git a/clients/b2/b2client.cpp b/clients/b2/b2client.cpp new file mode 100644 index 0000000000..b26e9b4733 --- /dev/null +++ b/clients/b2/b2client.cpp @@ -0,0 +1,1065 @@ +#include "b2client.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../workspace.h" +#include "../../options.h" +#include "bitmaps.h" + +using namespace KWinInternal; + + +// TODO: stick all these in an array +static KPixmap *aClosePix, *aClosePixDown; +static KPixmap *iClosePix, *iClosePixDown; +static KPixmap *aMaxPix, *aMaxPixDown; +static KPixmap *iMaxPix, *iMaxPixDown; +static KPixmap *aNormalizePix, *aNormalizePixDown; +static KPixmap *iNormalizePix, *iNormalizePixDown; +static KPixmap *aIconifyPix, *aIconifyPixDown; +static KPixmap *iIconifyPix, *iIconifyPixDown; +static KPixmap *aPinupPix, *aPinupPixDown; +static KPixmap *iPinupPix, *iPinupPixDown; +static KPixmap *aMenuPix, *aMenuPixDown; +static KPixmap *iMenuPix, *iMenuPixDown; +static KPixmap *aHelpPix, *aHelpPixDown; +static KPixmap *iHelpPix, *iHelpPixDown; + +static bool pixmaps_created = false; + +static void drawB2Rect(KPixmap *pix, const QColor &primary, bool down) +{ + QPainter p; + QColor hColor = primary.light(150); + QColor lColor = primary.dark(150); + + if(QPixmap::defaultDepth() > 8){ + if(down) + KPixmapEffect::gradient(*pix, lColor, hColor, + KPixmapEffect::DiagonalGradient); + else + KPixmapEffect::gradient(*pix, hColor, lColor, + KPixmapEffect::DiagonalGradient); + } + else + pix->fill(primary); + int x2 = pix->width()-1; + int y2 = pix->height()-1; + p.begin(pix); + p.setPen(down ? hColor : lColor); + p.drawLine(0, 0, x2, 0); + p.drawLine(0, 0, 0, y2); + p.drawLine(1, x2-1, y2-1, x2-1); + p.drawLine(x2-1, 1, x2-1, y2-1); + p.setPen(down ? lColor : hColor); + p.drawRect(1, 1, x2, y2); + p.end(); + +} + +static void create_pixmaps(); +static void redraw_pixmaps(); + +QPixmap* kwin_get_menu_pix_hack() +{ + //return menu_pix; FIXME + return aMenuPix; +} + +static void create_pixmaps() +{ + if ( pixmaps_created ) + return; + pixmaps_created = true; + + // TODO: Stick all these in an array + aClosePix = new KPixmap; + aClosePix->resize(16, 16); + aClosePixDown = new KPixmap; + aClosePixDown->resize(16, 16); + + iClosePix = new KPixmap; + iClosePix->resize(16, 16); + iClosePixDown = new KPixmap; + iClosePixDown->resize(16, 16); + + aMaxPix = new KPixmap; + aMaxPixDown = new KPixmap; + iMaxPix = new KPixmap; + iMaxPixDown = new KPixmap; + + aNormalizePix = new KPixmap(); + aNormalizePix->resize(16, 16); + aNormalizePixDown = new KPixmap(); + aNormalizePixDown->resize(16, 16); + + aIconifyPix = new KPixmap; + aIconifyPix->resize(10, 10); + aIconifyPixDown = new KPixmap; + aIconifyPixDown->resize(10, 10); + + iNormalizePix = new KPixmap(); + iNormalizePix->resize(16, 16); + iNormalizePixDown = new KPixmap(); + iNormalizePixDown->resize(16, 16); + + iIconifyPix = new KPixmap; + iIconifyPix->resize(10, 10); + iIconifyPixDown = new KPixmap; + iIconifyPixDown->resize(10, 10); + + aPinupPix = new KPixmap; + aPinupPix->resize(16, 16); + aPinupPixDown = new KPixmap; + aPinupPixDown->resize(16, 16); + + iPinupPix = new KPixmap; + iPinupPix->resize(16, 16); + iPinupPixDown = new KPixmap; + iPinupPixDown->resize(16, 16); + + aMenuPix = new KPixmap; + aMenuPix->resize(16, 16); + aMenuPixDown = new KPixmap; + aMenuPixDown->resize(16, 16); + + iMenuPix = new KPixmap; + iMenuPix->resize(16, 16); + iMenuPixDown = new KPixmap; + iMenuPixDown->resize(16, 16); + + aHelpPix = new KPixmap; + aHelpPix->resize(16, 16); + aHelpPixDown = new KPixmap; + aHelpPixDown->resize(16, 16); + iHelpPix = new KPixmap; + iHelpPix->resize(16, 16); + iHelpPixDown = new KPixmap; + iHelpPixDown->resize(16, 16); + + // there seems to be no way to load X bitmaps from data properly, so + // we need to create new ones for each mask :P + QBitmap pinupMask(16, 16, pinup_mask_bits, true); + aPinupPix->setMask(pinupMask); + iPinupPix->setMask(pinupMask); + QBitmap pindownMask(16, 16, pindown_mask_bits, true); + aPinupPixDown->setMask(pindownMask); + iPinupPixDown->setMask(pindownMask); + + QBitmap menuMask(16, 16, menu_mask_bits, true); + aMenuPix->setMask(menuMask); + iMenuPix->setMask(menuMask); + aMenuPixDown->setMask(menuMask); + iMenuPixDown->setMask(menuMask); + + QBitmap helpMask(16, 16, help_mask_bits, true); + aHelpPix->setMask(helpMask); + iHelpPix->setMask(helpMask); + aHelpPixDown->setMask(helpMask); + iHelpPixDown->setMask(helpMask); + redraw_pixmaps(); +} + +static void delete_pixmaps() +{ + delete aClosePix; + delete aClosePixDown; + delete iClosePix; + delete iClosePixDown; + delete aMaxPix; + delete aMaxPixDown; + delete iMaxPix; + delete iMaxPixDown; + delete aNormalizePix; + delete aNormalizePixDown; + delete iNormalizePix; + delete iNormalizePixDown; + delete aIconifyPix; + delete aIconifyPixDown; + delete iIconifyPix; + delete iIconifyPixDown; + delete aPinupPix; + delete aPinupPixDown; + delete iPinupPix; + delete iPinupPixDown; + delete aMenuPix; + delete aMenuPixDown; + delete iMenuPix; + delete iMenuPixDown; + delete aHelpPix; + delete aHelpPixDown; + delete iHelpPix; + delete iHelpPixDown; + + pixmaps_created = false; +} + +B2Button::B2Button(KPixmap *pix, KPixmap *pixDown, KPixmap *iPix, + KPixmap *iPixDown, Client *_client, QWidget *parent, + const char *name) + : QButton(parent, name) +{ + client = _client; + pNorm = pix; + pDown = pixDown; + iNorm = iPix; + iDown = iPixDown; + setFixedSize(16, 16); + setFocusPolicy(NoFocus); + resize(16, 16); +} + +QSize B2Button::sizeHint() const +{ + return(QSize(16, 16)); +} + +QSizePolicy B2Button::sizePolicy() const +{ + return(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); +} + + +void B2Button::drawButton(QPainter *p) +{ + p->fillRect(rect(), bg); + if(useMiniIcon && !client->miniIcon().isNull()){ + QPixmap miniIcon = client->miniIcon(); + p->drawPixmap((width()-miniIcon.width())/2, + (height()-miniIcon.height())/2, miniIcon); + } + else{ + if(client->isActive()){ + if(isOn() || isDown()) + p->drawPixmap((width()-pDown->width())/2, + (height()-pDown->height())/2, *pDown); + else + p->drawPixmap((width()-pNorm->width())/2, + (height()-pNorm->height())/2, *pNorm); + } + else{ + if(isOn() || isDown()) + p->drawPixmap((width()-pDown->width())/2, + (height()-pDown->height())/2, *iDown); + else + p->drawPixmap((width()-pNorm->width())/2, + (height()-pNorm->height())/2, *iNorm); + } + } +} + +void B2Button::setPixmaps(KPixmap *pix, KPixmap *pixDown, KPixmap *iPix, + KPixmap *iPixDown) +{ + pNorm = pix; + pDown = pixDown; + iNorm = iPix; + iDown = iPixDown; + repaint(false); +} + +void B2Button::mousePressEvent( QMouseEvent* e ) +{ + last_button = e->button(); + QMouseEvent me ( e->type(), e->pos(), e->globalPos(), LeftButton, e->state() ); + QButton::mousePressEvent( &me ); +} + +void B2Button::mouseReleaseEvent( QMouseEvent* e ) +{ + QMouseEvent me ( e->type(), e->pos(), e->globalPos(), LeftButton, e->state() ); + QButton::mouseReleaseEvent( &me ); +} + +B2Titlebar::B2Titlebar(B2Client *parent) + : QWidget(parent) +{ + set_x11mask = false; + isfullyobscured = false; + shift_move = false; + client = parent; +} + +bool B2Titlebar::x11Event(XEvent *e) +{ + if (!set_x11mask) { + set_x11mask = true; + XSelectInput(qt_xdisplay(), winId(), + KeyPressMask | KeyReleaseMask | + ButtonPressMask | ButtonReleaseMask | + KeymapStateMask | + ButtonMotionMask | + EnterWindowMask | LeaveWindowMask | + FocusChangeMask | + ExposureMask | + PropertyChangeMask | + StructureNotifyMask | SubstructureRedirectMask | + VisibilityChangeMask); + } + switch( e->type ) { + case VisibilityNotify: + isfullyobscured = false; + if (e->xvisibility.state == VisibilityFullyObscured) { + isfullyobscured = true; + client->unobscureTitlebar(); + } + break; + default: + break; + } + return QWidget::x11Event(e); +} + +void B2Titlebar::recalcBuffer() +{ + QFontMetrics fm(options->font(true)); + titleBuffer.resize(width(), height()); + + QPainter p; + p.begin(&titleBuffer); + QRect t=rect(); + + // black titlebar frame + p.setPen(Qt::black); + p.drawLine(0, 0, 0, t.bottom() ); + p.drawLine(0, 0, t.right(), 0); + p.drawLine(t.right(), 0, t.right(), t.bottom()); + + // titlebar fill + qDrawShadeRect(&p, 1, 1, t.right()-1, t.height()-1, + options->colorGroup(Options::TitleBar, true), + false, 1, 0, + &options->colorGroup(Options::TitleBar, true). + brush(QColorGroup::Background)); + + // and the caption + p.setPen(options->color(Options::Font, true)); + p.setFont(options->font(true)); + + QLayoutIterator it=layout()->iterator(); + ++it; + ++it; + ++it; + t=(++it)->geometry(); + + p.drawText(t, AlignLeft | AlignVCenter, client->caption()); + p.end(); + + oldTitle = caption(); +} + +void B2Titlebar::resizeEvent(QResizeEvent *) +{ + recalcBuffer(); + repaint(false); +} + + +void B2Titlebar::paintEvent(QPaintEvent * /*e*/) +{ + if(client->isActive()) + bitBlt(this, 0, 0, &titleBuffer, 0, 0, titleBuffer.width(), + titleBuffer.height(), Qt::CopyROP, true); + else{ + QPainter p(this); + QRect t=rect(); + // black titlebar frame + p.setPen(Qt::black); + p.drawLine(0, 0, 0, t.bottom() ); + p.drawLine(0, 0, t.right(), 0); + p.drawLine(t.right(), 0, t.right(), t.bottom()); + + // titlebar fill + qDrawShadeRect(&p, 1, 1, t.right()-1, t.height()-1, + options->colorGroup(Options::TitleBar, false), + false, 1, 0, + &options->colorGroup(Options::TitleBar, false). + brush(QColorGroup::Button)); + + // and the caption + p.setPen(options->color(Options::Font, false)); + p.setFont(options->font(false)); + + QLayoutIterator it=layout()->iterator(); + ++it; + ++it; + ++it; + t=(++it)->geometry(); + + p.drawText(t, AlignLeft | AlignVCenter, client->caption()); + } +} + +void B2Titlebar::mouseDoubleClickEvent( QMouseEvent * ) +{ + client->workspace()->performWindowOperation( client, options->operationTitlebarDblClick() ); + client->workspace()->requestFocus( client ); +} + +void B2Titlebar::mousePressEvent( QMouseEvent * e ) +{ + shift_move = e->state() & ShiftButton; + if (shift_move ) { + moveOffset = e->globalPos(); + } + QMouseEvent _e(QEvent::MouseButtonPress, mapToParent(e->pos()), + e->globalPos(), e->button(), e->state()); + //QWidget::mousePressEvent( e ); + client->mousePressEvent( &_e); +} + +void B2Titlebar::mouseReleaseEvent( QMouseEvent * e ) +{ + shift_move = false; + QMouseEvent _e(QEvent::MouseButtonRelease, mapToParent(e->pos()), + e->globalPos(), e->button(), e->state()); + //QWidget::mouseReleaseEvent( e ); + client->mouseReleaseEvent( &_e); +} + +void B2Titlebar::mouseMoveEvent( QMouseEvent * e ) +{ + if (shift_move) { + int oldx = mapFromGlobal(moveOffset).x(); + int xdiff = e->globalPos().x() - moveOffset.x(); + moveOffset = e->globalPos(); + if (oldx >= 0 && oldx <= rect().right()) { + client->titleMoveRel(xdiff); + } + } else { + QMouseEvent _e(QEvent::MouseMove, mapToParent(e->pos()), + e->globalPos(), e->button(), e->state()); + client->mouseMoveEvent( &_e); + } +} + +void B2Client::maxButtonClicked( ) +{ + switch ( button[BtnMax]->last_button ) { + case MidButton: + maximize( MaximizeVertical ); + break; + case RightButton: + maximize( MaximizeHorizontal ); + break; + default: //LeftButton: + maximize( MaximizeFull ); + break; + } +} + +B2Client::B2Client( Workspace *ws, WId w, QWidget *parent, + const char *name ) + : Client( ws, w, parent, name, WResizeNoErase ) +{ + bar_x_ofs = 0; + in_unobs = 0; + + g = new QGridLayout( this, 0, 0); + g->addMultiCellWidget(windowWrapper(), 1, 1, 1, 2); + + g->addColSpacing(0, 4); + + g->addColSpacing(1, 16); + + g->setColStretch(2, 1); + + g->setRowStretch(1, 1); + g->addColSpacing(3, 4); + g->addRowSpacing(2, 8); + + // titlebar + g->addRowSpacing(0, 20); + + titlebar = new B2Titlebar(this); + titlebar->setMinimumWidth(16); + titlebar->setFixedHeight(20); + + int i; + for(i=0; i < 6; ++i){ + button[i] = new B2Button(this, titlebar/*this*/); + button[i]->setFixedSize(16, 16); + } + + QHBoxLayout *titleLayout=new QHBoxLayout(titlebar); + titleLayout->setSpacing(1); + + titleLayout->addSpacing(3); + titleLayout->addWidget(button[BtnMenu]); + titleLayout->addWidget(button[BtnSticky]); + titleLayout->addWidget(button[BtnHelp]); + titleLayout->addStretch(1); + titleLayout->addWidget(button[BtnIconify]); + titleLayout->addWidget(button[BtnMax]); + titleLayout->addWidget(button[BtnClose]); + titleLayout->addSpacing(3); + + button[BtnSticky]->setToggle(); + button[BtnSticky]->setDown(isSticky()); + button[BtnMenu]->setUseMiniIcon(); + + if(!providesContextHelp()) + button[BtnHelp]->hide(); + + button[BtnMenu]->setPixmaps(aMenuPix, aMenuPixDown, iMenuPix, + iMenuPixDown); + button[BtnSticky]->setPixmaps(aPinupPix, aPinupPixDown, iPinupPix, + iPinupPixDown); + button[BtnIconify]->setPixmaps(aIconifyPix, aIconifyPixDown, + iIconifyPix, iIconifyPixDown); + button[BtnClose]->setPixmaps(aClosePix, aClosePixDown, iClosePix, + iClosePixDown); + button[BtnHelp]->setPixmaps(aHelpPix, aHelpPixDown, iHelpPix, + iHelpPixDown); + + if(isMaximized()) + button[BtnMax]->setPixmaps(aNormalizePix, aNormalizePixDown, + iNormalizePix, iNormalizePixDown); + else + button[BtnMax]->setPixmaps(aMaxPix, aMaxPixDown, iMaxPix, + iMaxPixDown); + + QColor c = options->colorGroup(Options::TitleBar, isActive()). + color(QColorGroup::Button); + titlebar->setBackgroundColor(c); + titlebar->recalcBuffer(); + for(i=0; i < 6; ++i) + button[i]->setBg(c); + + positionButtons(); + connect(button[BtnMenu], SIGNAL(clicked()), this, SLOT(menuButtonPressed())); + connect(button[BtnSticky], SIGNAL(clicked()), this, SLOT(toggleSticky())); + connect(button[BtnIconify], SIGNAL(clicked()), this, SLOT(iconify())); + connect(button[BtnMax], SIGNAL( clicked() ), this, SLOT( maxButtonClicked())); + connect(button[BtnClose], SIGNAL(clicked()), this, SLOT(closeWindow())); + connect(button[BtnHelp], SIGNAL(clicked()), this, SLOT(contextHelp())); + + connect(options, SIGNAL(resetClients()), this, SLOT(slotReset())); +} + +void B2Client::iconChange() +{ + button[BtnMenu]->repaint( false ); +} + +void B2Client::resizeEvent( QResizeEvent* e) +{ + Client::resizeEvent( e ); + + int sizeProblem = 0; + + if (width() < 45) sizeProblem = 3; + else if (width() < 70) sizeProblem = 2; + else if (width() < 120) sizeProblem = 1; + + switch (sizeProblem) { + + case 1: + button[BtnMenu] ->show(); + button[BtnClose] ->show(); + button[BtnSticky] ->hide(); + button[BtnIconify] ->show(); + button[BtnMax] ->hide(); + button[BtnHelp] ->hide(); + break; + + case 2: + button[BtnMenu] ->show(); + button[BtnClose] ->show(); + button[BtnSticky] ->hide(); + button[BtnIconify] ->hide(); + button[BtnMax] ->hide(); + button[BtnHelp] ->hide(); + break; + + case 3: + button[BtnMenu] ->hide(); + button[BtnClose] ->hide(); + button[BtnSticky] ->hide(); + button[BtnIconify] ->hide(); + button[BtnMax] ->hide(); + button[BtnHelp] ->hide(); + break; + + case 0: + default: + button[BtnMenu] ->show(); + button[BtnClose] ->show(); + button[BtnSticky] ->show(); + button[BtnIconify] ->show(); + button[BtnMax] ->show(); + if(providesContextHelp()) + button[BtnHelp]->show(); + break; + } + + titlebar->layout()->activate(); + + positionButtons(); + /* may be the resize cuted off some space occupied by titlebar, which + was moved, so instead of reducing it, we first try to move it */ + titleMoveAbs(bar_x_ofs); + doShape(); + + /* + What does this? (MM) + if ( isVisibleToTLW() && !testWFlags( WNorthWestGravity )) { + QPainter p( this ); + QRect t = titlebar->geometry(); + QRegion r = rect(); + r = r.subtract( t ); + p.setClipRegion( r ); + p.eraseRect( rect() ); + } + */ + repaint(); //there is some strange wrong repaint of the frame without +} + +void B2Client::captionChange( const QString &) +{ + positionButtons(); + titleMoveAbs(bar_x_ofs); + doShape(); + //repaint(); + titlebar->recalcBuffer(); + titlebar->repaint(false); +} + +void B2Client::paintEvent( QPaintEvent* e) +{ + QPainter p( this ); + + QRect t = titlebar->geometry(); + + // inner window rect + p.drawRect(3, t.bottom(), width()-6, height()-t.height()-6); + + // outer frame rect + p.drawRect(0, t.bottom()-3, width(), height()-t.height()); + + // frame shade panel + qDrawShadePanel(&p, 1, t.bottom()-2, width()-2, height()-t.height()-2, + options->colorGroup(Options::Frame, isActive()), + false); + + //bottom handle rect + int hx = width()-40; + int hw = 40; + + //p.drawRect(hx, height()-8, hw, 8); + p.drawLine(width()-1, height()-8, width()-1, height()-1); + p.drawLine(hx, height()-1, width()-1, height()-1); + p.drawLine(hx, height()-4, hx, height()-1); + + p.fillRect(hx+1, height()-7, hw-2, 6, + options->colorGroup(Options::Frame, isActive()) + .brush(QColorGroup::Button)); + + p.setPen(options->colorGroup(Options::Frame, isActive()).dark()); + p.drawLine(width()-2, height()-8, width()-2, height()-2); + p.drawLine(hx+1, height()-2, width()-2, height()-2); + p.setPen(options->colorGroup(Options::Frame, isActive()).light()); + p.drawLine(hx+1, height()-6, hx+1, height()-3); + p.drawLine(hx+1, height()-7, width()-3, height()-7); + + /* OK, we got a paint event, which means parts of us are now visible + which were not before. We try the titlebar if it is currently fully + obscured, and if yes, try to unobscure it, in the hope that some + of the parts which we just painted were in the titlebar area. + It can happen, that the titlebar, as it got the FullyObscured event + had no chance of becoming partly visible. The problem is, that + we now might have the space available, but the titlebar gets no + visibilitinotify events until its state changes, so we just try + */ + if (titlebar->isFullyObscured()) { + /* We first see, if our repaint contained the titlebar area */ + QRegion reg(QRect(0,0,width(),20)); + reg = reg.intersect(e->region()); + if (!reg.isEmpty()) + unobscureTitlebar(); + } +} + +#define QCOORDARRLEN(x) sizeof(x)/(sizeof(QCOORD)*2) + +void B2Client::doShape() +{ + QRect t = titlebar->geometry(); + QRegion mask(rect()); + // top to the tilebar right + if (bar_x_ofs) { + mask -= QRect(0, 0, bar_x_ofs, t.height()-4); //left from bar + mask -= QRect(0, t.height()-4, 1, 1); //top left point + } + if (t.right() < width()-1) { + mask -= QRect(width()-1, t.height()-4, 1, 1); // top right point + mask -= QRect(t.right()+1, 0, width()-t.right()-1, t.height()-4); + } + mask -= QRect(width()-1, height()-1, 1, 1); // bottom right point + mask -= QRect(0, height()-5, 1, 1); // bottom left point + mask -= QRect(width()-1, height()-1, 1, 1); // bottom right point + mask -= QRect(width()-40, height()-1, 1, 1); // handle left point + mask -= QRect(0, height()-4, width()-40, 4); // bottom left + + setMask(mask); +} + +void B2Client::showEvent(QShowEvent *ev) +{ + Client::showEvent(ev); + doShape(); + repaint(); + titlebar->repaint(); +} + +void B2Client::windowWrapperShowEvent( QShowEvent* ) +{ + doShape(); +} + +Client::MousePosition B2Client::mousePosition( const QPoint& p ) const +{ + const int range = 16; + const int border = 4; + /*QRect t = g->cellGeometry(0, 1); + t.setRight(button[BtnClose]->x()+17); + */ + QRect t = titlebar->geometry(); + t.setHeight(20-border); + int ly = t.bottom(); + int lx = t.right(); + + if ( p.x() > t.right() ) { + if ( p.y() <= ly + range && p.x() >= width()-range) + return TopRight; + else if ( p.y() <= ly + border ) + return Top; + } else if ( p.x() < bar_x_ofs ) { + if ( p.y() <= ly + range && p.x() <= range ) + return TopLeft; + else if ( p.y() <= ly+border ) + return Top; + } else if ( p.y() < ly ) { + if ( p.x() > bar_x_ofs+border && p.x() < lx-border && p.y() > border ) + return Client::mousePosition( p ); + if ( p.x() > bar_x_ofs+range && p.x() < lx - range) + return Top; + if ( p.y() <= range ) { + if ( p.x() <= bar_x_ofs+range ) + return TopLeft; + else return TopRight; + } else { + if ( p.x() <= bar_x_ofs+range ) + return Left; + else return Right; + } + } + + if (p.y() >= height() - 8) { + /* the normal Client:: only wants border of 4 pixels */ + if (p.x() <= range) return BottomLeft; + if (p.x() >= width()-range) return BottomRight; + return Bottom; + } + + return Client::mousePosition( p ); +} + + +void B2Client::titleMoveAbs(int new_ofs) +{ + if (new_ofs < 0) new_ofs = 0; + if (new_ofs + titlebar->width() > width()) { + new_ofs = width() - titlebar->width(); + } + if (bar_x_ofs != new_ofs) { + bar_x_ofs = new_ofs; + positionButtons(); + doShape(); + repaint( 0, 0, width(), 20, false ); + titlebar->repaint(false); + } +} + +void B2Client::titleMoveRel(int xdiff) +{ + titleMoveAbs(bar_x_ofs + xdiff); +} + +void B2Client::stickyChange(bool on) +{ + button[1]->setDown(on); +} + +void B2Client::maximizeChange(bool m) +{ + if(m){ + button[BtnMax]->setPixmaps(aNormalizePix, aNormalizePixDown, + iNormalizePix, iNormalizePixDown); + } + else{ + button[BtnMax]->setPixmaps(aMaxPix, aMaxPixDown, iMaxPix, + iMaxPixDown); + } + button[BtnMax]->repaint(); +} + + +void B2Client::activeChange(bool on) +{ + int i; + repaint(false); + titlebar->repaint(false); + QColor c = options->colorGroup(Options::TitleBar, on). + color(QColorGroup::Button); + for(i=0; i < 6; ++i){ + button[i]->setBg(c); + button[i]->repaint(); + } +} + +void B2Client::init() +{ + // +} + +void B2Client::menuButtonPressed() +{ + workspace()->clientPopup(this)-> + popup(button[BtnMenu]->mapToGlobal(button[BtnMenu]-> + rect().bottomLeft())); +} + +void B2Client::slotReset() +{ + redraw_pixmaps(); + QColor c = options->colorGroup(Options::TitleBar, isActive()). + color(QColorGroup::Button); + int i; + for(i=0; i < 6; ++i){ + button[i]->setBg(c); + button[i]->repaint(false); + } + repaint(); + titlebar->recalcBuffer(); + titlebar->repaint(false); +} + +void B2Client::unobscureTitlebar() +{ + /* we just noticed, that we got obscured by other windows + so we look at all windows above us (stacking_order) merging their + masks, intersecting it with our titlebar area, and see if we can + find a place not covered by any window */ + if (in_unobs) { + return; + } + in_unobs = 1; + QRegion reg(QRect(0,0,width(),20)); + ClientList::ConstIterator it = workspace()->stackingOrder().find(this); + ++it; + while (it != workspace()->stackingOrder().end()) { + /* the clients all have their mask-regions in local coords + so we have to translate them to a shared coord system + we choose ours */ + int dx = (*it)->x() - x(); + int dy = (*it)->y() - y(); + QRegion creg = (*it)->getMask(); + creg.translate(dx, dy); + reg -= creg; + if (reg.isEmpty()) { + // early out, we are completely obscured + break; + } + ++it; + } + if (!reg.isEmpty()) { + // there is at least _one_ pixel from our title area, which is not + // obscured, we use the first rect we find + // for a first test, we use boundingRect(), later we may refine + // to rect(), and search for the nearest, or biggest, or smthg. + titleMoveAbs(reg.boundingRect().x()); + } + in_unobs = 0; +} + +static void redraw_pixmaps() +{ + QColorGroup aGrp = options->colorGroup(Options::ButtonBg, true); + QColorGroup iGrp = options->colorGroup(Options::ButtonBg, false); + + // close + drawB2Rect(aClosePix, aGrp.button(), false); + drawB2Rect(aClosePixDown, aGrp.button(), true); + + drawB2Rect(iClosePix, iGrp.button(), false); + drawB2Rect(iClosePixDown, iGrp.button(), true); + + // maximize + *aMaxPix = *aClosePix; + aMaxPix->detach(); + *aMaxPixDown = *aClosePixDown; + aMaxPixDown->detach(); + *iMaxPix = *iClosePix; + iMaxPix->detach(); + *iMaxPixDown = *iClosePixDown; + iMaxPixDown->detach(); + + // normalize + KPixmap smallBox; + smallBox.resize(10, 10); + KPixmap largeBox; + largeBox.resize(12, 12); + + drawB2Rect(&smallBox, aGrp.button(), false); + drawB2Rect(&largeBox, aGrp.button(), false); + aNormalizePix->fill(options->color(Options::TitleBar, true)); + bitBlt(aNormalizePix, 3, 3, &largeBox, 0, 0, 12, 12, Qt::CopyROP, true); + bitBlt(aNormalizePix, 0, 0, &smallBox, 0, 0, 10, 10, Qt::CopyROP, true); + + bitBlt(aIconifyPix, 0, 0, &smallBox, 0, 0, 10, 10, Qt::CopyROP, true); + + drawB2Rect(&smallBox, aGrp.button(), true); + drawB2Rect(&largeBox, aGrp.button(), true); + aNormalizePixDown->fill(options->color(Options::TitleBar, true)); + bitBlt(aNormalizePixDown, 3, 3, &largeBox, 0, 0, 12, 12, Qt::CopyROP, true); + bitBlt(aNormalizePixDown, 0, 0, &smallBox, 0, 0, 10, 10, Qt::CopyROP, true); + + bitBlt(aIconifyPixDown, 0, 0, &smallBox, 0, 0, 10, 10, Qt::CopyROP, true); + + drawB2Rect(&smallBox, iGrp.button(), false); + drawB2Rect(&largeBox, iGrp.button(), false); + iNormalizePix->fill(options->color(Options::TitleBar, false)); + bitBlt(iNormalizePix, 3, 3, &largeBox, 0, 0, 12, 12, Qt::CopyROP, true); + bitBlt(iNormalizePix, 0, 0, &smallBox, 0, 0, 10, 10, Qt::CopyROP, true); + + bitBlt(iIconifyPix, 0, 0, &smallBox, 0, 0, 10, 10, Qt::CopyROP, true); + + drawB2Rect(&smallBox, iGrp.button(), true); + drawB2Rect(&largeBox, iGrp.button(), true); + iNormalizePixDown->fill(options->color(Options::TitleBar, false)); + bitBlt(iNormalizePixDown, 3, 3, &largeBox, 0, 0, 12, 12, Qt::CopyROP, true); + bitBlt(iNormalizePixDown, 0, 0, &smallBox, 0, 0, 10, 10, Qt::CopyROP, true); + + bitBlt(iIconifyPixDown, 0, 0, &smallBox, 0, 0, 10, 10, Qt::CopyROP, true); + + QPainter p; + // x for close + p.begin(aClosePix); + kColorBitmaps(&p, aGrp, 0, 0, 16, 16, true, close_white_bits, + NULL, NULL, close_dgray_bits, NULL, NULL); + p.end(); + p.begin(aClosePixDown); + kColorBitmaps(&p, aGrp, 0, 0, 16, 16, true, close_white_bits, + NULL, NULL, close_dgray_bits, NULL, NULL); + p.end(); + p.begin(iClosePix); + kColorBitmaps(&p, iGrp, 0, 0, 16, 16, true, close_white_bits, + NULL, NULL, close_dgray_bits, NULL, NULL); + p.end(); + p.begin(iClosePixDown); + kColorBitmaps(&p, iGrp, 0, 0, 16, 16, true, close_white_bits, + NULL, NULL, close_dgray_bits, NULL, NULL); + p.end(); + + // pin + p.begin(aPinupPix); + kColorBitmaps(&p, aGrp, 0, 0, 16, 16, true, pinup_white_bits, + pinup_gray_bits, NULL, pinup_dgray_bits, NULL, NULL); + p.end(); + p.begin(aPinupPixDown); + kColorBitmaps(&p, aGrp, 0, 0, 16, 16, true, pindown_white_bits, + pindown_gray_bits, NULL, pindown_dgray_bits, NULL, NULL); + p.end(); + p.begin(iPinupPix); + kColorBitmaps(&p, iGrp, 0, 0, 16, 16, true, pinup_white_bits, + pinup_gray_bits, NULL, pinup_dgray_bits, NULL, NULL); + p.end(); + p.begin(iPinupPixDown); + kColorBitmaps(&p, iGrp, 0, 0, 16, 16, true, pindown_white_bits, + pindown_gray_bits, NULL, pindown_dgray_bits, NULL, NULL); + p.end(); + + // menu + p.begin(aMenuPix); + kColorBitmaps(&p, aGrp, 0, 0, 16, 16, true, menu_white_bits, + NULL, NULL, menu_dgray_bits, NULL, NULL); + p.end(); + p.begin(aMenuPixDown); + kColorBitmaps(&p, aGrp, 0, 0, 16, 16, true, menu_white_bits, + NULL, NULL, menu_dgray_bits, NULL, NULL); + p.end(); + p.begin(iMenuPix); + kColorBitmaps(&p, iGrp, 0, 0, 16, 16, true, menu_white_bits, + NULL, NULL, menu_dgray_bits, NULL, NULL); + p.end(); + p.begin(iMenuPixDown); + kColorBitmaps(&p, iGrp, 0, 0, 16, 16, true, menu_white_bits, + NULL, NULL, menu_dgray_bits, NULL, NULL); + p.end(); + + // help + p.begin(aHelpPix); + kColorBitmaps(&p, aGrp, 0, 0, 16, 16, true, help_light_bits, + NULL, NULL, help_dark_bits, NULL, NULL); + p.end(); + p.begin(aHelpPixDown); + kColorBitmaps(&p, aGrp, 0, 0, 16, 16, true, help_light_bits, + NULL, NULL, help_dark_bits, NULL, NULL); + p.end(); + p.begin(iHelpPix); + kColorBitmaps(&p, aGrp, 0, 0, 16, 16, true, help_light_bits, + NULL, NULL, help_dark_bits, NULL, NULL); + p.end(); + p.begin(iHelpPixDown); + kColorBitmaps(&p, aGrp, 0, 0, 16, 16, true, help_light_bits, + NULL, NULL, help_dark_bits, NULL, NULL); + p.end(); +} + +void B2Client::positionButtons() +{ + QFontMetrics fm(options->font(isActive())); + + int textLen = fm.width(caption()); + QLayoutIterator it=titlebar->layout()->iterator(); + ++it; + ++it; + ++it; + + int titleWidth=titlebar->width()-(++it)->geometry().width()+textLen+2; + + if( titleWidth > width()) titleWidth=width(); + + titlebar->resize(titleWidth,20); + titlebar->move(bar_x_ofs, 0); +} + +extern "C" +{ + Client *allocate(Workspace *ws, WId w, int) + { + return(new B2Client(ws, w)); + } + void init() + { + create_pixmaps(); + } + void reset() + { + redraw_pixmaps(); + } + void deinit() + { + delete_pixmaps(); + } +} + +#include "b2client.moc" diff --git a/clients/b2/b2client.h b/clients/b2/b2client.h new file mode 100644 index 0000000000..b3328fc6c5 --- /dev/null +++ b/clients/b2/b2client.h @@ -0,0 +1,120 @@ +#ifndef __B2CLIENT_H +#define __B2CLIENT_H + +#include +#include +#include +#include "../../client.h" +class QLabel; +//class QSpacerItem; +//class QHBoxLayout; +class QGridLayout; + +namespace KWinInternal { + +class B2Button : public QButton +{ + Q_OBJECT +public: + B2Button(Client *_client=0, QWidget *parent=0, const char *name=0) + : QButton(parent, name){useMiniIcon = false; client = _client;} + B2Button(KPixmap *pix, KPixmap *pixDown, KPixmap *iPix, KPixmap *iPixDown, + Client *_client=0, QWidget *parent=0, const char *name=0); + void setBg(const QColor &c){bg = c;} + void setPixmaps(KPixmap *pix, KPixmap *pixDown, KPixmap *iPix, + KPixmap *iPixDown); + void setToggle(){setToggleType(Toggle);} + void setActive(bool on){setOn(on);} + void setUseMiniIcon(){useMiniIcon = true;} + QSize sizeHint() const; + QSizePolicy sizePolicy() const; +protected: + virtual void drawButton(QPainter *p); + void drawButtonLabel(QPainter *){;} + + bool useMiniIcon; + KPixmap *pNorm, *pDown, *iNorm, *iDown; + QColor bg; //only use one color (the rest is pixmap) so forget QPalette ;) + Client *client; + + void mousePressEvent( QMouseEvent* e ); + void mouseReleaseEvent( QMouseEvent* e ); + +public: + int last_button; +}; + +class B2Client; + +class B2Titlebar : public QWidget +{ + Q_OBJECT +public: + B2Titlebar(B2Client *parent); + ~B2Titlebar(){;} + bool isFullyObscured() const {return isfullyobscured;} + void recalcBuffer(); +protected: + void paintEvent( QPaintEvent* ); + bool x11Event(XEvent *e); + void mouseDoubleClickEvent( QMouseEvent * ); + void mousePressEvent( QMouseEvent * ); + void mouseReleaseEvent( QMouseEvent * ); + void mouseMoveEvent(QMouseEvent *); + void init(); + void resizeEvent(QResizeEvent *ev); + + QString oldTitle; + KPixmap titleBuffer; + bool set_x11mask; + bool isfullyobscured; + bool shift_move; + QPoint moveOffset; + B2Client *client; +}; + +class B2Client : public KWinInternal::Client +{ + Q_OBJECT + friend class B2Titlebar; +public: + B2Client( Workspace *ws, WId w, QWidget *parent=0, const char *name=0 ); + ~B2Client(){;} + void unobscureTitlebar(); + void titleMoveAbs(int new_ofs); + void titleMoveRel(int xdiff); +protected: + void resizeEvent( QResizeEvent* ); + void paintEvent( QPaintEvent* ); + void showEvent( QShowEvent* ); + void windowWrapperShowEvent( QShowEvent* ); + void init(); + void captionChange( const QString& name ); + void stickyChange(bool on); + void activeChange(bool on); + void maximizeChange(bool m); + void iconChange(); + void doShape(); + MousePosition mousePosition( const QPoint& p ) const; +private slots: + void menuButtonPressed(); + void slotReset(); + void maxButtonClicked(); +private: + void positionButtons(); + enum ButtonType{BtnMenu=0, BtnSticky, BtnIconify, BtnMax, BtnClose, + BtnHelp}; + //B2Button* button[5]; + B2Button* button[6]; + //QSpacerItem* titlebar; + //QHBoxLayout *tLayout; + QGridLayout *g; + int bar_x_ofs; + B2Titlebar *titlebar; + int in_unobs; + +}; + +}; + +#endif diff --git a/clients/b2/bitmaps.h b/clients/b2/bitmaps.h new file mode 100644 index 0000000000..9b7c31f7cc --- /dev/null +++ b/clients/b2/bitmaps.h @@ -0,0 +1,98 @@ +#ifndef __STDCLIENT_BITMAPS_H +#define __STDCLIENT_BITMAPS_H + +/** + * The standard client has the capability to color it's titlebar buttons + * according to the new color scheme. In order to do this it needs a bitmap + * for each shade which it draws into a pixmap with the appropriate color. + * These are all the bitmaps. + */ + +static unsigned char close_white_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x04, 0x10, 0x04, 0x08, 0x08, 0x04, 0x10, 0x02, + 0x20, 0x01, 0x40, 0x00, 0x40, 0x00, 0x20, 0x01, 0x10, 0x02, 0x08, 0x04, + 0x04, 0x08, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00}; + +static unsigned char close_dgray_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x18, 0x30, 0x30, 0x18, 0x60, 0x0c, + 0xc0, 0x06, 0x80, 0x03, 0x80, 0x03, 0xc0, 0x06, 0x60, 0x0c, 0x30, 0x18, + 0x18, 0x30, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00}; + +static unsigned char menu_white_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0x3f, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static unsigned char menu_dgray_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static unsigned char menu_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0x3f, 0x04, 0x20, 0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static 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 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 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 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 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 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 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 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}; + +static unsigned char help_mask_bits[] = { + 0x00,0x00,0x00,0x00,0xe0,0x03,0xf0,0x07,0x70,0x0e,0x60,0x0e,0x00,0x0f,0x80, + 0x07,0xc0,0x03,0xc0,0x01,0x80,0x01,0xc0,0x00,0xc0,0x01,0x80,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x4c,0x0b,0x08,0x58,0x65,0x09,0x08,0x90,0x00,0x00, + 0x00,0x09,0x04,0x00,0x00,0x72,0x6f,0x6f,0x74,0x00,0x24,0x31,0x24,0x47,0x6b, + 0x65,0x44,0x78,0x63 }; + +static unsigned char help_dark_bits[] = { + 0x00,0x00,0x00,0x00,0xe0,0x03,0x30,0x06,0x30,0x06,0x00,0x06,0x00,0x03,0x80, + 0x01,0xc0,0x00,0xc0,0x00,0x00,0x00,0xc0,0x00,0xc0,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x65,0x64,0x28,0x29,0x00,0x00,0x00,0x00,0x90,0x00,0x00, + 0x00,0x21,0x00,0x00,0x00,0x34,0xfe,0x12,0x2b,0x00,0x00,0xff,0xff,0x58,0xc0, + 0x01,0x2b,0x45,0xfe }; + +static unsigned char help_light_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0x40,0x08,0x60,0x08,0x00,0x0c,0x00, + 0x06,0x00,0x03,0x00,0x01,0x80,0x01,0x00,0x00,0x00,0x01,0x80,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x4c,0x0b,0x08,0x58,0x65,0x09,0x08,0x90,0x00,0x00, + 0x00,0x09,0x04,0x00,0x00,0x72,0x6f,0x6f,0x74,0x00,0x24,0x31,0x24,0x47,0x6b, + 0x65,0x44,0x78,0x63 }; + +#endif +