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 }
00138
00139 KSystemTray::~KSystemTray()
00140 {
00141 delete d;
00142 }
00143
00144
00145 void KSystemTray::showEvent( QShowEvent * )
00146 {
00147 if ( !hasQuit ) {
00148 menu->insertSeparator();
00149 KAction* action = d->actionCollection->action("minimizeRestore");
00150
00151 if (action)
00152 {
00153 action->plug(menu);
00154 }
00155
00156 action = d->actionCollection->action(KStdAction::name(KStdAction::Quit));
00157
00158 if (action)
00159 {
00160 action->plug(menu);
00161 }
00162
00163 hasQuit = 1;
00164 }
00165 }
00166
00167
00168 void KSystemTray::enterEvent( QEvent* e )
00169 {
00170 QLabel::enterEvent( e );
00171 }
00172
00173 KPopupMenu* KSystemTray::contextMenu() const
00174 {
00175 return menu;
00176 }
00177
00178
00179 void KSystemTray::mousePressEvent( QMouseEvent *e )
00180 {
00181 if ( !rect().contains( e->pos() ) )
00182 return;
00183
00184 switch ( e->button() ) {
00185 case LeftButton:
00186 toggleActive();
00187 break;
00188 case MidButton:
00189
00190 case RightButton:
00191 if ( parentWidget() ) {
00192 KAction* action = d->actionCollection->action("minimizeRestore");
00193 if ( parentWidget()->isVisible() )
00194 action->setText( i18n("&Minimize") );
00195 else
00196 action->setText( i18n("&Restore") );
00197 }
00198 contextMenuAboutToShow( menu );
00199 menu->popup( e->globalPos() );
00200 break;
00201 default:
00202
00203 break;
00204 }
00205 }
00206
00207 void KSystemTray::mouseReleaseEvent( QMouseEvent * )
00208 {
00209 }
00210
00211
00212 void KSystemTray::contextMenuAboutToShow( KPopupMenu* )
00213 {
00214 }
00215
00216
00217
00218
00219 void KSystemTray::minimizeRestoreAction()
00220 {
00221 if ( parentWidget() ) {
00222 bool restore = !( parentWidget()->isVisible() );
00223 minimizeRestore( restore );
00224 }
00225 }
00226
00227 void KSystemTray::maybeQuit()
00228 {
00229 QString query = i18n("<qt>Are you sure you want to quit <b>%1</b>?</qt>")
00230 .arg(kapp->caption());
00231 if (KMessageBox::warningContinueCancel(this, query,
00232 i18n("Confirm Quit From System Tray"),
00233 KStdGuiItem::quit(),
00234 QString("systemtrayquit%1")
00235 .arg(kapp->caption())) !=
00236 KMessageBox::Continue)
00237 {
00238 return;
00239 }
00240
00241 emit quitSelected();
00242
00243
00244
00245
00246 if (parentWidget())
00247 {
00248 parentWidget()->close();
00249 }
00250 else
00251 {
00252 qApp->closeAllWindows();
00253 }
00254 }
00255
00256 void KSystemTray::toggleActive()
00257 {
00258 activateOrHide();
00259 }
00260
00261 void KSystemTray::setActive()
00262 {
00263 minimizeRestore( true );
00264 }
00265
00266 void KSystemTray::setInactive()
00267 {
00268 minimizeRestore( false );
00269 }
00270
00271
00272
00273
00274 void KSystemTray::activateOrHide()
00275 {
00276 QWidget *pw = parentWidget();
00277
00278 if ( !pw )
00279 return;
00280
00281 #ifdef Q_WS_X11
00282 KWin::WindowInfo info1 = KWin::windowInfo( pw->winId(), NET::XAWMState | NET::WMState );
00283
00284 bool mapped = (info1.mappingState() == NET::Visible) && !info1.isMinimized();
00285
00286
00287
00288
00289 if( !mapped )
00290 minimizeRestore( true );
00291 else
00292 {
00293 KWinModule module;
00294 for( QValueList< WId >::ConstIterator it = module.stackingOrder().fromLast();
00295 it != module.stackingOrder().end() && (*it) != pw->winId();
00296 --it )
00297 {
00298 KWin::WindowInfo info2 = KWin::windowInfo( *it,
00299 NET::WMGeometry | NET::XAWMState | NET::WMState | NET::WMWindowType );
00300 if( info2.mappingState() != NET::Visible )
00301 continue;
00302 if( !info2.geometry().intersects( pw->geometry()))
00303 continue;
00304 if( !info1.hasState( NET::KeepAbove ) && info2.hasState( NET::KeepAbove ))
00305 continue;
00306 NET::WindowType type = info2.windowType( NET::NormalMask | NET::DesktopMask
00307 | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
00308 | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask );
00309 if( type == NET::Dock || type == NET::TopMenu )
00310 continue;
00311 pw->raise();
00312 KWin::activateWindow( pw->winId());
00313 return;
00314 }
00315 minimizeRestore( false );
00316 }
00317 #endif
00318 }
00319
00320 void KSystemTray::minimizeRestore( bool restore )
00321 {
00322 QWidget* pw = parentWidget();
00323 if( !pw )
00324 return;
00325 #ifdef Q_WS_X11
00326 KWin::WindowInfo info = KWin::windowInfo( pw->winId(), NET::WMGeometry | NET::WMDesktop );
00327 if ( restore )
00328 {
00329 if( d->on_all_desktops )
00330 KWin::setOnAllDesktops( pw->winId(), true );
00331 else
00332 KWin::setCurrentDesktop( info.desktop() );
00333 pw->move( info.geometry().topLeft() );
00334 pw->show();
00335 pw->raise();
00336 KWin::activateWindow( pw->winId() );
00337 } else {
00338 d->on_all_desktops = info.onAllDesktops();
00339 pw->hide();
00340 }
00341 #endif
00342 }
00343
00344 KActionCollection* KSystemTray::actionCollection()
00345 {
00346 return d->actionCollection;
00347 }
00348
00349 QPixmap KSystemTray::loadIcon( const QString &icon, KInstance *instance )
00350 {
00351 KConfig *appCfg = kapp->config();
00352 KConfigGroupSaver configSaver(appCfg, "System Tray");
00353 int iconWidth = appCfg->readNumEntry("systrayIconWidth", 22);
00354 return instance->iconLoader()->loadIcon( icon, KIcon::Panel, iconWidth );
00355 }
00356
00357 void KSystemTray::setPixmap( const QPixmap& p )
00358 {
00359 QLabel::setPixmap( p );
00360 #ifdef Q_WS_X11
00361 KWin::setIcons( winId(), p, QPixmap());
00362 #endif
00363 }
00364
00365 void KSystemTray::setCaption( const QString& s )
00366 {
00367 QLabel::setCaption( s );
00368 }
00369
00370 void KSystemTray::virtual_hook( int, void* )
00371 { }
00372
00373 #include "ksystemtray.moc"
00374 #include "kdockwindow.moc"