kwin Library API Documentation

kdedefault.cpp

00001 /* 00002 * $Id: kdedefault.cpp,v 1.35 2004/01/09 18:20:29 giessl Exp $ 00003 * 00004 * KDE2 Default KWin client 00005 * 00006 * Copyright (C) 1999, 2001 Daniel Duley <mosfet@kde.org> 00007 * Matthias Ettrich <ettrich@kde.org> 00008 * Karol Szwed <gallium@kde.org> 00009 * 00010 * Draws mini titlebars for tool windows. 00011 * Many features are now customizable. 00012 */ 00013 00014 #include "kdedefault.h" 00015 00016 #include <kconfig.h> 00017 #include <kglobal.h> 00018 #include <kpixmapeffect.h> 00019 #include <kimageeffect.h> 00020 #include <kdrawutil.h> 00021 #include <klocale.h> 00022 #include <qlayout.h> 00023 #include <qdrawutil.h> 00024 #include <qbitmap.h> 00025 #include <qimage.h> 00026 #include <qtooltip.h> 00027 #include <qapplication.h> 00028 #include <qlabel.h> 00029 #include <kdebug.h> 00030 00031 namespace Default 00032 { 00033 00034 static const unsigned char iconify_bits[] = { 00035 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 00036 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 00037 00038 static const unsigned char close_bits[] = { 00039 0x00, 0x00, 0x84, 0x00, 0xce, 0x01, 0xfc, 0x00, 0x78, 0x00, 0x78, 0x00, 00040 0xfc, 0x00, 0xce, 0x01, 0x84, 0x00, 0x00, 0x00}; 00041 00042 static const unsigned char maximize_bits[] = { 00043 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 00044 0x86, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00}; 00045 00046 static const unsigned char minmax_bits[] = { 00047 0x7f, 0x00, 0x7f, 0x00, 0x63, 0x00, 0xfb, 0x03, 0xfb, 0x03, 0x1f, 0x03, 00048 0x1f, 0x03, 0x18, 0x03, 0xf8, 0x03, 0xf8, 0x03}; 00049 00050 static const unsigned char question_bits[] = { 00051 0x00, 0x00, 0x78, 0x00, 0xcc, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 00052 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00}; 00053 00054 static const unsigned char pindown_white_bits[] = { 00055 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x1f, 0xa0, 0x03, 00056 0xb0, 0x01, 0x30, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x20, 0x00, 0x00, 0x00, 00057 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 00058 00059 static const unsigned char pindown_gray_bits[] = { 00060 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 00061 0x00, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x80, 0x07, 0xc0, 0x03, 0xe0, 0x01, 00062 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 00063 00064 static const unsigned char pindown_dgray_bits[] = { 00065 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x10, 0x70, 0x20, 0x50, 0x20, 00066 0x48, 0x30, 0xc8, 0x38, 0x08, 0x1f, 0x08, 0x18, 0x10, 0x1c, 0x10, 0x0e, 00067 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 00068 00069 static const unsigned char pindown_mask_bits[] = { 00070 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x1f, 0xf0, 0x3f, 0xf0, 0x3f, 00071 0xf8, 0x3f, 0xf8, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf0, 0x1f, 0xf0, 0x0f, 00072 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 00073 00074 static const unsigned char pinup_white_bits[] = { 00075 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x11, 00076 0x3f, 0x15, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00077 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 00078 00079 static const unsigned char pinup_gray_bits[] = { 00080 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00081 0x80, 0x0a, 0xbf, 0x0a, 0x80, 0x15, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 00082 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 00083 00084 static const unsigned char pinup_dgray_bits[] = { 00085 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x40, 0x31, 0x40, 0x2e, 00086 0x40, 0x20, 0x40, 0x20, 0x7f, 0x2a, 0x40, 0x3f, 0xc0, 0x31, 0xc0, 0x20, 00087 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 00088 00089 static const unsigned char pinup_mask_bits[] = { 00090 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0xc0, 0x31, 0xc0, 0x3f, 00091 0xff, 0x3f, 0xff, 0x3f, 0xff, 0x3f, 0xc0, 0x3f, 0xc0, 0x31, 0xc0, 0x20, 00092 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 00093 00094 // =========================================================================== 00095 00096 static QPixmap* titlePix; 00097 static KPixmap* titleBuffer; 00098 static KPixmap* aUpperGradient; 00099 static KPixmap* iUpperGradient; 00100 00101 static KPixmap* pinDownPix; 00102 static KPixmap* pinUpPix; 00103 static KPixmap* ipinDownPix; 00104 static KPixmap* ipinUpPix; 00105 00106 static KPixmap* rightBtnUpPix[2]; 00107 static KPixmap* rightBtnDownPix[2]; 00108 static KPixmap* irightBtnUpPix[2]; 00109 static KPixmap* irightBtnDownPix[2]; 00110 00111 static KPixmap* leftBtnUpPix[2]; 00112 static KPixmap* leftBtnDownPix[2]; 00113 static KPixmap* ileftBtnUpPix[2]; 00114 static KPixmap* ileftBtnDownPix[2]; 00115 00116 static KDEDefaultHandler* clientHandler; 00117 static int toolTitleHeight; 00118 static int normalTitleHeight; 00119 static int borderWidth; 00120 static int grabBorderWidth; 00121 static bool KDEDefault_initialized = false; 00122 static bool useGradients; 00123 static bool showGrabBar; 00124 static bool showTitleBarStipple; 00125 00126 00127 // =========================================================================== 00128 00129 KDEDefaultHandler::KDEDefaultHandler() 00130 { 00131 clientHandler = this; 00132 readConfig( false ); 00133 createPixmaps(); 00134 KDEDefault_initialized = true; 00135 } 00136 00137 00138 KDEDefaultHandler::~KDEDefaultHandler() 00139 { 00140 KDEDefault_initialized = false; 00141 freePixmaps(); 00142 clientHandler = NULL; 00143 } 00144 00145 KDecoration* KDEDefaultHandler::createDecoration( KDecorationBridge* b ) 00146 { 00147 return new KDEDefaultClient( b, this ); 00148 } 00149 00150 bool KDEDefaultHandler::reset( unsigned long changed ) 00151 { 00152 KDEDefault_initialized = false; 00153 changed |= readConfig( true ); 00154 if( changed & SettingColors ) 00155 { // pixmaps need to be recreated 00156 freePixmaps(); 00157 createPixmaps(); 00158 } 00159 KDEDefault_initialized = true; 00160 bool need_recreate = ( changed & ( SettingDecoration | SettingFont | SettingButtons | SettingBorder )) != 0; 00161 if( need_recreate ) // something else than colors changed 00162 return true; 00163 resetDecorations( changed ); 00164 return false; 00165 } 00166 00167 00168 unsigned long KDEDefaultHandler::readConfig( bool update ) 00169 { 00170 unsigned long changed = 0; 00171 KConfig* conf = KGlobal::config(); 00172 conf->setGroup("KDEDefault"); 00173 00174 bool new_showGrabBar = conf->readBoolEntry("ShowGrabBar", true); 00175 bool new_showTitleBarStipple = conf->readBoolEntry("ShowTitleBarStipple", true); 00176 bool new_useGradients = conf->readBoolEntry("UseGradients", true); 00177 int new_titleHeight = QFontMetrics(options()->font(true)).height(); 00178 int new_toolTitleHeight = QFontMetrics(options()->font(true, true)).height()-2; 00179 00180 int new_borderWidth; 00181 switch(options()->preferredBorderSize(this)) { 00182 case BorderLarge: 00183 new_borderWidth = 8; 00184 break; 00185 case BorderVeryLarge: 00186 new_borderWidth = 12; 00187 break; 00188 case BorderHuge: 00189 new_borderWidth = 18; 00190 break; 00191 case BorderVeryHuge: 00192 new_borderWidth = 27; 00193 break; 00194 case BorderOversized: 00195 new_borderWidth = 40; 00196 break; 00197 case BorderTiny: 00198 case BorderNormal: 00199 default: 00200 new_borderWidth = 4; 00201 } 00202 00203 if (new_titleHeight < 16) new_titleHeight = 16; 00204 if (new_titleHeight < new_borderWidth) new_titleHeight = new_borderWidth; 00205 if (new_toolTitleHeight < 12) new_toolTitleHeight = 12; 00206 if (new_toolTitleHeight < new_borderWidth) new_toolTitleHeight = new_borderWidth; 00207 00208 if( update ) 00209 { 00210 if( new_showGrabBar != showGrabBar 00211 || new_titleHeight != normalTitleHeight 00212 || new_toolTitleHeight != toolTitleHeight 00213 || new_borderWidth != borderWidth ) 00214 changed |= SettingDecoration; // need recreating the decoration 00215 if( new_showTitleBarStipple != showTitleBarStipple 00216 || new_useGradients != useGradients 00217 || new_titleHeight != normalTitleHeight 00218 || new_toolTitleHeight != toolTitleHeight ) 00219 changed |= SettingColors; // just recreate the pixmaps and repaint 00220 } 00221 00222 showGrabBar = new_showGrabBar; 00223 showTitleBarStipple = new_showTitleBarStipple; 00224 useGradients = new_useGradients; 00225 normalTitleHeight = new_titleHeight; 00226 toolTitleHeight = new_toolTitleHeight; 00227 borderWidth = new_borderWidth; 00228 grabBorderWidth = (borderWidth > 15) ? borderWidth + 15 : 2*borderWidth; 00229 return changed; 00230 } 00231 00232 00233 // This paints the button pixmaps upon loading the style. 00234 void KDEDefaultHandler::createPixmaps() 00235 { 00236 bool highcolor = useGradients && (QPixmap::defaultDepth() > 8); 00237 00238 // Make the titlebar stipple optional 00239 if (showTitleBarStipple) 00240 { 00241 QPainter p; 00242 QPainter maskPainter; 00243 int i, x, y; 00244 titlePix = new QPixmap(132, normalTitleHeight+2); 00245 QBitmap mask(132, normalTitleHeight+2); 00246 mask.fill(Qt::color0); 00247 00248 p.begin(titlePix); 00249 maskPainter.begin(&mask); 00250 maskPainter.setPen(Qt::color1); 00251 for(i=0, y=2; i < 9; ++i, y+=4) 00252 for(x=1; x <= 132; x+=3) 00253 { 00254 p.setPen(options()->color(ColorTitleBar, true).light(150)); 00255 p.drawPoint(x, y); 00256 maskPainter.drawPoint(x, y); 00257 p.setPen(options()->color(ColorTitleBar, true).dark(150)); 00258 p.drawPoint(x+1, y+1); 00259 maskPainter.drawPoint(x+1, y+1); 00260 } 00261 maskPainter.end(); 00262 p.end(); 00263 titlePix->setMask(mask); 00264 } else 00265 titlePix = NULL; 00266 00267 QColor activeTitleColor1(options()->color(ColorTitleBar, true)); 00268 QColor activeTitleColor2(options()->color(ColorTitleBlend, true)); 00269 00270 QColor inactiveTitleColor1(options()->color(ColorTitleBar, false)); 00271 QColor inactiveTitleColor2(options()->color(ColorTitleBlend, false)); 00272 00273 // Create titlebar gradient images if required 00274 aUpperGradient = NULL; 00275 iUpperGradient = NULL; 00276 00277 if(highcolor) 00278 { 00279 // Create the titlebar gradients 00280 if (activeTitleColor1 != activeTitleColor2) 00281 { 00282 aUpperGradient = new KPixmap; 00283 aUpperGradient->resize(128, normalTitleHeight+2); 00284 KPixmapEffect::gradient(*aUpperGradient, 00285 activeTitleColor1, 00286 activeTitleColor2, 00287 KPixmapEffect::VerticalGradient); 00288 } 00289 00290 if (inactiveTitleColor1 != inactiveTitleColor2) 00291 { 00292 iUpperGradient = new KPixmap; 00293 iUpperGradient->resize(128, normalTitleHeight+2); 00294 00295 KPixmapEffect::gradient(*iUpperGradient, 00296 inactiveTitleColor1, 00297 inactiveTitleColor2, 00298 KPixmapEffect::VerticalGradient); 00299 } 00300 } 00301 00302 // Set the sticky pin pixmaps; 00303 QColorGroup g; 00304 QPainter p; 00305 00306 // Active pins 00307 g = options()->colorGroup( ColorButtonBg, true ); 00308 pinUpPix = new KPixmap(); 00309 pinUpPix->resize(16, 16); 00310 p.begin( pinUpPix ); 00311 kColorBitmaps( &p, g, 0, 0, 16, 16, true, pinup_white_bits, 00312 pinup_gray_bits, NULL, NULL, pinup_dgray_bits, NULL ); 00313 p.end(); 00314 pinUpPix->setMask( QBitmap(16, 16, pinup_mask_bits, true) ); 00315 00316 pinDownPix = new KPixmap(); 00317 pinDownPix->resize(16, 16); 00318 p.begin( pinDownPix ); 00319 kColorBitmaps( &p, g, 0, 0, 16, 16, true, pindown_white_bits, 00320 pindown_gray_bits, NULL, NULL, pindown_dgray_bits, NULL ); 00321 p.end(); 00322 pinDownPix->setMask( QBitmap(16, 16, pindown_mask_bits, true) ); 00323 00324 // Inactive pins 00325 g = options()->colorGroup( ColorButtonBg, false ); 00326 ipinUpPix = new KPixmap(); 00327 ipinUpPix->resize(16, 16); 00328 p.begin( ipinUpPix ); 00329 kColorBitmaps( &p, g, 0, 0, 16, 16, true, pinup_white_bits, 00330 pinup_gray_bits, NULL, NULL, pinup_dgray_bits, NULL ); 00331 p.end(); 00332 ipinUpPix->setMask( QBitmap(16, 16, pinup_mask_bits, true) ); 00333 00334 ipinDownPix = new KPixmap(); 00335 ipinDownPix->resize(16, 16); 00336 p.begin( ipinDownPix ); 00337 kColorBitmaps( &p, g, 0, 0, 16, 16, true, pindown_white_bits, 00338 pindown_gray_bits, NULL, NULL, pindown_dgray_bits, NULL ); 00339 p.end(); 00340 ipinDownPix->setMask( QBitmap(16, 16, pindown_mask_bits, true) ); 00341 00342 // Create a title buffer for flicker-free painting 00343 titleBuffer = new KPixmap(); 00344 00345 // Cache all possible button states 00346 leftBtnUpPix[true] = new KPixmap(); 00347 leftBtnUpPix[true]->resize(normalTitleHeight, normalTitleHeight); 00348 leftBtnDownPix[true] = new KPixmap(); 00349 leftBtnDownPix[true]->resize(normalTitleHeight, normalTitleHeight); 00350 ileftBtnUpPix[true] = new KPixmap(); 00351 ileftBtnUpPix[true]->resize(normalTitleHeight, normalTitleHeight); 00352 ileftBtnDownPix[true] = new KPixmap(); 00353 ileftBtnDownPix[true]->resize(normalTitleHeight, normalTitleHeight); 00354 00355 rightBtnUpPix[true] = new KPixmap(); 00356 rightBtnUpPix[true]->resize(normalTitleHeight, normalTitleHeight); 00357 rightBtnDownPix[true] = new KPixmap(); 00358 rightBtnDownPix[true]->resize(normalTitleHeight, normalTitleHeight); 00359 irightBtnUpPix[true] = new KPixmap(); 00360 irightBtnUpPix[true]->resize(normalTitleHeight, normalTitleHeight); 00361 irightBtnDownPix[true] = new KPixmap(); 00362 irightBtnDownPix[true]->resize(normalTitleHeight, normalTitleHeight); 00363 00364 leftBtnUpPix[false] = new KPixmap(); 00365 leftBtnUpPix[false]->resize(toolTitleHeight, normalTitleHeight); 00366 leftBtnDownPix[false] = new KPixmap(); 00367 leftBtnDownPix[false]->resize(toolTitleHeight, normalTitleHeight); 00368 ileftBtnUpPix[false] = new KPixmap(); 00369 ileftBtnUpPix[false]->resize(normalTitleHeight, normalTitleHeight); 00370 ileftBtnDownPix[false] = new KPixmap(); 00371 ileftBtnDownPix[false]->resize(normalTitleHeight, normalTitleHeight); 00372 00373 rightBtnUpPix[false] = new KPixmap(); 00374 rightBtnUpPix[false]->resize(toolTitleHeight, toolTitleHeight); 00375 rightBtnDownPix[false] = new KPixmap(); 00376 rightBtnDownPix[false]->resize(toolTitleHeight, toolTitleHeight); 00377 irightBtnUpPix[false] = new KPixmap(); 00378 irightBtnUpPix[false]->resize(toolTitleHeight, toolTitleHeight); 00379 irightBtnDownPix[false] = new KPixmap(); 00380 irightBtnDownPix[false]->resize(toolTitleHeight, toolTitleHeight); 00381 00382 // Draw the button state pixmaps 00383 g = options()->colorGroup( ColorTitleBar, true ); 00384 drawButtonBackground( leftBtnUpPix[true], g, false ); 00385 drawButtonBackground( leftBtnDownPix[true], g, true ); 00386 drawButtonBackground( leftBtnUpPix[false], g, false ); 00387 drawButtonBackground( leftBtnDownPix[false], g, true ); 00388 00389 g = options()->colorGroup( ColorButtonBg, true ); 00390 drawButtonBackground( rightBtnUpPix[true], g, false ); 00391 drawButtonBackground( rightBtnDownPix[true], g, true ); 00392 drawButtonBackground( rightBtnUpPix[false], g, false ); 00393 drawButtonBackground( rightBtnDownPix[false], g, true ); 00394 00395 g = options()->colorGroup( ColorTitleBar, false ); 00396 drawButtonBackground( ileftBtnUpPix[true], g, false ); 00397 drawButtonBackground( ileftBtnDownPix[true], g, true ); 00398 drawButtonBackground( ileftBtnUpPix[false], g, false ); 00399 drawButtonBackground( ileftBtnDownPix[false], g, true ); 00400 00401 g = options()->colorGroup( ColorButtonBg, false ); 00402 drawButtonBackground( irightBtnUpPix[true], g, false ); 00403 drawButtonBackground( irightBtnDownPix[true], g, true ); 00404 drawButtonBackground( irightBtnUpPix[false], g, false ); 00405 drawButtonBackground( irightBtnDownPix[false], g, true ); 00406 } 00407 00408 00409 void KDEDefaultHandler::freePixmaps() 00410 { 00411 // Free button pixmaps 00412 if (rightBtnUpPix[true]) 00413 delete rightBtnUpPix[true]; 00414 if(rightBtnDownPix[true]) 00415 delete rightBtnDownPix[true]; 00416 if (irightBtnUpPix[true]) 00417 delete irightBtnUpPix[true]; 00418 if (irightBtnDownPix[true]) 00419 delete irightBtnDownPix[true]; 00420 00421 if (leftBtnUpPix[true]) 00422 delete leftBtnUpPix[true]; 00423 if(leftBtnDownPix[true]) 00424 delete leftBtnDownPix[true]; 00425 if (ileftBtnUpPix[true]) 00426 delete ileftBtnUpPix[true]; 00427 if (ileftBtnDownPix[true]) 00428 delete ileftBtnDownPix[true]; 00429 00430 if (rightBtnUpPix[false]) 00431 delete rightBtnUpPix[false]; 00432 if(rightBtnDownPix[false]) 00433 delete rightBtnDownPix[false]; 00434 if (irightBtnUpPix[false]) 00435 delete irightBtnUpPix[false]; 00436 if (irightBtnDownPix[false]) 00437 delete irightBtnDownPix[false]; 00438 00439 if (leftBtnUpPix[false]) 00440 delete leftBtnUpPix[false]; 00441 if(leftBtnDownPix[false]) 00442 delete leftBtnDownPix[false]; 00443 if (ileftBtnUpPix[false]) 00444 delete ileftBtnUpPix[false]; 00445 if (ileftBtnDownPix[false]) 00446 delete ileftBtnDownPix[false]; 00447 00448 // Title images 00449 if (titleBuffer) 00450 delete titleBuffer; 00451 if (titlePix) 00452 delete titlePix; 00453 if (aUpperGradient) 00454 delete aUpperGradient; 00455 if (iUpperGradient) 00456 delete iUpperGradient; 00457 00458 // Sticky pin images 00459 if (pinUpPix) 00460 delete pinUpPix; 00461 if (ipinUpPix) 00462 delete ipinUpPix; 00463 if (pinDownPix) 00464 delete pinDownPix; 00465 if (ipinDownPix) 00466 delete ipinDownPix; 00467 } 00468 00469 00470 void KDEDefaultHandler::drawButtonBackground(KPixmap *pix, 00471 const QColorGroup &g, bool sunken) 00472 { 00473 QPainter p; 00474 int w = pix->width(); 00475 int h = pix->height(); 00476 int x2 = w-1; 00477 int y2 = h-1; 00478 00479 bool highcolor = useGradients && (QPixmap::defaultDepth() > 8); 00480 QColor c = g.background(); 00481 00482 // Fill the background with a gradient if possible 00483 if (highcolor) 00484 KPixmapEffect::gradient(*pix, c.light(130), c.dark(130), 00485 KPixmapEffect::VerticalGradient); 00486 else 00487 pix->fill(c); 00488 00489 p.begin(pix); 00490 // outer frame 00491 p.setPen(g.mid()); 00492 p.drawLine(0, 0, x2, 0); 00493 p.drawLine(0, 0, 0, y2); 00494 p.setPen(g.light()); 00495 p.drawLine(x2, 0, x2, y2); 00496 p.drawLine(0, x2, y2, x2); 00497 p.setPen(g.dark()); 00498 p.drawRect(1, 1, w-2, h-2); 00499 p.setPen(sunken ? g.mid() : g.light()); 00500 p.drawLine(2, 2, x2-2, 2); 00501 p.drawLine(2, 2, 2, y2-2); 00502 p.setPen(sunken ? g.light() : g.mid()); 00503 p.drawLine(x2-2, 2, x2-2, y2-2); 00504 p.drawLine(2, x2-2, y2-2, x2-2); 00505 } 00506 00507 QValueList< KDEDefaultHandler::BorderSize > KDEDefaultHandler::borderSizes() const 00508 { // the list must be sorted 00509 return QValueList< BorderSize >() << BorderNormal << BorderLarge << 00510 BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized; 00511 } 00512 00513 00514 // =========================================================================== 00515 00516 KDEDefaultButton::KDEDefaultButton(KDEDefaultClient *parent, const char *name, 00517 bool largeButton, bool isLeftButton, bool isStickyButton, 00518 const unsigned char *bitmap, const QString& tip, const int realizeBtns ) 00519 : QButton(parent->widget(), name) 00520 { 00521 realizeButtons = realizeBtns; 00522 00523 QToolTip::add( this, tip ); 00524 setCursor( arrowCursor ); 00525 setBackgroundMode( QWidget::NoBackground ); 00526 setToggleButton( isStickyButton ); 00527 00528 isMouseOver = false; 00529 deco = NULL; 00530 large = largeButton; 00531 isLeft = isLeftButton; 00532 isSticky = isStickyButton; 00533 client = parent; 00534 00535 if (large) 00536 setFixedSize(normalTitleHeight, normalTitleHeight); 00537 else 00538 setFixedSize(toolTitleHeight, toolTitleHeight); 00539 00540 if (bitmap) 00541 setBitmap(bitmap); 00542 } 00543 00544 00545 KDEDefaultButton::~KDEDefaultButton() 00546 { 00547 if (deco) 00548 delete deco; 00549 } 00550 00551 00552 QSize KDEDefaultButton::sizeHint() const 00553 { 00554 if ( large ) 00555 return( QSize(normalTitleHeight, normalTitleHeight) ); 00556 else 00557 return( QSize(toolTitleHeight, toolTitleHeight) ); 00558 } 00559 00560 00561 void KDEDefaultButton::setBitmap(const unsigned char *bitmap) 00562 { 00563 if (deco) 00564 delete deco; 00565 00566 deco = new QBitmap(10, 10, bitmap, true); 00567 deco->setMask( *deco ); 00568 repaint( false ); 00569 } 00570 00571 00572 void KDEDefaultButton::drawButton(QPainter *p) 00573 { 00574 if (!KDEDefault_initialized) 00575 return; 00576 00577 if (deco) { 00578 // Fill the button background with an appropriate button image 00579 KPixmap btnbg; 00580 00581 if (isLeft) { 00582 if (isDown()) 00583 btnbg = client->isActive() ? 00584 *leftBtnDownPix[large] : *ileftBtnDownPix[large]; 00585 else 00586 btnbg = client->isActive() ? 00587 *leftBtnUpPix[large] : *ileftBtnUpPix[large]; 00588 } else { 00589 if (isDown()) 00590 btnbg = client->isActive() ? 00591 *rightBtnDownPix[large] : *irightBtnDownPix[large]; 00592 else 00593 btnbg = client->isActive() ? 00594 *rightBtnUpPix[large] : *irightBtnUpPix[large]; 00595 } 00596 00597 p->drawPixmap( 0, 0, btnbg ); 00598 00599 } else if ( isLeft ) { 00600 00601 // Fill the button background with an appropriate color/gradient 00602 // This is for sticky and menu buttons 00603 KPixmap* grad = client->isActive() ? aUpperGradient : iUpperGradient; 00604 if (!grad) { 00605 QColor c = KDecoration::options()->color(ColorTitleBar, client->isActive()); 00606 p->fillRect(0, 0, width(), height(), c ); 00607 } else 00608 p->drawPixmap( 0, 0, *grad, 0,1, width(), height() ); 00609 00610 } else { 00611 // Draw a plain background for menus or sticky buttons on RHS 00612 QColor c = KDecoration::options()->color(ColorFrame, client->isActive()); 00613 p->fillRect(0, 0, width(), height(), c); 00614 } 00615 00616 00617 // If we have a decoration bitmap, then draw that 00618 // otherwise we paint a menu button (with mini icon), or a sticky button. 00619 if( deco ) { 00620 // Select the appropriate button decoration color 00621 bool darkDeco = qGray( KDecoration::options()->color( 00622 isLeft? ColorTitleBar : ColorButtonBg, 00623 client->isActive()).rgb() ) > 127; 00624 00625 if (isMouseOver) 00626 p->setPen( darkDeco ? Qt::darkGray : Qt::lightGray ); 00627 else 00628 p->setPen( darkDeco ? Qt::black : Qt::white ); 00629 00630 int xOff = (width()-10)/2; 00631 int yOff = (height()-10)/2; 00632 p->drawPixmap(isDown() ? xOff+1: xOff, isDown() ? yOff+1 : yOff, *deco); 00633 00634 } else { 00635 KPixmap btnpix; 00636 00637 if (isSticky) { 00638 if (client->isActive()) 00639 btnpix = isOn() ? *pinDownPix : *pinUpPix; 00640 else 00641 btnpix = isOn() ? *ipinDownPix : *ipinUpPix; 00642 } else 00643 btnpix = client->icon().pixmap( QIconSet::Small, QIconSet::Normal ); 00644 00645 // Intensify the image if required 00646 if (isMouseOver) { 00647 btnpix = KPixmapEffect::intensity(btnpix, 0.8); 00648 } 00649 00650 // Smooth scale the pixmap for small titlebars 00651 // This is slow, but we assume this isn't done too often 00652 if ( width() < 16 ) { 00653 btnpix.convertFromImage(btnpix.convertToImage().smoothScale(12, 12)); 00654 p->drawPixmap( 0, 0, btnpix ); 00655 } 00656 else 00657 p->drawPixmap( width()/2-8, height()/2-8, btnpix ); 00658 } 00659 } 00660 00661 00662 // Make the protected member public 00663 void KDEDefaultButton::turnOn( bool isOn ) 00664 { 00665 if ( isToggleButton() ) 00666 setOn( isOn ); 00667 } 00668 00669 00670 void KDEDefaultButton::enterEvent(QEvent *e) 00671 { 00672 isMouseOver=true; 00673 repaint(false); 00674 QButton::enterEvent(e); 00675 } 00676 00677 00678 void KDEDefaultButton::leaveEvent(QEvent *e) 00679 { 00680 isMouseOver=false; 00681 repaint(false); 00682 QButton::leaveEvent(e); 00683 } 00684 00685 00686 void KDEDefaultButton::mousePressEvent( QMouseEvent* e ) 00687 { 00688 last_button = e->button(); 00689 QMouseEvent me( e->type(), e->pos(), e->globalPos(), 00690 (e->button()&realizeButtons)?LeftButton:NoButton, e->state() ); 00691 QButton::mousePressEvent( &me ); 00692 } 00693 00694 00695 void KDEDefaultButton::mouseReleaseEvent( QMouseEvent* e ) 00696 { 00697 last_button = e->button(); 00698 QMouseEvent me( e->type(), e->pos(), e->globalPos(), 00699 (e->button()&realizeButtons)?LeftButton:NoButton, e->state() ); 00700 QButton::mouseReleaseEvent( &me ); 00701 } 00702 00703 00704 // =========================================================================== 00705 00706 KDEDefaultClient::KDEDefaultClient( KDecorationBridge* b, KDecorationFactory* f ) 00707 : KDecoration( b, f ), 00708 m_closing(false) 00709 { 00710 } 00711 00712 void KDEDefaultClient::init() 00713 { 00714 createMainWidget( WResizeNoErase | WStaticContents | WRepaintNoErase ); 00715 widget()->installEventFilter( this ); 00716 00717 // No flicker thanks 00718 widget()->setBackgroundMode( QWidget::NoBackground ); 00719 00720 // Set button pointers to NULL so we can track things 00721 for(int i=0; i < KDEDefaultClient::BtnCount; i++) 00722 button[i] = NULL; 00723 00724 // Finally, toolWindows look small 00725 if ( isTool() ) { 00726 titleHeight = toolTitleHeight; 00727 largeButtons = false; 00728 } 00729 else { 00730 titleHeight = normalTitleHeight; 00731 largeButtons = true; 00732 } 00733 00734 // Pack the windowWrapper() window within a grid 00735 g = new QGridLayout(widget(), 0, 0, 0); 00736 g->setResizeMode(QLayout::FreeResize); 00737 g->addRowSpacing(0, 3); // Top grab bar 00738 g->addRowSpacing(2, 1); // line under titlebar 00739 if( isPreview()) 00740 g->addWidget( new QLabel( i18n( "<b><center>KDE2 preview</center></b>" ), widget()), 3, 1); 00741 else 00742 g->addItem( new QSpacerItem( 0, 0 ), 3, 1); // no widget in the middle 00743 00744 // without the next line, unshade flickers 00745 g->addItem( new QSpacerItem( 0, 0, QSizePolicy::Fixed, 00746 QSizePolicy::Expanding ) ); 00747 g->setRowStretch(3, 10); // Wrapped window 00748 00749 // Determine the size of the lower grab bar 00750 spacer = new QSpacerItem(10, 00751 showGrabBar && isResizable() ? grabBorderWidth : borderWidth, 00752 QSizePolicy::Expanding, QSizePolicy::Minimum); 00753 g->addItem(spacer, 4, 1); 00754 00755 g->addColSpacing(0, borderWidth); 00756 g->addColSpacing(2, borderWidth); 00757 00758 // Pack the titlebar HBox with items 00759 hb = new QBoxLayout(0, QBoxLayout::LeftToRight, 0, 0, 0 ); 00760 hb->setResizeMode( QLayout::FreeResize ); 00761 g->addLayout ( hb, 1, 1 ); 00762 00763 addClientButtons( options()->titleButtonsLeft() ); 00764 titlebar = new QSpacerItem( 10, titleHeight, QSizePolicy::Expanding, 00765 QSizePolicy::Minimum ); 00766 hb->addItem(titlebar); 00767 hb->addSpacing(2); 00768 addClientButtons( options()->titleButtonsRight(), false ); 00769 } 00770 00771 00772 void KDEDefaultClient::addClientButtons( const QString& s, bool isLeft ) 00773 { 00774 if (s.length() > 0) 00775 for(unsigned int i = 0; i < s.length(); i++) { 00776 switch( s[i].latin1() ) 00777 { 00778 // Menu button 00779 case 'M': 00780 if (!button[BtnMenu]) 00781 { 00782 button[BtnMenu] = new KDEDefaultButton(this, "menu", 00783 largeButtons, isLeft, false, NULL, i18n("Menu"), LeftButton|RightButton); 00784 connect( button[BtnMenu], SIGNAL(pressed()), 00785 this, SLOT(menuButtonPressed()) ); 00786 connect( button[BtnMenu], SIGNAL(released()), 00787 this, SLOT(menuButtonReleased())); 00788 hb->addWidget( button[BtnMenu] ); 00789 } 00790 break; 00791 00792 // Sticky button 00793 case 'S': 00794 if (!button[BtnSticky]) 00795 { 00796 button[BtnSticky] = new KDEDefaultButton(this, "sticky", 00797 largeButtons, isLeft, true, NULL, isOnAllDesktops()?i18n("Un-Sticky"):i18n("Sticky")); 00798 button[BtnSticky]->turnOn( isOnAllDesktops() ); 00799 connect( button[BtnSticky], SIGNAL(clicked()), 00800 this, SLOT(toggleOnAllDesktops()) ); 00801 hb->addWidget( button[BtnSticky] ); 00802 } 00803 break; 00804 00805 // Help button 00806 case 'H': 00807 if( providesContextHelp() && (!button[BtnHelp]) ) 00808 { 00809 button[BtnHelp] = new KDEDefaultButton(this, "help", 00810 largeButtons, isLeft, true, question_bits, 00811 i18n("Help")); 00812 connect( button[BtnHelp], SIGNAL( clicked() ), 00813 this, SLOT( showContextHelp() )); 00814 hb->addWidget( button[BtnHelp] ); 00815 } 00816 break; 00817 00818 // Minimize button 00819 case 'I': 00820 if ( (!button[BtnIconify]) && isMinimizable()) 00821 { 00822 button[BtnIconify] = new KDEDefaultButton(this, "iconify", 00823 largeButtons, isLeft, true, iconify_bits, 00824 i18n("Minimize")); 00825 connect( button[BtnIconify], SIGNAL( clicked()), 00826 this, SLOT(minimize()) ); 00827 hb->addWidget( button[BtnIconify] ); 00828 } 00829 break; 00830 00831 // Maximize button 00832 case 'A': 00833 if ( (!button[BtnMax]) && isMaximizable()) 00834 { 00835 button[BtnMax] = new KDEDefaultButton(this, "maximize", 00836 largeButtons, isLeft, true, maximize_bits, 00837 i18n("Maximize"), LeftButton|MidButton|RightButton); 00838 connect( button[BtnMax], SIGNAL( clicked()), 00839 this, SLOT(slotMaximize()) ); 00840 hb->addWidget( button[BtnMax] ); 00841 } 00842 break; 00843 00844 // Close button 00845 case 'X': 00846 if (!button[BtnClose] && isCloseable()) 00847 { 00848 button[BtnClose] = new KDEDefaultButton(this, "close", 00849 largeButtons, isLeft, true, close_bits, 00850 i18n("Close")); 00851 connect( button[BtnClose], SIGNAL( clicked()), 00852 this, SLOT(closeWindow()) ); 00853 hb->addWidget( button[BtnClose] ); 00854 } 00855 break; 00856 00857 // Spacer item (only for non-tool windows) 00858 case '_': 00859 if ( !isTool() ) 00860 hb->addSpacing(borderWidth/2); 00861 } 00862 } 00863 } 00864 00865 void KDEDefaultClient::reset( unsigned long ) 00866 { 00867 widget()->repaint(); 00868 } 00869 00870 void KDEDefaultClient::iconChange() 00871 { 00872 if (button[BtnMenu] && button[BtnMenu]->isVisible()) 00873 button[BtnMenu]->repaint(false); 00874 } 00875 00876 void KDEDefaultClient::desktopChange() 00877 { 00878 if (button[BtnSticky]) { 00879 bool on = isOnAllDesktops(); 00880 button[BtnSticky]->turnOn(on); 00881 button[BtnSticky]->repaint(false); 00882 QToolTip::remove( button[BtnSticky] ); 00883 QToolTip::add( button[BtnSticky], on ? i18n("Un-Sticky") : i18n("Sticky")); 00884 } 00885 } 00886 00887 void KDEDefaultClient::slotMaximize() 00888 { 00889 if ( button[BtnMax]->last_button == MidButton ) 00890 maximize( maximizeMode() ^ MaximizeVertical ); 00891 else if ( button[BtnMax]->last_button == RightButton ) 00892 maximize( maximizeMode() ^ MaximizeHorizontal ); 00893 else 00894 maximize( maximizeMode() == MaximizeFull ? MaximizeRestore : MaximizeFull ); 00895 } 00896 00897 00898 void KDEDefaultClient::resizeEvent( QResizeEvent* e) 00899 { 00900 doShape(); 00901 calcHiddenButtons(); 00902 00903 if ( widget()->isShown()) 00904 { 00905 widget()->update( widget()->rect()); 00906 #if 1 // what's the point of this, when paintEvent() repaints everything anyway? 00907 int dx = 0; 00908 int dy = 0; 00909 00910 if ( e->oldSize().width() != width() ) 00911 dx = 32 + QABS( e->oldSize().width() - width() ); 00912 00913 if ( e->oldSize().height() != height() ) 00914 dy = 8 + QABS( e->oldSize().height() - height() ); 00915 00916 if ( dy ) 00917 widget()->update( 0, height() - dy + 1, width(), dy ); 00918 00919 if ( dx ) 00920 { 00921 widget()->update( width() - dx + 1, 0, dx, height() ); 00922 widget()->update( QRect( QPoint(4,4), titlebar->geometry().bottomLeft() - 00923 QPoint(1,0) ) ); 00924 widget()->update( QRect( titlebar->geometry().topRight(), QPoint(width() - 4, 00925 titlebar->geometry().bottom()) ) ); 00926 // Titlebar needs no paint event 00927 QApplication::postEvent( widget(), new QPaintEvent(titlebar->geometry(), 00928 FALSE) ); 00929 } 00930 #endif 00931 } 00932 } 00933 00934 00935 void KDEDefaultClient::captionChange() 00936 { 00937 widget()->repaint( titlebar->geometry(), false ); 00938 } 00939 00940 00941 void KDEDefaultClient::paintEvent( QPaintEvent* ) 00942 { 00943 if (!KDEDefault_initialized) 00944 return; 00945 00946 QColorGroup g; 00947 int offset; 00948 00949 KPixmap* upperGradient = isActive() ? aUpperGradient : iUpperGradient; 00950 00951 QPainter p(widget()); 00952 00953 // Obtain widget bounds. 00954 QRect r(widget()->rect()); 00955 int x = r.x(); 00956 int y = r.y(); 00957 int x2 = r.width() - 1; 00958 int y2 = r.height() - 1; 00959 int w = r.width(); 00960 int h = r.height(); 00961 00962 // Determine where to place the extended left titlebar 00963 int leftFrameStart = (h > 42) ? y+titleHeight+26: y+titleHeight; 00964 00965 // Determine where to make the titlebar color transition 00966 r = titlebar->geometry(); 00967 int rightOffset = r.x()+r.width()+1; 00968 00969 // Create a disposable pixmap buffer for the titlebar 00970 // very early before drawing begins so there is no lag 00971 // during painting pixels. 00972 titleBuffer->resize( rightOffset-3, titleHeight+1 ); 00973 00974 // Draw an outer black frame 00975 p.setPen(Qt::black); 00976 p.drawRect(x,y,w,h); 00977 00978 // Draw part of the frame that is the titlebar color 00979 g = options()->colorGroup(ColorTitleBar, isActive()); 00980 p.setPen(g.light()); 00981 p.drawLine(x+1, y+1, rightOffset-1, y+1); 00982 p.drawLine(x+1, y+1, x+1, leftFrameStart+borderWidth-4); 00983 00984 // Draw titlebar colour separator line 00985 p.setPen(g.dark()); 00986 p.drawLine(rightOffset-1, y+1, rightOffset-1, titleHeight+2); 00987 00988 p.fillRect(x+2, y+titleHeight+3, 00989 borderWidth-4, leftFrameStart+borderWidth-y-titleHeight-8, 00990 options()->color(ColorTitleBar, isActive() )); 00991 00992 // Finish drawing the titlebar extension 00993 p.setPen(Qt::black); 00994 p.drawLine(x+1, leftFrameStart+borderWidth-4, x+borderWidth-2, leftFrameStart-1); 00995 p.setPen(g.mid()); 00996 p.drawLine(x+borderWidth-2, y+titleHeight+3, x+borderWidth-2, leftFrameStart-2); 00997 00998 // Fill out the border edges 00999 g = options()->colorGroup(ColorFrame, isActive()); 01000 p.setPen(g.light()); 01001 p.drawLine(rightOffset, y+1, x2-1, y+1); 01002 p.drawLine(x+1, leftFrameStart+borderWidth-3, x+1, y2-1); 01003 p.setPen(g.dark()); 01004 p.drawLine(x2-1, y+1, x2-1, y2-1); 01005 p.drawLine(x+1, y2-1, x2-1, y2-1); 01006 01007 p.setPen(options()->color(ColorFrame, isActive())); 01008 QPointArray a; 01009 QBrush brush( options()->color(ColorFrame, isActive()), Qt::SolidPattern ); 01010 p.setBrush( brush ); // use solid, yellow brush 01011 a.setPoints( 4, x+2, leftFrameStart+borderWidth-4, 01012 x+borderWidth-2, leftFrameStart, 01013 x+borderWidth-2, y2-2, 01014 x+2, y2-2); 01015 p.drawPolygon( a ); 01016 p.fillRect(x2-borderWidth+2, y+titleHeight+3, 01017 borderWidth-3, y2-y-titleHeight-4, 01018 options()->color(ColorFrame, isActive() )); 01019 01020 // Draw the bottom handle if required 01021 if (showGrabBar && isResizable()) 01022 { 01023 if(w > 50) 01024 { 01025 qDrawShadePanel(&p, x+1, y2-grabBorderWidth+2, 2*borderWidth+12, grabBorderWidth-2, 01026 g, false, 1, &g.brush(QColorGroup::Mid)); 01027 qDrawShadePanel(&p, x+2*borderWidth+13, y2-grabBorderWidth+2, w-4*borderWidth-26, grabBorderWidth-2, 01028 g, false, 1, isActive() ? 01029 &g.brush(QColorGroup::Background) : 01030 &g.brush(QColorGroup::Mid)); 01031 qDrawShadePanel(&p, x2-2*borderWidth-12, y2-grabBorderWidth+2, 2*borderWidth+12, grabBorderWidth-2, 01032 g, false, 1, &g.brush(QColorGroup::Mid)); 01033 } else 01034 qDrawShadePanel(&p, x+1, y2-grabBorderWidth+2, w-2, grabBorderWidth-2, 01035 g, false, 1, isActive() ? 01036 &g.brush(QColorGroup::Background) : 01037 &g.brush(QColorGroup::Mid)); 01038 offset = grabBorderWidth; 01039 } else 01040 { 01041 p.fillRect(x+2, y2-borderWidth+2, w-4, borderWidth-3, 01042 options()->color(ColorFrame, isActive() )); 01043 offset = borderWidth; 01044 } 01045 01046 // Draw a frame around the wrapped widget. 01047 p.setPen( g.dark() ); 01048 p.drawRect( x+borderWidth-1, y+titleHeight+3, w-2*borderWidth+2, h-titleHeight-offset-2 ); 01049 01050 // Draw the title bar. 01051 r = titlebar->geometry(); 01052 01053 // Obtain titlebar blend colours 01054 QColor c1 = options()->color(ColorTitleBar, isActive() ); 01055 QColor c2 = options()->color(ColorFrame, isActive() ); 01056 01057 // Fill with frame color behind RHS buttons 01058 p.fillRect( rightOffset, y+2, x2-rightOffset-1, titleHeight+1, c2); 01059 01060 QPainter p2( titleBuffer, this ); 01061 01062 // Draw the titlebar gradient 01063 if (upperGradient) 01064 p2.drawTiledPixmap(0, 0, rightOffset-3, titleHeight+1, *upperGradient); 01065 else 01066 p2.fillRect(0, 0, rightOffset-3, titleHeight+1, c1); 01067 01068 // Draw the title text on the pixmap, and with a smaller font 01069 // for toolwindows than the default. 01070 QFont fnt = options()->font(true); 01071 01072 if ( isTool() ) 01073 fnt.setPointSize( fnt.pointSize()-2 ); // Shrink font by 2pt 01074 01075 p2.setFont( fnt ); 01076 01077 // Draw the titlebar stipple if active and available 01078 if (isActive() && titlePix) 01079 { 01080 QFontMetrics fm(fnt); 01081 int captionWidth = fm.width(caption()); 01082 if (caption().isRightToLeft()) 01083 p2.drawTiledPixmap( r.x(), 0, r.width()-captionWidth-4, 01084 titleHeight+1, *titlePix ); 01085 else 01086 p2.drawTiledPixmap( r.x()+captionWidth+3, 0, r.width()-captionWidth-4, 01087 titleHeight+1, *titlePix ); 01088 } 01089 01090 p2.setPen( options()->color(ColorFont, isActive()) ); 01091 p2.drawText(r.x(), 1, r.width()-1, r.height(), 01092 (caption().isRightToLeft() ? AlignRight : AlignLeft) | AlignVCenter, 01093 caption() ); 01094 01095 bitBlt( widget(), 2, 2, titleBuffer ); 01096 01097 p2.end(); 01098 01099 // Ensure a shaded window has no unpainted areas 01100 // Is this still needed? 01101 #if 1 01102 p.setPen(c2); 01103 p.drawLine(x+borderWidth, y+titleHeight+4, x2-borderWidth, y+titleHeight+4); 01104 #endif 01105 } 01106 01107 01108 void KDEDefaultClient::doShape() 01109 { 01110 QRegion mask(QRect(0, 0, width(), height())); 01111 mask -= QRect(0, 0, 1, 1); 01112 mask -= QRect(width()-1, 0, 1, 1); 01113 mask -= QRect(0, height()-1, 1, 1); 01114 mask -= QRect(width()-1, height()-1, 1, 1); 01115 setMask(mask); 01116 } 01117 01118 01119 void KDEDefaultClient::showEvent(QShowEvent *) 01120 { 01121 calcHiddenButtons(); 01122 doShape(); 01123 } 01124 01125 01126 void KDEDefaultClient::mouseDoubleClickEvent( QMouseEvent * e ) 01127 { 01128 if (titlebar->geometry().contains( e->pos() ) ) 01129 titlebarDblClickOperation(); 01130 } 01131 01132 01133 void KDEDefaultClient::maximizeChange() 01134 { 01135 if (button[BtnMax]) { 01136 bool m = maximizeMode() == MaximizeFull; 01137 button[BtnMax]->setBitmap(m ? minmax_bits : maximize_bits); 01138 QToolTip::remove( button[ BtnMax ] ); 01139 QToolTip::add( button[BtnMax], m ? i18n("Restore") : i18n("Maximize")); 01140 } 01141 spacer->changeSize(10, showGrabBar && isResizable() ? 8 : 4, 01142 QSizePolicy::Expanding, QSizePolicy::Minimum); 01143 g->activate(); 01144 } 01145 01146 01147 void KDEDefaultClient::activeChange() 01148 { 01149 for(int i=KDEDefaultClient::BtnHelp; i < KDEDefaultClient::BtnCount; i++) 01150 if(button[i]) 01151 button[i]->repaint(false); 01152 widget()->repaint(false); 01153 } 01154 01155 void KDEDefaultClient::shadeChange() 01156 { 01157 } 01158 01159 QSize KDEDefaultClient::minimumSize() const 01160 { 01161 return QSize( 100, 50 ); // FRAME 01162 } 01163 01164 void KDEDefaultClient::resize( const QSize& s ) 01165 { 01166 widget()->resize( s ); 01167 } 01168 01169 void KDEDefaultClient::borders( int& left, int& right, int& top, int& bottom ) const 01170 { // FRAME 01171 left = right = borderWidth; 01172 // , y+titleHeight+3, w-6, h-titleHeight-offset-6 ); 01173 top = titleHeight + 4; 01174 bottom = (showGrabBar && isResizable()) ? grabBorderWidth : borderWidth; 01175 } 01176 01177 // The hiding button while shrinking, show button while expanding magic 01178 void KDEDefaultClient::calcHiddenButtons() 01179 { 01180 // Hide buttons in this order: 01181 // Sticky, Help, Maximize, Minimize, Close, Menu. 01182 KDEDefaultButton* btnArray[] = { button[BtnSticky], button[BtnHelp], 01183 button[BtnMax], button[BtnIconify], button[BtnClose], 01184 button[BtnMenu] }; 01185 01186 int minwidth = largeButtons ? 10 * normalTitleHeight : 10 * toolTitleHeight; // Start hiding at this width 01187 int btn_width = largeButtons ? normalTitleHeight : toolTitleHeight; 01188 int current_width = width(); 01189 int count = 0; 01190 int i; 01191 01192 // Find out how many buttons we need to hide. 01193 while (current_width < minwidth) 01194 { 01195 current_width += btn_width; 01196 count++; 01197 } 01198 01199 // Bound the number of buttons to hide 01200 if (count > 6) count = 6; 01201 01202 // Hide the required buttons... 01203 for(i = 0; i < count; i++) 01204 { 01205 if (btnArray[i] && btnArray[i]->isVisible() ) 01206 btnArray[i]->hide(); 01207 } 01208 01209 // Show the rest of the buttons... 01210 for(i = count; i < 6; i++) 01211 { 01212 if (btnArray[i] && (!btnArray[i]->isVisible()) ) 01213 btnArray[i]->show(); 01214 } 01215 } 01216 01217 01218 KDecoration::Position KDEDefaultClient::mousePosition( const QPoint& p ) const 01219 { 01220 Position m = PositionCenter; 01221 01222 int bottomSize = (showGrabBar && isResizable()) ? grabBorderWidth : borderWidth; 01223 01224 const int range = 14 + 3*borderWidth/2; 01225 01226 if ( ( p.x() > borderWidth && p.x() < width() - borderWidth ) 01227 && ( p.y() > 4 && p.y() < height() - bottomSize ) ) 01228 m = PositionCenter; 01229 else if ( p.y() <= range && p.x() <= range) 01230 m = PositionTopLeft; 01231 else if ( p.y() >= height()-range && p.x() >= width()-range) 01232 m = PositionBottomRight; 01233 else if ( p.y() >= height()-range && p.x() <= range) 01234 m = PositionBottomLeft; 01235 else if ( p.y() <= range && p.x() >= width()-range) 01236 m = PositionTopRight; 01237 else if ( p.y() <= 4 ) 01238 m = PositionTop; 01239 else if ( p.y() >= height()-bottomSize ) 01240 m = PositionBottom; 01241 else if ( p.x() <= borderWidth ) 01242 m = PositionLeft; 01243 else if ( p.x() >= width()-borderWidth ) 01244 m = PositionRight; 01245 else 01246 m = PositionCenter; 01247 01248 // Modify the mouse position if we are using a grab bar. 01249 if (showGrabBar && isResizable()) 01250 if (p.y() >= (height() - grabBorderWidth)) 01251 { 01252 if (p.x() >= (width() - 2*borderWidth - 12)) 01253 m = PositionBottomRight; 01254 else if (p.x() <= 2*borderWidth + 12) 01255 m = PositionBottomLeft; 01256 else 01257 m = PositionBottom; 01258 } 01259 01260 return m; 01261 } 01262 01263 01264 // Make sure the menu button follows double click conventions set in kcontrol 01265 void KDEDefaultClient::menuButtonPressed() 01266 { 01267 static QTime t; 01268 static KDEDefaultClient* lastClient = NULL; 01269 bool dbl = ( lastClient == this && t.elapsed() <= QApplication::doubleClickInterval()); 01270 lastClient = this; 01271 t.start(); 01272 01273 if (dbl) 01274 { 01275 m_closing = true; 01276 return; 01277 } 01278 01279 QPoint menupoint ( button[BtnMenu]->rect().bottomLeft().x()-1, 01280 button[BtnMenu]->rect().bottomLeft().y()+2 ); 01281 KDecorationFactory* f = factory(); 01282 showWindowMenu( button[BtnMenu]->mapToGlobal( menupoint )); 01283 if( !f->exists( this )) // 'this' was destroyed 01284 return; 01285 button[BtnMenu]->setDown(false); 01286 } 01287 01288 void KDEDefaultClient::menuButtonReleased() 01289 { 01290 if (m_closing) 01291 closeWindow(); 01292 } 01293 01294 const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask 01295 | NET::ToolbarMask | NET::MenuMask | NET::DialogMask | NET::OverrideMask | NET::TopMenuMask 01296 | NET::UtilityMask | NET::SplashMask; 01297 01298 bool KDEDefaultClient::isTool() const 01299 { 01300 NET::WindowType type = windowType( SUPPORTED_WINDOW_TYPES_MASK ); 01301 return type == NET::Toolbar || type == NET::Utility || type == NET::Menu; 01302 } 01303 01304 01305 bool KDEDefaultClient::eventFilter( QObject* o, QEvent* e ) 01306 { 01307 if( o != widget()) 01308 return false; 01309 switch( e->type()) 01310 { 01311 case QEvent::Resize: 01312 resizeEvent( static_cast< QResizeEvent* >( e )); 01313 return true; 01314 case QEvent::Paint: 01315 paintEvent( static_cast< QPaintEvent* >( e )); 01316 return true; 01317 case QEvent::MouseButtonDblClick: 01318 mouseDoubleClickEvent( static_cast< QMouseEvent* >( e )); 01319 return true; 01320 case QEvent::MouseButtonPress: 01321 processMousePressEvent( static_cast< QMouseEvent* >( e )); 01322 return true; 01323 case QEvent::Show: 01324 showEvent( static_cast< QShowEvent* >( e )); 01325 return true; 01326 default: 01327 break; 01328 } 01329 return false; 01330 } 01331 01332 01333 } // namespace 01334 01335 // Extended KWin plugin interface 01336 extern "C" KDecorationFactory* create_factory() 01337 { 01338 return new Default::KDEDefaultHandler(); 01339 } 01340 01341 #include "kdedefault.moc" 01342 // vim: ts=4
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 Dec 16 19:08:41 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003