1 #include "systemclient.h"
11 #include <QPaintEvent>
12 #include <QGridLayout>
15 #include <Q3ValueList>
17 #include <QResizeEvent>
18 #include <QMouseEvent>
20 #include <kpixmapeffect.h>
21 #include <kdrawutil.h>
23 #include <kapplication.h>
26 // Default button layout
27 const char default_left
[] = "X";
28 const char default_right
[] = "HSIA";
32 static unsigned char iconify_bits
[] = {
33 0x00, 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00};
35 static unsigned char maximize_bits
[] = {
36 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00};
38 static unsigned char r_minmax_bits
[] = {
39 0x0c, 0x18, 0x33, 0x67, 0xcf, 0x9f, 0x3f, 0x3f};
41 static unsigned char l_minmax_bits
[] = {
42 0x30, 0x18, 0xcc, 0xe6, 0xf3, 0xf9, 0xfc, 0xfc};
44 static unsigned char unsticky_bits
[] = {
45 0x00, 0x18, 0x18, 0x7e, 0x7e, 0x18, 0x18, 0x00};
47 static unsigned char sticky_bits
[] = {
48 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00};
50 static unsigned char question_bits
[] = {
51 0x3c, 0x66, 0x60, 0x30, 0x18, 0x00, 0x18, 0x18};
53 static KPixmap
*aUpperGradient
=0;
54 static KPixmap
*iUpperGradient
=0;
56 static KPixmap
*btnPix
=0;
57 static KPixmap
*btnPixDown
=0;
58 static KPixmap
*iBtnPix
=0;
59 static KPixmap
*iBtnPixDown
=0;
60 static QColor
*btnForeground
;
62 static bool pixmaps_created
= false;
64 static void drawButtonFrame(KPixmap
*pix
, const QColorGroup
&g
)
69 p
.drawLine(0, 0, 13, 0);
70 p
.drawLine(0, 0, 0, 13);
72 p
.drawLine(13, 0, 13, 13);
73 p
.drawLine(0, 13, 13, 13);
75 p
.drawRect(1, 1, 12, 12);
79 static void create_pixmaps()
83 pixmaps_created
= true;
85 if(QPixmap::defaultDepth() > 8){
87 aUpperGradient
= new KPixmap
;
88 aUpperGradient
->resize(32, 18);
89 iUpperGradient
= new KPixmap
;
90 iUpperGradient
->resize(32, 18);
91 QColor bgColor
= kapp
->palette().active().background();
92 KPixmapEffect::gradient(*aUpperGradient
,
93 KDecoration::options()->color(KDecorationOptions::ColorFrame
, true).light(130),
95 KPixmapEffect::VerticalGradient
);
96 KPixmapEffect::gradient(*iUpperGradient
,
97 KDecoration::options()->color(KDecorationOptions::ColorFrame
, false).light(130),
99 KPixmapEffect::VerticalGradient
);
107 aInternal
.resize(8, 8);
109 iInternal
.resize(8, 8);
111 QColor
hColor(KDecoration::options()->color(KDecorationOptions::ColorButtonBg
, false));
112 KPixmapEffect::gradient(iInternal
,
115 KPixmapEffect::DiagonalGradient
);
116 KPixmapEffect::gradient(iPix
,
119 KPixmapEffect::DiagonalGradient
);
121 hColor
=KDecoration::options()->color(KDecorationOptions::ColorButtonBg
, true);
122 KPixmapEffect::gradient(aInternal
,
125 KPixmapEffect::DiagonalGradient
);
126 KPixmapEffect::gradient(aPix
,
129 KPixmapEffect::DiagonalGradient
);
130 bitBlt(&aPix
, 1, 1, &aInternal
, 0, 0, 8, 8, Qt::CopyROP
, true);
131 bitBlt(&iPix
, 1, 1, &iInternal
, 0, 0, 8, 8, Qt::CopyROP
, true);
134 btnPix
= new KPixmap
;
135 btnPix
->resize(14, 14);
136 bitBlt(btnPix
, 2, 2, &aPix
, 0, 0, 10, 10, Qt::CopyROP
, true);
137 drawButtonFrame(btnPix
, KDecoration::options()->colorGroup(KDecorationOptions::ColorFrame
, true));
139 iBtnPix
= new KPixmap
;
140 iBtnPix
->resize(14, 14);
141 bitBlt(iBtnPix
, 2, 2, &iPix
, 0, 0, 10, 10, Qt::CopyROP
, true);
142 drawButtonFrame(iBtnPix
, KDecoration::options()->colorGroup(KDecorationOptions::ColorFrame
, false));
146 hColor
= KDecoration::options()->color(KDecorationOptions::ColorButtonBg
, false);
147 KPixmapEffect::gradient(iInternal
,
150 KPixmapEffect::DiagonalGradient
);
151 KPixmapEffect::gradient(iPix
,
154 KPixmapEffect::DiagonalGradient
);
156 hColor
=KDecoration::options()->color(KDecorationOptions::ColorButtonBg
, true);
157 KPixmapEffect::gradient(aInternal
,
160 KPixmapEffect::DiagonalGradient
);
161 KPixmapEffect::gradient(aPix
,
164 KPixmapEffect::DiagonalGradient
);
165 bitBlt(&aPix
, 1, 1, &aInternal
, 0, 0, 8, 8, Qt::CopyROP
, true);
166 bitBlt(&iPix
, 1, 1, &iInternal
, 0, 0, 8, 8, Qt::CopyROP
, true);
168 btnPixDown
= new KPixmap
;
169 btnPixDown
->resize(14, 14);
170 bitBlt(btnPixDown
, 2, 2, &aPix
, 0, 0, 10, 10, Qt::CopyROP
, true);
171 drawButtonFrame(btnPixDown
, KDecoration::options()->colorGroup(KDecorationOptions::ColorFrame
,
174 iBtnPixDown
= new KPixmap
;
175 iBtnPixDown
->resize(14, 14);
176 bitBlt(iBtnPixDown
, 2, 2, &iPix
, 0, 0, 10, 10, Qt::CopyROP
, true);
177 drawButtonFrame(iBtnPixDown
, KDecoration::options()->colorGroup(KDecorationOptions::ColorFrame
,
180 if(qGray(KDecoration::options()->color(KDecorationOptions::ColorButtonBg
, true).rgb()) > 128)
181 btnForeground
= new QColor(Qt::black
);
183 btnForeground
= new QColor(Qt::white
);
186 static void delete_pixmaps()
189 delete aUpperGradient
;
190 delete iUpperGradient
;
197 delete btnForeground
;
198 pixmaps_created
= false;
201 SystemButton::SystemButton(SystemClient
*parent
, const char *name
,
202 const unsigned char *bitmap
, const QString
& tip
)
203 : Q3Button(parent
->widget(), name
)
206 setBackgroundMode( Qt::NoBackground
);
207 setCursor(Qt::ArrowCursor
);
214 void SystemButton::setTipText(const QString
&tip
)
216 if (KDecoration::options()->showTooltips())
218 QToolTip::remove(this );
219 this->setToolTip( tip
);
224 QSize
SystemButton::sizeHint() const
226 return(QSize(14, 14));
229 void SystemButton::reset()
234 void SystemButton::setBitmap(const unsigned char *bitmap
)
236 deco
= QBitmap(8, 8, bitmap
, true);
241 void SystemButton::drawButton(QPainter
*p
)
244 if(client
->isActive())
245 p
->drawPixmap(0, 0, isDown() ? *btnPixDown
: *btnPix
);
247 p
->drawPixmap(0, 0, isDown() ? *iBtnPixDown
: *iBtnPix
);
250 QColorGroup g
= KDecoration::options()->color(KDecorationOptions::ColorFrame
,
256 p
->drawLine(0, 0, x2
, 0);
257 p
->drawLine(0, 0, 0, y2
);
258 p
->setPen(g
.light());
259 p
->drawLine(x2
, 0, x2
, y2
);
260 p
->drawLine(0, x2
, y2
, x2
);
262 p
->drawRect(1, 1, width()-2, height()-2);
264 g
= KDecoration::options()->colorGroup(KDecorationOptions::ColorButtonBg
, client
->isActive());
265 p
->fillRect(3, 3, width()-6, height()-6, g
.background());
266 p
->setPen(isDown() ? g
.mid() : g
.light());
267 p
->drawLine(2, 2, x2
-2, 2);
268 p
->drawLine(2, 2, 2, y2
-2);
269 p
->setPen(isDown() ? g
.light() : g
.mid());
270 p
->drawLine(x2
-2, 2, x2
-2, y2
-2);
271 p
->drawLine(2, x2
-2, y2
-2, x2
-2);
276 p
->setPen(*btnForeground
);
277 p
->drawPixmap(isDown() ? 4 : 3, isDown() ? 4 : 3, deco
);
281 void SystemButton::mousePressEvent( QMouseEvent
* e
)
283 last_button
= e
->button();
284 QMouseEvent
me ( e
->type(), e
->pos(), e
->globalPos(), Qt::LeftButton
, e
->state() );
285 Q3Button::mousePressEvent( &me
);
288 void SystemButton::mouseReleaseEvent( QMouseEvent
* e
)
290 last_button
= e
->button();
291 QMouseEvent
me ( e
->type(), e
->pos(), e
->globalPos(), Qt::LeftButton
, e
->state() );
292 Q3Button::mouseReleaseEvent( &me
);
297 SystemClient::SystemClient(KDecorationBridge
* bridge
, KDecorationFactory
* factory
)
298 : KDecoration(bridge
, factory
)
301 SystemClient::~SystemClient()
303 for (int n
=0; n
<ButtonTypeCount
; n
++) {
304 if (button
[n
]) delete button
[n
];
308 void SystemClient::init()
311 widget()->installEventFilter( this );
313 QGridLayout
* g
= new QGridLayout(widget(), 0, 0, 2);
317 g
->addWidget(new QLabel(i18n("<center><b>System++ preview</b></center>"), widget()), 1, 1);
321 g
->addItem(new QSpacerItem( 0, 0 ), 1, 1); // no widget in the middle
323 // g->addItem( new QSpacerItem( 0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding ) );
324 g
->setRowStretch(1, 10);
326 g
->addColSpacing(0, 2);
327 g
->addColSpacing(2, 2);
328 g
->addRowSpacing(2, 6);
330 QBoxLayout
* hb
= new QBoxLayout(0, QBoxLayout::LeftToRight
, 0, 0, 0);
331 hb
->setResizeMode(QLayout::FreeResize
);
332 g
->addLayout( hb
, 0, 1 );
335 titlebar
= new QSpacerItem(10, 14, QSizePolicy::Expanding
,
336 QSizePolicy::Minimum
);
338 // setup titlebar buttons
339 for (int n
=0; n
<ButtonTypeCount
; n
++) button
[n
] = 0;
340 addButtons(hb
, KDecoration::options()->customButtonPositions() ?
341 KDecoration::options()->titleButtonsLeft() : QString(default_left
));
343 hb
->addItem(titlebar
);
345 addButtons(hb
, KDecoration::options()->customButtonPositions() ?
346 KDecoration::options()->titleButtonsRight() : QString(default_right
));
349 widget()->setBackgroundMode(QWidget::NoBackground
);
353 void SystemClient::addButtons(QBoxLayout
*hb
, const QString
& s
)
355 unsigned char *minmax_bits
;
356 int l_max
= KDecoration::options()->titleButtonsLeft().count('A');
357 if (s
.length() > 0) {
358 for (unsigned n
=0; n
< s
.length(); n
++) {
360 case 'X': // Close button
361 if ((!button
[ButtonClose
]) && isCloseable()) {
362 button
[ButtonClose
] = new SystemButton(this, "close", NULL
, i18n("Close"));
363 connect( button
[ButtonClose
], SIGNAL( clicked() ), this, ( SLOT( closeWindow() ) ) );
364 hb
->addWidget(button
[ButtonClose
]);
369 case 'S': // Sticky button
370 if (!button
[ButtonSticky
]) {
371 button
[ButtonSticky
] = new SystemButton(this, "sticky", NULL
, i18n("On all desktops"));
372 if(isOnAllDesktops())
373 button
[ButtonSticky
]->setBitmap(unsticky_bits
);
375 button
[ButtonSticky
]->setBitmap(sticky_bits
);
376 connect( button
[ButtonSticky
], SIGNAL( clicked() ), this, ( SLOT( toggleOnAllDesktops() ) ) );
377 hb
->addWidget(button
[ButtonSticky
]);
382 case 'I': // Minimize button
383 if ((!button
[ButtonMinimize
]) && isMinimizable()) {
384 button
[ButtonMinimize
] = new SystemButton(this, "iconify", iconify_bits
, i18n("Minimize"));
385 connect( button
[ButtonMinimize
], SIGNAL( clicked() ), this, ( SLOT( minimize() ) ) );
386 hb
->addWidget(button
[ButtonMinimize
]);
391 case 'A': // Maximize button
392 if ((!button
[ButtonMaximize
]) && isMaximizable()) {
393 if (maximizeMode()==MaximizeFull
) {
394 if (KDecoration::options()->customButtonPositions() && (l_max
>-1))
395 minmax_bits
= l_minmax_bits
;
397 minmax_bits
= r_minmax_bits
;
398 button
[ButtonMaximize
] = new SystemButton(this, "maximize", minmax_bits
, i18n("Restore"));
401 button
[ButtonMaximize
] = new SystemButton(this, "maximize", maximize_bits
, i18n("Maximize"));
402 connect( button
[ButtonMaximize
], SIGNAL( clicked() ), this, ( SLOT( maxButtonClicked() ) ) );
403 hb
->addWidget(button
[ButtonMaximize
]);
408 case 'H': // Help button
409 if ((!button
[ButtonHelp
]) && providesContextHelp()) {
410 button
[ButtonHelp
] = new SystemButton(this, "help", question_bits
, i18n("Help"));
411 connect( button
[ButtonHelp
], SIGNAL( clicked() ), this, ( SLOT( showContextHelp() ) ) );
412 hb
->addWidget(button
[ButtonHelp
]);
422 bool SystemClient::eventFilter( QObject
* o
, QEvent
* e
)
429 resizeEvent(static_cast< QResizeEvent
* >( e
) );
432 paintEvent(static_cast< QPaintEvent
* >( e
) );
434 case QEvent::MouseButtonDblClick
:
435 mouseDoubleClickEvent(static_cast< QMouseEvent
* >( e
) );
437 case QEvent::MouseButtonPress
:
438 processMousePressEvent(static_cast< QMouseEvent
* >( e
) );
446 void SystemClient::reset(unsigned long)
448 titleBuffer
.resize(0, 0);
451 if (button
[ButtonClose
])
452 button
[ButtonClose
]->reset();
453 if (button
[ButtonSticky
])
454 button
[ButtonSticky
]->reset();
455 if (button
[ButtonMinimize
])
456 button
[ButtonMinimize
]->reset();
457 if (button
[ButtonMaximize
])
458 button
[ButtonMaximize
]->reset();
459 if (button
[ButtonHelp
])
460 button
[ButtonHelp
]->reset();
463 void SystemClient::maxButtonClicked()
465 maximize( button
[ButtonMaximize
]->last_button
);
468 void SystemClient::resizeEvent( QResizeEvent
* )
470 //Client::resizeEvent( e );
474 if ( isVisibleToTLW() && !testWFlags( WStaticContents )) {
476 QRect t = titlebar->geometry();
480 p.setClipRegion( r );
481 p.eraseRect( rect() );
485 void SystemClient::resize( const QSize
& s
)
487 widget()->resize( s
);
491 QSize
SystemClient::minimumSize() const
493 return widget()->minimumSize();
497 void SystemClient::recalcTitleBuffer()
499 if(oldTitle
== caption() && width() == titleBuffer
.width())
501 QFontMetrics
fm(options()->font(true));
502 titleBuffer
.resize(width(), 18);
504 p
.begin(&titleBuffer
);
506 p
.drawTiledPixmap(0, 0, width(), 18, *aUpperGradient
);
508 p
.fillRect(0, 0, width(), 18,
509 options()->colorGroup(KDecorationOptions::ColorFrame
, true).
510 brush(QColorGroup::Button
));
512 QRect t
= titlebar
->geometry();
514 t
.setLeft( t
.left() + 4 );
515 t
.setRight( t
.right() - 2 );
517 QRegion
r(t
.x(), 0, t
.width(), 18);
518 r
-= QRect(t
.x()+((t
.width()-fm
.width(caption()))/2)-4,
519 0, fm
.width(caption())+8, 18);
522 for(i
=0, ly
=4; i
< 4; ++i
, ly
+=3){
523 p
.setPen(options()->color(KDecorationOptions::ColorTitleBar
, true).light(150));
524 p
.drawLine(0, ly
, width()-1, ly
);
525 p
.setPen(options()->color(KDecorationOptions::ColorTitleBar
, true).dark(120));
526 p
.drawLine(0, ly
+1, width()-1, ly
+1);
529 p
.setPen(options()->color(KDecorationOptions::ColorFont
, true));
530 p
.setFont(options()->font(true));
532 p
.drawText(t
.x()+((t
.width()-fm
.width(caption()))/2)-4,
533 0, fm
.width(caption())+8, 18, Qt::AlignCenter
, caption());
534 p
.setClipping(false);
536 oldTitle
= caption();
539 void SystemClient::captionChange()
542 widget()->repaint(titlebar
->geometry(), false);
545 void SystemClient::drawRoundFrame(QPainter
&p
, int x
, int y
, int w
, int h
)
547 kDrawRoundButton(&p
, x
, y
, w
, h
,
548 options()->colorGroup(KDecorationOptions::ColorFrame
, isActive()), false);
552 void SystemClient::paintEvent( QPaintEvent
* )
554 QPainter
p(widget());
555 QRect t
= titlebar
->geometry();
557 QBrush
fillBrush(widget()->colorGroup().brush(QColorGroup::Background
).pixmap() ?
558 widget()->colorGroup().brush(QColorGroup::Background
) :
559 options()->colorGroup(KDecorationOptions::ColorFrame
, isActive()).
560 brush(QColorGroup::Button
));
562 p
.fillRect(1, 18, width()-2, height()-19, fillBrush
);
565 t
.setLeft( t
.left() + 4 );
566 t
.setRight( t
.right() - 2 );
569 p
.drawPixmap(0, 0, titleBuffer
);
572 p
.drawTiledPixmap(0, 0, width(), 18, *iUpperGradient
);
574 p
.fillRect(0, 0, width(), 18, fillBrush
);
575 p
.setPen(options()->color(KDecorationOptions::ColorFont
, isActive()));
576 p
.setFont(options()->font(isActive()));
577 p
.drawText(t
, Qt::AlignCenter
, caption() );
580 p
.setPen(options()->color(KDecorationOptions::ColorFrame
, isActive()).light());
581 p
.drawLine(width()-20, height()-7, width()-10, height()-7);
582 p
.drawLine(width()-20, height()-5, width()-10, height()-5);
583 p
.setPen(options()->color(KDecorationOptions::ColorFrame
, isActive()).dark());
584 p
.drawLine(width()-20, height()-6, width()-10, height()-6);
585 p
.drawLine(width()-20, height()-4, width()-10, height()-4);
587 drawRoundFrame(p
, 0, 0, width(), height());
590 #define QCOORDARRLEN(x) sizeof(x)/(sizeof(QCOORD)*2)
592 void SystemClient::doShape()
594 // using a bunch of QRect lines seems much more efficent than bitmaps or
598 kRoundMaskRegion(mask
, 0, 0, width(), height());
602 void SystemClient::showEvent(QShowEvent
*)
604 // Client::showEvent(ev);
607 // widget()->repaint();
610 /*void SystemClient::windowWrapperShowEvent( QShowEvent* )
615 void SystemClient::mouseDoubleClickEvent( QMouseEvent
* e
)
617 if ( e
->button() == Qt::LeftButton
&& titlebar
->geometry().contains( e
->pos() ) )
618 titlebarDblClickOperation();
621 void SystemClient::maximizeChange()
623 unsigned char *minmax_bits
;
624 int l_max
= KDecoration::options()->titleButtonsLeft().count('A');
625 if (KDecoration::options()->customButtonPositions() && (l_max
>-1))
626 minmax_bits
= l_minmax_bits
;
628 minmax_bits
= r_minmax_bits
;
629 if (button
[ButtonMaximize
]) {
630 button
[ButtonMaximize
]->setBitmap((maximizeMode()==MaximizeFull
) ? minmax_bits
: maximize_bits
);
631 button
[ButtonMaximize
]->setTipText((maximizeMode()==MaximizeFull
) ? i18n("Restore") : i18n("Maximize"));
635 void SystemClient::activeChange()
637 widget()->repaint(false);
638 if (button
[ButtonClose
])
639 button
[ButtonClose
]->reset();
640 if (button
[ButtonSticky
])
641 button
[ButtonSticky
]->reset();
642 if (button
[ButtonMinimize
])
643 button
[ButtonMinimize
]->reset();
644 if (button
[ButtonMaximize
])
645 button
[ButtonMaximize
]->reset();
646 if (button
[ButtonHelp
])
647 button
[ButtonHelp
]->reset();
650 void SystemClient::iconChange()
652 // if (button[BtnMenu] && button[BtnMenu]->isVisible())
653 // button[BtnMenu]->repaint(false);
656 void SystemClient::desktopChange()
658 if (button
[ButtonSticky
]) {
659 button
[ButtonSticky
]->setBitmap(isOnAllDesktops() ? unsticky_bits
: sticky_bits
);
660 button
[ButtonSticky
]->setTipText(isOnAllDesktops() ? i18n("Not on all desktops") : i18n("On all desktops"));
664 /*void SystemClient::stickyChange(bool on)
668 KDecoration::Position
SystemClient::mousePosition(const QPoint
&p
) const
670 return KDecoration::mousePosition(p
);
673 void SystemClient::borders(int& left
, int& right
, int& top
, int& bottom
) const
680 /* if ((maximizeMode()==MaximizeFull) && !options()->moveResizeMaximizedWindows()) {
681 left = right = bottom = 0;
682 top = 1 + titleHeight + (borderSize-1);
686 SystemDecoFactory::SystemDecoFactory()
691 SystemDecoFactory::~SystemDecoFactory()
696 KDecoration
*SystemDecoFactory::createDecoration( KDecorationBridge
*b
)
698 return new SystemClient(b
, this);
701 bool SystemDecoFactory::reset( unsigned long changed
)
703 System::delete_pixmaps();
704 System::create_pixmaps();
705 // Ensure changes in tooltip state get applied
706 resetDecorations(changed
);
710 bool SystemDecoFactory::supports( Ability ability
)
714 case AbilityAnnounceButtons
:
715 case AbilityButtonOnAllDesktops
:
716 case AbilityButtonHelp
:
717 case AbilityButtonMinimize
:
718 case AbilityButtonMaximize
:
719 case AbilityButtonClose
:
726 QList
<KDecorationFactory::BorderSize
> SystemDecoFactory::borderSizes() const
727 { // the list must be sorted
728 return Q3ValueList
< BorderSize
>() << BorderNormal
;
733 extern "C" KDE_EXPORT KDecorationFactory
*create_factory()
735 return new System::SystemDecoFactory();
738 #include "systemclient.moc"