00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "b2client.h"
00014 #include <qapplication.h>
00015 #include <qlayout.h>
00016 #include <qdrawutil.h>
00017 #include <kpixmapeffect.h>
00018 #include <kimageeffect.h>
00019 #include <kicontheme.h>
00020 #include <kiconeffect.h>
00021 #include <kdrawutil.h>
00022 #include <klocale.h>
00023 #include <kconfig.h>
00024 #include <qbitmap.h>
00025 #include <qlabel.h>
00026 #include <qtooltip.h>
00027
00028 #include <X11/Xlib.h>
00029
00030 namespace B2 {
00031
00032 #include "bitmaps.h"
00033
00034 enum {
00035 Norm = 0,
00036 Hover, Down, INorm, IHover, IDown,
00037 NumStates
00038 };
00039
00040 enum {
00041 P_CLOSE = 0,
00042 P_MAX, P_NORMALIZE, P_ICONIFY, P_PINUP, P_MENU, P_HELP, P_SHADE, P_RESIZE,
00043 P_NUM_BUTTON_TYPES
00044 };
00045
00046 #define NUM_PIXMAPS (P_NUM_BUTTON_TYPES * NumStates)
00047
00048 static KPixmap *pixmap[NUM_PIXMAPS];
00049
00050
00051 #define PIXMAP_A(i) (pixmap[(i) * NumStates + Norm])
00052
00053 #define PIXMAP_AH(i) (pixmap[(i) * NumStates + Hover])
00054
00055 #define PIXMAP_AD(i) (pixmap[(i) * NumStates + Down])
00056
00057 #define PIXMAP_I(i) (pixmap[(i) * NumStates + INorm])
00058
00059 #define PIXMAP_IH(i) (pixmap[(i) * NumStates + IHover])
00060
00061 #define PIXMAP_ID(i) (pixmap[(i) * NumStates + IDown])
00062
00063 static KPixmap* titleGradient[2] = {0, 0};
00064
00065 static int thickness = 4;
00066 static int buttonSize = 16;
00067
00068 enum DblClickOperation {
00069 NoOp = 0,
00070 MinimizeOp,
00071 ShadeOp,
00072 CloseOp
00073 };
00074
00075 static DblClickOperation menu_dbl_click_op = NoOp;
00076
00077 static bool pixmaps_created = false;
00078 static bool colored_frame = false;
00079 static bool do_draw_handle = true;
00080 static bool drawSmallBorders = false;
00081
00082
00083
00084 extern "C" KDE_EXPORT KDecorationFactory* create_factory()
00085 {
00086 return new B2::B2ClientFactory();
00087 }
00088
00089
00090
00091 static inline const KDecorationOptions *options()
00092 {
00093 return KDecoration::options();
00094 }
00095
00096 static void redraw_pixmaps();
00097
00098 static void read_config(B2ClientFactory *f)
00099 {
00100
00101
00102 buttonSize = (QFontMetrics(options()->font(true)).height() + 1) & 0x3e;
00103 if (buttonSize < 16) buttonSize = 16;
00104
00105 KConfig conf("kwinb2rc");
00106 conf.setGroup("General");
00107 colored_frame = conf.readBoolEntry("UseTitleBarBorderColors", false);
00108 do_draw_handle = conf.readBoolEntry("DrawGrabHandle", true);
00109 drawSmallBorders = !options()->moveResizeMaximizedWindows();
00110
00111 QString opString = conf.readEntry("MenuButtonDoubleClickOperation", "NoOp");
00112 if (opString == "Close") {
00113 menu_dbl_click_op = B2::CloseOp;
00114 } else if (opString == "Minimize") {
00115 menu_dbl_click_op = B2::MinimizeOp;
00116 } else if (opString == "Shade") {
00117 menu_dbl_click_op = B2::ShadeOp;
00118 } else {
00119 menu_dbl_click_op = B2::NoOp;
00120 }
00121
00122 switch (options()->preferredBorderSize(f)) {
00123 case KDecoration::BorderTiny:
00124 thickness = 2;
00125 break;
00126 case KDecoration::BorderLarge:
00127 thickness = 5;
00128 break;
00129 case KDecoration::BorderVeryLarge:
00130 thickness = 8;
00131 break;
00132 case KDecoration::BorderHuge:
00133 thickness = 12;
00134 break;
00135 case KDecoration::BorderVeryHuge:
00136 case KDecoration::BorderOversized:
00137 case KDecoration::BorderNormal:
00138 default:
00139 thickness = 4;
00140 }
00141 }
00142
00143 static void drawB2Rect(KPixmap *pix, const QColor &primary, bool down)
00144 {
00145 QPainter p(pix);
00146 QColor hColor = primary.light(150);
00147 QColor lColor = primary.dark(150);
00148
00149 if (QPixmap::defaultDepth() > 8) {
00150 if (down)
00151 KPixmapEffect::gradient(*pix, lColor, hColor,
00152 KPixmapEffect::DiagonalGradient);
00153 else
00154 KPixmapEffect::gradient(*pix, hColor, lColor,
00155 KPixmapEffect::DiagonalGradient);
00156 }
00157 else
00158 pix->fill(primary);
00159 int x2 = pix->width() - 1;
00160 int y2 = pix->height() - 1;
00161 p.setPen(down ? hColor : lColor);
00162 p.drawLine(0, 0, x2, 0);
00163 p.drawLine(0, 0, 0, y2);
00164 p.drawLine(1, x2 - 1, x2 - 1, y2 - 1);
00165 p.drawLine(x2 - 1, 1, x2 - 1, y2 - 1);
00166 p.setPen(down ? lColor : hColor);
00167 p.drawRect(1, 1, x2, y2);
00168
00169 }
00170
00171 QPixmap* kwin_get_menu_pix_hack()
00172 {
00173
00174 return PIXMAP_A(P_MENU);
00175 }
00176
00177 static void create_pixmaps()
00178 {
00179 if (pixmaps_created)
00180 return;
00181 pixmaps_created = true;
00182
00183 int i;
00184 int bsize = buttonSize - 2;
00185 if (bsize < 16) bsize = 16;
00186
00187 for (i = 0; i < NUM_PIXMAPS; i++) {
00188 pixmap[i] = new KPixmap;
00189 switch (i / NumStates) {
00190 case P_MAX:
00191 case P_RESIZE:
00192 break;
00193 case P_ICONIFY:
00194 pixmap[i]->resize(10, 10); break;
00195 case P_SHADE:
00196 case P_CLOSE:
00197 pixmap[i]->resize(bsize, bsize); break;
00198 default:
00199 pixmap[i]->resize(16, 16); break;
00200 }
00201 }
00202
00203
00204
00205 QBitmap pinupMask(16, 16, pinup_mask_bits, true);
00206 PIXMAP_A(P_PINUP)->setMask(pinupMask);
00207 PIXMAP_I(P_PINUP)->setMask(pinupMask);
00208 QBitmap pindownMask(16, 16, pindown_mask_bits, true);
00209 PIXMAP_AD(P_PINUP)->setMask(pindownMask);
00210 PIXMAP_ID(P_PINUP)->setMask(pindownMask);
00211
00212 QBitmap menuMask(16, 16, menu_mask_bits, true);
00213 for (i = 0; i < NumStates; i++)
00214 pixmap[P_MENU * NumStates + i]->setMask(menuMask);
00215
00216 QBitmap helpMask(16, 16, help_mask_bits, true);
00217 for (i = 0; i < NumStates; i++)
00218 pixmap[P_HELP * NumStates + i]->setMask(helpMask);
00219
00220 QBitmap normalizeMask(16, 16, true);
00221
00222 QPainter mask;
00223 mask.begin(&normalizeMask);
00224
00225 QBrush one(Qt::color1);
00226 mask.fillRect(normalizeMask.width() - 12, normalizeMask.height() - 12,
00227 12, 12, one);
00228 mask.fillRect(0, 0, 10, 10, one);
00229 mask.end();
00230
00231 for (i = 0; i < NumStates; i++)
00232 pixmap[P_NORMALIZE * NumStates + i]->setMask(normalizeMask);
00233
00234 QBitmap shadeMask(bsize, bsize, true);
00235 mask.begin(&shadeMask);
00236 mask.fillRect(0, 0, bsize, 6, one);
00237 mask.end();
00238 for (i = 0; i < NumStates; i++)
00239 pixmap[P_SHADE * NumStates + i]->setMask(shadeMask);
00240
00241 titleGradient[0] = 0;
00242 titleGradient[1] = 0;
00243
00244 redraw_pixmaps();
00245 }
00246
00247 static void delete_pixmaps()
00248 {
00249 for (int i = 0; i < NUM_PIXMAPS; i++) {
00250 delete pixmap[i];
00251 pixmap[i] = 0;
00252 }
00253 for (int i = 0; i < 2; i++) {
00254 delete titleGradient[i];
00255 titleGradient[i] = 0;
00256 }
00257 pixmaps_created = false;
00258 }
00259
00260
00261
00262 B2ClientFactory::B2ClientFactory()
00263 {
00264 read_config(this);
00265 create_pixmaps();
00266 }
00267
00268 B2ClientFactory::~B2ClientFactory()
00269 {
00270 delete_pixmaps();
00271 }
00272
00273 KDecoration *B2ClientFactory::createDecoration(KDecorationBridge *b)
00274 {
00275 return new B2::B2Client(b, this);
00276 }
00277
00278 bool B2ClientFactory::reset(unsigned long changed)
00279 {
00280 bool needsReset = SettingColors ? true : false;
00281
00282
00283 read_config(this);
00284 if (changed & SettingFont) {
00285 delete_pixmaps();
00286 create_pixmaps();
00287 needsReset = true;
00288 }
00289 redraw_pixmaps();
00290
00291 return needsReset;
00292 }
00293
00294 bool B2ClientFactory::supports( Ability ability )
00295 {
00296 switch( ability )
00297 {
00298 case AbilityAnnounceButtons:
00299 case AbilityButtonMenu:
00300 case AbilityButtonOnAllDesktops:
00301 case AbilityButtonSpacer:
00302 case AbilityButtonHelp:
00303 case AbilityButtonMinimize:
00304 case AbilityButtonMaximize:
00305 case AbilityButtonClose:
00306 case AbilityButtonAboveOthers:
00307 case AbilityButtonBelowOthers:
00308 case AbilityButtonShade:
00309 case AbilityButtonResize:
00310 return true;
00311 default:
00312 return false;
00313 };
00314 }
00315
00316 QValueList< B2ClientFactory::BorderSize > B2ClientFactory::borderSizes() const
00317 {
00318
00319 return QValueList< BorderSize >() << BorderTiny << BorderNormal <<
00320 BorderLarge << BorderVeryLarge << BorderHuge;
00321 }
00322
00323
00324
00325 void B2Client::maxButtonClicked()
00326 {
00327 maximize(button[BtnMax]->last_button);
00328 }
00329
00330 void B2Client::shadeButtonClicked()
00331 {
00332 setShade(!isSetShade());
00333 }
00334
00335 void B2Client::resizeButtonPressed()
00336 {
00337 performWindowOperation(ResizeOp);
00338 }
00339
00340 B2Client::B2Client(KDecorationBridge *b, KDecorationFactory *f)
00341 : KDecoration(b, f), bar_x_ofs(0), in_unobs(0)
00342 {
00343 }
00344
00345 void B2Client::init()
00346 {
00347 const QString tips[] = {
00348 i18n("Menu"),
00349 isOnAllDesktops() ?
00350 i18n("Not on all desktops") : i18n("On all desktops"),
00351 i18n("Minimize"), i18n("Maximize"),
00352 i18n("Close"), i18n("Help"),
00353 isSetShade() ? i18n("Unshade") : i18n("Shade"),
00354 i18n("Resize")
00355 };
00356
00357 createMainWidget(WResizeNoErase | WRepaintNoErase);
00358 widget()->installEventFilter(this);
00359
00360 widget()->setBackgroundMode(NoBackground);
00361
00362
00363 for (int i = 0; i < BtnCount; i++)
00364 button[i] = NULL;
00365
00366 g = new QGridLayout(widget(), 0, 0);
00367 if (isPreview()) {
00368 g->addMultiCellWidget(
00369 new QLabel(i18n("<b><center>B II preview</center></b>"),
00370 widget()),
00371 1, 1, 1, 2);
00372 } else {
00373 g->addMultiCell(new QSpacerItem(0, 0), 1, 1, 1, 2);
00374 }
00375
00376
00377 leftSpacer = new QSpacerItem(thickness, 16,
00378 QSizePolicy::Fixed, QSizePolicy::Expanding);
00379 rightSpacer = new QSpacerItem(thickness, 16,
00380 QSizePolicy::Fixed, QSizePolicy::Expanding);
00381
00382 g->addItem(leftSpacer, 1, 0);
00383 g->addColSpacing(1, 16);
00384 g->setColStretch(2, 1);
00385 g->setRowStretch(1, 1);
00386 g->addItem(rightSpacer, 1, 3);
00387
00388
00389 spacer = new QSpacerItem(10, thickness + (mustDrawHandle() ? 4 : 0),
00390 QSizePolicy::Expanding, QSizePolicy::Fixed);
00391 g->addItem(spacer, 3, 1);
00392
00393
00394 g->addRowSpacing(0, buttonSize + 4);
00395
00396 titlebar = new B2Titlebar(this);
00397 titlebar->setMinimumWidth(buttonSize + 4);
00398 titlebar->setFixedHeight(buttonSize + 4);
00399
00400 QBoxLayout *titleLayout = new QBoxLayout(titlebar,
00401 QBoxLayout::LeftToRight, 0, 1, 0);
00402 titleLayout->addSpacing(3);
00403
00404 if (options()->customButtonPositions()) {
00405 addButtons(options()->titleButtonsLeft(), tips, titlebar, titleLayout);
00406 titleLayout->addItem(titlebar->captionSpacer);
00407 addButtons(options()->titleButtonsRight(), tips, titlebar, titleLayout);
00408 } else {
00409 addButtons("MSH", tips, titlebar, titleLayout);
00410 titleLayout->addItem(titlebar->captionSpacer);
00411 addButtons("IAX", tips, titlebar, titleLayout);
00412 }
00413
00414 titleLayout->addSpacing(3);
00415
00416 QColor c = options()->colorGroup(KDecoration::ColorTitleBar, isActive()).
00417 color(QColorGroup::Button);
00418
00419 for (int i = 0; i < BtnCount; i++) {
00420 if (button[i])
00421 button[i]->setBg(c);
00422 }
00423
00424 titlebar->updateGeometry();
00425 positionButtons();
00426 titlebar->recalcBuffer();
00427 titlebar->installEventFilter(this);
00428 resizable = isResizable();
00429 }
00430
00431 void B2Client::addButtons(const QString& s, const QString tips[],
00432 B2Titlebar* tb, QBoxLayout* titleLayout)
00433 {
00434 if (s.length() <= 0)
00435 return;
00436
00437 for (unsigned int i = 0; i < s.length(); i++) {
00438 switch (s[i].latin1()) {
00439 case 'M':
00440 if (!button[BtnMenu]) {
00441 button[BtnMenu] = new B2Button(this, tb, tips[BtnMenu],
00442 LeftButton | RightButton);
00443 button[BtnMenu]->setPixmaps(P_MENU);
00444 button[BtnMenu]->setUseMiniIcon();
00445 connect(button[BtnMenu], SIGNAL(pressed()),
00446 this, SLOT(menuButtonPressed()));
00447 titleLayout->addWidget(button[BtnMenu]);
00448 }
00449 break;
00450 case 'S':
00451 if (!button[BtnSticky]) {
00452 button[BtnSticky] = new B2Button(this, tb, tips[BtnSticky]);
00453 button[BtnSticky]->setPixmaps(P_PINUP);
00454 button[BtnSticky]->setToggle();
00455 button[BtnSticky]->setDown(isOnAllDesktops());
00456 connect(button[BtnSticky], SIGNAL(clicked()),
00457 this, SLOT(toggleOnAllDesktops()));
00458 titleLayout->addWidget(button[BtnSticky]);
00459 }
00460 break;
00461 case 'H':
00462 if (providesContextHelp() && (!button[BtnHelp])) {
00463 button[BtnHelp] = new B2Button(this, tb, tips[BtnHelp]);
00464 button[BtnHelp]->setPixmaps(P_HELP);
00465 connect(button[BtnHelp], SIGNAL(clicked()),
00466 this, SLOT(showContextHelp()));
00467 titleLayout->addWidget(button[BtnHelp]);
00468 }
00469 break;
00470 case 'I':
00471 if (isMinimizable() && (!button[BtnIconify])) {
00472 button[BtnIconify] = new B2Button(this, tb,tips[BtnIconify]);
00473 button[BtnIconify]->setPixmaps(P_ICONIFY);
00474 connect(button[BtnIconify], SIGNAL(clicked()),
00475 this, SLOT(minimize()));
00476 titleLayout->addWidget(button[BtnIconify]);
00477 }
00478 break;
00479 case 'A':
00480 if (isMaximizable() && (!button[BtnMax])) {
00481 button[BtnMax] = new B2Button(this, tb, tips[BtnMax],
00482 LeftButton | MidButton | RightButton);
00483 button[BtnMax]->setPixmaps(maximizeMode() == MaximizeFull ?
00484 P_NORMALIZE : P_MAX);
00485 connect(button[BtnMax], SIGNAL(clicked()),
00486 this, SLOT(maxButtonClicked()));
00487 titleLayout->addWidget(button[BtnMax]);
00488 }
00489 break;
00490 case 'X':
00491 if (isCloseable() && !button[BtnClose]) {
00492 button[BtnClose] = new B2Button(this, tb, tips[BtnClose]);
00493 button[BtnClose]->setPixmaps(P_CLOSE);
00494 connect(button[BtnClose], SIGNAL(clicked()),
00495 this, SLOT(closeWindow()));
00496 titleLayout->addWidget(button[BtnClose]);
00497 }
00498 break;
00499 case 'L':
00500 if (isShadeable() && !button[BtnShade]) {
00501 button[BtnShade] = new B2Button(this, tb, tips[BtnShade]);
00502 button[BtnShade]->setPixmaps(P_SHADE);
00503 connect(button[BtnShade], SIGNAL(clicked()),
00504 this, SLOT(shadeButtonClicked()));
00505 titleLayout->addWidget(button[BtnShade]);
00506 }
00507 break;
00508 case 'R':
00509 if (resizable && !button[BtnResize]) {
00510 button[BtnResize] = new B2Button(this, tb, tips[BtnResize]);
00511 button[BtnResize]->setPixmaps(P_RESIZE);
00512 connect(button[BtnResize], SIGNAL(pressed()),
00513 this, SLOT(resizeButtonPressed()));
00514 titleLayout->addWidget(button[BtnResize]);
00515 }
00516 break;
00517 case '_':
00518 titleLayout->addSpacing(4);
00519 break;
00520 }
00521 }
00522 }
00523
00524 bool B2Client::mustDrawHandle() const
00525 {
00526 if (drawSmallBorders && (maximizeMode() & MaximizeVertical)) {
00527 return false;
00528 } else {
00529 return do_draw_handle & resizable;
00530 }
00531 }
00532
00533 void B2Client::iconChange()
00534 {
00535 if (button[BtnMenu])
00536 button[BtnMenu]->repaint(false);
00537 }
00538
00539
00540
00541 void B2Client::calcHiddenButtons()
00542 {
00543
00544
00545 B2Button* btnArray[] = {
00546 button[BtnShade], button[BtnSticky], button[BtnHelp], button[BtnResize],
00547 button[BtnMax], button[BtnIconify], button[BtnClose], button[BtnMenu]
00548 };
00549 int minWidth = 120;
00550 int currentWidth = width();
00551 int count = 0;
00552 int i;
00553
00554
00555 while (currentWidth < minWidth) {
00556 currentWidth += buttonSize + 1;
00557 count++;
00558 }
00559
00560 if (count > BtnCount) count = BtnCount;
00561
00562
00563 for (i = 0; i < count; i++) {
00564 if (btnArray[i] && btnArray[i]->isVisible())
00565 btnArray[i]->hide();
00566 }
00567
00568 for (i = count; i < BtnCount; i++) {
00569 if (btnArray[i] && (!btnArray[i]->isVisible()))
00570 btnArray[i]->show();
00571 }
00572 }
00573
00574 void B2Client::resizeEvent(QResizeEvent * )
00575 {
00576 calcHiddenButtons();
00577 titlebar->layout()->activate();
00578 positionButtons();
00579
00580
00581
00582 titleMoveAbs(bar_x_ofs);
00583
00584 doShape();
00585 widget()->repaint();
00586 }
00587
00588 void B2Client::captionChange()
00589 {
00590 positionButtons();
00591 titleMoveAbs(bar_x_ofs);
00592 doShape();
00593 titlebar->recalcBuffer();
00594 titlebar->repaint(false);
00595 }
00596
00597 void B2Client::paintEvent(QPaintEvent* e)
00598 {
00599 QPainter p(widget());
00600
00601 KDecoration::ColorType frameColorGroup = colored_frame ?
00602 KDecoration::ColorTitleBar : KDecoration::ColorFrame;
00603
00604 QRect t = titlebar->geometry();
00605
00606
00607 int fHeight = height() - t.height();
00608
00609
00610 int bb = mustDrawHandle() ? 4 : 0;
00611 int bDepth = thickness + bb;
00612
00613 QColorGroup fillColor = options()->colorGroup(frameColorGroup, isActive());
00614 QBrush fillBrush(options()->color(frameColorGroup, isActive()));
00615
00616
00617 p.drawRect(0, t.bottom() - thickness + 1,
00618 width(), fHeight - bb + thickness);
00619
00620 if (thickness >= 2) {
00621
00622 p.drawRect(thickness - 1, t.bottom(),
00623 width() - 2 * (thickness - 1), fHeight - bDepth + 2);
00624
00625 if (thickness >= 3) {
00626
00627 qDrawShadePanel(&p, 1, t.bottom() - thickness + 2,
00628 width() - 2, fHeight - 2 - bb + thickness, fillColor, false);
00629 if (thickness == 4) {
00630 p.setPen(fillColor.background());
00631 p.drawRect(thickness - 2, t.bottom() - 1,
00632 width() - 2 * (thickness - 2), fHeight + 4 - bDepth);
00633 } else if (thickness > 4) {
00634 qDrawShadePanel(&p, thickness - 2,
00635 t.bottom() - 1, width() - 2 * (thickness - 2),
00636 fHeight + 4 - bDepth, fillColor, true);
00637 if (thickness >= 5) {
00638
00639 p.fillRect(2, t.bottom() - thickness + 3,
00640 width() - 4, thickness - 4, fillBrush);
00641 p.fillRect(2, height() - bDepth + 2,
00642 width() - 4, thickness - 4, fillBrush);
00643 p.fillRect(2, t.bottom() - 1,
00644 thickness - 4, fHeight - bDepth + 4, fillBrush);
00645 p.fillRect(width() - thickness + 2, t.bottom() - 1,
00646 thickness - 4, fHeight - bDepth + 4, fillBrush);
00647 }
00648 }
00649 }
00650 }
00651
00652
00653 if (mustDrawHandle()) {
00654 p.setPen(Qt::black);
00655 int hx = width() - 40;
00656 int hw = 40;
00657
00658 p.drawLine(width() - 1, height() - thickness - 4,
00659 width() - 1, height() - 1);
00660 p.drawLine(hx, height() - 1, width() - 1, height() - 1);
00661 p.drawLine(hx, height() - 4, hx, height() - 1);
00662
00663 p.fillRect(hx + 1, height() - thickness - 3,
00664 hw - 2, thickness + 2, fillBrush);
00665
00666 p.setPen(fillColor.dark());
00667 p.drawLine(width() - 2, height() - thickness - 4,
00668 width() - 2, height() - 2);
00669 p.drawLine(hx + 1, height() - 2, width() - 2, height() - 2);
00670
00671 p.setPen(fillColor.light());
00672 p.drawLine(hx + 1, height() - thickness - 2,
00673 hx + 1, height() - 3);
00674 p.drawLine(hx + 1, height() - thickness - 3,
00675 width() - 3, height() - thickness - 3);
00676 }
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687 if (titlebar->isFullyObscured()) {
00688
00689 QRegion reg(QRect(0, 0, width(), buttonSize + 4));
00690 reg = reg.intersect(e->region());
00691 if (!reg.isEmpty())
00692 unobscureTitlebar();
00693 }
00694 }
00695
00696 void B2Client::doShape()
00697 {
00698 QRect t = titlebar->geometry();
00699 QRegion mask(widget()->rect());
00700
00701 if (bar_x_ofs) {
00702 mask -= QRect(0, 0, bar_x_ofs, t.height() - thickness);
00703 mask -= QRect(0, t.height() - thickness, 1, 1);
00704 }
00705 if (t.right() < width() - 1) {
00706 mask -= QRect(width() - 1,
00707 t.height() - thickness, 1, 1);
00708 mask -= QRect(t.right() + 1, 0,
00709 width() - t.right() - 1, t.height() - thickness);
00710 }
00711 mask -= QRect(width() - 1, height() - 1, 1, 1);
00712 if (mustDrawHandle()) {
00713 mask -= QRect(0, height() - 5, 1, 1);
00714 mask -= QRect(width() - 40, height() - 1, 1, 1);
00715 mask -= QRect(0, height() - 4, width() - 40, 4);
00716 } else {
00717 mask -= QRect(0, height() - 1, 1, 1);
00718 }
00719
00720 setMask(mask);
00721 }
00722
00723 void B2Client::showEvent(QShowEvent *)
00724 {
00725 calcHiddenButtons();
00726 positionButtons();
00727 doShape();
00728 }
00729
00730 KDecoration::Position B2Client::mousePosition(const QPoint& p) const
00731 {
00732 const int range = 16;
00733 QRect t = titlebar->geometry();
00734 t.setHeight(buttonSize + 4 - thickness);
00735 int ly = t.bottom();
00736 int lx = t.right();
00737 int bb = mustDrawHandle() ? 0 : 5;
00738
00739 if (p.x() > t.right()) {
00740 if (p.y() <= ly + range && p.x() >= width() - range)
00741 return PositionTopRight;
00742 else if (p.y() <= ly + thickness)
00743 return PositionTop;
00744 } else if (p.x() < bar_x_ofs) {
00745 if (p.y() <= ly + range && p.x() <= range)
00746 return PositionTopLeft;
00747 else if (p.y() <= ly + thickness)
00748 return PositionTop;
00749 } else if (p.y() < ly) {
00750 if (p.x() > bar_x_ofs + thickness &&
00751 p.x() < lx - thickness && p.y() > thickness)
00752 return KDecoration::mousePosition(p);
00753 if (p.x() > bar_x_ofs + range && p.x() < lx - range)
00754 return PositionTop;
00755 if (p.y() <= range) {
00756 if (p.x() <= bar_x_ofs + range)
00757 return PositionTopLeft;
00758 else return PositionTopRight;
00759 } else {
00760 if (p.x() <= bar_x_ofs + range)
00761 return PositionLeft;
00762 else return PositionRight;
00763 }
00764 }
00765
00766 if (p.y() >= height() - 8 + bb) {
00767
00768 if (p.x() <= range) return PositionBottomLeft;
00769 if (p.x() >= width() - range) return PositionBottomRight;
00770 return PositionBottom;
00771 }
00772
00773 return KDecoration::mousePosition(p);
00774 }
00775
00776 void B2Client::titleMoveAbs(int new_ofs)
00777 {
00778 if (new_ofs < 0) new_ofs = 0;
00779 if (new_ofs + titlebar->width() > width()) {
00780 new_ofs = width() - titlebar->width();
00781 }
00782 if (bar_x_ofs != new_ofs) {
00783 bar_x_ofs = new_ofs;
00784 positionButtons();
00785 doShape();
00786 widget()->repaint(0, 0, width(), buttonSize + 4, false);
00787 titlebar->repaint(false);
00788 }
00789 }
00790
00791 void B2Client::titleMoveRel(int xdiff)
00792 {
00793 titleMoveAbs(bar_x_ofs + xdiff);
00794 }
00795
00796 void B2Client::desktopChange()
00797 {
00798 bool on = isOnAllDesktops();
00799 if (B2Button *b = button[BtnSticky]) {
00800 b->setDown(on);
00801 QToolTip::remove(b);
00802 QToolTip::add(b,
00803 on ? i18n("Not on all desktops") : i18n("On all desktops"));
00804 }
00805 }
00806
00807 void B2Client::maximizeChange()
00808 {
00809 bool m = maximizeMode() == MaximizeFull;
00810 if (button[BtnMax]) {
00811 button[BtnMax]->setPixmaps(m ? P_NORMALIZE : P_MAX);
00812 button[BtnMax]->repaint();
00813 QToolTip::remove(button[BtnMax]);
00814 QToolTip::add(button[BtnMax],
00815 m ? i18n("Restore") : i18n("Maximize"));
00816 }
00817 spacer->changeSize(10, thickness + (mustDrawHandle() ? 4 : 0),
00818 QSizePolicy::Expanding, QSizePolicy::Minimum);
00819
00820 g->activate();
00821 doShape();
00822 widget()->repaint(false);
00823 }
00824
00825 void B2Client::activeChange()
00826 {
00827 widget()->repaint(false);
00828 titlebar->repaint(false);
00829
00830 QColor c = options()->colorGroup(
00831 KDecoration::ColorTitleBar, isActive()).color(QColorGroup::Button);
00832
00833 for (int i = 0; i < BtnCount; i++)
00834 if (button[i]) {
00835 button[i]->setBg(c);
00836 button[i]->repaint(false);
00837 }
00838 }
00839
00840 void B2Client::shadeChange()
00841 {
00842 spacer->changeSize(10, thickness + (mustDrawHandle() ? 4 : 0),
00843 QSizePolicy::Expanding, QSizePolicy::Minimum);
00844 g->activate();
00845 doShape();
00846 if (B2Button *b = button[BtnShade]) {
00847 QToolTip::remove(b);
00848 QToolTip::add(b, isSetShade() ? i18n("Unshade") : i18n("Shade"));
00849 }
00850 }
00851
00852 QSize B2Client::minimumSize() const
00853 {
00854 int left, right, top, bottom;
00855 borders(left, right, top, bottom);
00856 return QSize(left + right + 2 * buttonSize, top + bottom);
00857 }
00858
00859 void B2Client::resize(const QSize& s)
00860 {
00861 widget()->resize(s);
00862 }
00863
00864 void B2Client::borders(int &left, int &right, int &top, int &bottom) const
00865 {
00866 left = right = thickness;
00867 top = buttonSize + 4;
00868 bottom = thickness + (mustDrawHandle() ? 4 : 0);
00869 }
00870
00871 void B2Client::menuButtonPressed()
00872 {
00873 static B2Client *lastClient = NULL;
00874
00875 bool dbl = (lastClient == this &&
00876 time.elapsed() <= QApplication::doubleClickInterval());
00877 lastClient = this;
00878 time.start();
00879 if (!dbl) {
00880 KDecorationFactory* f = factory();
00881 QRect menuRect = button[BtnMenu]->rect();
00882 QPoint menuTop = button[BtnMenu]->mapToGlobal(menuRect.topLeft());
00883 QPoint menuBottom = button[BtnMenu]->mapToGlobal(menuRect.bottomRight());
00884 showWindowMenu(QRect(menuTop, menuBottom));
00885 if (!f->exists(this))
00886 return;
00887 button[BtnMenu]->setDown(false);
00888 } else {
00889 switch (menu_dbl_click_op) {
00890 case B2::MinimizeOp:
00891 minimize();
00892 break;
00893 case B2::ShadeOp:
00894 setShade(!isSetShade());
00895 break;
00896 case B2::CloseOp:
00897 closeWindow();
00898 break;
00899 case B2::NoOp:
00900 default:
00901 break;
00902 }
00903 }
00904 }
00905
00906 void B2Client::unobscureTitlebar()
00907 {
00908
00909
00910
00911
00912 if (in_unobs) {
00913 return;
00914 }
00915 in_unobs = 1;
00916 QRegion reg(QRect(0,0,width(), buttonSize + 4));
00917 reg = unobscuredRegion(reg);
00918 if (!reg.isEmpty()) {
00919
00920
00921
00922
00923 titleMoveAbs(reg.boundingRect().x());
00924 }
00925 in_unobs = 0;
00926 }
00927
00928 static void redraw_pixmaps()
00929 {
00930 int i;
00931 QColorGroup aGrp = options()->colorGroup(KDecoration::ColorButtonBg, true);
00932 QColorGroup iGrp = options()->colorGroup(KDecoration::ColorButtonBg, false);
00933
00934
00935 drawB2Rect(PIXMAP_A(P_CLOSE), aGrp.button(), false);
00936 drawB2Rect(PIXMAP_AH(P_CLOSE), aGrp.button(), true);
00937 drawB2Rect(PIXMAP_AD(P_CLOSE), aGrp.button(), true);
00938
00939 drawB2Rect(PIXMAP_I(P_CLOSE), iGrp.button(), false);
00940 drawB2Rect(PIXMAP_IH(P_CLOSE), iGrp.button(), true);
00941 drawB2Rect(PIXMAP_ID(P_CLOSE), iGrp.button(), true);
00942
00943
00944 KPixmap thinBox;
00945 thinBox.resize(buttonSize - 2, 6);
00946 for (i = 0; i < NumStates; i++) {
00947 bool is_act = (i < 2);
00948 bool is_down = ((i & 1) == 1);
00949 KPixmap *pix = pixmap[P_SHADE * NumStates + i];
00950 QColor color = is_act ? aGrp.button() : iGrp.button();
00951 drawB2Rect(&thinBox, color, is_down);
00952 pix->fill(Qt::black);
00953 bitBlt(pix, 0, 0, &thinBox,
00954 0, 0, thinBox.width(), thinBox.height(), Qt::CopyROP, true);
00955 }
00956
00957
00958 for (i = 0; i < NumStates; i++) {
00959 *pixmap[P_MAX * NumStates + i] = *pixmap[P_CLOSE * NumStates + i];
00960 pixmap[P_MAX * NumStates + i]->detach();
00961 }
00962
00963
00964 KPixmap smallBox;
00965 smallBox.resize(10, 10);
00966 KPixmap largeBox;
00967 largeBox.resize(12, 12);
00968
00969 for (i = 0; i < NumStates; i++) {
00970 bool is_act = (i < 3);
00971 bool is_down = (i == Down || i == IDown);
00972 KPixmap *pix = pixmap[P_NORMALIZE * NumStates + i];
00973 drawB2Rect(&smallBox, is_act ? aGrp.button() : iGrp.button(), is_down);
00974 drawB2Rect(&largeBox, is_act ? aGrp.button() : iGrp.button(), is_down);
00975 pix->fill(options()->color(KDecoration::ColorTitleBar, is_act));
00976 bitBlt(pix, pix->width() - 12, pix->width() - 12, &largeBox,
00977 0, 0, 12, 12, Qt::CopyROP, true);
00978 bitBlt(pix, 0, 0, &smallBox, 0, 0, 10, 10, Qt::CopyROP, true);
00979
00980 bitBlt(pixmap[P_ICONIFY * NumStates + i], 0, 0,
00981 &smallBox, 0, 0, 10, 10, Qt::CopyROP, true);
00982 }
00983
00984
00985 for (i = 0; i < NumStates; i++) {
00986 bool is_act = (i < 3);
00987 bool is_down = (i == Down || i == IDown);
00988 *pixmap[P_RESIZE * NumStates + i] = *pixmap[P_CLOSE * NumStates + i];
00989 pixmap[P_RESIZE * NumStates + i]->detach();
00990 drawB2Rect(&smallBox, is_act ? aGrp.button() : iGrp.button(), is_down);
00991 bitBlt(pixmap[P_RESIZE * NumStates + i],
00992 0, 0, &smallBox, 0, 0, 10, 10, Qt::CopyROP, true);
00993 }
00994
00995
00996 QPainter p;
00997
00998 for (int j = 0; j < 3; j++) {
00999 int pix;
01000 unsigned const char *light, *dark;
01001 switch (j) {
01002 case 0:
01003 pix = P_CLOSE; light = close_white_bits; dark = close_dgray_bits;
01004 break;
01005 case 1:
01006 pix = P_MENU; light = menu_white_bits; dark = menu_dgray_bits;
01007 break;
01008 default:
01009 pix = P_HELP; light = help_light_bits; dark = help_dark_bits;
01010 break;
01011 }
01012 int off = (pixmap[pix * NumStates]->width() - 16) / 2;
01013 for (i = 0; i < NumStates; i++) {
01014 p.begin(pixmap[pix * NumStates + i]);
01015 kColorBitmaps(&p, (i < 3) ? aGrp : iGrp, off, off, 16, 16, true,
01016 light, NULL, NULL, dark, NULL, NULL);
01017 p.end();
01018 }
01019 }
01020
01021
01022 for (i = 0; i < NumStates; i++) {
01023 bool isDown = (i == Down || i == IDown);
01024 unsigned const char *white = isDown ? pindown_white_bits : pinup_white_bits;
01025 unsigned const char *gray = isDown ? pindown_gray_bits : pinup_gray_bits;
01026 unsigned const char *dgray =isDown ? pindown_dgray_bits : pinup_dgray_bits;
01027 p.begin(pixmap[P_PINUP * NumStates + i]);
01028 kColorBitmaps(&p, (i < 3) ? aGrp : iGrp, 0, 0, 16, 16, true, white,
01029 gray, NULL, dgray, NULL, NULL);
01030 p.end();
01031 }
01032
01033
01034 KIconEffect ie;
01035 QPixmap hilighted;
01036 for (i = 0; i < P_NUM_BUTTON_TYPES; i++) {
01037 int offset = i * NumStates;
01038 hilighted = ie.apply(*pixmap[offset + Norm],
01039 KIcon::Small, KIcon::ActiveState);
01040 *pixmap[offset + Hover] = hilighted;
01041
01042 hilighted = ie.apply(*pixmap[offset + INorm],
01043 KIcon::Small, KIcon::ActiveState);
01044 *pixmap[offset + IHover] = hilighted;
01045 }
01046
01047
01048
01049 if (QPixmap::defaultDepth() > 8) {
01050 QColor titleColor[4] = {
01051 options()->color(KDecoration::ColorTitleBar, true),
01052 options()->color(KDecoration::ColorFrame, true),
01053
01054 options()->color(KDecoration::ColorTitleBlend, false),
01055 options()->color(KDecoration::ColorTitleBar, false)
01056 };
01057
01058 if (colored_frame) {
01059 titleColor[0] = options()->color(KDecoration::ColorTitleBlend, true);
01060 titleColor[1] = options()->color(KDecoration::ColorTitleBar, true);
01061 }
01062
01063 for (i = 0; i < 2; i++) {
01064 if (titleColor[2 * i] != titleColor[2 * i + 1]) {
01065 if (!titleGradient[i]) {
01066 titleGradient[i] = new KPixmap;
01067 }
01068 titleGradient[i]->resize(64, buttonSize + 3);
01069 KPixmapEffect::gradient(*titleGradient[i],
01070 titleColor[2 * i], titleColor[2 * i + 1],
01071 KPixmapEffect::VerticalGradient);
01072 } else {
01073 delete titleGradient[i];
01074 titleGradient[i] = 0;
01075 }
01076 }
01077 }
01078 }
01079
01080 void B2Client::positionButtons()
01081 {
01082 QFontMetrics fm(options()->font(isActive()));
01083 QString cap = caption();
01084 if (cap.length() < 5)
01085 cap = "XXXXX";
01086 int textLen = fm.width(cap);
01087
01088 QRect t = titlebar->captionSpacer->geometry();
01089 int titleWidth = titlebar->width() - t.width() + textLen + 2;
01090 if (titleWidth > width()) titleWidth = width();
01091
01092 titlebar->resize(titleWidth, buttonSize + 4);
01093 titlebar->move(bar_x_ofs, 0);
01094 }
01095
01096
01097
01098 static QRect *visible_bound;
01099 static QPointArray bound_shape;
01100
01101 bool B2Client::drawbound(const QRect& geom, bool clear)
01102 {
01103 if (clear) {
01104 if (!visible_bound) return true;
01105 }
01106
01107 if (!visible_bound) {
01108 visible_bound = new QRect(geom);
01109 QRect t = titlebar->geometry();
01110 int frameTop = geom.top() + t.bottom();
01111 int barLeft = geom.left() + bar_x_ofs;
01112 int barRight = barLeft + t.width() - 1;
01113 if (barRight > geom.right()) barRight = geom.right();
01114
01115 QRect g = geom;
01116 g.setLeft( g.left() + 2 );
01117 g.setTop( g.top() + 2 );
01118 g.setRight( g.right() - 2 );
01119 g.setBottom( g.bottom() - 2 );
01120 frameTop += 2;
01121 barLeft += 2;
01122 barRight -= 2;
01123
01124 bound_shape.putPoints(0, 8,
01125 g.left(), frameTop,
01126 barLeft, frameTop,
01127 barLeft, g.top(),
01128 barRight, g.top(),
01129 barRight, frameTop,
01130 g.right(), frameTop,
01131 g.right(), g.bottom(),
01132 g.left(), g.bottom());
01133 } else {
01134 *visible_bound = geom;
01135 }
01136 QPainter p(workspaceWidget());
01137 p.setPen(QPen(Qt::white, 5));
01138 p.setRasterOp(Qt::XorROP);
01139 p.drawPolygon(bound_shape);
01140
01141 if (clear) {
01142 delete visible_bound;
01143 visible_bound = 0;
01144 }
01145 return true;
01146 }
01147
01148 bool B2Client::eventFilter(QObject *o, QEvent *e)
01149 {
01150 if (o != widget())
01151 return false;
01152 switch (e->type()) {
01153 case QEvent::Resize:
01154 resizeEvent(static_cast< QResizeEvent* >(e));
01155 return true;
01156 case QEvent::Paint:
01157 paintEvent(static_cast< QPaintEvent* >(e));
01158 return true;
01159 case QEvent::MouseButtonDblClick:
01160 titlebar->mouseDoubleClickEvent(static_cast< QMouseEvent* >(e));
01161 return true;
01162 case QEvent::MouseButtonPress:
01163 processMousePressEvent(static_cast< QMouseEvent* >(e));
01164 return true;
01165 case QEvent::Show:
01166 showEvent(static_cast< QShowEvent* >(e));
01167 return true;
01168 default:
01169 break;
01170 }
01171 return false;
01172 }
01173
01174
01175
01176 B2Button::B2Button(B2Client *_client, QWidget *parent,
01177 const QString& tip, const int realizeBtns)
01178 : QButton(parent, 0), hover(false)
01179 {
01180 setBackgroundMode(NoBackground);
01181 setCursor(arrowCursor);
01182 realizeButtons = realizeBtns;
01183 client = _client;
01184 useMiniIcon = false;
01185 setFixedSize(buttonSize, buttonSize);
01186 QToolTip::add(this, tip);
01187 }
01188
01189
01190 QSize B2Button::sizeHint() const
01191 {
01192 return QSize(buttonSize, buttonSize);
01193 }
01194
01195 QSizePolicy B2Button::sizePolicy() const
01196 {
01197 return(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
01198 }
01199
01200 void B2Button::drawButton(QPainter *p)
01201 {
01202 KPixmap* gradient = titleGradient[client->isActive() ? 0 : 1];
01203 if (gradient) {
01204 p->drawTiledPixmap(0, 0, buttonSize, buttonSize, *gradient, 0, 2);
01205 } else {
01206 p->fillRect(rect(), bg);
01207 }
01208 if (useMiniIcon) {
01209 QPixmap miniIcon = client->icon().pixmap(QIconSet::Small,
01210 client->isActive() ? QIconSet::Normal : QIconSet::Disabled);
01211 p->drawPixmap((width() - miniIcon.width()) / 2,
01212 (height() - miniIcon.height()) / 2, miniIcon);
01213 } else {
01214 int type;
01215 if (client->isActive()) {
01216 if (isOn() || isDown())
01217 type = Down;
01218 else if (hover)
01219 type = Hover;
01220 else
01221 type = Norm;
01222 } else {
01223 if (isOn() || isDown())
01224 type = IDown;
01225 else if (hover)
01226 type = IHover;
01227 else
01228 type = INorm;
01229 }
01230 p->drawPixmap((width() - icon[type]->width()) / 2,
01231 (height() - icon[type]->height()) / 2, *icon[type]);
01232 }
01233 }
01234
01235 void B2Button::setPixmaps(int button_id)
01236 {
01237 button_id *= NumStates;
01238 for (int i = 0; i < NumStates; i++) {
01239 icon[i] = B2::pixmap[button_id + i];
01240 }
01241 repaint(false);
01242 }
01243
01244 void B2Button::mousePressEvent(QMouseEvent * e)
01245 {
01246 last_button = e->button();
01247 QMouseEvent me(e->type(), e->pos(), e->globalPos(),
01248 (e->button() & realizeButtons) ? LeftButton : NoButton,
01249 e->state());
01250 QButton::mousePressEvent(&me);
01251 }
01252
01253 void B2Button::mouseReleaseEvent(QMouseEvent * e)
01254 {
01255 last_button = e->button();
01256 QMouseEvent me(e->type(), e->pos(), e->globalPos(),
01257 (e->button() & realizeButtons) ? LeftButton : NoButton,
01258 e->state());
01259 QButton::mouseReleaseEvent(&me);
01260 }
01261
01262 void B2Button::enterEvent(QEvent *e)
01263 {
01264 hover = true;
01265 repaint(false);
01266 QButton::enterEvent(e);
01267 }
01268
01269 void B2Button::leaveEvent(QEvent *e)
01270 {
01271 hover = false;
01272 repaint(false);
01273 QButton::leaveEvent(e);
01274 }
01275
01276
01277
01278 B2Titlebar::B2Titlebar(B2Client *parent)
01279 : QWidget(parent->widget(), 0, WStyle_Customize | WRepaintNoErase),
01280 client(parent),
01281 set_x11mask(false), isfullyobscured(false), shift_move(false)
01282 {
01283 setBackgroundMode(NoBackground);
01284 captionSpacer = new QSpacerItem(buttonSize, buttonSize + 4,
01285 QSizePolicy::Expanding, QSizePolicy::Fixed);
01286 }
01287
01288 bool B2Titlebar::x11Event(XEvent *e)
01289 {
01290 if (!set_x11mask) {
01291 set_x11mask = true;
01292 XSelectInput(qt_xdisplay(), winId(),
01293 KeyPressMask | KeyReleaseMask |
01294 ButtonPressMask | ButtonReleaseMask |
01295 KeymapStateMask |
01296 ButtonMotionMask |
01297 EnterWindowMask | LeaveWindowMask |
01298 FocusChangeMask |
01299 ExposureMask |
01300 PropertyChangeMask |
01301 StructureNotifyMask | SubstructureRedirectMask |
01302 VisibilityChangeMask);
01303 }
01304 switch (e->type) {
01305 case VisibilityNotify:
01306 isfullyobscured = false;
01307 if (e->xvisibility.state == VisibilityFullyObscured) {
01308 isfullyobscured = true;
01309 client->unobscureTitlebar();
01310 }
01311 break;
01312 default:
01313 break;
01314 }
01315 return QWidget::x11Event(e);
01316 }
01317
01318 void B2Titlebar::drawTitlebar(QPainter &p, bool state)
01319 {
01320 KPixmap* gradient = titleGradient[state ? 0 : 1];
01321
01322 QRect t = rect();
01323
01324 p.setPen(Qt::black);
01325 p.drawLine(0, 0, 0, t.bottom());
01326 p.drawLine(0, 0, t.right(), 0);
01327 p.drawLine(t.right(), 0, t.right(), t.bottom());
01328
01329
01330 const QColorGroup cg =
01331 options()->colorGroup(KDecoration::ColorTitleBar, state);
01332 QBrush brush(cg.background());
01333 if (gradient) brush.setPixmap(*gradient);
01334 qDrawShadeRect(&p, 1, 1, t.right() - 1, t.height() - 1,
01335 cg, false, 1, 0, &brush);
01336
01337
01338 p.setPen(options()->color(KDecoration::ColorFont, state));
01339 p.setFont(options()->font(state));
01340 t = captionSpacer->geometry();
01341 p.drawText(t, AlignLeft | AlignVCenter, client->caption());
01342 }
01343
01344 void B2Titlebar::recalcBuffer()
01345 {
01346 titleBuffer.resize(width(), height());
01347
01348 QPainter p(&titleBuffer);
01349 drawTitlebar(p, true);
01350 oldTitle = caption();
01351 }
01352
01353 void B2Titlebar::resizeEvent(QResizeEvent *)
01354 {
01355 recalcBuffer();
01356 repaint(false);
01357 }
01358
01359
01360 void B2Titlebar::paintEvent(QPaintEvent *)
01361 {
01362 if(client->isActive())
01363 bitBlt(this, 0, 0, &titleBuffer, 0, 0, titleBuffer.width(),
01364 titleBuffer.height(), Qt::CopyROP, true);
01365 else {
01366 QPainter p(this);
01367 drawTitlebar(p, false);
01368 }
01369 }
01370
01371 void B2Titlebar::mouseDoubleClickEvent(QMouseEvent *e)
01372 {
01373 if (e->y() < height()) {
01374 client->titlebarDblClickOperation();
01375 }
01376 }
01377
01378 void B2Titlebar::mousePressEvent(QMouseEvent * e)
01379 {
01380 shift_move = e->state() & ShiftButton;
01381 if (shift_move) {
01382 moveOffset = e->globalPos();
01383 } else {
01384 e->ignore();
01385 }
01386 }
01387
01388 void B2Titlebar::mouseReleaseEvent(QMouseEvent * e)
01389 {
01390 if (shift_move) shift_move = false;
01391 else e->ignore();
01392 }
01393
01394 void B2Titlebar::mouseMoveEvent(QMouseEvent * e)
01395 {
01396 if (shift_move) {
01397 int oldx = mapFromGlobal(moveOffset).x();
01398 int xdiff = e->globalPos().x() - moveOffset.x();
01399 moveOffset = e->globalPos();
01400 if (oldx >= 0 && oldx <= rect().right()) {
01401 client->titleMoveRel(xdiff);
01402 }
01403 } else {
01404 e->ignore();
01405 }
01406 }
01407
01408 }
01409
01410 #include "b2client.moc"
01411
01412
01413