/* * $Id$ * * KWin client button tooltip support module * * Copyright (c) 2001 * Karol Szwed * * Uses portions of QToolTip code * Copyright (c) TrollTech AS * * Since Qt installs its own internal event filter when using * a QToolTip, kwin doesn't obtain the necessary events and hence * focus problems and loss of window frames occur if they are used * for kwin styles. Thus, this small class implements a bare subset * of QToolTip designed especially for kwin client buttons without * installing any event filters that confuse kwin. * * For all normal clients, simply use the KWinButton class instead * of QButton, which will use a KWinToolTip internally. Other clients * which rely on QToolButton or QWidget for client buttons may use the * KWinToolButton and KWinWidgetButton classes to automatically take * care of tooltips. * */ #include #include "kwinbutton.h" #include "options.h" #include "workspace.h" // This is a hack to ensure that we use Qt fade and scroll effects // This code is copied directly from qeffects_p.h struct QEffects { enum Direction { LeftScroll = 0x0001, RightScroll = 0x0002, UpScroll = 0x0004, DownScroll = 0x0008 }; typedef uint DirFlags; }; extern void Q_EXPORT qScrollEffect( QWidget*, QEffects::DirFlags dir = QEffects::DownScroll, int time = -1 ); extern void Q_EXPORT qFadeEffect( QWidget*, int time = -1 ); // end qeffects_p.h code using namespace KWinInternal; KWinToolTip::KWinToolTip( QWidget* parent, const QString& tip ) : QLabel( NULL, "KWinToolTip", WStyle_StaysOnTop + WStyle_Customize + WStyle_NoBorder + WStyle_Tool ) { setMargin(1); setIndent(0); setFrameStyle( QFrame::Plain | QFrame::Box ); setLineWidth(1); setAlignment( AlignLeft | AlignTop ); setText(tip); adjustSize(); // Use stock Qt tooltip colors as defined in qapplication.cpp QColorGroup clrGroup( Qt::black, QColor(255,255,220), QColor(96,96,96), Qt::black, Qt::black, Qt::black, QColor(255,255,220) ); setPalette( QPalette( clrGroup, clrGroup, clrGroup ) ); btn = parent; connect(&hideTimer, SIGNAL(timeout()), SLOT(hideTip())); connect(&showTimer, SIGNAL(timeout()), SLOT(showTip())); } KWinToolTip::~KWinToolTip() { } void KWinToolTip::setTipText( const QString& tip ) { bool visible = isVisible(); if (visible) hide(); setText(tip); adjustSize(); positionTip(); if (visible) showTip(); } void KWinToolTip::enterTip() { // Show after 1 second showTimer.start( 1000, TRUE ); } void KWinToolTip::leaveTip() { if (hideTimer.isActive()) hideTimer.stop(); if (showTimer.isActive()) showTimer.stop(); if (isVisible()) hide(); } /* Internal */ void KWinToolTip::showTip() { if (isVisible()) return; // Ignore empty tooltips if (text().isEmpty()) return; positionTip(); // Show tooltips the Qt way if (options->fadeTooltips()) qFadeEffect(this); else if (options->animateTooltips()) qScrollEffect(this); else show(); raise(); // Hide after 10 seconds hideTimer.start( 10000, TRUE ); } /* Internal */ void KWinToolTip::hideTip() { if (isVisible()) hide(); } /* Internal */ void KWinToolTip::positionTip() { QPoint p = btn->mapToGlobal(btn->rect().bottomLeft()) + QPoint(0, 16); int screen = QApplication::desktop()->screenNumber(btn->mapToGlobal(btn->rect().center())); QRect screenGeom = QApplication::desktop()->screenGeometry(screen); // Ensure the tooltip is displayed within the current desktop if ( screenGeom.right() < p.x() + width() ) p.setX( screenGeom.right() - width()); if ( screenGeom.bottom() < p.y() + height() ) p.setY( screenGeom.bottom() - height() ); if (p.x() < screenGeom.x()) p.setX(screenGeom.x()); if (p.y() < screenGeom.y()) p.setY(screenGeom.y()); move(p); // Ensure we don't get enter/leave event race conditions when a // tooltip is over a button. QRect btnGlobalRect( btn->mapToGlobal(btn->rect().topLeft()), btn->mapToGlobal(btn->rect().bottomRight()) ); QRect tipGlobalRect( mapToGlobal(rect().topLeft()), mapToGlobal(rect().bottomRight()) ); if (btnGlobalRect.intersects( tipGlobalRect )) { // Only intersects when button is at lower part of screen p.setY( btn->mapToGlobal(btn->rect().topLeft()).y() - height() - 5 ); move(p); } } // KWinButton class KWinButton::KWinButton(QWidget *parent, const char *name, const QString& tip) : QButton(parent, name, WStyle_Customize | WRepaintNoErase | WResizeNoErase | WStyle_NoBorder ) { buttonTip = options->showTooltips() ? new KWinToolTip(this, tip) : NULL; } KWinButton::~KWinButton() { if (buttonTip) delete buttonTip; } void KWinButton::setTipText(const QString& newTip) { if (buttonTip) buttonTip->setTipText( newTip ); } void KWinButton::enterEvent(QEvent *e) { if (buttonTip) buttonTip->enterTip(); QButton::enterEvent( e ); } void KWinButton::leaveEvent(QEvent *e) { if (buttonTip) buttonTip->leaveTip(); QButton::leaveEvent( e ); } void KWinButton::mousePressEvent(QMouseEvent* e) { // Hide tooltips if a button is pressed if (buttonTip) buttonTip->leaveTip(); QButton::mousePressEvent( e ); } // KWinToolButton class KWinToolButton::KWinToolButton(QWidget *parent, const char *name, const QString& tip) : QToolButton(parent, name) { buttonTip = options->showTooltips() ? new KWinToolTip(this, tip) : NULL; } KWinToolButton::~KWinToolButton() { if (buttonTip) delete buttonTip; } void KWinToolButton::setTipText(const QString& newTip) { if (buttonTip) buttonTip->setTipText( newTip ); } void KWinToolButton::enterEvent(QEvent *e) { if (buttonTip) buttonTip->enterTip(); QToolButton::enterEvent( e ); } void KWinToolButton::leaveEvent(QEvent *e) { if (buttonTip) buttonTip->leaveTip(); QToolButton::leaveEvent( e ); } void KWinToolButton::mousePressEvent(QMouseEvent* e) { // Hide tooltips if a button is pressed if (buttonTip) buttonTip->leaveTip(); QToolButton::mousePressEvent( e ); } // KWinWidgetButton class KWinWidgetButton::KWinWidgetButton(QWidget *parent, const char *name, WFlags f, const QString& tip) : QWidget(parent, name, f) { buttonTip = options->showTooltips() ? new KWinToolTip(this, tip) : NULL; } KWinWidgetButton::~KWinWidgetButton() { if (buttonTip) delete buttonTip; } void KWinWidgetButton::setTipText(const QString& newTip) { if (buttonTip) buttonTip->setTipText( newTip ); } void KWinWidgetButton::enterEvent(QEvent *e) { if (buttonTip) buttonTip->enterTip(); QWidget::enterEvent( e ); } void KWinWidgetButton::leaveEvent(QEvent *e) { if (buttonTip) buttonTip->leaveTip(); QWidget::leaveEvent( e ); } void KWinWidgetButton::mousePressEvent(QMouseEvent* /*e*/) { // Hide tooltips if a button is pressed if (buttonTip) buttonTip->leaveTip(); } #include "kwinbutton.moc" // vim: ts=4