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