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 maximize( static_cast<ButtonState>(button) ); 00347 } 00348 00349 WebButton * 00350 WebClient::_createButton(const QString & s, QWidget * parent) 00351 { 00352 WebButton * b = 0; 00353 00354 if (("Help" == s) && providesContextHelp()) 00355 { 00356 b = new WebButtonHelp(parent, this); 00357 connect(b, SIGNAL(help()), this, SLOT(showContextHelp())); 00358 } 00359 00360 else if ("OnAllDesktops" == s) 00361 { 00362 b = new WebButtonSticky(isOnAllDesktops(), parent, this); 00363 connect(b, SIGNAL(toggleSticky()), this, SLOT(toggleOnAllDesktops())); 00364 connect(this, SIGNAL(oadChange(bool)), b, SLOT(slotOnAllDesktopsChange(bool))); 00365 } 00366 00367 else if ("Minimize" == s && isMinimizable()) 00368 { 00369 b = new WebButtonIconify(parent, this); 00370 connect(b, SIGNAL(minimize()), this, SLOT(minimize())); 00371 } 00372 00373 else if ("Maximize" == s && isMaximizable()) 00374 { 00375 b = new WebButtonMaximize((maximizeMode()==MaximizeFull), parent, this); 00376 connect(b, SIGNAL(maximize(int)), this, SLOT(slotMaximize(int))); 00377 connect(this, SIGNAL(maxChange(bool)), b, SLOT(slotMaximizeChange(bool))); 00378 } 00379 00380 else if ("Close" == s && isCloseable()) 00381 { 00382 b = new WebButtonClose(parent, this); 00383 connect(b, SIGNAL(closeWindow()), this, SLOT(closeWindow())); 00384 } 00385 00386 else if ("Lower" == s) 00387 { 00388 b = new WebButtonLower(parent, this); 00389 connect(b, SIGNAL(lowerWindow()), this, SLOT(slotLowerWindow())); 00390 } 00391 00392 if (0 != b) 00393 { 00394 b->setShape(shape_); 00395 } 00396 00397 return b; 00398 } 00399 00400 void 00401 WebClient::_createButtons() 00402 { 00403 leftButtonList_ .clear(); 00404 rightButtonList_ .clear(); 00405 00406 QString buttons = options()->titleButtonsLeft() + "|" + options()->titleButtonsRight(); 00407 QPtrList<WebButton> *buttonList = &leftButtonList_; 00408 for (unsigned int i = 0; i < buttons.length(); ++i) 00409 { 00410 WebButton * tb = 0; 00411 switch (buttons[i].latin1()) 00412 { 00413 case 'S': // OnAllDesktops 00414 tb = _createButton("OnAllDesktops", widget()); 00415 break; 00416 00417 case 'H': // Help 00418 tb = _createButton("Help", widget()); 00419 break; 00420 00421 case 'I': // Minimize 00422 tb = _createButton("Minimize", widget()); 00423 break; 00424 00425 case 'A': // Maximize 00426 tb = _createButton("Maximize", widget()); 00427 break; 00428 00429 case 'X': // Close 00430 tb = _createButton("Close", widget()); 00431 break; 00432 00433 case '|': 00434 buttonList = &rightButtonList_; 00435 break; 00436 } 00437 if (0 != tb) 00438 buttonList->append(tb); 00439 } 00440 00441 if (!leftButtonList_.isEmpty()) 00442 leftButtonList_.first()->setPosition(WebButton::Left); 00443 00444 if (!rightButtonList_.isEmpty()) 00445 rightButtonList_.last()->setPosition(WebButton::Right); 00446 } 00447 00448 void 00449 WebClient::_resetLayout() 00450 { 00451 KConfig c("kwinwebrc"); 00452 c.setGroup("General"); 00453 shape_ = c.readBoolEntry("Shape", true); 00454 00455 // ____________________________________ 00456 // | | | | 00457 // |Xo| titleSpacer |v^| <--- topLayout 00458 // |__|______________________________|__| 00459 // | | | | 00460 // | | | | 00461 // | | fake window | | 00462 // | | | | <--- midLayout 00463 // | | | | 00464 // | | | | 00465 // | |________________________________| | 00466 // |____________________________________| 00467 00468 const uint sideMargin = borderSize_; 00469 const uint bottomMargin = borderSize_; 00470 00471 if (0 != titleHeight_ % 2) 00472 titleHeight_ += 1; 00473 00474 delete mainLayout_; 00475 00476 mainLayout_ = new QVBoxLayout(widget(), 0, 0); 00477 00478 titleSpacer_ = new QSpacerItem ( 0, titleHeight_, QSizePolicy::Expanding, 00479 QSizePolicy::Fixed); 00480 00481 QBoxLayout * topLayout = new QBoxLayout(mainLayout_, QBoxLayout::LeftToRight, 0, 0); 00482 00483 _createButtons(); 00484 00485 // Add left-side buttons. 00486 00487 for (QPtrListIterator<WebButton> it(leftButtonList_); it.current(); ++it) 00488 { 00489 topLayout->addWidget(it.current(), Qt::AlignVCenter); 00490 topLayout->setStretchFactor(it.current(), 0); 00491 it.current()->setFixedSize(titleHeight_, titleHeight_); 00492 } 00493 00494 topLayout->addItem(titleSpacer_); 00495 00496 // Add right-side buttons. 00497 00498 for (QPtrListIterator<WebButton> it(rightButtonList_); it.current(); ++it) 00499 { 00500 topLayout->addWidget(it.current(), Qt::AlignVCenter); 00501 it.current()->setFixedSize(titleHeight_, titleHeight_); 00502 } 00503 00504 // ------------------------------------------------------------------- 00505 00506 QHBoxLayout * midLayout = new QHBoxLayout(mainLayout_, 0, 0); 00507 00508 midLayout->addSpacing(sideMargin); 00509 if( isPreview()) 00510 midLayout->addWidget(new QLabel( i18n( "<center><b>Web</b></center>" ), widget())); 00511 else 00512 midLayout->addItem( new QSpacerItem( 0, 0 )); // no widget in the middle 00513 midLayout->addSpacing(sideMargin); 00514 00515 // ------------------------------------------------------------------- 00516 00517 mainLayout_->addSpacing(bottomMargin); 00518 00519 // Make sure that topLayout doesn't stretch - midLayout should take 00520 // all spare space. 00521 00522 mainLayout_->setStretchFactor(topLayout, 0); 00523 mainLayout_->setStretchFactor(midLayout, 1); 00524 } 00525 00526 void WebClient::borders(int& left, int& right, int& top, int& bottom) const 00527 { 00528 left = borderSize_; 00529 right = borderSize_; 00530 top = titleHeight_; 00531 bottom = borderSize_; 00532 } 00533 00534 void WebClient::resize( const QSize& s ) 00535 { 00536 widget()->resize( s ); 00537 } 00538 00539 QSize WebClient::minimumSize() const 00540 { 00541 return QSize( 200, 50 ); 00542 } 00543 00544 const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask 00545 | NET::ToolbarMask | NET::MenuMask | NET::DialogMask | NET::OverrideMask | NET::TopMenuMask 00546 | NET::UtilityMask | NET::SplashMask; 00547 00548 bool WebClient::isTool() 00549 { 00550 NET::WindowType type = windowType( SUPPORTED_WINDOW_TYPES_MASK ); 00551 return ((type==NET::Toolbar)||(type==NET::Utility)||(type==NET::Menu)); 00552 } 00553 00554 bool WebClient::eventFilter( QObject* o, QEvent* e ) 00555 { 00556 if( o != widget()) 00557 return false; 00558 switch( e->type()) 00559 { 00560 case QEvent::Resize: 00561 resizeEvent(static_cast< QResizeEvent* >( e ) ); 00562 return true; 00563 case QEvent::Paint: 00564 paintEvent(static_cast< QPaintEvent* >( e ) ); 00565 return true; 00566 case QEvent::MouseButtonDblClick: 00567 mouseDoubleClickEvent(static_cast< QMouseEvent* >( e ) ); 00568 return true; 00569 case QEvent::MouseButtonPress: 00570 processMousePressEvent(static_cast< QMouseEvent* >( e ) ); 00571 return true; 00572 default: 00573 break; 00574 } 00575 return false; 00576 } 00577 00578 00579 KDecoration* WebFactory::createDecoration( KDecorationBridge* b ) 00580 { 00581 return(new WebClient(b, this)); 00582 } 00583 00584 bool WebFactory::reset(unsigned long changed) 00585 { 00586 // Do we need to "hit the wooden hammer" ? 00587 bool needHardReset = true; 00588 if (changed & SettingColors || changed & SettingFont) 00589 { 00590 needHardReset = false; 00591 } 00592 00593 if (needHardReset) { 00594 return true; 00595 } else { 00596 resetDecorations(changed); 00597 return false; 00598 } 00599 } 00600 00601 QValueList< WebFactory::BorderSize > WebFactory::borderSizes() const 00602 { // the list must be sorted 00603 return QValueList< BorderSize >() << BorderNormal << BorderLarge << 00604 BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized; 00605 } 00606 00607 } 00608 00609 #include "Web.moc" 00610 // vim:ts=2:sw=2:tw=78:set et:
KDE Logo
This file is part of the documentation for kwin Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 13 21:47:06 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003