1 /********************************************************************
2 This program is free software; you can redistribute it and/or modify
3 it under the terms of the GNU General Public License as published by
4 the Free Software Foundation; either version 2 of the License, or
5 (at your option) any later version.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *********************************************************************/
16 #include "nextclient.h"
21 #include <QHBoxLayout>
22 #include <QVBoxLayout>
24 #include <QPaintEvent>
26 #include <QResizeEvent>
27 #include <QMouseEvent>
34 static const unsigned char close_bits
[] = {
35 0x03, 0x03, 0x87, 0x03, 0xce, 0x01, 0xfc, 0x00, 0x78, 0x00, 0x78, 0x00,
36 0xfc, 0x00, 0xce, 0x01, 0x87, 0x03, 0x03, 0x03};
38 static const unsigned char iconify_bits
[] = {
39 0xff, 0x03, 0xff, 0x03, 0xff, 0x03, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03,
40 0x03, 0x03, 0x03, 0x03, 0xff, 0x03, 0xff, 0x03};
42 static const unsigned char question_bits
[] = {
43 0x00, 0x00, 0x78, 0x00, 0xcc, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00,
44 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00};
46 static const unsigned char sticky_bits
[] = {
47 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xfe, 0x01, 0xfe, 0x01,
48 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00};
50 static const unsigned char unsticky_bits
[] = {
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01,
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
54 static const unsigned char maximize_bits
[] = {
55 0x30, 0x00, 0x78, 0x00, 0xfc, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x01,
56 0x02, 0x01, 0x84, 0x00, 0x48, 0x00, 0x30, 0x00 };
58 static const unsigned char shade_bits
[] = {
71 static const unsigned char unshade_bits
[] = {
84 static const unsigned char keep_above_bits
[] = {
97 static const unsigned char from_above_bits
[] = {
110 static const unsigned char keep_below_bits
[] = {
123 static const unsigned char from_below_bits
[] = {
136 static const unsigned char resize_bits
[] = {
150 // If the maximize graphic above (which I did quickly in about a
151 // minute, just so I could have something) doesn't please, maybe one
152 // of the following would be better. IMO it doesn't matter, as long
153 // as it's not offensive---people will get used to whatever you use.
154 // True NeXT fans won't turn on the maximize button anyway.
156 // static const unsigned char maximize_bits[] = {
157 // 0xcf, 0x03, 0x87, 0x03, 0xcf, 0x03, 0xfd, 0x02, 0x48, 0x00, 0x48, 0x00,
158 // 0xfd, 0x02, 0xcf, 0x03, 0x87, 0x03, 0xcf, 0x03 };
160 // static const unsigned char maximize_bits[] = {
161 // 0xcf, 0x03, 0x87, 0x03, 0x87, 0x03, 0x79, 0x02, 0x48, 0x00, 0x48, 0x00,
162 // 0x79, 0x02, 0x87, 0x03, 0x87, 0x03, 0xcf, 0x03 };
164 // static const unsigned char maximize_bits[] = {
165 // 0x87, 0x03, 0x03, 0x03, 0xfd, 0x02, 0x84, 0x00, 0x84, 0x00, 0x84, 0x00,
166 // 0x84, 0x00, 0xfd, 0x02, 0x03, 0x03, 0x87, 0x03 };
168 // static const unsigned char maximize_bits[] = {
169 // 0x30, 0x00, 0x78, 0x00, 0xcc, 0x00, 0x86, 0x01, 0x33, 0x03, 0x79, 0x02,
170 // 0xcd, 0x02, 0x87, 0x03, 0x03, 0x03, 0x01, 0x02 };
172 // static const unsigned char maximize_bits[] = {
173 // 0x30, 0x00, 0x78, 0x00, 0x78, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfe, 0x01,
174 // 0xfe, 0x01, 0xff, 0x03, 0xff, 0x03, 0xff, 0x03 };
177 static QPixmap
*aTitlePix
;
178 static QPixmap
*iTitlePix
;
179 static QPixmap
*aFramePix
;
180 static QPixmap
*iFramePix
;
181 static QPixmap
*aHandlePix
;
182 static QPixmap
*iHandlePix
;
183 static QPixmap
*aBtn
;
184 static QPixmap
*aBtnDown
;
185 static QPixmap
*iBtn
;
186 static QPixmap
*iBtnDown
;
187 static QColor
*btnForeground
;
188 static bool pixmaps_created
= false;
190 static int titleHeight
= 16;
192 // Precomputed border sizes for accessibility
193 // The sizes are applied for tiny -> normal -> large -> very large -> huge -> very huge -> oversized
194 static const int borderSizes
[] = { 4, 6, 9, 14, 21, 32, 48 };
196 static int handleSize
= 6; // the resize handle size in pixels
198 static inline const KDecorationOptions
* options()
200 return KDecoration::options();
203 static void verticalGradient(QPixmap
*pix
, QColor first
, QColor second
)
205 QLinearGradient
gradient(0, 0, 0, pix
->height());
206 gradient
.setColorAt(0.0, first
);
207 gradient
.setColorAt(1.0, second
);
208 QBrush
brush(gradient
);
211 p
.fillRect(pix
->rect(), brush
);
215 static void diagonalGradient(QPixmap
*pix
, QColor first
, QColor second
)
217 QLinearGradient
gradient(0, 0, pix
->width(), pix
->height());
218 gradient
.setColorAt(0.0, first
);
219 gradient
.setColorAt(1.0, second
);
220 QBrush
brush(gradient
);
223 p
.fillRect(pix
->rect(), brush
);
227 static void create_pixmaps(NextClientFactory
*f
)
231 pixmaps_created
= true;
233 // find preferred border size
234 int i
= options()->preferredBorderSize(f
);
235 if (i
>= 0 && i
<= 6) handleSize
= borderSizes
[i
];
237 titleHeight
= QFontMetrics(options()->font(true)).height() + 4;
238 if (titleHeight
< handleSize
) titleHeight
= handleSize
;
239 titleHeight
&= ~1; // Make title height even
240 if (titleHeight
< 16) titleHeight
= 16;
242 const int gradientHeight
= titleHeight
- 2;
243 aTitlePix
= new QPixmap(32, gradientHeight
);
245 verticalGradient(aTitlePix
,
246 options()->color(KDecoration::ColorTitleBar
, true),
247 options()->color(KDecoration::ColorTitleBlend
, true));
248 iTitlePix
= new QPixmap(32, titleHeight
- 2);
250 verticalGradient(iTitlePix
,
251 options()->color(KDecoration::ColorTitleBar
, false),
252 options()->color(KDecoration::ColorTitleBlend
, false));
253 // Bottom frame gradient
254 aFramePix
= new QPixmap(32, handleSize
);
255 verticalGradient(aFramePix
,
256 options()->color(KDecoration::ColorFrame
, true).light(150),
257 options()->color(KDecoration::ColorFrame
, true).dark(120));
258 iFramePix
= new QPixmap(32, handleSize
);
259 verticalGradient(iFramePix
,
260 options()->color(KDecoration::ColorFrame
, false).light(150),
261 options()->color(KDecoration::ColorFrame
, false).dark(120));
263 aHandlePix
= new QPixmap(32, handleSize
);
264 verticalGradient(aHandlePix
,
265 options()->color(KDecoration::ColorHandle
, true).light(150),
266 options()->color(KDecoration::ColorHandle
, true).dark(120));
267 iHandlePix
= new QPixmap(32, handleSize
);
268 verticalGradient(iHandlePix
,
269 options()->color(KDecoration::ColorHandle
, true).light(150),
270 options()->color(KDecoration::ColorHandle
, true).dark(120));
272 int btnWidth
= titleHeight
;
273 iBtn
= new QPixmap(btnWidth
, btnWidth
);
274 iBtnDown
= new QPixmap(btnWidth
, btnWidth
);
275 aBtn
= new QPixmap(btnWidth
, btnWidth
);
276 aBtnDown
= new QPixmap(btnWidth
, btnWidth
);
277 int internalHeight
= btnWidth
- 6;
278 QPixmap
internal(internalHeight
, internalHeight
);
279 QRect
dest(internal
.rect());
285 QColor
c(options()->color(KDecoration::ColorButtonBg
, false));
286 diagonalGradient(iBtn
, c
.light(120), c
.dark(120));
287 diagonalGradient(&internal
, c
.dark(120), c
.light(120));
289 p
.drawPixmap(dest
, internal
, internal
.rect());
291 //bitBlt(iBtn, 3, 3, &internal, 0, 0, internalHeight, internalHeight, Qt::CopyROP, true);
294 diagonalGradient(iBtnDown
, c
.dark(120), c
.light(120));
295 diagonalGradient(&internal
, c
.light(120), c
.dark(120));
296 //bitBlt(iBtnDown, 3, 3, &internal, 0, 0, internalHeight, internalHeight, Qt::CopyROP, true);
299 p
.drawPixmap(dest
, internal
, internal
.rect());
303 c
= options()->color(KDecoration::ColorButtonBg
, true);
304 diagonalGradient(aBtn
, c
.light(120), c
.dark(120));
305 diagonalGradient(&internal
, c
.dark(120), c
.light(120));
306 //bitBlt(aBtn, 3, 3, &internal, 0, 0, internalHeight, internalHeight, Qt::CopyROP, true);
308 p
.drawPixmap(dest
, internal
, internal
.rect());
311 diagonalGradient(aBtnDown
, c
.dark(120), c
.light(120));
312 diagonalGradient(&internal
, c
.light(120), c
.dark(120));
313 //bitBlt(aBtnDown, 3, 3, &internal, 0, 0, internalHeight, internalHeight, Qt::CopyROP, true);
315 p
.drawPixmap(dest
, internal
, internal
.rect());
320 p
.drawRect(0, 0, btnWidth
, btnWidth
);
324 p
.drawRect(0, 0, btnWidth
, btnWidth
);
328 p
.drawRect(0, 0, btnWidth
, btnWidth
);
332 p
.drawRect(0, 0, btnWidth
, btnWidth
);
335 if(qGray(options()->color(KDecoration::ColorButtonBg
, true).rgb()) > 128)
336 btnForeground
= new QColor(Qt::black
);
338 btnForeground
= new QColor(Qt::white
);
341 static void delete_pixmaps()
353 delete btnForeground
;
355 pixmaps_created
= false;
358 // =====================================
360 NextButton::NextButton(NextClient
*parent
,
361 const unsigned char *bitmap
, int bw
, int bh
,
362 const QString
& tip
, const int realizeBtns
)
363 : QAbstractButton(parent
->widget()),
364 client(parent
), last_button(Qt::NoButton
)
366 realizeButtons
= realizeBtns
;
368 setAttribute(Qt::WA_NoSystemBackground
);
369 resize(titleHeight
, titleHeight
);
370 setFixedSize(titleHeight
, titleHeight
);
373 setBitmap(bitmap
, bw
, bh
);
375 this->setToolTip( tip
);
378 void NextButton::reset()
383 void NextButton::setBitmap(const unsigned char *bitmap
, int w
, int h
)
386 deco
= QBitmap::fromData(s
, bitmap
, QImage::Format_MonoLSB
);
391 void NextButton::paintEvent(QPaintEvent
*)
394 if (client
->isActive())
395 p
.drawPixmap(0, 0, isDown() ? *aBtnDown
: *aBtn
);
397 p
.drawPixmap(0, 0, isDown() ? *iBtnDown
: *iBtn
);
399 // If we have a decoration, draw it; otherwise, we have the menu
400 // button (remember, we set the bitmap to NULL).
402 if (!deco
.isNull()) {
403 offset
= (titleHeight
- 10) / 2 + (isDown() ? 1 : 0);
404 p
.setPen(*btnForeground
);
405 p
.drawPixmap(offset
, offset
, deco
);
407 offset
= (titleHeight
- 16) / 2;
408 QPixmap btnpix
= client
->icon().pixmap(
409 style()->pixelMetric(QStyle::PM_SmallIconSize
),
410 client
->isActive() ? QIcon::Normal
: QIcon::Disabled
);
411 p
.drawPixmap(offset
, offset
, btnpix
);
415 void NextButton::mousePressEvent( QMouseEvent
* e
)
417 last_button
= e
->button();
418 QMouseEvent
me(e
->type(), e
->pos(), e
->globalPos(),
419 (e
->button() & realizeButtons
) ? Qt::LeftButton
: Qt::NoButton
,
420 (e
->button() & realizeButtons
) ? Qt::LeftButton
: Qt::NoButton
,
422 QAbstractButton::mousePressEvent(&me
);
425 void NextButton::mouseReleaseEvent( QMouseEvent
* e
)
427 last_button
= e
->button();
428 QMouseEvent
me(e
->type(), e
->pos(), e
->globalPos(),
429 (e
->button() & realizeButtons
) ? Qt::LeftButton
: Qt::NoButton
,
430 (e
->button() & realizeButtons
) ? Qt::LeftButton
: Qt::NoButton
,
432 QAbstractButton::mouseReleaseEvent(&me
);
435 // =====================================
437 NextClient::NextClient(KDecorationBridge
*b
, KDecorationFactory
*f
)
442 void NextClient::init()
445 widget()->setAttribute(Qt::WA_NoSystemBackground
);
446 widget()->installEventFilter(this);
448 //widget()->setBackgroundMode( NoBackground );
450 QVBoxLayout
*mainLayout
= new QVBoxLayout(widget());
451 QBoxLayout
*titleLayout
= new QBoxLayout(QBoxLayout::LeftToRight
);
452 QHBoxLayout
*windowLayout
= new QHBoxLayout();
453 mainLayout
->setMargin(0);
454 titleLayout
->setMargin(0);
455 titleLayout
->setSpacing(0);
456 mainLayout
->addLayout(titleLayout
);
457 mainLayout
->addLayout(windowLayout
, 1);
458 mainLayout
->addSpacing(mustDrawHandle() ? handleSize
: 1);
460 windowLayout
->addSpacing(1);
462 windowLayout
->addWidget(new QLabel(i18n(
463 "<center><b>KStep preview</b></center>"), widget()));
465 windowLayout
->addItem(new QSpacerItem( 0, 0 ));
467 windowLayout
->addSpacing(1);
469 initializeButtonsAndTitlebar(titleLayout
);
474 + button is an array of length MAX_NUM_BUTTONS
477 + Title bar and buttons have been initialized and laid out
478 + for all i in 0..(MAX_NUM_BUTTONS-1), button[i] points to
479 either (1) a valid NextButton instance, if the corresponding
480 button is selected in the current button scheme, or (2) null
483 void NextClient::initializeButtonsAndTitlebar(QBoxLayout
* titleLayout
)
485 // Null the buttons to begin with (they are not guaranteed to be null).
486 for (int i
=0; i
<MAX_NUM_BUTTONS
; i
++) {
490 // The default button positions for other styles do not match the
491 // behavior of older versions of KStep, so we have to set these
492 // manually when customButtonPositions isn't enabled.
494 if (options()->customButtonPositions()) {
495 left
= options()->titleButtonsLeft();
496 right
= options()->titleButtonsRight();
499 right
= QString("SX");
502 // Do actual creation and addition to titleLayout
503 addButtons(titleLayout
, left
);
505 titlebar
= new QSpacerItem(10, titleHeight
, QSizePolicy::Expanding
,
506 QSizePolicy::Minimum
);
507 titleLayout
->addItem(titlebar
);
508 addButtons(titleLayout
, right
);
510 // Finally, activate all live buttons
511 for (int i
= 0; i
< MAX_NUM_BUTTONS
; i
++) {
513 button
[i
]->setMouseTracking( TRUE
);
518 /** Adds the buttons for one side of the title bar, based on the spec
519 * string; see the KWin::KDecoration class, methods
520 * titleButtonsLeft and titleBUttonsRight. */
521 void NextClient::addButtons(QBoxLayout
* titleLayout
, const QString
& spec
)
523 for (int i
= 0; i
< spec
.length(); i
++) {
524 switch (spec
[i
].toLatin1()) {
526 if (isMaximizable()) {
527 button
[MAXIMIZE_IDX
] =
528 new NextButton(this, maximize_bits
, 10, 10,
529 i18n("Maximize"), Qt::LeftButton
|Qt::MidButton
|Qt::RightButton
);
530 titleLayout
->addWidget( button
[MAXIMIZE_IDX
] );
531 connect( button
[MAXIMIZE_IDX
], SIGNAL(clicked()),
532 this, SLOT(maximizeButtonClicked()) );
537 if (providesContextHelp()) {
538 button
[HELP_IDX
] = new NextButton(this, question_bits
, 10, 10, i18n("Help"));
539 titleLayout
->addWidget( button
[HELP_IDX
] );
540 connect( button
[HELP_IDX
], SIGNAL(clicked()),
541 this, SLOT(showContextHelp()) );
546 if (isMinimizable()) {
547 button
[ICONIFY_IDX
] =
548 new NextButton(this, iconify_bits
, 10, 10,
550 titleLayout
->addWidget( button
[ICONIFY_IDX
] );
551 connect( button
[ICONIFY_IDX
], SIGNAL(clicked()),
552 this, SLOT(minimize()) );
558 new NextButton(this, NULL
, 10, 10, i18n("Menu"), Qt::LeftButton
|Qt::RightButton
);
559 titleLayout
->addWidget( button
[MENU_IDX
] );
560 // NOTE DIFFERENCE: capture pressed(), not clicked()
561 connect( button
[MENU_IDX
], SIGNAL(pressed()),
562 this, SLOT(menuButtonPressed()) );
567 new NextButton(this, NULL
, 0, 0, i18n("Shade"));
568 titleLayout
->addWidget( button
[SHADE_IDX
] );
569 connect( button
[SHADE_IDX
], SIGNAL(clicked()),
570 this, SLOT(shadeClicked()) );
571 // NOTE DIFFERENCE: set the pixmap separately (2 states)
577 new NextButton(this, NULL
, 0, 0, i18n("On all desktops"));
578 titleLayout
->addWidget( button
[STICKY_IDX
] );
579 connect( button
[STICKY_IDX
], SIGNAL(clicked()),
580 this, SLOT(toggleOnAllDesktops()) );
581 // NOTE DIFFERENCE: set the pixmap separately (2 states)
586 button
[ABOVE_IDX
] = new NextButton(this, NULL
, 0, 0, "");
587 titleLayout
->addWidget( button
[ABOVE_IDX
] );
588 connect( button
[ABOVE_IDX
], SIGNAL(clicked()),
589 this, SLOT(aboveClicked()) );
590 connect(this, SIGNAL(keepAboveChanged(bool)),
591 SLOT(keepAboveChange(bool)));
592 keepAboveChange(keepAbove());
596 button
[BELOW_IDX
] = new NextButton(this, NULL
, 0, 0, "");
597 titleLayout
->addWidget( button
[BELOW_IDX
] );
598 connect( button
[BELOW_IDX
], SIGNAL(clicked()),
599 this, SLOT(belowClicked()) );
600 connect(this, SIGNAL(keepBelowChanged(bool)),
601 SLOT(keepBelowChange(bool)));
602 keepBelowChange(keepBelow());
608 new NextButton(this, close_bits
, 10, 10,
610 titleLayout
->addWidget(button
[CLOSE_IDX
]);
611 connect(button
[CLOSE_IDX
], SIGNAL(clicked()),
612 this, SLOT(closeWindow()));
617 if (mustDrawHandle()) {
619 new NextButton(this, resize_bits
, 10, 10,
621 titleLayout
->addWidget(button
[RESIZE_IDX
]);
622 // NOTE DIFFERENCE: capture pressed(), not clicked()
623 connect(button
[RESIZE_IDX
], SIGNAL(pressed()),
624 this, SLOT(resizePressed()));
628 // TODO: Add spacer handling
632 kDebug() << " Can't happen: unknown button code "
639 bool NextClient::mustDrawHandle() const
641 bool drawSmallBorders
= !options()->moveResizeMaximizedWindows();
642 if (drawSmallBorders
&& (maximizeMode() & MaximizeVertical
)) {
645 return isResizable();
649 void NextClient::iconChange()
651 if (button
[MENU_IDX
] && button
[MENU_IDX
]->isVisible())
652 button
[MENU_IDX
]->repaint();
655 void NextClient::menuButtonPressed()
657 // Probably don't need this null check, but we might as well.
658 if (button
[MENU_IDX
]) {
659 QRect menuRect
= button
[MENU_IDX
]->rect();
660 QPoint menuTop
= button
[MENU_IDX
]->mapToGlobal(menuRect
.topLeft());
661 QPoint menuBottom
= button
[MENU_IDX
]->mapToGlobal(menuRect
.bottomRight());
662 menuTop
+= QPoint(1, 1);
663 menuBottom
+= QPoint(1, 1);
664 KDecorationFactory
* f
= factory();
665 showWindowMenu(QRect(menuTop
, menuBottom
));
666 if( !f
->exists( this )) // 'this' was deleted
668 button
[MENU_IDX
]->setDown(false);
672 // Copied, with minor edits, from KDEDefaultClient::slotMaximize()
673 void NextClient::maximizeButtonClicked()
675 if (button
[MAXIMIZE_IDX
]) {
676 maximize(button
[MAXIMIZE_IDX
]->lastButton());
680 void NextClient::shadeClicked()
682 setShade(!isSetShade());
685 void NextClient::aboveClicked()
687 setKeepAbove(!keepAbove());
690 void NextClient::belowClicked()
692 setKeepBelow(!keepBelow());
693 keepAboveChange(keepAbove());
694 keepBelowChange(keepBelow());
697 void NextClient::resizePressed()
699 performWindowOperation(ResizeOp
);
702 void NextClient::resizeEvent(QResizeEvent
*)
704 if (widget()->isVisible()) {
705 // TODO ? update border area only?
708 widget()->update(titlebar
->geometry());
709 QPainter
p(widget());
710 QRect t
= titlebar
->geometry();
712 QRegion r
= widget()->rect();
714 p
.setClipRegion( r
);
715 p
.eraseRect(widget()->rect());
720 void NextClient::captionChange()
722 widget()->repaint(titlebar
->geometry());
726 void NextClient::paintEvent( QPaintEvent
* )
728 QPainter
p(widget());
731 QRect fr
= widget()->rect();
736 QRect t
= titlebar
->geometry();
738 p
.drawTiledPixmap(t
.x()+1, t
.y()+1, t
.width()-2, t
.height()-2,
739 isActive() ? *aTitlePix
: *iTitlePix
);
740 qDrawShadePanel(&p
, t
.x(), t
.y(), t
.width(), t
.height()-1,
741 options()->palette(KDecoration::ColorTitleBar
, isActive()));
742 p
.drawLine(t
.x(), t
.bottom(), t
.right(), t
.bottom());
745 // Why setting up a clipping region if it is not used? (setClipping(false))
748 p
.setClipRegion( r
);
749 p
.setClipping(false);
753 t
.setHeight(t
.height()-2);
754 t
.setLeft( t
.left() + 4 );
755 t
.setRight( t
.right() - 2 );
757 p
.setPen(options()->color(KDecoration::ColorFont
, isActive()));
758 p
.setFont(options()->font(isActive()));
759 p
.drawText( t
, Qt::AlignCenter
| Qt::AlignVCenter
, caption() );
761 // Draw resize handle
762 if (mustDrawHandle()) {
763 int corner
= 16 + 3*handleSize
/2;
765 fr
.x() + 1, fr
.bottom() - handleSize
, corner
-1, handleSize
,
766 options()->palette(KDecoration::ColorHandle
, isActive()),
768 p
.drawTiledPixmap(fr
.x() + 2, fr
.bottom() - handleSize
+ 1,
769 corner
- 3, handleSize
- 2, isActive() ? *aHandlePix
: *iHandlePix
);
772 fr
.x() + corner
, fr
.bottom() - handleSize
,
773 fr
.width() - 2*corner
, handleSize
,
774 options()->palette(KDecoration::ColorFrame
, isActive()),
776 p
.drawTiledPixmap(fr
.x() + corner
+ 1, fr
.bottom() - handleSize
+ 1,
777 fr
.width() - 2*corner
- 2, handleSize
- 2,
778 isActive() ? *aFramePix
: *iFramePix
);
781 fr
.right() - corner
+ 1, fr
.bottom() - handleSize
, corner
- 1, handleSize
,
782 options()->palette(KDecoration::ColorHandle
, isActive()),
784 p
.drawTiledPixmap(fr
.right() - corner
+ 2, fr
.bottom() - handleSize
+ 1,
785 corner
- 3, handleSize
- 2, isActive() ? *aHandlePix
: *iHandlePix
);
789 void NextClient::mouseDoubleClickEvent( QMouseEvent
* e
)
791 if (e
->button() == Qt::LeftButton
&& titlebar
->geometry().contains( e
->pos() ) )
792 titlebarDblClickOperation();
795 void NextClient::showEvent(QShowEvent
*)
800 void NextClient::desktopChange()
802 bool on
= isOnAllDesktops();
803 if (NextButton
* b
= button
[STICKY_IDX
]) {
804 b
->setBitmap( on
? unsticky_bits
: sticky_bits
, 10, 10);
805 //QToolTip::remove(b);
806 b
->setToolTip( on
? i18n("Not on all desktops") : i18n("On all desktops"));
810 void NextClient::maximizeChange()
812 if (button
[MAXIMIZE_IDX
]) {
813 bool m
= maximizeMode() == MaximizeFull
;
814 //button[MAXIMIZE_IDX]->setBitmap(m ? minmax_bits : maximize_bits);
815 //QToolTip::remove(button[MAXIMIZE_IDX]);
816 button
[MAXIMIZE_IDX
]->setToolTip(
817 m
? i18n("Restore") : i18n("Maximize"));
819 //spacer->changeSize(10, mustDrawHandle() ? handleSize : 1,
820 // QSizePolicy::Expanding, QSizePolicy::Minimum);
821 //mainLayout->activate();
824 void NextClient::activeChange()
830 void NextClient::slotReset()
832 for (int i
=0; i
<MAX_NUM_BUTTONS
; i
++) {
839 KDecoration::Position
840 NextClient::mousePosition( const QPoint
& p
) const
842 Position m
= PositionCenter
;
844 if (p
.y() < (height() - handleSize
))
845 m
= KDecoration::mousePosition(p
);
848 int corner
= 16 + 3*handleSize
/2;
849 if (p
.x() >= (width() - corner
))
850 m
= PositionBottomRight
;
851 else if (p
.x() <= corner
)
852 m
= PositionBottomLeft
;
860 void NextClient::borders(int &left
, int &right
, int &top
, int &bottom
) const
863 top
= titleHeight
; // FRAME is this ok?
864 bottom
= mustDrawHandle() ? handleSize
: 1;
867 void NextClient::shadeChange()
869 if (NextButton
*b
= button
[SHADE_IDX
]) {
870 b
->setBitmap(isSetShade() ? unshade_bits
: shade_bits
, 10, 10);
871 //QToolTip::remove(b);
872 b
->setToolTip( isSetShade() ? i18n("Unshade") : i18n("Shade"));
876 void NextClient::keepAboveChange(bool above
)
878 if (NextButton
*b
= button
[ABOVE_IDX
]) {
879 b
->setBitmap(above
? from_above_bits
: keep_above_bits
, 10, 10);
880 //QToolTip::remove(b);
881 b
->setToolTip( above
?
882 i18n("Do not keep above others") : i18n("Keep above others"));
887 void NextClient::keepBelowChange(bool below
)
889 if (NextButton
*b
= button
[BELOW_IDX
]) {
890 b
->setBitmap(below
? from_below_bits
: keep_below_bits
, 10, 10);
891 //QToolTip::remove(b);
892 b
->setToolTip( below
?
893 i18n("Do not keep below others") : i18n("Keep below others"));
898 QSize
NextClient::minimumSize() const
900 return QSize(titleHeight
* 6 + 2, titleHeight
+ handleSize
+ 2);
903 void NextClient::resize(const QSize
& s
)
908 void NextClient::reset(unsigned long)
910 for (int i
= 0; i
< MAX_NUM_BUTTONS
; ++i
) {
917 bool NextClient::eventFilter(QObject
*o
, QEvent
*e
)
923 resizeEvent(static_cast< QResizeEvent
* >( e
));
926 paintEvent(static_cast< QPaintEvent
* >( e
));
928 case QEvent::MouseButtonDblClick
:
929 mouseDoubleClickEvent(static_cast< QMouseEvent
* >( e
));
931 case QEvent::MouseButtonPress
:
932 processMousePressEvent(static_cast< QMouseEvent
* >( e
));
935 showEvent(static_cast< QShowEvent
* >( e
));
943 bool NextClient::drawbound(const QRect
& geom
, bool /* clear */)
945 // Let kwin draw the bounds, for now.
948 QPainter
p(workspaceWidget());
949 p
.setPen(QPen(Qt::white
, 3));
950 p
.setCompositionMode(QPainter::CompositionMode_Xor
);
952 int leftMargin
= geom
.left() + 2;
953 p
.fillRect(leftMargin
, geom
.top() + titleHeight
- 1,
954 geom
.width() - 4, 3, Qt::white
);
955 if (mustDrawHandle()) {
956 p
.fillRect(leftMargin
, geom
.bottom() - handleSize
- 1,
957 geom
.width() - 4, 3, Qt::white
);
963 // =====================================
965 NextClientFactory::NextClientFactory()
967 create_pixmaps(this);
970 NextClientFactory::~NextClientFactory()
975 KDecoration
*NextClientFactory::createDecoration(KDecorationBridge
*b
)
977 return new NextClient(b
, this);
980 bool NextClientFactory::reset(unsigned long /*changed*/)
982 // TODO Do not recreate decorations if it is not needed. Look at
983 // ModernSystem for how to do that
985 create_pixmaps(this);
986 // For now just return true.
990 bool NextClientFactory::supports( Ability ability
) const
994 case AbilityAnnounceButtons
:
995 case AbilityButtonMenu
:
996 case AbilityButtonOnAllDesktops
:
997 case AbilityButtonHelp
:
998 case AbilityButtonMinimize
:
999 case AbilityButtonMaximize
:
1000 case AbilityButtonClose
:
1001 case AbilityButtonAboveOthers
:
1002 case AbilityButtonBelowOthers
:
1003 case AbilityButtonShade
:
1004 case AbilityButtonResize
:
1011 QList
< NextClientFactory::BorderSize
>
1012 NextClientFactory::borderSizes() const
1014 // the list must be sorted
1015 return QList
< BorderSize
>() << BorderTiny
<< BorderNormal
<<
1016 BorderLarge
<< BorderVeryLarge
<< BorderHuge
<<
1017 BorderVeryHuge
<< BorderOversized
;
1020 } // KStep namespace
1022 extern "C" KDE_EXPORT KDecorationFactory
* create_factory()
1024 return new KStep::NextClientFactory();
1027 #include "nextclient.moc"