kwin Library API Documentation

Web.cpp

00001 /*
00002   'Web' kwin client
00003 
00004   Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org>
00005 
00006   This program is free software; you can redistribute it and/or
00007   modify it under the terms of the GNU General Public
00008   License as published by the Free Software Foundation; either
00009   version 2 of the License, or (at your option) any later version.
00010 
00011   This program is distributed in the hope that it will be useful,
00012   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014   General Public License for more details.
00015 
00016   You should have received a copy of the GNU General Public License
00017   along with this program; see the file COPYING.  If not, write to
00018   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019   Boston, MA 02111-1307, USA.
00020 */
00021 
00022 #include <qlabel.h>
00023 #include <qlayout.h>
00024 #include <qpainter.h>
00025 
00026 #include <kconfig.h>
00027 
00028 #include "Web.h"
00029 #include "WebButton.h"
00030 #include "WebButtonHelp.h"
00031 #include "WebButtonIconify.h" // minimize button
00032 #include "WebButtonClose.h"
00033 #include "WebButtonSticky.h" // onAllDesktops button
00034 #include "WebButtonMaximize.h"
00035 #include "WebButtonLower.h"
00036 
00037 extern "C"
00038 {
00039   KDecorationFactory *create_factory()
00040   {
00041     return new Web::WebFactory();
00042   }
00043 }
00044 
00045 namespace Web {
00046 
00047 WebClient::WebClient(KDecorationBridge* bridge, KDecorationFactory* factory)
00048   : KDecoration(bridge, factory),
00049     mainLayout_   (0),
00050     titleSpacer_  (0)
00051 {
00052   // Empty.
00053 }
00054 
00055 WebClient::~WebClient()
00056 {
00057   // Empty.
00058 }
00059 
00060   void
00061 WebClient::init()
00062 {
00063   createMainWidget(WNoAutoErase);
00064   widget()->installEventFilter( this );
00065   widget()->setBackgroundMode(NoBackground);
00066 
00067   // title height
00068   const int textVMargin   = 2;
00069   QFontMetrics fm(options()->font(isActive(), isTool()));
00070 
00071   // border size
00072   switch(options()->preferredBorderSize( factory())) {
00073     case BorderLarge:
00074       borderSize_ = 8;
00075       break;
00076     case BorderVeryLarge:
00077       borderSize_ = 12;
00078       break;
00079     case BorderHuge:
00080       borderSize_ = 18;
00081       break;
00082     case BorderVeryHuge:
00083       borderSize_ = 27;
00084       break;
00085     case BorderOversized:
00086       borderSize_ = 40;
00087       break;
00088     case BorderNormal:
00089     default:
00090       borderSize_ = 4;
00091   }
00092   titleHeight_ = QMAX(QMAX(14, fm.height() + textVMargin * 2), borderSize_);
00093 
00094   _resetLayout();
00095 
00096   leftButtonList_   .setAutoDelete(true);
00097   rightButtonList_  .setAutoDelete(true);
00098 }
00099 
00100   void
00101 WebClient::reset( unsigned long changed )
00102 {
00103   if (changed & SettingColors)
00104   {
00105     // repaint the whole thing
00106     widget()->repaint(false);
00107   } else if (changed & SettingFont) {
00108     // font has changed -- update title height
00109     // title height
00110     const uint textVMargin   = 2;
00111     QFontMetrics fm(options()->font(isActive(), isTool()));
00112     titleHeight_ = QMAX(14, fm.height() + textVMargin * 2);
00113     // update buttons
00114     for (QPtrListIterator<WebButton> it(leftButtonList_); it.current(); ++it)
00115     {
00116       it.current()->setFixedSize(titleHeight_, titleHeight_);
00117     }
00118     for (QPtrListIterator<WebButton> it(rightButtonList_); it.current(); ++it)
00119     {
00120       it.current()->setFixedSize(titleHeight_, titleHeight_);
00121     }
00122 //     for (int n=0; n<NumButtons; n++) {
00123 //         if (m_button[n]) m_button[n]->setSize(s_titleHeight-1);
00124 //     }
00125     // update the spacer
00126     titleSpacer_->changeSize(0, titleHeight_, QSizePolicy::Expanding,
00127                              QSizePolicy::Fixed);
00128     widget()->repaint(false);
00129   }
00130 }
00131 
00132   void
00133 WebClient::resizeEvent(QResizeEvent *)
00134 {
00135   doShape();
00136   widget()->repaint();
00137 }
00138 
00139   void
00140 WebClient::captionChange()
00141 {
00142   widget()->repaint();
00143 }
00144 
00145 void WebClient::iconChange()
00146 {
00147 // Empty.
00148 }
00149 
00150   void
00151 WebClient::paintEvent(QPaintEvent * pe)
00152 {
00153   QRect titleRect(titleSpacer_->geometry());
00154   titleRect.setTop(1);
00155 
00156   QPainter p(widget());
00157 
00158   p.setPen(Qt::black);
00159   p.setBrush(options()->colorGroup(ColorFrame, isActive()).background());
00160 
00161   p.setClipRegion(pe->region() - titleRect);
00162 
00163   p.drawRect(widget()->rect());
00164 
00165   p.setClipRegion(pe->region());
00166 
00167   p.fillRect(titleRect, options()->color(ColorTitleBar, isActive()));
00168 
00169   if (shape_)
00170   {
00171     int r(width());
00172     int b(height());
00173 
00174     // Draw edge of top-left corner inside the area removed by the mask.
00175 
00176     p.drawPoint(3, 1);
00177     p.drawPoint(4, 1);
00178     p.drawPoint(2, 2);
00179     p.drawPoint(1, 3);
00180     p.drawPoint(1, 4);
00181 
00182     // Draw edge of top-right corner inside the area removed by the mask.
00183 
00184     p.drawPoint(r - 5, 1);
00185     p.drawPoint(r - 4, 1);
00186     p.drawPoint(r - 3, 2);
00187     p.drawPoint(r - 2, 3);
00188     p.drawPoint(r - 2, 4);
00189 
00190     // Draw edge of bottom-left corner inside the area removed by the mask.
00191 
00192     p.drawPoint(1, b - 5);
00193     p.drawPoint(1, b - 4);
00194     p.drawPoint(2, b - 3);
00195     p.drawPoint(3, b - 2);
00196     p.drawPoint(4, b - 2);
00197 
00198     // Draw edge of bottom-right corner inside the area removed by the mask.
00199 
00200     p.drawPoint(r - 2, b - 5);
00201     p.drawPoint(r - 2, b - 4);
00202     p.drawPoint(r - 3, b - 3);
00203     p.drawPoint(r - 4, b - 2);
00204     p.drawPoint(r - 5, b - 2);
00205   }
00206 
00207   p.setFont(options()->font(isActive(), isTool()));
00208 
00209   p.setPen(options()->color(ColorFont, isActive()));
00210 
00211   p.drawText(titleSpacer_->geometry(), AlignCenter, caption());
00212 }
00213 
00214   void
00215 WebClient::doShape()
00216 {
00217   if (!shape_)
00218     return;
00219 
00220   QRegion mask(0, 0, width(), height());
00221 
00222   int r(width());
00223   int b(height());
00224 
00225   // Remove top-left corner.
00226 
00227   mask -= QRegion(0, 0, 5, 1);
00228   mask -= QRegion(0, 1, 3, 1);
00229   mask -= QRegion(0, 2, 2, 1);
00230   mask -= QRegion(0, 3, 1, 2);
00231 
00232   // Remove top-right corner.
00233 
00234   mask -= QRegion(r - 5, 0, 5, 1);
00235   mask -= QRegion(r - 3, 1, 3, 1);
00236   mask -= QRegion(r - 2, 2, 2, 1);
00237   mask -= QRegion(r - 1, 3, 1, 2);
00238 
00239   // Remove bottom-left corner.
00240 
00241   mask -= QRegion(0, b - 5, 1, 3);
00242   mask -= QRegion(0, b - 3, 2, 1);
00243   mask -= QRegion(0, b - 2, 3, 1);
00244   mask -= QRegion(0, b - 1, 5, 1);
00245 
00246   // Remove bottom-right corner.
00247 
00248   mask -= QRegion(r - 5, b - 1, 5, 1);
00249   mask -= QRegion(r - 3, b - 2, 3, 1);
00250   mask -= QRegion(r - 2, b - 3, 2, 1);
00251   mask -= QRegion(r - 1, b - 5, 1, 2);
00252 
00253   setMask(mask);
00254 }
00255 
00256   void
00257 WebClient::showEvent(QShowEvent *)
00258 {
00259   doShape();
00260   widget()->repaint();
00261 }
00262 
00263   void
00264 WebClient::windowWrapperShowEvent(QShowEvent *)
00265 {
00266   doShape();
00267   widget()->repaint();
00268 }
00269 
00270   void
00271 WebClient::mouseDoubleClickEvent(QMouseEvent * e)
00272 {
00273   if (titleSpacer_->geometry().contains(e->pos()))
00274   {
00275     titlebarDblClickOperation();
00276   }
00277 }
00278 
00279   void
00280 WebClient::desktopChange()
00281 {
00282   emit(oadChange(isOnAllDesktops()));
00283 }
00284 
00285   void
00286 WebClient::maximizeChange()
00287 {
00288   emit(maxChange(maximizeMode()==MaximizeFull));
00289 }
00290 
00291   void
00292 WebClient::activeChange()
00293 {
00294   widget()->repaint();
00295 }
00296 
00297   WebClient::Position
00298 WebClient::mousePosition(const QPoint & p) const
00299 {
00300   int x = p.x();
00301   int y = p.y();
00302   int corner = 14 + 3*borderSize_/2;
00303 
00304   if (y < titleSpacer_->geometry().height())
00305   {
00306     // rikkus: this style is not designed to be resizable at the top edge.
00307 
00308 #if 0
00309     if ((y < 4 && x < corner) || x < 4)
00310       return Client::TopLeft;
00311     else if ((y < 4 && x > width() - corner) || x > width() - 4)
00312       return Client::TopRight;
00313     else if (y < 4)
00314       return Client::Top;
00315     else
00316 #endif
00317       return KDecoration::PositionCenter;
00318   }
00319   else if (y < height() - borderSize_)
00320   {
00321     if (x < borderSize_)
00322       return KDecoration::PositionLeft;
00323     else
00324       if (x > width() - borderSize_)
00325         return KDecoration::PositionRight;
00326       else
00327         return KDecoration::PositionCenter;
00328   }
00329   else
00330   {
00331     if (x < 12 + corner)
00332       return KDecoration::PositionBottomLeft;
00333     else
00334       if (x > width() - corner)
00335         return KDecoration::PositionBottomRight;
00336       else
00337         return KDecoration::PositionBottom;
00338   }
00339 
00340   return KDecoration::mousePosition(p);
00341 }
00342 
00343   void
00344 WebClient::slotMaximize(int button)
00345 {
00346   switch (button)
00347   {
00348     case MidButton:
00349       maximize(maximizeMode() ^ MaximizeVertical);
00350       break;
00351 
00352     case RightButton:
00353       maximize(maximizeMode() ^ MaximizeHorizontal);
00354       break;
00355 
00356     case LeftButton:
00357     default:
00358       maximize(maximizeMode() == MaximizeFull ? MaximizeRestore : MaximizeFull);
00359   }
00360 }
00361 
00362   WebButton *
00363 WebClient::_createButton(const QString & s, QWidget * parent)
00364 {
00365   WebButton * b = 0;
00366 
00367   if (("Help" == s) && providesContextHelp())
00368   {
00369     b = new WebButtonHelp(parent, this);
00370     connect(b, SIGNAL(help()), this, SLOT(showContextHelp()));
00371   }
00372 
00373   else if ("OnAllDesktops" == s)
00374   {
00375     b = new WebButtonSticky(isOnAllDesktops(), parent, this);
00376     connect(b, SIGNAL(toggleSticky()), this, SLOT(toggleOnAllDesktops()));
00377     connect(this, SIGNAL(oadChange(bool)), b, SLOT(slotOnAllDesktopsChange(bool)));
00378   }
00379 
00380   else if ("Minimize" == s && isMinimizable())
00381   {
00382     b = new WebButtonIconify(parent, this);
00383     connect(b, SIGNAL(minimize()), this, SLOT(minimize()));
00384   }
00385 
00386   else if ("Maximize" == s && isMaximizable())
00387   {
00388     b = new WebButtonMaximize((maximizeMode()==MaximizeFull), parent, this);
00389     connect(b, SIGNAL(maximize(int)), this, SLOT(slotMaximize(int)));
00390     connect(this, SIGNAL(maxChange(bool)), b, SLOT(slotMaximizeChange(bool)));
00391   }
00392 
00393   else if ("Close" == s && isCloseable())
00394   {
00395     b = new WebButtonClose(parent, this);
00396     connect(b, SIGNAL(closeWindow()), this, SLOT(closeWindow()));
00397   }
00398 
00399   else if ("Lower" == s)
00400   {
00401     b = new WebButtonLower(parent, this);
00402     connect(b, SIGNAL(lowerWindow()), this, SLOT(slotLowerWindow()));
00403   }
00404 
00405   if (0 != b)
00406   {
00407     b->setShape(shape_);
00408   }
00409 
00410   return b;
00411 }
00412 
00413   void
00414 WebClient::_createButtons()
00415 {
00416   leftButtonList_   .clear();
00417   rightButtonList_  .clear();
00418 
00419   QString buttons = options()->titleButtonsLeft() + "|" + options()->titleButtonsRight();
00420   QPtrList<WebButton> *buttonList = &leftButtonList_;
00421   for (unsigned int i = 0; i < buttons.length(); ++i)
00422   {
00423     WebButton * tb = 0;
00424     switch (buttons[i].latin1())
00425     {
00426       case 'S': // OnAllDesktops
00427         tb = _createButton("OnAllDesktops", widget());
00428         break;
00429 
00430       case 'H': // Help
00431         tb = _createButton("Help", widget());
00432         break;
00433 
00434       case 'I': // Minimize
00435         tb = _createButton("Minimize", widget());
00436         break;
00437 
00438       case 'A': // Maximize
00439         tb = _createButton("Maximize", widget());
00440         break;
00441 
00442       case 'X': // Close
00443         tb = _createButton("Close", widget());
00444         break;
00445 
00446       case '|':
00447         buttonList = &rightButtonList_;
00448         break;
00449     }
00450     if (0 != tb)
00451       buttonList->append(tb);
00452   }
00453 
00454   if (!leftButtonList_.isEmpty())
00455     leftButtonList_.first()->setPosition(WebButton::Left);
00456 
00457   if (!rightButtonList_.isEmpty())
00458     rightButtonList_.last()->setPosition(WebButton::Right);
00459 }
00460 
00461   void
00462 WebClient::_resetLayout()
00463 {
00464   KConfig c("kwinwebrc");
00465   c.setGroup("General");
00466   shape_ = c.readBoolEntry("Shape", true);
00467 
00468   //  ____________________________________
00469   // |  |                              |  |
00470   // |Xo|     titleSpacer              |v^| <--- topLayout
00471   // |__|______________________________|__|
00472   // | |                                | |
00473   // | |                                | |
00474   // | |     fake window                | |
00475   // | |                                | | <--- midLayout
00476   // | |                                | |
00477   // | |                                | |
00478   // | |________________________________| |
00479   // |____________________________________|
00480 
00481   const uint sideMargin    = borderSize_;
00482   const uint bottomMargin  = borderSize_;
00483 
00484   if (0 != titleHeight_ % 2)
00485     titleHeight_ += 1;
00486 
00487   delete mainLayout_;
00488 
00489   mainLayout_  = new QVBoxLayout(widget(), 0, 0);
00490 
00491   titleSpacer_ = new QSpacerItem ( 0, titleHeight_, QSizePolicy::Expanding,
00492       QSizePolicy::Fixed);
00493 
00494   QBoxLayout * topLayout = new QBoxLayout(mainLayout_, QBoxLayout::LeftToRight, 0, 0);
00495 
00496   _createButtons();
00497 
00498   // Add left-side buttons.
00499 
00500   for (QPtrListIterator<WebButton> it(leftButtonList_); it.current(); ++it)
00501   {
00502     topLayout->addWidget(it.current(), Qt::AlignVCenter);
00503     topLayout->setStretchFactor(it.current(), 0);
00504     it.current()->setFixedSize(titleHeight_, titleHeight_);
00505   }
00506 
00507   topLayout->addItem(titleSpacer_);
00508 
00509   // Add right-side buttons.
00510 
00511   for (QPtrListIterator<WebButton> it(rightButtonList_); it.current(); ++it)
00512   {
00513     topLayout->addWidget(it.current(), Qt::AlignVCenter);
00514     it.current()->setFixedSize(titleHeight_, titleHeight_);
00515   }
00516 
00517   // -------------------------------------------------------------------
00518 
00519   QHBoxLayout * midLayout   = new QHBoxLayout(mainLayout_, 0, 0);
00520 
00521   midLayout->addSpacing(sideMargin);
00522   if( isPreview())
00523     midLayout->addWidget(new QLabel( i18n( "<center><b>Web</b></center>" ), widget()));
00524   else
00525     midLayout->addItem( new QSpacerItem( 0, 0 )); // no widget in the middle
00526   midLayout->addSpacing(sideMargin);
00527 
00528   // -------------------------------------------------------------------
00529 
00530   mainLayout_->addSpacing(bottomMargin);
00531 
00532   // Make sure that topLayout doesn't stretch - midLayout should take
00533   // all spare space.
00534 
00535   mainLayout_->setStretchFactor(topLayout, 0);
00536   mainLayout_->setStretchFactor(midLayout, 1);
00537 }
00538 
00539 void WebClient::borders(int& left, int& right, int& top, int& bottom) const
00540 {
00541     left = borderSize_;
00542     right = borderSize_;
00543     top =  titleHeight_;
00544     bottom = borderSize_;
00545 }
00546 
00547 void WebClient::resize( const QSize& s )
00548 {
00549     widget()->resize( s );
00550 }
00551 
00552 QSize WebClient::minimumSize() const
00553 {
00554     return QSize( 200, 50 );
00555 }
00556 
00557 const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask
00558     | NET::ToolbarMask | NET::MenuMask | NET::DialogMask | NET::OverrideMask | NET::TopMenuMask
00559     | NET::UtilityMask | NET::SplashMask;
00560 
00561 bool WebClient::isTool()
00562 {
00563   NET::WindowType type = windowType( SUPPORTED_WINDOW_TYPES_MASK );
00564   return ((type==NET::Toolbar)||(type==NET::Utility)||(type==NET::Menu));
00565 }
00566 
00567 bool WebClient::eventFilter( QObject* o, QEvent* e )
00568 {
00569     if( o != widget())
00570     return false;
00571     switch( e->type())
00572     {
00573     case QEvent::Resize:
00574         resizeEvent(static_cast< QResizeEvent* >( e ) );
00575         return true;
00576     case QEvent::Paint:
00577         paintEvent(static_cast< QPaintEvent* >( e ) );
00578         return true;
00579     case QEvent::MouseButtonDblClick:
00580         mouseDoubleClickEvent(static_cast< QMouseEvent* >( e ) );
00581         return true;
00582     case QEvent::MouseButtonPress:
00583         processMousePressEvent(static_cast< QMouseEvent* >( e ) );
00584         return true;
00585     default:
00586         break;
00587     }
00588     return false;
00589 }
00590 
00591 
00592 KDecoration* WebFactory::createDecoration( KDecorationBridge* b )
00593 {
00594   return(new WebClient(b, this));
00595 }
00596 
00597 bool WebFactory::reset(unsigned long changed)
00598 {
00599   // Do we need to "hit the wooden hammer" ?
00600   bool needHardReset = true;
00601   if (changed & SettingColors || changed & SettingFont)
00602   {
00603     needHardReset = false;
00604   }
00605 
00606   if (needHardReset) {
00607     return true;
00608   } else {
00609     resetDecorations(changed);
00610     return false;
00611   }
00612 }
00613 
00614 QValueList< WebFactory::BorderSize > WebFactory::borderSizes() const
00615 { // the list must be sorted
00616   return QValueList< BorderSize >() << BorderNormal << BorderLarge <<
00617       BorderVeryLarge <<  BorderHuge << BorderVeryHuge << BorderOversized;
00618 }
00619 
00620 }
00621 
00622 #include "Web.moc"
00623 // vim:ts=2:sw=2:tw=78:set et:
KDE Logo
This file is part of the documentation for kwin Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 29 21:20:54 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003