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.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Aug 31 00:02:14 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003