00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "kaction.h"
00023 #include "kmessagebox.h"
00024 #include "kshortcut.h"
00025 #include "ksystemtray.h"
00026 #include "kpopupmenu.h"
00027 #include "kapplication.h"
00028 #include "klocale.h"
00029 #include "kaboutdata.h"
00030
00031 #ifdef Q_WS_X11
00032 #include <kwin.h>
00033 #include <kwinmodule.h>
00034 #include <qxembed.h>
00035 #include <X11/Xlib.h>
00036 #endif
00037
00038 #include <kiconloader.h>
00039 #include <kconfig.h>
00040
00041 #include <qapplication.h>
00042
00043 extern Time qt_x_time;
00044
00045 class KSystemTrayPrivate
00046 {
00047 public:
00048 KSystemTrayPrivate()
00049 {
00050 actionCollection = 0;
00051 }
00052
00053 ~KSystemTrayPrivate()
00054 {
00055 delete actionCollection;
00056 }
00057
00058 KActionCollection* actionCollection;
00059 bool on_all_desktops;
00060 };
00061
00062 KSystemTray::KSystemTray( QWidget* parent, const char* name )
00063 : QLabel( parent, name, WType_TopLevel )
00064 {
00065 #ifdef Q_WS_X11
00066 QXEmbed::initialize();
00067 #endif
00068
00069 {
00070 XGrabServer (qt_xdisplay());
00071 static Atom selection = XInternAtom( qt_xdisplay(), "_NET_SYSTEM_TRAY_S" + QCString().setNum( qt_xscreen()), False );
00072
00073
00074 Window tray = XGetSelectionOwner (qt_xdisplay(), selection);
00075
00076 if (tray != None)
00077 {
00078
00079 XSelectInput (qt_xdisplay(), tray, StructureNotifyMask);
00080 }
00081
00082 XUngrabServer (qt_xdisplay());
00083 XFlush (qt_xdisplay());
00084
00085 if ( tray != None )
00086 {
00087 XEvent ev;
00088 memset(&ev, 0, sizeof( ev ));
00089 static Atom atom = XInternAtom( qt_xdisplay(), "_NET_SYSTEM_TRAY_OPCODE", False );
00090 ev.xclient.type = ClientMessage;
00091 ev.xclient.window = tray;
00092 ev.xclient.message_type = atom;
00093 ev.xclient.format = 32;
00094 ev.xclient.data.l[ 0 ] = qt_x_time;
00095 ev.xclient.data.l[ 1 ] = 0;
00096 ev.xclient.data.l[ 2 ] = winId();
00097 ev.xclient.data.l[ 3 ] = 0;
00098 ev.xclient.data.l[ 4 ] = 0;
00099
00100 XSendEvent( qt_xdisplay(), tray, False, NoEventMask, (XEvent *)&ev );
00101 XSync(qt_xdisplay(), FALSE );
00102 }
00103 }
00104
00105
00106 d = new KSystemTrayPrivate;
00107 d->actionCollection = new KActionCollection(this);
00108
00109 #ifdef Q_WS_X11
00110 KWin::setSystemTrayWindowFor( winId(), parent?parent->topLevelWidget()->winId(): qt_xrootwin() );
00111 #endif
00112 setBackgroundMode(X11ParentRelative);
00113 setBackgroundOrigin(WindowOrigin);
00114 hasQuit = 0;
00115 menu = new KPopupMenu( this );
00116 menu->insertTitle( kapp->miniIcon(), kapp->caption() );
00117 move( -1000, -1000 );
00118 KStdAction::quit(this, SLOT(maybeQuit()), d->actionCollection);
00119
00120 if (parentWidget())
00121 {
00122 new KAction(i18n("Minimize"), KShortcut(),
00123 this, SLOT( minimizeRestoreAction() ),
00124 d->actionCollection, "minimizeRestore");
00125 #ifdef Q_WS_X11
00126 KWin::WindowInfo info = KWin::windowInfo( parentWidget()->winId());
00127 d->on_all_desktops = info.onAllDesktops();
00128 #else
00129 d->on_all_desktops = false;
00130 #endif
00131 }
00132 else
00133 {
00134 d->on_all_desktops = false;
00135 }
00136 setCaption( KGlobal::instance()->aboutData()->programName());
00137 setAlignment( alignment() | Qt::AlignVCenter | Qt::AlignHCenter );
00138 }
00139
00140 KSystemTray::~KSystemTray()
00141 {
00142 delete d;
00143 }
00144
00145
00146 void KSystemTray::showEvent( QShowEvent * )
00147 {
00148 if ( !hasQuit ) {
00149 menu->insertSeparator();
00150 KAction* action = d->actionCollection->action("minimizeRestore");
00151
00152 if (action)
00153 {
00154 action->plug(menu);
00155 }
00156
00157 action = d->actionCollection->action(KStdAction::name(KStdAction::Quit));
00158
00159 if (action)
00160 {
00161 action->plug(menu);
00162 }
00163
00164 hasQuit = 1;
00165 }
00166 }
00167
00168
00169 void KSystemTray::enterEvent( QEvent* e )
00170 {
00171 QLabel::enterEvent( e );
00172 }
00173
00174 KPopupMenu* KSystemTray::contextMenu() const
00175 {
00176 return menu;
00177 }
00178
00179
00180 void KSystemTray::mousePressEvent( QMouseEvent *e )
00181 {
00182 if ( !rect().contains( e->pos() ) )
00183 return;
00184
00185 switch ( e->button() ) {
00186 case LeftButton:
00187 toggleActive();
00188 break;
00189 case MidButton:
00190
00191 case RightButton:
00192 if ( parentWidget() ) {
00193 KAction* action = d->actionCollection->action("minimizeRestore");
00194 if ( parentWidget()->isVisible() )
00195 action->setText( i18n("&Minimize") );
00196 else
00197 action->setText( i18n("&Restore") );
00198 }
00199 contextMenuAboutToShow( menu );
00200 menu->popup( e->globalPos() );
00201 break;
00202 default:
00203
00204 break;
00205 }
00206 }
00207
00208 void KSystemTray::mouseReleaseEvent( QMouseEvent * )
00209 {
00210 }
00211
00212
00213 void KSystemTray::contextMenuAboutToShow( KPopupMenu* )
00214 {
00215 }
00216
00217
00218
00219
00220 void KSystemTray::minimizeRestoreAction()
00221 {
00222 if ( parentWidget() ) {
00223 bool restore = !( parentWidget()->isVisible() );
00224 minimizeRestore( restore );
00225 }
00226 }
00227
00228 void KSystemTray::maybeQuit()
00229 {
00230 QString query = i18n("<qt>Are you sure you want to quit <b>%1</b>?</qt>")
00231 .arg(kapp->caption());
00232 if (KMessageBox::warningContinueCancel(this, query,
00233 i18n("Confirm Quit From System Tray"),
00234 KStdGuiItem::quit(),
00235 QString("systemtrayquit%1")
00236 .arg(kapp->caption())) !=
00237 KMessageBox::Continue)
00238 {
00239 return;
00240 }
00241
00242 emit quitSelected();
00243
00244
00245
00246
00247 if (parentWidget())
00248 {
00249 parentWidget()->close();
00250 }
00251 else
00252 {
00253 qApp->closeAllWindows();
00254 }
00255 }
00256
00257 void KSystemTray::toggleActive()
00258 {
00259 activateOrHide();
00260 }
00261
00262 void KSystemTray::setActive()
00263 {
00264 minimizeRestore( true );
00265 }
00266
00267 void KSystemTray::setInactive()
00268 {
00269 minimizeRestore( false );
00270 }
00271
00272
00273
00274
00275 void KSystemTray::activateOrHide()
00276 {
00277 QWidget *pw = parentWidget();
00278
00279 if ( !pw )
00280 return;
00281
00282 #ifdef Q_WS_X11
00283 KWin::WindowInfo info1 = KWin::windowInfo( pw->winId(), NET::XAWMState | NET::WMState );
00284
00285 bool mapped = (info1.mappingState() == NET::Visible) && !info1.isMinimized();
00286
00287
00288
00289
00290 if( !mapped )
00291 minimizeRestore( true );
00292 else
00293 {
00294 KWinModule module;
00295 for( QValueList< WId >::ConstIterator it = module.stackingOrder().fromLast();
00296 it != module.stackingOrder().end() && (*it) != pw->winId();
00297 --it )
00298 {
00299 KWin::WindowInfo info2 = KWin::windowInfo( *it,
00300 NET::WMGeometry | NET::XAWMState | NET::WMState | NET::WMWindowType );
00301 if( info2.mappingState() != NET::Visible )
00302 continue;
00303 if( !info2.geometry().intersects( pw->geometry()))
00304 continue;
00305 if( !info1.hasState( NET::KeepAbove ) && info2.hasState( NET::KeepAbove ))
00306 continue;
00307 NET::WindowType type = info2.windowType( NET::NormalMask | NET::DesktopMask
00308 | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
00309 | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask );
00310 if( type == NET::Dock || type == NET::TopMenu )
00311 continue;
00312 pw->raise();
00313 KWin::activateWindow( pw->winId());
00314 return;
00315 }
00316 minimizeRestore( false );
00317 }
00318 #endif
00319 }
00320
00321 void KSystemTray::minimizeRestore( bool restore )
00322 {
00323 QWidget* pw = parentWidget();
00324 if( !pw )
00325 return;
00326 #ifdef Q_WS_X11
00327 KWin::WindowInfo info = KWin::windowInfo( pw->winId(), NET::WMGeometry | NET::WMDesktop );
00328 if ( restore )
00329 {
00330 if( d->on_all_desktops )
00331 KWin::setOnAllDesktops( pw->winId(), true );
00332 else
00333 KWin::setCurrentDesktop( info.desktop() );
00334 pw->move( info.geometry().topLeft() );
00335 pw->show();
00336 pw->raise();
00337 KWin::activateWindow( pw->winId() );
00338 } else {
00339 d->on_all_desktops = info.onAllDesktops();
00340 pw->hide();
00341 }
00342 #endif
00343 }
00344
00345 KActionCollection* KSystemTray::actionCollection()
00346 {
00347 return d->actionCollection;
00348 }
00349
00350 QPixmap KSystemTray::loadIcon( const QString &icon, KInstance *instance )
00351 {
00352 KConfig *appCfg = kapp->config();
00353 KConfigGroupSaver configSaver(appCfg, "System Tray");
00354 int iconWidth = appCfg->readNumEntry("systrayIconWidth", 22);
00355 return instance->iconLoader()->loadIcon( icon, KIcon::Panel, iconWidth );
00356 }
00357
00358 void KSystemTray::setPixmap( const QPixmap& p )
00359 {
00360 QLabel::setPixmap( p );
00361 #ifdef Q_WS_X11
00362 KWin::setIcons( winId(), p, QPixmap());
00363 #endif
00364 }
00365
00366 void KSystemTray::setCaption( const QString& s )
00367 {
00368 QLabel::setCaption( s );
00369 }
00370
00371 void KSystemTray::virtual_hook( int, void* )
00372 { }
00373
00374 #include "ksystemtray.moc"
00375 #include "kdockwindow.moc"