/* RISC OS KWin client Copyright 2000 Rik Hemsley 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Qt includes #include #include #include // Local includes #include "../../options.h" #include "../../workspace.h" #include "riscosclient.h" #include "title_inactive_left.xpm" #include "title_inactive.xpm" #include "title_inactive_right.xpm" #include "title_active_left.xpm" #include "title_active.xpm" #include "title_active_right.xpm" #include "resize_bar_left.xpm" #include "resize_bar_mid.xpm" #include "resize_bar_right.xpm" #include "button_base_up.xpm" #include "button_base_down.xpm" #include "button_base_up_active.xpm" #include "button_base_down_active.xpm" #include "button_close.xpm" #include "button_unmax.xpm" #include "button_max.xpm" #include "button_lower.xpm" #include "button_iconify.xpm" #include "button_close_active.xpm" #include "button_unmax_active.xpm" #include "button_max_active.xpm" #include "button_lower_active.xpm" #include "button_iconify_active.xpm" #include extern "C" { Client * allocate(Workspace * workSpace, WId winId) { return new RiscOS::Manager(workSpace, winId); } } using namespace RiscOS; QPixmap * px_button_base_up = 0L; QPixmap * px_button_base_down = 0L; QPixmap * px_button_base_up_active = 0L; QPixmap * px_button_base_down_active = 0L; QPixmap * px_button_iconify = 0L; QPixmap * px_button_close = 0L; QPixmap * px_button_lower = 0L; QPixmap * px_button_max = 0L; QPixmap * px_button_unmax = 0L; QPixmap * px_button_iconify_active = 0L; QPixmap * px_button_close_active = 0L; QPixmap * px_button_lower_active = 0L; QPixmap * px_button_max_active = 0L; QPixmap * px_button_unmax_active = 0L; QPixmap * px_title_inactive_left = 0L; QPixmap * px_title_inactive = 0L; QPixmap * px_title_inactive_right = 0L; QPixmap * px_title_active_left = 0L; QPixmap * px_title_active = 0L; QPixmap * px_title_active_right = 0L; QPixmap * px_resize_left = 0L; QPixmap * px_resize_mid = 0L; QPixmap * px_resize_right = 0L; Button::Button(Manager * parent) : QButton(parent, "Button"), client_(parent), px_symbol_inactive_(0L), px_symbol_active_(0L) { setFixedSize(18, 18); XSetWindowAttributes wsa; wsa.save_under = true; XChangeWindowAttributes(qt_xdisplay(), winId(), 0, &wsa); } void Button::update() { repaint(false); } void Button::drawButton(QPainter * p) { // Excuse my minimalism. QPixmap * px = client_->isActive() ? (isDown() ? px_button_base_down_active : px_button_base_up_active) : (isDown() ? px_button_base_down : px_button_base_up); p->drawPixmap(0, 0, *px); if (client_->isActive()) p->drawPixmap(3, 3, *px_symbol_active_); else p->drawPixmap(3, 3, *px_symbol_inactive_); } void Button::setSymbols(QPixmap * inactive, QPixmap * active) { px_symbol_inactive_ = inactive; px_symbol_active_ = active; repaint(false); } LowerButton::LowerButton(Manager * parent) : Button(parent) { // TODO connect(this, SIGNAL(clicked()), client(), (SLOT(lowerAndDeactivate()))); setSymbols(px_button_lower, px_button_lower_active); } CloseButton::CloseButton(Manager * parent) : Button(parent) { connect(this, SIGNAL(clicked()), client(), (SLOT(closeWindow()))); setSymbols(px_button_close, px_button_close_active); } IconifyButton::IconifyButton(Manager * parent) : Button(parent) { connect(this, SIGNAL(clicked()), client(), (SLOT(iconify()))); setSymbols(px_button_iconify, px_button_iconify_active); } MaximiseButton::MaximiseButton(Manager * parent) : Button(parent) { setSymbols(px_button_max, px_button_max_active); } void MaximiseButton::setOn(bool on) { if (on) setSymbols(px_button_unmax, px_button_unmax_active); else setSymbols(px_button_max, px_button_max_active); } void MaximiseButton::mouseReleaseEvent(QMouseEvent * e) { Button::mouseReleaseEvent(e); if (!rect().contains(e->pos())) return; switch (e->button()) { case RightButton: client()->maximizeNoRaise(); break; case MidButton: client()->maximizeVertically(); break; case LeftButton: default: client()->maximizeAndRaise(); break; } } ResizeButton::ResizeButton(Manager * parent) : Button(parent) { } TitleBar::TitleBar(Manager * parent) : QWidget(parent, "TitleBar"), client_(parent) { setFixedHeight(18); XSetWindowAttributes wsa; wsa.save_under = true; XChangeWindowAttributes(qt_xdisplay(), winId(), 0, &wsa); buf_ = new QPixmap; buf_->resize(128, 18); _updatePixmap(); } TitleBar::~TitleBar() { delete buf_; } void TitleBar::_updatePixmap() { if (size().width() > buf_->width()) buf_->resize(size()); QPainter p; p.begin(buf_); if (client_->isActive()) { p.drawPixmap(0, 0, *px_title_active_left); p.drawTiledPixmap(2, 0, width() - 4, 18, *px_title_active); p.drawPixmap(width() - 2, 0, *px_title_active_right); p.setPen(Qt::white); p.setFont(options->font()); p.drawText(3, 0, width() - 6, 18, AlignCenter, client_->caption()); } else { p.drawPixmap(0, 0, *px_title_inactive_left); p.drawTiledPixmap(2, 0, width() - 4, 18, *px_title_inactive); p.drawPixmap(width() - 2, 0, *px_title_inactive_right); p.setPen(QColor(0xC3, 0xC3, 0xC3)); p.setFont(options->font()); QRect textRect; p.drawText( 3, 0, width() - 6, 18, AlignCenter, client_->caption(), -1, &textRect); textRect.setTop(2); textRect.setBottom(15); textRect.setLeft(textRect.left() - 4); textRect.setRight(textRect.right() + 4); p.fillRect(textRect, QBrush(QColor(0xC3, 0xC3, 0xC3))); int l = textRect.left() - 2; int r = textRect.right() + 2; p.drawLine(l, 2, l, 15); p.drawLine(r, 2, r, 15); l -= 1; r += 1; p.drawLine(l, 2, l, 15); p.drawLine(r, 2, r, 15); l -= 1; r += 1; p.drawLine(l, 2, l, 15); p.drawLine(r, 2, r, 15); l -= 2; r += 2; p.drawLine(l, 2, l, 15); p.drawLine(r, 2, r, 15); l -= 1; r += 1; p.drawLine(l, 2, l, 15); p.drawLine(r, 2, r, 15); l -= 1; r += 1; p.drawLine(l, 2, l, 15); p.drawLine(r, 2, r, 15); l -= 2; r += 2; p.drawLine(l, 2, l, 15); p.drawLine(r, 2, r, 15); l -= 2; r += 2; p.drawLine(l, 2, l, 15); p.drawLine(r, 2, r, 15); l -= 2; r += 2; p.drawLine(l, 2, l, 15); p.drawLine(r, 2, r, 15); p.setPen(Qt::black); p.drawText(3, 0, width() - 6, 18, AlignCenter, client_->caption()); } } void TitleBar::resizeEvent(QResizeEvent * e) { QWidget::resizeEvent(e); _updatePixmap(); } void TitleBar::paintEvent(QPaintEvent * e) { QRect r(e->rect()); bitBlt(this, r.topLeft(), buf_, r, Qt::CopyROP); } void TitleBar::mousePressEvent(QMouseEvent * e) { switch (e->button()) { case MidButton: client_->workspace()->clientPopup(client_)->popup(e->globalPos()); break; case LeftButton: client_->workspace()->raiseClient(client_); client_->workspace()->requestFocus(client_); case RightButton: clientPosToMousePos_ = e->globalPos() - client_->pos(); break; default: break; } } void TitleBar::mouseReleaseEvent(QMouseEvent * e) { } void TitleBar::mouseMoveEvent(QMouseEvent * e) { QPoint adjustedForCursor = e->globalPos() - clientPosToMousePos_; QPoint adjustedForSnap = client_->workspace()->adjustClientPosition(client_, adjustedForCursor); client_->move(adjustedForSnap); // Do we really need this ? // QApplication::syncX(); } void TitleBar::mouseDoubleClickEvent(QMouseEvent * e) { client_->setShade(!client_->isShade()); } void TitleBar::update() { _updatePixmap(); repaint(false); } ResizeBar::ResizeBar(Manager * parent) : QWidget(parent, "ResizeBar") { setFixedHeight(8); left_ = new ResizeLeft(this, parent); mid_ = new ResizeMid(this, parent); right_ = new ResizeRight(this, parent); QHBoxLayout * layout = new QHBoxLayout(this); layout->addWidget(left_); layout->addWidget(mid_, 1); layout->addWidget(right_); XSetWindowAttributes wsa; wsa.save_under = true; XChangeWindowAttributes(qt_xdisplay(), winId(), 0, &wsa); XChangeWindowAttributes(qt_xdisplay(), left_->winId(), 0, &wsa); XChangeWindowAttributes(qt_xdisplay(), mid_->winId(), 0, &wsa); XChangeWindowAttributes(qt_xdisplay(), right_->winId(), 0, &wsa); } void ResizeBar::update() { mid_->update(); } ResizeMid::ResizeMid(ResizeBar * parent, Manager * c) : QWidget(parent, "ResizeMid"), client_(c) { setCursor(Qt::sizeVerCursor); buf_ = new QPixmap; buf_->resize(128, 8); } ResizeMid::~ResizeMid() { delete buf_; } void ResizeMid::_updatePixmap() { if (size().width() > buf_->width()) buf_->resize(size()); QPainter p; p.begin(buf_); p.drawLine(0, 8, width(), 8); p.drawPixmap(0, 0, *px_resize_left); p.drawTiledPixmap(2, 0, width() - 4, 7, *px_resize_mid); p.drawPixmap(width() - 2, 0, *px_resize_right); } void ResizeMid::update() { _updatePixmap(); repaint(false); } void ResizeMid::resizeEvent(QResizeEvent * e) { QWidget::resizeEvent(e); _updatePixmap(); } void ResizeMid::paintEvent(QPaintEvent * e) { QRect r(e->rect()); bitBlt(this, r.topLeft(), buf_, r, Qt::CopyROP); } void ResizeMid::mouseMoveEvent(QMouseEvent * e) { QRect g = client_->geometry(); g.setBottom(e->globalPos().y()); QSize adjustedSize = client_->adjustedSize(g.size()); if (adjustedSize != client_->size()) { g.setBottom(g.top() + adjustedSize.height()); client_->setGeometry(g); } } ResizeLeft::ResizeLeft(ResizeBar * parent, Manager * c) : QWidget(parent, "ResizeLeft"), client_(c) { setCursor(Qt::sizeBDiagCursor); setFixedSize(30, 8); setBackgroundColor(Qt::black); QPixmap pixmap; pixmap.resize(30, 8); pixmap.fill(Qt::black); QPainter p(&pixmap); p.drawPixmap(1, 0, *px_resize_left); p.drawPixmap(3, 0, *px_resize_mid); p.drawPixmap(28, 0, *px_resize_right); setBackgroundPixmap(pixmap); } void ResizeLeft::mouseMoveEvent(QMouseEvent * e) { QRect g = client_->geometry(); g.setBottom(e->globalPos().y()); g.setLeft(e->globalPos().x()); QSize adjustedSize = client_->adjustedSize(g.size()); if (adjustedSize != client_->size()) { g.setLeft(g.right() - adjustedSize.width()); g.setBottom(g.top() + adjustedSize.height()); client_->setGeometry(g); } } ResizeRight::ResizeRight(ResizeBar * parent, Manager * c) : QWidget(parent, "ResizeRight"), client_(c) { setCursor(Qt::sizeFDiagCursor); setFixedSize(30, 8); setBackgroundColor(Qt::black); QPixmap pixmap; pixmap.resize(30, 8); pixmap.fill(Qt::black); QPainter p(&pixmap); p.drawPixmap(0, 0, *px_resize_left); p.drawPixmap(2, 0, *px_resize_mid); p.drawPixmap(27, 0, *px_resize_right); setBackgroundPixmap(pixmap); } void ResizeRight::mouseMoveEvent(QMouseEvent * e) { QRect g = client_->geometry(); g.setBottom(e->globalPos().y()); g.setRight(e->globalPos().x()); QSize adjustedSize = client_->adjustedSize(g.size()); if (adjustedSize != client_->size()) { g.setRight(g.left() + adjustedSize.width()); g.setBottom(g.top() + adjustedSize.height()); client_->setGeometry(g); } } Manager::Manager( Workspace * workSpace, WId winId, QWidget * parent, const char * name ) : Client(workSpace, winId, parent, name, WResizeNoErase), pixmapsLoaded_(false) { setMouseTracking(false); // I don't want this ! setBackgroundColor(Qt::black); _loadPixmaps(); connect(options, SIGNAL(resetClients()), this, SLOT(slotReset())); lower_ = new LowerButton (this); close_ = new CloseButton (this); title_ = new TitleBar (this); iconify_ = new IconifyButton (this); maximize_ = new MaximiseButton (this); resizeBar_ = new ResizeBar (this); // Layout // Border | Close | Titlebar | Max | Lower | Border QHBoxLayout * titleLayout = new QHBoxLayout(0, "titleLayout"); titleLayout->addSpacing(1); titleLayout->addWidget(lower_); titleLayout->addSpacing(1); titleLayout->addWidget(close_); titleLayout->addSpacing(1); titleLayout->addWidget(title_, 1); titleLayout->addSpacing(1); titleLayout->addWidget(iconify_); titleLayout->addSpacing(1); titleLayout->addWidget(maximize_); titleLayout->addSpacing(1); // Border // Window // Border QHBoxLayout * windowLayout = new QHBoxLayout(0, "windowLayout"); windowLayout->addSpacing(1); windowLayout->addWidget(windowWrapper(), 1); windowLayout->addSpacing(1); // Border // Titlebar // Window layout // Resize bar QVBoxLayout * mainLayout = new QVBoxLayout(this, 0, 0, "mainLayout"); mainLayout->addSpacing(1); mainLayout->addLayout(titleLayout); mainLayout->addSpacing(1); mainLayout->addLayout(windowLayout, 1); mainLayout->addSpacing(1); mainLayout->addWidget(resizeBar_); title_->update(); resizeBar_->update(); } void Manager::slotReset() { // Empty. } void Manager::captionChange(const QString &) { title_->update(); } void Manager::activeChange(bool b) { title_->update(); lower_->update(); close_->update(); iconify_->update(); maximize_->update(); } void Manager::maximizeChange(bool b) { maximize_->setOn(b); } void Manager::maximizeAndRaise() { maximize(MaximizeFull); workspace()->raiseClient(this); workspace()->requestFocus(this); } void Manager::maximizeVertically() { maximize(MaximizeVertical); workspace()->raiseClient(this); workspace()->requestFocus(this); } void Manager::maximizeNoRaise() { maximize(MaximizeFull); } void Manager::resize(int w, int h) { Client::resize(w, h); } void Manager::setShade(bool b) { #if 0 // Hmm. This does screwy things to the layout. if (b) resizeBar_->hide(); else resizeBar_->show(); #endif // And this is screwed. My window ends up the wrong size when unshaded. // Client::setShade(b); } void Manager::_loadPixmaps() { if (pixmapsLoaded_) { delete px_button_base_up; px_button_base_up = 0L; delete px_button_base_down; px_button_base_down = 0L; delete px_button_base_up_active; px_button_base_up_active = 0L; delete px_button_base_down_active; px_button_base_down_active = 0L; delete px_button_iconify; px_button_iconify = 0L; delete px_button_close; px_button_close = 0L; delete px_button_lower; px_button_lower = 0L; delete px_button_max; px_button_max = 0L; delete px_button_unmax; px_button_unmax = 0L; delete px_button_iconify_active; px_button_iconify_active = 0L; delete px_button_close_active; px_button_close_active = 0L; delete px_button_lower_active; px_button_lower_active = 0L; delete px_button_max_active; px_button_max_active = 0L; delete px_button_unmax_active; px_button_unmax_active = 0L; delete px_title_inactive_left; px_title_inactive_left = 0L; delete px_title_inactive; px_title_inactive = 0L; delete px_title_inactive_right; px_title_inactive_right = 0L; delete px_title_active_left; px_title_active_left = 0L; delete px_title_active; px_title_active = 0L; delete px_title_active_right; px_title_active_right = 0L; delete px_resize_left; px_resize_left = 0L; delete px_resize_mid; px_resize_mid = 0L; delete px_resize_right; px_resize_right = 0L; } px_button_base_up = new QPixmap(button_base_up_xpm); px_button_base_down = new QPixmap(button_base_down_xpm); px_button_base_up_active = new QPixmap(button_base_up_active_xpm); px_button_base_down_active = new QPixmap(button_base_down_active_xpm); px_button_iconify = new QPixmap(button_iconify_xpm); px_button_close = new QPixmap(button_close_xpm); px_button_lower = new QPixmap(button_lower_xpm); px_button_max = new QPixmap(button_max_xpm); px_button_unmax = new QPixmap(button_unmax_xpm); px_button_iconify_active = new QPixmap(button_iconify_active_xpm); px_button_close_active = new QPixmap(button_close_active_xpm); px_button_lower_active = new QPixmap(button_lower_active_xpm); px_button_max_active = new QPixmap(button_max_active_xpm); px_button_unmax_active = new QPixmap(button_unmax_active_xpm); px_title_inactive_left = new QPixmap(title_inactive_left_xpm); px_title_inactive = new QPixmap(title_inactive_xpm); px_title_inactive_right = new QPixmap(title_inactive_right_xpm); px_title_active_left = new QPixmap(title_active_left_xpm); px_title_active = new QPixmap(title_active_xpm); px_title_active_right = new QPixmap(title_active_right_xpm); px_resize_left = new QPixmap(resize_bar_left_xpm); px_resize_mid = new QPixmap(resize_bar_mid_xpm); px_resize_right = new QPixmap(resize_bar_right_xpm); pixmapsLoaded_ = true; } // vim:ts=2:sw=2:tw=78