00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
#include <kconfig.h>
00025
#include <klocale.h>
00026
#include <kiconeffect.h>
00027
00028
#include <qpainter.h>
00029
#include <qlayout.h>
00030
#include <qbitmap.h>
00031
#include <qstyle.h>
00032
#include <qtooltip.h>
00033
#include <qwidget.h>
00034
#include <qlabel.h>
00035
00036
#include <X11/Xlib.h>
00037
00038
#include "keramik.h"
00039
#include "keramik.moc"
00040
00041
00042
00043
00044
00045
00046
00047
namespace Keramik
00048 {
00049
00050
const int buttonMargin = 9;
00051
const int buttonSpacing = 4;
00052
const int iconSpacing = 5;
00053
00054
00055
const char default_left[] =
"M";
00056
const char default_right[] =
"HIAX";
00057
00058
00059
const unsigned char menu_bits[] = {
00060 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00061 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0xf0, 0x07, 0x00,
00062 0xe0, 0x03, 0x00, 0xc0, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
00063 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00064 0x00, 0x00, 0x00};
00065
00066
const unsigned char on_all_desktops_bits[] = {
00067 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00068 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0xf0, 0x0f, 0x00,
00069 0xf0, 0x0f, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00,
00070 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00071 0x00, 0x00, 0x00};
00072
00073
const unsigned char not_on_all_desktops_bits[] = {
00074 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00075 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00,
00076 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00077 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00078 0x00, 0x00, 0x00};
00079
00080
const unsigned char help_bits[] = {
00081 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00,
00082 0xf0, 0x07, 0x00, 0x30, 0x06, 0x00, 0x00, 0x07, 0x00, 0x80, 0x03, 0x00,
00083 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00,
00084 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00085 0x00, 0x00, 0x00};
00086
00087
const unsigned char minimize_bits[] = {
00088 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00089 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00090 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00,
00091 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00092 0x00, 0x00, 0x00};
00093
00094
const unsigned char maximize_bits[] = {
00095 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00096 0x80, 0x01, 0x00, 0xc0, 0x03, 0x00, 0xe0, 0x07, 0x00, 0xf0, 0x0f, 0x00,
00097 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00,
00098 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00099 0x00, 0x00, 0x00};
00100
00101
const unsigned char restore_bits[] = {
00102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00103 0xf0, 0x0f, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00,
00104 0xf0, 0x0f, 0x00, 0xe0, 0x07, 0x00, 0xc0, 0x03, 0x00, 0x80, 0x01, 0x00,
00105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00106 0x00, 0x00, 0x00};
00107
00108
const unsigned char close_bits[] = {
00109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00110 0x30, 0x0c, 0x00, 0x70, 0x0e, 0x00, 0xe0, 0x07, 0x00, 0xc0, 0x03, 0x00,
00111 0xc0, 0x03, 0x00, 0xe0, 0x07, 0x00, 0x70, 0x0e, 0x00, 0x30, 0x0c, 0x00,
00112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00113 0x00, 0x00, 0x00};
00114
00115
00116 KeramikHandler *clientHandler = NULL;
00117
bool keramik_initialized =
false;
00118
00119
00120
00121
00122
00123
00124
00125 KeramikHandler::KeramikHandler()
00126 {
00127
for (
int i = 0; i < NumTiles; i++ ) {
00128 activeTiles[i] = NULL;
00129 inactiveTiles[i] = NULL;
00130 }
00131
00132 settings_cache = NULL;
00133
00134 imageDb = KeramikImageDb::instance();
00135
00136
00137 buttonDecos[ Menu ] =
new QBitmap( 17, 17, menu_bits,
true );
00138 buttonDecos[ OnAllDesktops ] =
new QBitmap( 17, 17, on_all_desktops_bits,
true );
00139 buttonDecos[ NotOnAllDesktops ] =
new QBitmap( 17, 17, not_on_all_desktops_bits,
true );
00140 buttonDecos[ Help ] =
new QBitmap( 17, 17, help_bits,
true );
00141 buttonDecos[ Minimize ] =
new QBitmap( 17, 17, minimize_bits,
true );
00142 buttonDecos[ Maximize ] =
new QBitmap( 17, 17, maximize_bits,
true );
00143 buttonDecos[ Restore ] =
new QBitmap( 17, 17, restore_bits,
true );
00144 buttonDecos[ Close ] =
new QBitmap( 17, 17, close_bits,
true );
00145
00146
00147
for (
int i = 0; i < NumButtonDecos; i++ )
00148 buttonDecos[i]->setMask( *buttonDecos[i] );
00149
00150
00151
if ( QApplication::reverseLayout() ) {
00152
for (
int i = 0; i < Help; i++ )
00153 flip( reinterpret_cast<QPixmap**>(buttonDecos)[i] );
00154
00155
for (
int i = Help + 1; i < NumButtonDecos; i++ )
00156 flip( reinterpret_cast<QPixmap**>(buttonDecos)[i] );
00157 }
00158
00159 readConfig();
00160 createPixmaps();
00161
00162 keramik_initialized =
true;
00163 }
00164
00165
00166 KeramikHandler::~KeramikHandler()
00167 {
00168 keramik_initialized =
false;
00169 destroyPixmaps();
00170
00171
for (
int i = 0; i < NumButtonDecos; i++ )
00172
delete buttonDecos[i];
00173
00174
delete settings_cache;
00175
00176 KeramikImageDb::release();
00177 imageDb = NULL;
00178 clientHandler = NULL;
00179 }
00180
00181
00182
void KeramikHandler::createPixmaps()
00183 {
00184
int heightOffset;
00185
int widthOffset;
00186
switch(
options()->
preferredBorderSize(
this)) {
00187
case BorderLarge:
00188 widthOffset = 4;
00189 heightOffset = 0;
00190
break;
00191
case BorderVeryLarge:
00192 widthOffset = 8;
00193 heightOffset = 0;
00194
break;
00195
case BorderHuge:
00196 widthOffset = 14;
00197 heightOffset = 0;
00198
break;
00199
case BorderVeryHuge:
00200 widthOffset = 23;
00201 heightOffset = 10;
00202
break;
00203
case BorderOversized:
00204 widthOffset = 36;
00205 heightOffset = 25;
00206
break;
00207
case BorderTiny:
00208
case BorderNormal:
00209
default:
00210 widthOffset = 0;
00211 heightOffset = 0;
00212 }
00213
int fontHeight = QFontMetrics(
options()->font(
true)).height();
00214
if (fontHeight > heightOffset + 20)
00215 heightOffset = fontHeight - 20;
00216
00217 QString size = (heightOffset < 8) ?
"" : (heightOffset < 20) ?
"-large" :
"-huge";
00218
00219 QColor titleColor, captionColor, buttonColor;
00220 QImage *titleCenter = NULL, *captionLeft = NULL,
00221 *captionRight = NULL, *captionCenter = NULL;
00222
00223
00224
00225
00226 captionColor =
KDecoration::options()->
color( ColorTitleBar,
true );
00227 titleColor =
KDecoration::options()->
color( ColorTitleBlend,
true );
00228
00229
00230 activeTiles[ TitleLeft ] = loadPixmap(
"titlebar-left", titleColor );
00231 activeTiles[ TitleRight ] = loadPixmap(
"titlebar-right", titleColor );
00232
00233
00234
00235 titleCenter = loadImage(
"titlebar-center", titleColor );
00236
00237
00238 captionLeft = loadImage(
"caption-small-left", captionColor );
00239 captionRight = loadImage(
"caption-small-right", captionColor );
00240 captionCenter = loadImage(
"caption-small-center", captionColor );
00241
00242
00243 activeTiles[ CaptionSmallLeft ] = composite( captionLeft, titleCenter );
00244 activeTiles[ CaptionSmallRight ] = composite( captionRight, titleCenter );
00245 activeTiles[ CaptionSmallCenter ] = composite( captionCenter, titleCenter );
00246
00247
delete captionLeft;
00248
delete captionRight;
00249
delete captionCenter;
00250
00251
00252 captionLeft = loadImage(
"caption-large-left", captionColor );
00253 captionRight = loadImage(
"caption-large-right", captionColor );
00254 captionCenter = loadImage(
"caption-large-center", captionColor );
00255
00256 activeTiles[ CaptionLargeLeft ] = composite( captionLeft, titleCenter );
00257 activeTiles[ CaptionLargeRight ] = composite( captionRight, titleCenter );
00258 activeTiles[ CaptionLargeCenter ] = composite( captionCenter, titleCenter );
00259
00260
delete captionLeft;
00261
delete captionRight;
00262
delete captionCenter;
00263
00264
00265 activeTiles[ TitleCenter ] =
new QPixmap( *titleCenter );
00266
00267
delete titleCenter;
00268
00269
00270 activeTiles[ BorderLeft ] = loadPixmap(
"border-left", titleColor );
00271 activeTiles[ BorderRight ] = loadPixmap(
"border-right", titleColor );
00272
00273
00274
if ( largeGrabBars ) {
00275 activeTiles[ GrabBarLeft ] = loadPixmap(
"grabbar-left", titleColor );
00276 activeTiles[ GrabBarRight ] = loadPixmap(
"grabbar-right", titleColor );
00277 activeTiles[ GrabBarCenter ] = loadPixmap(
"grabbar-center", titleColor );
00278 }
else {
00279 activeTiles[ GrabBarLeft ] = loadPixmap(
"bottom-left", titleColor );
00280 activeTiles[ GrabBarRight ] = loadPixmap(
"bottom-right", titleColor );
00281 activeTiles[ GrabBarCenter ] = loadPixmap(
"bottom-center", titleColor );
00282 }
00283
00284
00285
00286 captionColor =
KDecoration::options()->
color( ColorTitleBar,
false );
00287 titleColor =
KDecoration::options()->
color( ColorTitleBlend,
false );
00288
00289 inactiveTiles[ TitleLeft ] = loadPixmap(
"titlebar-left", titleColor );
00290 inactiveTiles[ TitleRight ] = loadPixmap(
"titlebar-right", titleColor );
00291
00292 titleCenter = loadImage(
"titlebar-center", titleColor );
00293
00294 captionLeft = loadImage(
"caption-small-left", captionColor );
00295 captionRight = loadImage(
"caption-small-right", captionColor );
00296 captionCenter = loadImage(
"caption-small-center", captionColor );
00297
00298 inactiveTiles[ CaptionSmallLeft ] = composite( captionLeft, titleCenter );
00299 inactiveTiles[ CaptionSmallRight ] = composite( captionRight, titleCenter );
00300 inactiveTiles[ CaptionSmallCenter ] = composite( captionCenter, titleCenter );
00301
00302
delete captionLeft;
00303
delete captionRight;
00304
delete captionCenter;
00305
00306 inactiveTiles[ TitleCenter ] =
new QPixmap( *titleCenter );
00307
00308
delete titleCenter;
00309
00310 inactiveTiles[ BorderLeft ] = loadPixmap(
"border-left", titleColor );
00311 inactiveTiles[ BorderRight ] = loadPixmap(
"border-right", titleColor );
00312
00313
if ( largeGrabBars ) {
00314 inactiveTiles[ GrabBarLeft ] = loadPixmap(
"grabbar-left", titleColor );
00315 inactiveTiles[ GrabBarRight ] = loadPixmap(
"grabbar-right", titleColor );
00316 inactiveTiles[ GrabBarCenter ] = loadPixmap(
"grabbar-center", titleColor );
00317 }
else {
00318 inactiveTiles[ GrabBarLeft ] = loadPixmap(
"bottom-left", titleColor );
00319 inactiveTiles[ GrabBarRight ] = loadPixmap(
"bottom-right", titleColor );
00320 inactiveTiles[ GrabBarCenter ] = loadPixmap(
"bottom-center", titleColor );
00321 }
00322
00323
00324
00325 buttonColor = QColor();
00326
00327 titleButtonRound = loadPixmap(
"titlebutton-round"+size, buttonColor );
00328 titleButtonSquare = loadPixmap(
"titlebutton-square"+size, buttonColor );
00329
00330
00331
00332
00333
if ( QApplication::reverseLayout() ) {
00334
00335
00336 flip( activeTiles[CaptionSmallLeft], activeTiles[CaptionSmallRight] );
00337 flip( inactiveTiles[CaptionSmallLeft], inactiveTiles[CaptionSmallRight] );
00338
00339 flip( activeTiles[CaptionLargeLeft], activeTiles[CaptionLargeRight] );
00340
00341 flip( activeTiles[TitleLeft], activeTiles[TitleRight] );
00342 flip( inactiveTiles[TitleLeft], inactiveTiles[TitleRight] );
00343
00344 flip( activeTiles[BorderLeft], activeTiles[BorderRight] );
00345 flip( inactiveTiles[BorderLeft], inactiveTiles[BorderRight] );
00346
00347 flip( activeTiles[GrabBarLeft], activeTiles[GrabBarRight] );
00348 flip( inactiveTiles[GrabBarLeft], inactiveTiles[GrabBarRight] );
00349
00350 flip( titleButtonRound );
00351 flip( titleButtonSquare );
00352 }
00353
00354
00355 pretile( activeTiles[ CaptionSmallCenter ], 64, Qt::Horizontal );
00356 pretile( activeTiles[ CaptionLargeCenter ], 64, Qt::Horizontal );
00357 pretile( activeTiles[ TitleCenter ], 64, Qt::Horizontal );
00358 pretile( activeTiles[ GrabBarCenter ], 128, Qt::Horizontal );
00359 pretile( activeTiles[ BorderLeft ], 128, Qt::Vertical );
00360 pretile( activeTiles[ BorderRight ], 128, Qt::Vertical );
00361
00362 pretile( inactiveTiles[ CaptionSmallCenter ], 64, Qt::Horizontal );
00363 pretile( inactiveTiles[ TitleCenter ], 64, Qt::Horizontal );
00364 pretile( inactiveTiles[ GrabBarCenter ], 128, Qt::Horizontal );
00365 pretile( inactiveTiles[ BorderLeft ], 128, Qt::Vertical );
00366 pretile( inactiveTiles[ BorderRight ], 128, Qt::Vertical );
00367
00368
if (heightOffset > 0) {
00369 addHeight (heightOffset, activeTiles[TitleLeft]);
00370 addHeight (heightOffset, activeTiles[TitleCenter]);
00371 addHeight (heightOffset, activeTiles[TitleRight]);
00372 addHeight (heightOffset, activeTiles[CaptionSmallLeft]);
00373 addHeight (heightOffset, activeTiles[CaptionSmallCenter]);
00374 addHeight (heightOffset, activeTiles[CaptionSmallRight]);
00375 addHeight (heightOffset, activeTiles[CaptionLargeLeft]);
00376 addHeight (heightOffset, activeTiles[CaptionLargeCenter]);
00377 addHeight (heightOffset, activeTiles[CaptionLargeRight]);
00378
00379 addHeight (heightOffset, inactiveTiles[TitleLeft]);
00380 addHeight (heightOffset, inactiveTiles[TitleCenter]);
00381 addHeight (heightOffset, inactiveTiles[TitleRight]);
00382 addHeight (heightOffset, inactiveTiles[CaptionSmallLeft]);
00383 addHeight (heightOffset, inactiveTiles[CaptionSmallCenter]);
00384 addHeight (heightOffset, inactiveTiles[CaptionSmallRight]);
00385 }
00386
00387
if (widthOffset > 0) {
00388 addWidth (widthOffset, activeTiles[BorderLeft],
true, activeTiles[GrabBarCenter]);
00389 addWidth (widthOffset, activeTiles[BorderRight],
false, activeTiles[GrabBarCenter]);
00390 addWidth (widthOffset, inactiveTiles[BorderLeft],
true, inactiveTiles[GrabBarCenter]);
00391 addWidth (widthOffset, inactiveTiles[BorderRight],
false, inactiveTiles[GrabBarCenter]);
00392
00393
if (largeGrabBars)
00394 widthOffset = widthOffset*3/2;
00395
00396 addHeight (widthOffset, activeTiles[GrabBarLeft]);
00397 addHeight (widthOffset, activeTiles[GrabBarCenter]);
00398 addHeight (widthOffset, activeTiles[GrabBarRight]);
00399 addHeight (widthOffset, inactiveTiles[GrabBarLeft]);
00400 addHeight (widthOffset, inactiveTiles[GrabBarCenter]);
00401 addHeight (widthOffset, inactiveTiles[GrabBarRight]);
00402 }
00403 }
00404
00405
00406
00407
void KeramikHandler::destroyPixmaps()
00408 {
00409
for (
int i = 0; i < NumTiles; i++ ) {
00410
delete activeTiles[i];
00411
delete inactiveTiles[i];
00412 activeTiles[i] = NULL;
00413 inactiveTiles[i] = NULL;
00414 }
00415
00416
delete titleButtonRound;
00417
delete titleButtonSquare;
00418 }
00419
00420
00421
void KeramikHandler::addWidth (
int width, QPixmap *&pix,
bool left, QPixmap *bottomPix) {
00422
int w = pix->width()+width;
00423
int h = pix->height();
00424
00425 QPixmap *tmp =
new QPixmap (w, h);
00426 tmp->fill ();
00427 QPainter p;
00428 p.begin (tmp);
00429
00430
for (
int i = 0; i < h; i++)
00431 p.drawPixmap (0, i, *bottomPix, i%2, 0, w,1);
00432
00433
if (left)
00434 p.drawPixmap(0, 0, *pix);
00435
else
00436 p.drawPixmap(width, 0, *pix);
00437
00438 p.end();
00439
00440
delete pix;
00441 pix = tmp;
00442 }
00443
00444
00445
void KeramikHandler::addHeight (
int height, QPixmap *&pix) {
00446
int w = pix->width();
00447
int h = pix->height()+height;
00448
00449 QPixmap *tmp =
new QPixmap (w, h);
00450 QPainter p;
00451 p.begin (tmp);
00452
if (pix->height() > 10) {
00453 p.drawPixmap(0, 0, *pix, 0, 0, w, 11);
00454
for (
int i = 0; i < height; i+=2)
00455 p.drawPixmap(0, 11+i, *pix, 0, 11, w, 2);
00456 p.drawPixmap(0, 11+height, *pix, 0, 11, w, -1);
00457 }
00458
else {
00459
int lines = h-3;
00460
int factor = pix->height()-3;
00461
for (
int i = 0; i < lines; i++)
00462 p.drawPixmap(0, i, *pix, 0, i*factor/lines, w, 1);
00463 p.drawPixmap(0, lines, *pix, 0, factor, w, 3);
00464 }
00465 p.end();
00466
00467
delete pix;
00468 pix = tmp;
00469 }
00470
00471
00472
void KeramikHandler::flip( QPixmap *&pix1, QPixmap *&pix2 )
00473 {
00474
00475 QPixmap *tmp =
new QPixmap( pix1->xForm( QWMatrix(-1,0,0,1,pix1->width(),0) ) );
00476
00477
delete pix1;
00478 pix1 =
new QPixmap( pix2->xForm( QWMatrix(-1,0,0,1,pix2->width(),0) ) );
00479
00480
delete pix2;
00481 pix2 = tmp;
00482 }
00483
00484
00485
void KeramikHandler::flip( QPixmap *&pix )
00486 {
00487
00488 QPixmap *tmp =
new QPixmap( pix->xForm( QWMatrix(-1,0,0,1,pix->width(),0) ) );
00489
delete pix;
00490 pix = tmp;
00491 }
00492
00493
00494
void KeramikHandler::pretile( QPixmap *&pix,
int size, Qt::Orientation dir )
00495 {
00496 QPixmap *newpix;
00497 QPainter p;
00498
00499
if ( dir == Qt::Horizontal )
00500 newpix =
new QPixmap( size, pix->height() );
00501
else
00502 newpix =
new QPixmap( pix->width(), size );
00503
00504 p.begin( newpix );
00505 p.drawTiledPixmap( newpix->rect(), *pix ) ;
00506 p.end();
00507
00508
delete pix;
00509 pix = newpix;
00510 }
00511
00512
00513
void KeramikHandler::readConfig()
00514 {
00515 KConfig *c =
new KConfig(
"kwinkeramikrc" );
00516
00517 c->setGroup(
"General" );
00518 showIcons = c->readBoolEntry(
"ShowAppIcons",
true );
00519 shadowedText = c->readBoolEntry(
"UseShadowedText",
true );
00520 smallCaptionBubbles = c->readBoolEntry(
"SmallCaptionBubbles",
false );
00521 largeGrabBars = c->readBoolEntry(
"LargeGrabBars",
true );
00522
00523
if ( ! settings_cache ) {
00524 settings_cache =
new SettingsCache;
00525 settings_cache->largeGrabBars = largeGrabBars;
00526 settings_cache->smallCaptionBubbles = smallCaptionBubbles;
00527 }
00528
00529
delete c;
00530 }
00531
00532
00533 QPixmap *KeramikHandler::composite( QImage *over, QImage *under )
00534 {
00535 QImage dest( over->width(), over->height(), 32 );
00536
int width = over->width(),
height = over->height();
00537
00538
00539 Q_UINT32 *data = reinterpret_cast<Q_UINT32*>( dest.bits() );
00540
for (
int i = 0; i < width *
height; i++)
00541 *(data++) = 0;
00542
00543
00544
for (
int y1 = height - under->height(), y2 = 0; y1 < height; y1++, y2++ )
00545 {
00546
register Q_UINT32 *dst = reinterpret_cast<Q_UINT32*>( dest.scanLine(y1) );
00547
register Q_UINT32 *src = reinterpret_cast<Q_UINT32*>( under->scanLine(y2) );
00548
00549
for (
int x = 0; x < width; x++ )
00550 *(dst++) = *(src++);
00551 }
00552
00553
00554
register Q_UINT32 *dst = reinterpret_cast<Q_UINT32*>( dest.bits() );
00555
register Q_UINT32 *src = reinterpret_cast<Q_UINT32*>( over->bits() );
00556
for (
int i = 0; i < width * height; i++ )
00557 {
00558
int r1 = qRed( *dst ), g1 = qGreen( *dst ), b1 = qBlue( *dst );
00559
int r2 = qRed( *src ), g2 = qGreen( *src ), b2 = qBlue( *src );
00560
int a = qAlpha( *src );
00561
00562
if ( a == 0xff )
00563 *dst = *src;
00564
00565
else if ( a != 0x00 )
00566 *dst = qRgba( Q_UINT8( r1 + (((r2 - r1) * a) >> 8) ),
00567 Q_UINT8( g1 + (((g2 - g1) * a) >> 8) ),
00568 Q_UINT8( b1 + (((b2 - b1) * a) >> 8) ),
00569 0xff );
00570
00571
else if ( qAlpha(*dst) == 0x00 )
00572 *dst = 0;
00573
00574 src++; dst++;
00575 }
00576
00577
00578
return new QPixmap( dest );
00579 }
00580
00581
00582 QImage *KeramikHandler::loadImage(
const QString &name,
const QColor &col )
00583 {
00584
if ( col.isValid() ) {
00585 QImage *img =
new QImage( imageDb->image(name)->copy() );
00586 KIconEffect::colorize( *img, col, 1.0 );
00587
return img;
00588 }
else
00589
return new QImage( imageDb->image(name)->copy() );
00590 }
00591
00592
00593 QPixmap *KeramikHandler::loadPixmap(
const QString &name,
const QColor &col )
00594 {
00595 QImage *img = loadImage( name, col );
00596 QPixmap *pix =
new QPixmap( *img );
00597
delete img;
00598
00599
return pix;
00600 }
00601
00602
00603
bool KeramikHandler::reset(
unsigned long changed )
00604 {
00605 keramik_initialized =
false;
00606
00607
bool needHardReset =
false;
00608
bool pixmapsInvalid =
false;
00609
00610
00611 readConfig();
00612
00613
if ( changed &
SettingBorder )
00614 {
00615 pixmapsInvalid =
true;
00616 needHardReset =
true;
00617 }
00618
if ( changed &
SettingFont )
00619 {
00620 pixmapsInvalid =
true;
00621 needHardReset =
true;
00622 }
00623
00624
if ( changed &
SettingColors )
00625 {
00626 pixmapsInvalid =
true;
00627 }
00628
00629
00630
if ( changed &
SettingButtons ) {
00631 needHardReset =
true;
00632 }
00633
00634
00635
if ( changed &
SettingTooltips ) {
00636 needHardReset =
true;
00637 }
00638
00639
if ( (settings_cache->largeGrabBars != largeGrabBars) ) {
00640 pixmapsInvalid =
true;
00641 needHardReset =
true;
00642 }
00643
00644
if ( (settings_cache->smallCaptionBubbles != smallCaptionBubbles) ) {
00645 needHardReset =
true;
00646 }
00647
00648
00649 settings_cache->largeGrabBars = largeGrabBars;
00650 settings_cache->smallCaptionBubbles = smallCaptionBubbles;
00651
00652
00653
if ( pixmapsInvalid ) {
00654 destroyPixmaps();
00655 createPixmaps();
00656 }
00657
00658 keramik_initialized =
true;
00659
00660
00661
if ( !needHardReset )
00662 resetDecorations( changed );
00663
return needHardReset;
00664 }
00665
00666
00667
const QPixmap *KeramikHandler::tile( TilePixmap tilePix,
bool active )
const
00668
{
00669
return ( active ? activeTiles[ tilePix ] : inactiveTiles[ tilePix ] );
00670 }
00671
00672
KDecoration* KeramikHandler::createDecoration( KDecorationBridge* bridge )
00673 {
00674
return new KeramikClient( bridge,
this );
00675 }
00676
00677 QValueList< KeramikHandler::BorderSize > KeramikHandler::borderSizes()
const
00678
{
00679
return QValueList< BorderSize >() <<
BorderNormal <<
BorderLarge <<
00680
BorderVeryLarge <<
BorderHuge <<
BorderVeryHuge <<
BorderOversized;
00681 }
00682
00683
00684
00685
00686
00687
00688 KeramikButton::KeramikButton( KeramikClient* c,
const char *name, Button btn,
const QString &tip,
const int realizeBtns )
00689 : QButton( c->widget(), name ),
00690 client( c ), button( btn ), hover( false ), lastbutton( 0 )
00691 {
00692 realizeButtons = realizeBtns;
00693
00694 QToolTip::add(
this, tip );
00695 setBackgroundMode( NoBackground );
00696 setCursor( arrowCursor );
00697
int size = clientHandler->roundButton()->height();
00698 setFixedSize( size, size );
00699
00700 setToggleButton( (button == OnAllDesktopsButton) );
00701 }
00702
00703
00704 KeramikButton::~KeramikButton()
00705 {
00706
00707 }
00708
00709
00710
void KeramikButton::enterEvent( QEvent *e )
00711 {
00712 QButton::enterEvent( e );
00713
00714 hover =
true;
00715 repaint(
false );
00716 }
00717
00718
00719
void KeramikButton::leaveEvent( QEvent *e )
00720 {
00721 QButton::leaveEvent( e );
00722
00723 hover =
false;
00724 repaint(
false );
00725 }
00726
00727
00728
void KeramikButton::mousePressEvent( QMouseEvent *e )
00729 {
00730 lastbutton = e->button();
00731 QMouseEvent me( e->type(), e->pos(), e->globalPos(), (e->button()&realizeButtons)?LeftButton:NoButton, e->state() );
00732 QButton::mousePressEvent( &me );
00733 }
00734
00735
00736
void KeramikButton::mouseReleaseEvent( QMouseEvent *e )
00737 {
00738 lastbutton = e->button();
00739 QMouseEvent me( e->type(), e->pos(), e->globalPos(), (e->button()&realizeButtons)?LeftButton:NoButton, e->state() );
00740 QButton::mouseReleaseEvent( &me );
00741 }
00742
00743
00744
void KeramikButton::drawButton( QPainter *p )
00745 {
00746
const QPixmap *pix;
00747
const QBitmap *deco;
00748
int size = clientHandler->roundButton()->height();
00749
00750
00751
if ( button == MenuButton || button == OnAllDesktopsButton || button == HelpButton )
00752 pix = clientHandler->roundButton();
00753
else
00754 pix = clientHandler->squareButton();
00755
00756
00757
const QPixmap *background = clientHandler->tile( TitleCenter, client->isActive() );
00758 p->drawPixmap( 0, 0, *background,
00759 0, (background->height()-size+1)/2, size, size );
00760
00761
if ( isDown() ) {
00762
00763 p->drawPixmap( QPoint(), *pix, QStyle::visualRect( QRect(2*size, 0, size, size), pix->rect() ) );
00764 p->translate( QApplication::reverseLayout() ? -1 : 1, 1 );
00765 }
else if ( hover )
00766
00767 p->drawPixmap( QPoint(), *pix, QStyle::visualRect( QRect(size, 0, size, size), pix->rect() ) );
00768
else
00769
00770 p->drawPixmap( QPoint(), *pix, QStyle::visualRect( QRect(0, 0, size, size), pix->rect() ) );
00771
00772
00773
00774
switch ( button ) {
00775
case MenuButton:
00776 deco = clientHandler->buttonDeco( Menu );
00777
break;
00778
00779
case OnAllDesktopsButton:
00780 deco = clientHandler->buttonDeco( isOn() ? NotOnAllDesktops : OnAllDesktops );
00781
break;
00782
00783
case HelpButton:
00784 deco = clientHandler->buttonDeco( Help );
00785
00786
00787
00788
if ( QApplication::reverseLayout() )
00789 p->translate( 2, 0 );
00790
break;
00791
00792
case MinButton:
00793 deco = clientHandler->buttonDeco( Minimize );
00794
break;
00795
00796
case MaxButton:
00797 deco = clientHandler->buttonDeco( client->maximizeMode() == KeramikClient::MaximizeFull ? Restore : Maximize );
00798
break;
00799
00800
case CloseButton:
00801 deco = clientHandler->buttonDeco( Close );
00802
break;
00803
00804
default:
00805 deco = NULL;
00806 }
00807
00808 p->setPen( Qt::black );
00809 p->drawPixmap( (size-17)/2, (size-17)/2, *deco );
00810 }
00811
00812
00813
00814
00815
00816
00817
00818 KeramikClient::KeramikClient( KDecorationBridge* bridge, KDecorationFactory* factory )
00819 :
KDecoration( bridge, factory ),
00820 activeIcon( NULL ), inactiveIcon( NULL ), captionBufferDirty( true ), maskDirty( true )
00821 {
00822 }
00823
00824
void KeramikClient::init()
00825 {
00826
createMainWidget( WStaticContents | WResizeNoErase | WRepaintNoErase );
00827
widget()->installEventFilter(
this );
00828
00829
00830
widget()->setBackgroundMode( NoBackground );
00831
00832
for (
int i=0; i < NumButtons; i++ )
00833 button[i] = NULL;
00834
00835 createLayout();
00836 }
00837
00838
void KeramikClient::createLayout()
00839 {
00840
00841 QVBoxLayout *mainLayout =
new QVBoxLayout(
widget() );
00842 QBoxLayout *titleLayout =
new QBoxLayout( 0, QBoxLayout::LeftToRight, 0, 0, 0 );
00843 QHBoxLayout *windowLayout =
new QHBoxLayout();
00844
00845 largeTitlebar = ( !maximizedVertical() && clientHandler->largeCaptionBubbles() );
00846 largeCaption = (
isActive() && largeTitlebar );
00847
00848
int grabBarHeight = clientHandler->grabBarHeight();
00849
int topSpacing = ( largeTitlebar ? 4 : 1 );
00850
int leftBorderWidth = clientHandler->tile( BorderLeft,
true )->width();
00851
int rightBorderWidth = clientHandler->tile( BorderRight,
true )->width();
00852 topSpacer =
new QSpacerItem( 10, topSpacing,
00853 QSizePolicy::Expanding, QSizePolicy::Minimum );
00854
00855 mainLayout->addItem( topSpacer );
00856
00857 mainLayout->addLayout( titleLayout );
00858 mainLayout->addLayout( windowLayout, 1 );
00859 mainLayout->addSpacing( grabBarHeight );
00860
00861 titleLayout->setSpacing( buttonSpacing );
00862
00863 titleLayout->addSpacing( buttonMargin );
00864 addButtons( titleLayout,
options()->customButtonPositions() ?
00865
options()->titleButtonsLeft() : QString(default_left) );
00866
00867 titlebar =
new QSpacerItem( 10, clientHandler->titleBarHeight(largeTitlebar)
00868 - topSpacing, QSizePolicy::Expanding, QSizePolicy::Minimum );
00869 titleLayout->addItem( titlebar );
00870
00871 titleLayout->addSpacing( buttonSpacing );
00872 addButtons( titleLayout,
options()->customButtonPositions() ?
00873
options()->titleButtonsRight() : QString(default_right) );
00874 titleLayout->addSpacing( buttonMargin - 1 );
00875
00876 windowLayout->addSpacing( leftBorderWidth );
00877
if(
isPreview())
00878 windowLayout->addWidget(
new QLabel( i18n(
"<center><b>Keramik</b></center>" ),
widget()));
00879
else
00880 windowLayout->addItem(
new QSpacerItem( 0, 0 ));
00881 windowLayout->addSpacing( rightBorderWidth );
00882 }
00883
00884
00885 KeramikClient::~KeramikClient()
00886 {
00887
delete activeIcon;
00888
delete inactiveIcon;
00889
00890 activeIcon = inactiveIcon = NULL;
00891 }
00892
00893
00894
void KeramikClient::reset(
unsigned long )
00895 {
00896
if ( clientHandler->largeCaptionBubbles() && !largeTitlebar )
00897 {
00898
00899
if ( !maximizedVertical() ) {
00900 topSpacer->changeSize( 10, 4, QSizePolicy::Expanding, QSizePolicy::Minimum );
00901 largeTitlebar =
true;
00902 largeCaption =
isActive();
00903
00904
widget()->layout()->activate();
00905
00906
00907
00908
00909
00910
widget()->setGeometry(
widget()->x(),
widget()->y() - 3,
width(),
height() + 3 );
00911 }
00912 }
00913
else if ( !clientHandler->largeCaptionBubbles() && largeTitlebar )
00914 {
00915
00916 topSpacer->changeSize( 10, 1, QSizePolicy::Expanding, QSizePolicy::Minimum );
00917 largeTitlebar = largeCaption =
false;
00918
00919
widget()->layout()->activate();
00920
00921
00922
00923
widget()->setGeometry(
widget()->x(),
widget()->y() + 3,
width(),
height() - 3 );
00924 }
00925
00926 calculateCaptionRect();
00927
00928 captionBufferDirty = maskDirty =
true;
00929
00930
00931
00932
if (
widget()->isVisible() ) {
00933
widget()->repaint(
false );
00934
00935
for (
int i = 0; i < NumButtons; i++ )
00936
if ( button[i] ) button[i]->repaint(
false );
00937 }
00938 }
00939
00940
00941
void KeramikClient::addButtons( QBoxLayout *layout,
const QString &s )
00942 {
00943
for ( uint i=0; i < s.length(); i++ )
00944 {
00945
switch ( s[i].latin1() )
00946 {
00947
00948
case 'M' :
00949
if ( !button[MenuButton] ) {
00950 button[MenuButton] =
new KeramikButton(
this,
"menu", MenuButton, i18n(
"Menu"), LeftButton|RightButton );
00951 connect( button[MenuButton], SIGNAL( pressed() ), SLOT( menuButtonPressed() ) );
00952 layout->addWidget( button[MenuButton] );
00953 }
00954
break;
00955
00956
00957
case 'S' :
00958
if ( !button[OnAllDesktopsButton] ) {
00959 button[OnAllDesktopsButton] =
new KeramikButton(
this,
"on_all_desktops",
00960 OnAllDesktopsButton,
isOnAllDesktops()?i18n(
"Not On All Desktops"):i18n(
"On All Desktops") );
00961
if(
isOnAllDesktops())
00962 button[OnAllDesktopsButton]->toggle();
00963 connect( button[OnAllDesktopsButton], SIGNAL( clicked() ), SLOT(
toggleOnAllDesktops() ) );
00964 layout->addWidget( button[OnAllDesktopsButton] );
00965 }
00966
break;
00967
00968
00969
case 'H' :
00970
if ( !button[HelpButton] &&
providesContextHelp() ) {
00971 button[HelpButton] =
new KeramikButton(
this,
"help", HelpButton, i18n(
"Help") );
00972 connect( button[HelpButton], SIGNAL( clicked() ), SLOT(
showContextHelp() ) );
00973 layout->addWidget( button[HelpButton] );
00974 }
00975
break;
00976
00977
00978
case 'I' :
00979
if ( !button[MinButton] &&
isMinimizable() ) {
00980 button[MinButton] =
new KeramikButton(
this,
"minimize", MinButton, i18n(
"Minimize") );
00981 connect( button[MinButton], SIGNAL( clicked() ), SLOT(
minimize() ) );
00982 layout->addWidget( button[MinButton] );
00983 }
00984
break;
00985
00986
00987
case 'A' :
00988
if ( !button[MaxButton] &&
isMaximizable() ) {
00989 button[MaxButton] =
new KeramikButton(
this,
"maximize", MaxButton, i18n(
"Maximize"), LeftButton|MidButton|RightButton );
00990 connect( button[MaxButton], SIGNAL( clicked() ), SLOT( slotMaximize() ) );
00991 layout->addWidget( button[MaxButton] );
00992 }
00993
break;
00994
00995
00996
case 'X' :
00997
if ( !button[CloseButton] &&
isCloseable() ) {
00998 button[CloseButton] =
new KeramikButton(
this,
"close", CloseButton, i18n(
"Close") );
00999 connect( button[CloseButton], SIGNAL( clicked() ), SLOT(
closeWindow() ) );
01000 layout->addWidget( button[CloseButton] );
01001 }
01002
break;
01003
01004
01005
case '_' :
01006 layout->addSpacing( buttonSpacing );
01007
break;
01008 }
01009 }
01010 }
01011
01012
01013
void KeramikClient::updateMask()
01014 {
01015
if ( !keramik_initialized )
01016
return;
01017
01018
01019
01020
01021
01022
01023 QRegion r;
01024
register int w, y = 0;
01025
int nrects;
01026
01027
if ( QApplication::reverseLayout() ) {
01028
01029
01030
if ( largeCaption && captionRect.width() >= 25 ) {
01031
register int x = captionRect.left();
01032 w = captionRect.width();
01033 r += QRegion( x + 11, y++, w - 19, 1 );
01034 r += QRegion( x + 9, y++, w - 15, 1 );
01035 r += QRegion( x + 7, y++, w - 12, 1 );
01036 }
else {
01037 nrects = 8;
01038
01039
01040
01041
01042
if ( largeTitlebar )
01043 y = 3;
01044 }
01045
01046 w =
width();
01047
01048
01049 r += QRegion( 9, y++, w - 17, 1 );
01050 r += QRegion( 7, y++, w - 13, 1 );
01051 r += QRegion( 5, y++, w - 9, 1 );
01052 r += QRegion( 4, y++, w - 7, 1 );
01053 r += QRegion( 3, y++, w - 5, 1 );
01054 r += QRegion( 2, y++, w - 4, 1 );
01055 r += QRegion( 1, y++, w - 2, 2 );
01056 }
else {
01057
01058
01059
if ( largeCaption && captionRect.width() >= 25 ) {
01060 nrects = 11;
01061
register int x = captionRect.left();
01062 w = captionRect.width();
01063 r += QRegion( x + 8, y++, w - 19, 1 );
01064 r += QRegion( x + 6, y++, w - 15, 1 );
01065 r += QRegion( x + 5, y++, w - 12, 1 );
01066 }
else {
01067 nrects = 8;
01068
01069
01070
01071
01072
if ( largeTitlebar )
01073 y = 3;
01074 }
01075
01076 w =
width();
01077
01078
01079 r += QRegion( 8, y++, w - 17, 1 );
01080 r += QRegion( 6, y++, w - 13, 1 );
01081 r += QRegion( 4, y++, w - 9, 1 );
01082 r += QRegion( 3, y++, w - 7, 1 );
01083 r += QRegion( 2, y++, w - 5, 1 );
01084 r += QRegion( 2, y++, w - 4, 1 );
01085 r += QRegion( 1, y++, w - 2, 2 );
01086 }
01087
01088 y++;
01089
01090
01091 r += QRegion( 0, y, w,
height() - y );
01092
01093
setMask( r, YXBanded );
01094
01095 maskDirty =
false;
01096 }
01097
01098
01099
void KeramikClient::updateCaptionBuffer()
01100 {
01101
if ( !keramik_initialized )
01102
return;
01103
01104
bool active =
isActive();
01105 QPixmap *
icon = NULL;
01106
01107
if ( captionBuffer.size() != captionRect.size() )
01108 captionBuffer.resize( captionRect.size() );
01109
01110
if ( captionBuffer.isNull() )
01111
return;
01112
01113 QPainter p( &captionBuffer );
01114
01115
01116
if ( active && largeCaption ) {
01117 p.drawPixmap( 0, 0, *clientHandler->tile( CaptionLargeLeft,
true ) );
01118 p.drawTiledPixmap( 15, 0, captionRect.width() - 30, captionRect.height(),
01119 *clientHandler->tile( CaptionLargeCenter,
true ) );
01120 p.drawPixmap( captionRect.width() - 15, 0, *clientHandler->tile( CaptionLargeRight,
true ) );
01121 }
else {
01122 p.drawPixmap( 0, 0, *clientHandler->tile( CaptionSmallLeft, active ) );
01123 p.drawTiledPixmap( 15, 0, captionRect.width() - 30, captionRect.height(),
01124 *clientHandler->tile( CaptionSmallCenter, active ) );
01125 p.drawPixmap( captionRect.width() - 15, 0, *clientHandler->tile( CaptionSmallRight, active ) );
01126 }
01127
01128
if ( clientHandler->showAppIcons() )
01129 {
01130
if ( active ) {
01131
if ( ! activeIcon )
01132 activeIcon =
new QPixmap( this->icon().pixmap( QIconSet::Small, QIconSet::Normal ));
01133 icon = activeIcon;
01134 }
else {
01135
if ( ! inactiveIcon ) {
01136 QImage img = this->
icon().pixmap( QIconSet::Small, QIconSet::Normal ).convertToImage();
01137 KIconEffect::semiTransparent( img );
01138 inactiveIcon =
new QPixmap( img );
01139 }
01140 icon = inactiveIcon;
01141 }
01142 }
01143
01144 p.setFont(
options()->font( active ) );
01145
int tw = p.fontMetrics().width(
caption() ) +
01146 ( clientHandler->showAppIcons() ? 16 + iconSpacing : 0 );
01147
01148
int xpos = QMAX( (captionRect.width() - tw) / 3, 8 );
01149 QRect tr = QStyle::visualRect( QRect(xpos, 1, captionRect.width() - xpos - 10,
01150 captionRect.height() - 4), captionBuffer.rect() );
01151
01152
01153
01154
01155
01156
if ( clientHandler->showAppIcons() )
01157 {
01158 QRect iconRect = QStyle::visualRect( QRect(tr.x(),
01159 1 + (captionRect.height() - 4 - 16) / 2, 16, 16), tr );
01160 QRect r( icon->rect() );
01161 r.moveCenter( iconRect.center() );
01162
01163
if ( tr.width() > 16 ) {
01164 p.drawPixmap( r, *icon );
01165 }
else {
01166 QRect sr( 0, 0, icon->width(), icon->height() );
01167
01168
if ( QApplication::reverseLayout() )
01169 sr.addCoords( icon->width() - tr.width(), 0, 0, 0 );
01170
else
01171 sr.addCoords( 0, 0, -( icon->width() - tr.width() ), 0 );
01172
01173 p.drawPixmap( r.x() + sr.x(), r.y() + sr.y(), *icon,
01174 sr.x(), sr.y(), sr.width(), sr.height() );
01175 }
01176
01177
01178
01179
if ( QApplication::reverseLayout() )
01180 tr.addCoords( 0, 0, -(16 + iconSpacing), 0 );
01181
else
01182 tr.addCoords( (16 + iconSpacing), 0, 0, 0 );
01183 }
01184
01185
01186
int flags = AlignVCenter | SingleLine;
01187 flags |= ( QApplication::reverseLayout() ? AlignRight : AlignLeft );
01188
01189
if ( clientHandler->useShadowedText() )
01190 {
01191 p.translate( QApplication::reverseLayout() ? -1 : 1, 1 );
01192 p.setPen(
options()->color(ColorTitleBar, active).dark() );
01193 p.setPen( black );
01194 p.drawText( tr, flags,
caption() );
01195 p.translate( QApplication::reverseLayout() ? 1 : -1, -1 );
01196 }
01197
01198 p.setPen(
options()->color( ColorFont, active ) );
01199 p.drawText( tr, flags,
caption() );
01200
01201 captionBufferDirty =
false;
01202 }
01203
01204
01205
void KeramikClient::calculateCaptionRect()
01206 {
01207 QFontMetrics fm(
options()->font(
isActive()) );
01208
int cw = fm.width(
caption() ) + 95;
01209
int titleBaseY = ( largeTitlebar ? 3 : 0 );
01210
01211
if ( clientHandler->showAppIcons() )
01212 cw += 16 + 4;
01213
01214 cw = QMIN( cw, titlebar->geometry().width() );
01215 captionRect = QStyle::visualRect( QRect(titlebar->geometry().x(), (largeCaption ? 0 : titleBaseY),
01216 cw, clientHandler->titleBarHeight(largeCaption) ),
01217 titlebar->geometry() );
01218 }
01219
01220
01221
void KeramikClient::captionChange()
01222 {
01223 QRect r( captionRect );
01224 calculateCaptionRect();
01225
01226
if ( r.size() != captionRect.size() )
01227 maskDirty =
true;
01228
01229 captionBufferDirty =
true;
01230
01231
widget()->repaint( r | captionRect,
false );
01232 }
01233
01234
01235
void KeramikClient::iconChange()
01236 {
01237
if ( clientHandler->showAppIcons() ) {
01238
01239
01240
if ( activeIcon )
01241
delete activeIcon;
01242
01243
if ( inactiveIcon )
01244
delete inactiveIcon;
01245
01246 activeIcon = inactiveIcon = NULL;
01247
01248 captionBufferDirty =
true;
01249
widget()->repaint( captionRect,
false );
01250 }
01251 }
01252
01253
01254
void KeramikClient::activeChange()
01255 {
01256
bool active =
isActive();
01257
01258
01259
01260
if ( largeTitlebar ) {
01261 largeCaption = ( active && !maximizedVertical() );
01262 calculateCaptionRect();
01263 maskDirty =
true;
01264 }
01265
01266 captionBufferDirty =
true;
01267
01268
widget()->repaint(
false );
01269
01270
for (
int i=0; i < NumButtons; i++ )
01271
if ( button[i] ) button[i]->repaint(
false );
01272 }
01273
01274
01275
void KeramikClient::maximizeChange()
01276 {
01277
if ( clientHandler->largeCaptionBubbles() )
01278 {
01279
if (
maximizeMode() &
MaximizeVertical ) {
01280
01281 topSpacer->changeSize( 10, 1, QSizePolicy::Expanding, QSizePolicy::Minimum );
01282 largeCaption = largeTitlebar =
false;
01283
01284 calculateCaptionRect();
01285 captionBufferDirty = maskDirty =
true;
01286
01287
widget()->layout()->activate();
01288
widget()->repaint(
false );
01289 }
else if ((
maximizeMode() &
MaximizeVertical ) == 0 && !largeTitlebar ) {
01290
01291 topSpacer->changeSize( 10, 4, QSizePolicy::Expanding, QSizePolicy::Minimum );
01292 largeCaption = largeTitlebar =
true;
01293
01294 calculateCaptionRect();
01295 captionBufferDirty = maskDirty =
true;
01296
01297
widget()->layout()->activate();
01298
widget()->repaint(
false );
01299 }
01300 }
01301
01302
if ( button[ MaxButton ] ) {
01303 QToolTip::remove( button[ MaxButton ] );
01304 QToolTip::add( button[ MaxButton ],
maximizeMode() == MaximizeFull ? i18n(
"Restore") : i18n(
"Maximize") );
01305 button[ MaxButton ]->repaint();
01306 }
01307 }
01308
01309
01310
void KeramikClient::desktopChange()
01311 {
01312
if ( button[ OnAllDesktopsButton ] )
01313 {
01314 QToolTip::remove( button[ OnAllDesktopsButton ] );
01315 QToolTip::add( button[ OnAllDesktopsButton ],
isOnAllDesktops() ? i18n(
"Not On All Desktops") : i18n(
"On All Desktops") );
01316 }
01317 }
01318
01319
01320
void KeramikClient::menuButtonPressed()
01321 {
01322 QPoint menuPoint ( button[MenuButton]->rect().bottomLeft().x() - 6,
01323 button[MenuButton]->rect().bottomLeft().y() + 3 );
01324 KDecorationFactory* f =
factory();
01325
showWindowMenu( button[MenuButton]->mapToGlobal( menuPoint ));
01326
if( !f->exists(
this ))
01327
return;
01328 button[MenuButton]->setDown(
false);
01329 }
01330
01331
01332
void KeramikClient::slotMaximize()
01333 {
01334
switch ( button[ MaxButton ]->lastButton() )
01335 {
01336
case MidButton:
01337
maximize(
maximizeMode() ^ MaximizeVertical );
01338
break;
01339
01340
case RightButton:
01341
maximize(
maximizeMode() ^ MaximizeHorizontal );
01342
break;
01343
01344
case LeftButton:
01345
maximize(
maximizeMode() == MaximizeFull ? MaximizeRestore : MaximizeFull );
01346
break;
01347 }
01348 }
01349
01350
01351
void KeramikClient::paintEvent( QPaintEvent *e )
01352 {
01353
if ( !keramik_initialized )
01354
return;
01355
01356 QPainter p(
widget());
01357 QRect updateRect( e->rect() );
01358
bool active =
isActive();
01359
01360
int titleBaseY = ( largeTitlebar ? 3 : 0 );
01361
int titleBarHeight = clientHandler->titleBarHeight( largeTitlebar );
01362
int grabBarHeight = clientHandler->grabBarHeight();
01363
int leftBorderWidth = clientHandler->tile( BorderLeft, active )->width();
01364
int rightBorderWidth = clientHandler->tile( BorderRight, active )->width();
01365
01366
if ( maskDirty )
01367 updateMask();
01368
01369
01370
01371
if ( updateRect.y() < titleBarHeight )
01372 {
01373
int titleBarBaseHeight = titleBarHeight - titleBaseY;
01374
01375
if ( captionBufferDirty )
01376 updateCaptionBuffer();
01377
01378
01379
if ( updateRect.x() < 15 )
01380 p.drawPixmap( 0, titleBaseY,
01381 *clientHandler->tile( TitleLeft, active ) );
01382
01383
01384
if ( updateRect.x() < captionRect.left() && updateRect.right() >= 15 ) {
01385
int x1 = QMAX( 15, updateRect.x() );
01386
int x2 = QMIN( captionRect.left(), updateRect.right() );
01387
01388 p.drawTiledPixmap( x1, titleBaseY, x2 - x1 + 1, titleBarBaseHeight,
01389 *clientHandler->tile( TitleCenter, active ) );
01390 }
01391
01392
01393
if ( updateRect.x() <= captionRect.right() && updateRect.right() > 15 ) {
01394
if ( captionRect.width() >= 25 )
01395 p.drawPixmap( captionRect.left(), active ? 0 : titleBaseY, captionBuffer );
01396
else
01397 p.drawTiledPixmap( captionRect.x(), titleBaseY, captionRect.width(),
01398 titleBarBaseHeight, *clientHandler->tile( TitleCenter, active ) );
01399 }
01400
01401
01402
if ( updateRect.right() > captionRect.right() && updateRect.x() <
width() - 15 ) {
01403
int x1 = QMAX( captionRect.right() + 1, updateRect.x() );
01404
int x2 = QMIN(
width() - 15, updateRect.right() );
01405
01406 p.drawTiledPixmap( x1, titleBaseY, x2 - x1 + 1, titleBarBaseHeight,
01407 *clientHandler->tile( TitleCenter, active ) );
01408 }
01409
01410
01411
if ( updateRect.right() >=
width() - 15 )
01412 p.drawPixmap(
width() - 15, titleBaseY,
01413 *clientHandler->tile( TitleRight, active ) );
01414 }
01415
01416
01417
01418
if ( updateRect.bottom() >= titleBarHeight &&
01419 updateRect.top() <
height() - grabBarHeight )
01420 {
01421
int top = QMAX( titleBarHeight, updateRect.top() );
01422
int bottom = QMIN( updateRect.bottom(),
height() - grabBarHeight );
01423
01424
01425
if ( updateRect.x() < leftBorderWidth )
01426 p.drawTiledPixmap( 0, top, leftBorderWidth, bottom - top + 1,
01427 *clientHandler->tile( BorderLeft, active ) );
01428
01429
01430
if ( e->rect().right() >
width() - rightBorderWidth - 1 )
01431 p.drawTiledPixmap(
width() - rightBorderWidth, top, rightBorderWidth,
01432 bottom - top + 1, *clientHandler->tile( BorderRight, active ) );
01433 }
01434
01435
01436
01437
if ( updateRect.bottom() >=
height() - grabBarHeight ) {
01438
01439
if ( updateRect.x() < 9 )
01440 p.drawPixmap( 0,
height() - grabBarHeight,
01441 *clientHandler->tile( GrabBarLeft, active ) );
01442
01443
01444
if ( updateRect.x() <
width() - 9 ) {
01445
int x1 = QMAX( 9, updateRect.x() );
01446
int x2 = QMIN(
width() - 9, updateRect.right() );
01447
01448 p.drawTiledPixmap( x1,
height() - grabBarHeight, x2 - x1 + 1,
01449 grabBarHeight, *clientHandler->tile( GrabBarCenter, active ) );
01450 }
01451
01452
01453
if ( updateRect.right() >
width() - 9 )
01454 p.drawPixmap(
width() - 9,
height() - grabBarHeight,
01455 *clientHandler->tile( GrabBarRight, active ) );
01456 }
01457
01458
01459 p.setPen(
options()->color( ColorTitleBlend, active ) );
01460 p.drawLine( leftBorderWidth,
height() - grabBarHeight - 1,
01461
width() - rightBorderWidth - 1,
height() - grabBarHeight - 1 );
01462 }
01463
01464
01465
void KeramikClient::resizeEvent( QResizeEvent *e )
01466 {
01467
01468
01469 QRect r( captionRect );
01470 calculateCaptionRect();
01471
01472
if ( r.size() != captionRect.size() )
01473 captionBufferDirty =
true;
01474
01475 maskDirty =
true;
01476
01477
if (
widget()->isVisible() )
01478 {
01479
widget()->update(
widget()->rect() );
01480
int dx = 0;
01481
int dy = 0;
01482
01483
if ( e->oldSize().width() !=
width() )
01484 dx = 32 + QABS( e->oldSize().width() -
width() );
01485
01486
if ( e->oldSize().height() !=
height() )
01487 dy = 8 + QABS( e->oldSize().height() -
height() );
01488
01489
if ( dy )
01490
widget()->update( 0,
height() - dy + 1,
width(), dy );
01491
01492
if ( dx )
01493 {
01494
widget()->update(
width() - dx + 1, 0, dx,
height() );
01495
widget()->update( QRect( QPoint(4,4), titlebar->geometry().bottomLeft() - QPoint(1,0) ) );
01496
widget()->update( QRect( titlebar->geometry().topRight(), QPoint(
width() - 4,
01497 titlebar->geometry().bottom() ) ) );
01498
01499 QApplication::postEvent(
this,
new QPaintEvent( titlebar->geometry(), FALSE ) );
01500 }
01501 }
01502 }
01503
01504
01505
void KeramikClient::mouseDoubleClickEvent( QMouseEvent *e )
01506 {
01507
if ( QRect( 0, 0,
width(), clientHandler->titleBarHeight( largeTitlebar ) ).contains( e->pos() ) )
01508
titlebarDblClickOperation();
01509 }
01510
01511
01512 KeramikClient::Position KeramikClient::mousePosition(
const QPoint &p )
const
01513
{
01514
int titleBaseY = (largeTitlebar ? 3 : 0);
01515
01516
int leftBorder = clientHandler->tile( BorderLeft,
true )->width();
01517
int rightBorder =
width() - clientHandler->tile( BorderRight,
true )->width() - 1;
01518
int bottomBorder =
height() - clientHandler->grabBarHeight() - 1;
01519
int bottomCornerSize = 3*clientHandler->tile( BorderRight,
true )->width()/2 + 24;
01520
01521
01522
if ( p.y() < titleBaseY + 11 ) {
01523
01524
if ( p.x() < leftBorder + 11 ) {
01525
if ( (p.y() < titleBaseY + 3 && p.x() < leftBorder + 11) ||
01526 (p.y() < titleBaseY + 6 && p.x() < leftBorder + 6) ||
01527 (p.y() < titleBaseY + 11 && p.x() < leftBorder + 3) )
01528
return PositionTopLeft;
01529 }
01530
01531
01532
if ( p.x() > rightBorder - 11 ) {
01533
if ( (p.y() < titleBaseY + 3 && p.x() > rightBorder - 11) ||
01534 (p.y() < titleBaseY + 6 && p.x() > rightBorder - 6) ||
01535 (p.y() < titleBaseY + 11 && p.x() > rightBorder - 3) )
01536
return PositionTopRight;
01537 }
01538
01539
01540
if ( p.y() <= 3 || (p.y() <= titleBaseY+3 &&
01541 (p.x() < captionRect.left() || p.x() > captionRect.right()) ) )
01542
return PositionTop;
01543
01544
01545
return PositionCenter;
01546 }
01547
01548
01549
else if ( p.y() < bottomBorder ) {
01550
01551
if ( p.x() < leftBorder ) {
01552
if ( p.y() <
height() - bottomCornerSize )
01553
return PositionLeft;
01554
else
01555
return PositionBottomLeft;
01556 }
01557
01558
01559
else if ( p.x() > rightBorder ) {
01560
if ( p.y() <
height() - bottomCornerSize )
01561
return PositionRight;
01562
else
01563
return PositionBottomRight;
01564 }
01565
01566
01567
return PositionCenter;
01568 }
01569
01570
01571
else {
01572
01573
if ( p.x() < bottomCornerSize )
01574
return PositionBottomLeft;
01575
01576
01577
else if ( p.x() >
width() - bottomCornerSize - 1 )
01578
return PositionBottomRight;
01579
01580
01581
return PositionBottom;
01582 }
01583
01584
01585
return PositionCenter;
01586 }
01587
01588
01589
void KeramikClient::resize(
const QSize& s )
01590 {
01591
widget()->resize( s );
01592 }
01593
01594
01595
void KeramikClient::borders(
int& left,
int& right,
int& top,
int& bottom )
const
01596
{
01597
int titleBarHeight = clientHandler->titleBarHeight( clientHandler->largeCaptionBubbles() );
01598
int grabBarHeight = clientHandler->grabBarHeight();
01599
int leftBorderWidth = clientHandler->tile( BorderLeft,
isActive() )->width();
01600
int rightBorderWidth = clientHandler->tile( BorderRight,
isActive() )->width();
01601
01602 left = leftBorderWidth;
01603 right = rightBorderWidth;
01604 top = titleBarHeight;
01605 bottom = grabBarHeight;
01606
01607
if ( (
maximizeMode() &
MaximizeHorizontal ) && !
options()->
moveResizeMaximizedWindows())
01608 left = right = 0;
01609
if(
maximizeMode() &
MaximizeVertical)
01610 {
01611 top = clientHandler->titleBarHeight(
false );
01612
if( !
options()->
moveResizeMaximizedWindows())
01613 bottom = 0;
01614 }
01615 }
01616
01617
01618 QSize KeramikClient::minimumSize()
const
01619
{
01620
return widget()->minimumSize();
01621 }
01622
01623
01624
bool KeramikClient::eventFilter( QObject* o, QEvent* e )
01625 {
01626
if ( o !=
widget() )
01627
return false;
01628
01629
switch ( e->type() )
01630 {
01631
case QEvent::Resize:
01632 resizeEvent( static_cast< QResizeEvent* >( e ) );
01633
return true;
01634
01635
case QEvent::Paint:
01636 paintEvent( static_cast< QPaintEvent* >( e ) );
01637
return true;
01638
01639
case QEvent::MouseButtonDblClick:
01640 mouseDoubleClickEvent( static_cast< QMouseEvent* >( e ) );
01641
return true;
01642
01643
case QEvent::MouseButtonPress:
01644
processMousePressEvent( static_cast< QMouseEvent* >( e ) );
01645
return true;
01646
01647
default:
01648
return false;
01649 }
01650 }
01651
01652 }
01653
01654
01655
01656
01657
01658
01659
01660
extern "C"
01661 {
01662 KDecorationFactory *create_factory()
01663 {
01664 Keramik::clientHandler =
new Keramik::KeramikHandler();
01665
return Keramik::clientHandler;
01666 }
01667 }
01668
01669
01670
01671