KDEUI
ksystemtrayicon.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "ksystemtrayicon.h"
00022 #include "kaboutdata.h"
00023 #include "kaction.h"
00024 #include "kcomponentdata.h"
00025 #include "klocale.h"
00026 #include "kmenu.h"
00027 #include "kmessagebox.h"
00028 #include "kshortcut.h"
00029 #include "kactioncollection.h"
00030 #include "kstandardaction.h"
00031 #include <kwindowsystem.h>
00032
00033 #ifdef Q_WS_X11
00034 #include <QX11Info>
00035 #endif
00036 #ifdef Q_WS_WIN
00037 #include <windows.h>
00038 #endif
00039
00040 #include <kiconloader.h>
00041 #include <kapplication.h>
00042 #include <kconfiggroup.h>
00043
00044 #include <QMouseEvent>
00045 #include <QToolButton>
00046
00047 #ifdef Q_WS_WIN
00048 class KSystemTrayIconPrivate : public QObject
00049 #else
00050 class KSystemTrayIconPrivate
00051 #endif
00052 {
00053 public:
00054 KSystemTrayIconPrivate(KSystemTrayIcon* trayIcon, QWidget* parent)
00055 {
00056 actionCollection = new KActionCollection( trayIcon );
00057 hasQuit = false;
00058 onAllDesktops = false;
00059 window = parent;
00060 #ifdef Q_WS_WIN
00061
00062
00063
00064 #endif
00065 }
00066
00067 ~KSystemTrayIconPrivate()
00068 {
00069 #ifdef Q_WS_WIN
00070
00071
00072 #endif
00073 delete actionCollection;
00074 delete menu;
00075 }
00076
00077 #ifdef Q_WS_WIN
00078 bool eventFilter(QObject *obj, QEvent *ev)
00079 {
00080 if(ev->type() == QEvent::ActivationChange) {
00081 dwTickCount = GetTickCount();
00082 }
00083 return QObject::eventFilter(obj, ev);
00084 }
00085 DWORD dwTickCount;
00086 #endif
00087
00088 KActionCollection* actionCollection;
00089 KMenu* menu;
00090 QWidget* window;
00091 QAction* titleAction;
00092 bool onAllDesktops : 1;
00093 bool hasQuit : 1;
00094 };
00095
00096 KSystemTrayIcon::KSystemTrayIcon( QWidget* parent )
00097 : QSystemTrayIcon( parent ),
00098 d( new KSystemTrayIconPrivate( this, parent ) )
00099 {
00100 init( parent );
00101 }
00102
00103 KSystemTrayIcon::KSystemTrayIcon( const QString& icon, QWidget* parent )
00104 : QSystemTrayIcon( loadIcon( icon ), parent ),
00105 d( new KSystemTrayIconPrivate( this, parent ) )
00106 {
00107 init( parent );
00108 }
00109
00110 KSystemTrayIcon::KSystemTrayIcon( const QIcon& icon, QWidget* parent )
00111 : QSystemTrayIcon( icon, parent ),
00112 d( new KSystemTrayIconPrivate( this, parent ) )
00113 {
00114 init( parent );
00115 }
00116
00117 void KSystemTrayIcon::init( QWidget* parent )
00118 {
00119
00120
00121 KGlobal::ref();
00122 d->menu = new KMenu( parent );
00123 d->titleAction = d->menu->addTitle( qApp->windowIcon(), KGlobal::caption() );
00124 d->menu->setTitle( KGlobal::mainComponent().aboutData()->programName() );
00125 connect( d->menu, SIGNAL( aboutToShow() ), this, SLOT( contextMenuAboutToShow() ) );
00126 setContextMenu( d->menu );
00127
00128 KStandardAction::quit( this, SLOT( maybeQuit() ), d->actionCollection );
00129
00130 if ( parent )
00131 {
00132 QAction *action = d->actionCollection->addAction("minimizeRestore");
00133 action->setText(i18n("Minimize"));
00134 connect( action, SIGNAL( triggered( bool ) ), this, SLOT( minimizeRestoreAction() ) );
00135
00136 #ifdef Q_WS_X11
00137 KWindowInfo info = KWindowSystem::windowInfo( parent->winId(), NET::WMDesktop );
00138 d->onAllDesktops = info.onAllDesktops();
00139 #else
00140 d->onAllDesktops = false;
00141 #endif
00142 }
00143 else
00144 {
00145 d->onAllDesktops = false;
00146 }
00147
00148 connect( this, SIGNAL( activated( QSystemTrayIcon::ActivationReason ) ),
00149 SLOT( activateOrHide( QSystemTrayIcon::ActivationReason ) ) );
00150 }
00151
00152 QWidget *KSystemTrayIcon::parentWidget() const
00153 {
00154 return d->window;
00155 }
00156
00157 KSystemTrayIcon::~KSystemTrayIcon()
00158 {
00159 delete d;
00160 KGlobal::deref();
00161 }
00162
00163 void KSystemTrayIcon::contextMenuAboutToShow( )
00164 {
00165 if ( !d->hasQuit )
00166 {
00167
00168
00169 d->menu->addSeparator();
00170 QAction* action = d->actionCollection->action( "minimizeRestore" );
00171
00172 if ( action )
00173 {
00174 d->menu->addAction( action );
00175 }
00176
00177 action = d->actionCollection->action( KStandardAction::name( KStandardAction::Quit ) );
00178
00179 if ( action )
00180 {
00181 d->menu->addAction( action );
00182 }
00183
00184 d->hasQuit = true;
00185 }
00186
00187 if ( d->window )
00188 {
00189 QAction* action = d->actionCollection->action("minimizeRestore");
00190 if ( d->window->isVisible() )
00191 {
00192 action->setText( i18n("&Minimize") );
00193 }
00194 else
00195 {
00196 action->setText( i18n("&Restore") );
00197 }
00198 }
00199 }
00200
00201
00202
00203
00204 void KSystemTrayIcon::minimizeRestoreAction()
00205 {
00206 if ( d->window )
00207 {
00208 bool restore = !( d->window->isVisible() );
00209 minimizeRestore( restore );
00210 }
00211 }
00212
00213 void KSystemTrayIcon::maybeQuit()
00214 {
00215 QString caption = KGlobal::caption();
00216 QString query = i18n("<qt>Are you sure you want to quit <b>%1</b>?</qt>",
00217 caption);
00218 if (KMessageBox::warningContinueCancel(d->window, query,
00219 i18n("Confirm Quit From System Tray"),
00220 KStandardGuiItem::quit(),
00221 KStandardGuiItem::cancel(),
00222 QString("systemtrayquit%1")
00223 .arg(caption)) !=
00224 KMessageBox::Continue)
00225 {
00226 return;
00227 }
00228
00229 emit quitSelected();
00230 qApp->quit();
00231 }
00232
00233
00234
00235 void KSystemTrayIcon::activateOrHide( QSystemTrayIcon::ActivationReason reasonCalled )
00236 {
00237 if ( reasonCalled != QSystemTrayIcon::Trigger )
00238 {
00239 return;
00240 }
00241
00242 QWidget *pw = d->window;
00243 if ( !pw )
00244 {
00245 return;
00246 }
00247 #ifdef Q_WS_WIN
00248
00249
00250
00251 if( GetTickCount() - d->dwTickCount < 300 ) {
00252
00253 minimizeRestore( false );
00254 } else {
00255 minimizeRestore( true );
00256 }
00257 #elif defined(Q_WS_X11)
00258 KWindowInfo info1 = KWindowSystem::windowInfo( pw->winId(), NET::XAWMState | NET::WMState );
00259
00260 bool mapped = (info1.mappingState() == NET::Visible) && !info1.isMinimized();
00261
00262
00263
00264
00265 if( !mapped )
00266 minimizeRestore( true );
00267 else
00268 {
00269 QListIterator< WId > it (KWindowSystem::stackingOrder());
00270 it.toBack();
00271 while( it.hasPrevious() )
00272 {
00273 WId id = it.previous();
00274 if( id == pw->winId() )
00275 break;
00276 KWindowInfo info2 = KWindowSystem::windowInfo( id,
00277 NET::WMGeometry | NET::XAWMState | NET::WMState | NET::WMWindowType );
00278 if( info2.mappingState() != NET::Visible )
00279 continue;
00280 if( !info2.geometry().intersects( pw->geometry()))
00281 continue;
00282 if( !info1.hasState( NET::KeepAbove ) && info2.hasState( NET::KeepAbove ))
00283 continue;
00284 NET::WindowType type = info2.windowType( NET::NormalMask | NET::DesktopMask
00285 | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
00286 | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask );
00287 if( type == NET::Dock || type == NET::TopMenu )
00288 continue;
00289 pw->raise();
00290 KWindowSystem::activateWindow( pw->winId());
00291 return;
00292 }
00293 minimizeRestore( false );
00294 }
00295 #endif
00296 }
00297
00298 void KSystemTrayIcon::minimizeRestore( bool restore )
00299 {
00300 QWidget* pw = d->window;
00301 if (!pw)
00302 return;
00303 #ifdef Q_WS_X11
00304 KWindowInfo info = KWindowSystem::windowInfo(pw->winId(), NET::WMGeometry | NET::WMDesktop);
00305 if (restore) {
00306 if (d->onAllDesktops) {
00307 KWindowSystem::setOnAllDesktops(pw->winId(), true);
00308 } else {
00309 KWindowSystem::setCurrentDesktop(info.desktop());
00310 }
00311 pw->move(info.geometry().topLeft());
00312 pw->show();
00313 pw->raise();
00314 KWindowSystem::activateWindow(pw->winId());
00315 } else {
00316 d->onAllDesktops = info.onAllDesktops();
00317 pw->hide();
00318 }
00319 #else
00320 if ( restore )
00321 {
00322 pw->show();
00323 pw->raise();
00324 KWindowSystem::forceActiveWindow( pw->winId() );
00325 } else {
00326 pw->hide();
00327 }
00328 #endif
00329 }
00330
00331 KActionCollection* KSystemTrayIcon::actionCollection()
00332 {
00333 return d->actionCollection;
00334 }
00335
00336 QIcon KSystemTrayIcon::loadIcon(const QString &icon, const KComponentData &componentData)
00337 {
00338 KConfigGroup cg(componentData.config(), "System Tray");
00339 int iconWidth = cg.readEntry("systrayIconWidth", 22);
00340 return KIconLoader::global()->loadIcon( icon, KIconLoader::Panel, iconWidth );
00341 }
00342
00343 void KSystemTrayIcon::toggleActive()
00344 {
00345 activateOrHide( QSystemTrayIcon::Trigger );
00346 }
00347
00348 bool KSystemTrayIcon::parentWidgetTrayClose() const
00349 {
00350 if( kapp != NULL && kapp->sessionSaving())
00351 return false;
00352 return true;
00353 }
00354
00355 void KSystemTrayIcon::setContextMenuTitle(QAction *action)
00356 {
00357
00358 QToolButton *button = static_cast<QToolButton*>((static_cast<QWidgetAction*>(d->titleAction))->defaultWidget());
00359 button->setDefaultAction(action);
00360 }
00361
00362 QAction *KSystemTrayIcon::contextMenuTitle() const
00363 {
00364 QToolButton *button = static_cast<QToolButton*>((static_cast<QWidgetAction*>(d->titleAction))->defaultWidget());
00365 return button->defaultAction();
00366 }
00367
00368 #include "ksystemtrayicon.moc"