kdeui Library API Documentation

ksystemtray.cpp

00001 /* This file is part of the KDE libraries
00002 
00003     Copyright (C) 1999 Matthias Ettrich (ettrich@kde.org)
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to
00017     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018     Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #include "config.h"
00022 #include "kaction.h"
00023 #include "kshortcut.h"
00024 #include "ksystemtray.h"
00025 #include "kpopupmenu.h"
00026 #include "kapplication.h"
00027 #include "klocale.h"
00028 
00029 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00030 #include <kwin.h> // schroder
00031 #include <kwinmodule.h> // schroder
00032 #endif
00033 
00034 #include <kiconloader.h>
00035 #include <kconfig.h>
00036 
00037 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00038 #include <qxembed.h> // schroder
00039 #endif
00040 
00041 #include <qapplication.h>
00042 
00043 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00044 #include <X11/Xlib.h> // schroder
00045 #ifndef KDE_USE_FINAL
00046 const int XFocusOut = FocusOut;
00047 const int XFocusIn = FocusIn;
00048 #endif
00049 #undef FocusOut
00050 #undef FocusIn
00051 #undef KeyPress
00052 #undef KeyRelease
00053 
00054 extern Time qt_x_time;
00055 #endif // Q_WS_X11 && ! K_WS_QTONLY
00056 
00057 class KSystemTrayPrivate
00058 {
00059 public:
00060     KSystemTrayPrivate()
00061     {
00062         actionCollection = 0;
00063     }
00064 
00065     ~KSystemTrayPrivate()
00066     {
00067         delete actionCollection;
00068     }
00069 
00070     KActionCollection* actionCollection;
00071     bool on_all_desktops; // valid only when the parent widget was hidden
00072 };
00073 
00074 KSystemTray::KSystemTray( QWidget* parent, const char* name )
00075     : QLabel( parent, name, WType_TopLevel )
00076 {
00077 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00078     QXEmbed::initialize();
00079 #endif
00080     
00081     d = new KSystemTrayPrivate;
00082     d->actionCollection = new KActionCollection(this);
00083 
00084 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00085 //#ifndef Q_WS_QWS
00086     // FIXME(E): Talk with QWS
00087     KWin::setSystemTrayWindowFor( winId(), parent?parent->topLevelWidget()->winId(): qt_xrootwin() );
00088     setBackgroundMode(X11ParentRelative);
00089     setBackgroundOrigin(WindowOrigin);
00090 #endif
00091     hasQuit = 0;
00092     menu = new KPopupMenu( this );
00093     menu->insertTitle( kapp->miniIcon(), kapp->caption() );
00094     move( -1000, -1000 );
00095     KAction* quitAction = KStdAction::quit(this, SIGNAL(quitSelected()), d->actionCollection);
00096 
00097     if (parentWidget())
00098     {
00099         connect(quitAction, SIGNAL(activated()), parentWidget(), SLOT(close()));
00100         new KAction(i18n("Minimize"), KShortcut(),
00101                     this, SLOT( minimizeRestoreAction() ),
00102                     d->actionCollection, "minimizeRestore");
00103 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00104     KWin::WindowInfo info = KWin::windowInfo( parentWidget()->winId());
00105     d->on_all_desktops = info.onAllDesktops();
00106 #endif
00107     }
00108     else
00109     {
00110         connect(quitAction, SIGNAL(activated()), qApp, SLOT(closeAllWindows()));
00111     d->on_all_desktops = false;
00112     }
00113     // Set this for the freedesktop/GNOME System Tray protocol,
00114     // which resizes to the minimum height
00115     setMinimumSize((minimumWidth() < 25) ? 25 : minimumWidth(),
00116            (minimumHeight() < 25) ? 25 : minimumHeight());
00117     if (width() < minimumWidth())
00118       resize(minimumWidth(), height());
00119     if (height() < minimumHeight())
00120       resize(width(), minimumHeight());
00121 }
00122 
00123 KSystemTray::~KSystemTray()
00124 {
00125     delete d;
00126 }
00127 
00128 
00129 void KSystemTray::showEvent( QShowEvent * )
00130 {
00131     if ( !hasQuit ) {
00132     menu->insertSeparator();
00133         KAction* action = d->actionCollection->action("minimizeRestore");
00134 
00135         if (action)
00136         {
00137             action->plug(menu);
00138         }
00139 
00140         action = d->actionCollection->action(KStdAction::name(KStdAction::Quit));
00141 
00142         if (action)
00143         {
00144             action->plug(menu);
00145         }
00146 
00147     hasQuit = 1;
00148     }
00149 }
00150 
00151 // KDE4 remove
00152 void KSystemTray::enterEvent( QEvent* e )
00153 {
00154 #if QT_VERSION < 0x030200
00155 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00156 //#ifndef Q_WS_QWS
00157     // FIXME(E): Implement for Qt Embedded
00158     if ( !qApp->focusWidget() ) {
00159     XEvent ev;
00160     memset(&ev, 0, sizeof(ev));
00161     ev.xfocus.display = qt_xdisplay();
00162     ev.xfocus.type = XFocusIn;
00163     ev.xfocus.window = winId();
00164     ev.xfocus.mode = NotifyNormal;
00165     ev.xfocus.detail = NotifyAncestor;
00166     Time time = qt_x_time;
00167     qt_x_time = 1;
00168     qApp->x11ProcessEvent( &ev );
00169     qt_x_time = time;
00170     }
00171 #endif
00172 #endif
00173     QLabel::enterEvent( e );
00174 }
00175 
00176 KPopupMenu* KSystemTray::contextMenu() const
00177 {
00178     return menu;
00179 }
00180 
00181 
00182 void KSystemTray::mousePressEvent( QMouseEvent *e )
00183 {
00184     if ( !rect().contains( e->pos() ) )
00185     return;
00186 
00187     switch ( e->button() ) {
00188     case LeftButton:
00189         activateOrHide();
00190     break;
00191     case MidButton:
00192     // fall through
00193     case RightButton:
00194     if ( parentWidget() ) {
00195             KAction* action = d->actionCollection->action("minimizeRestore");
00196         if ( parentWidget()->isVisible() )
00197         action->setText( i18n("&Minimize") );
00198         else
00199         action->setText( i18n("&Restore") );
00200     }
00201     contextMenuAboutToShow( menu );
00202     menu->popup( e->globalPos() );
00203     break;
00204     default:
00205     // nothing
00206     break;
00207     }
00208 }
00209 
00210 void KSystemTray::mouseReleaseEvent( QMouseEvent * )
00211 {
00212 }
00213 
00214 
00215 void KSystemTray::contextMenuAboutToShow( KPopupMenu* )
00216 {
00217 }
00218 
00219 // called from the popup menu - always do what the menu entry says,
00220 // i.e. if the window is shown, no matter if active or not, the menu
00221 // entry is "minimize", otherwise it's "restore"
00222 void KSystemTray::minimizeRestoreAction()
00223 {
00224     if ( parentWidget() ) {
00225         bool restore = !( parentWidget()->isVisible() );
00226     minimizeRestore( restore );
00227     }
00228 }
00229 
00230 // called when left-clicking the tray icon
00231 // if the window is not the active one, show it if needed, and activate it
00232 // (just like taskbar); otherwise hide it
00233 void KSystemTray::activateOrHide()
00234 {
00235     QWidget *pw = parentWidget();
00236 
00237     if ( !pw )
00238     return;
00239 
00240 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00241     KWin::WindowInfo info1 = KWin::windowInfo( pw->winId(), NET::XAWMState | NET::WMState );
00242     // mapped = visible (but possibly obscured)
00243     bool mapped = (info1.mappingState() == NET::Visible) && !info1.isMinimized();
00244 //    - not mapped -> show, raise, focus
00245 //    - mapped
00246 //        - obscured -> raise, focus
00247 //        - not obscured -> hide
00248     if( !mapped )
00249         minimizeRestore( true );
00250     else
00251     {
00252         KWinModule module;
00253         for( QValueList< WId >::ConstIterator it = module.stackingOrder().fromLast();
00254              it != module.stackingOrder().end() && (*it) != pw->winId();
00255              --it )
00256         {
00257             KWin::WindowInfo info2 = KWin::windowInfo( *it,
00258                 NET::WMGeometry | NET::XAWMState | NET::WMState | NET::WMWindowType );
00259             if( info2.mappingState() != NET::Visible )
00260                 continue; // not visible on current desktop -> ignore
00261             if( !info2.geometry().intersects( pw->geometry()))
00262                 continue; // not obscuring the window -> ignore
00263             if( !info1.hasState( NET::KeepAbove ) && info2.hasState( NET::KeepAbove ))
00264                 continue; // obscured by window kept above -> ignore
00265             NET::WindowType type = info2.windowType( NET::NormalMask | NET::DesktopMask
00266                 | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
00267                 | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask );
00268             if( type == NET::Dock || type == NET::TopMenu )
00269                 continue; // obscured by dock or topmenu -> ignore
00270             pw->raise();
00271             KWin::activateWindow( pw->winId());
00272             return;
00273         }
00274         minimizeRestore( false ); // hide
00275     }
00276 #endif
00277 }
00278 
00279 void KSystemTray::minimizeRestore( bool restore )
00280 {
00281     QWidget* pw = parentWidget();
00282     if( !pw )
00283     return;
00284 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00285     KWin::WindowInfo info = KWin::windowInfo( pw->winId(), NET::WMGeometry | NET::WMDesktop );
00286     if ( restore )
00287     {
00288 //#ifndef Q_WS_QWS //FIXME
00289 //#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00290     if( d->on_all_desktops )
00291         KWin::setOnAllDesktops( pw->winId(), true );
00292     else
00293         KWin::setOnDesktop( pw->winId(), KWin::currentDesktop());
00294         pw->move( info.geometry().topLeft() ); // avoid placement policies
00295         pw->show();
00296         pw->raise();
00297     KWin::activateWindow( pw->winId() );
00298     } else {
00299     d->on_all_desktops = info.onAllDesktops();
00300     pw->hide();
00301     }
00302 #endif
00303 }
00304 
00305 KActionCollection* KSystemTray::actionCollection()
00306 {
00307     return d->actionCollection;
00308 }
00309     
00310 QPixmap KSystemTray::loadIcon( const QString &icon, KInstance *instance )
00311 {
00312     KConfig *appCfg = kapp->config();
00313     KConfigGroupSaver configSaver(appCfg, "System Tray");
00314     int iconWidth = appCfg->readNumEntry("systrayIconWidth", 22);
00315     return instance->iconLoader()->loadIcon( icon, KIcon::Panel, iconWidth );
00316 }
00317 
00318 void KSystemTray::virtual_hook( int, void* )
00319 { /*BASE::virtual_hook( id, data );*/ }
00320 
00321 #include "ksystemtray.moc"
00322 #include "kdockwindow.moc"
KDE Logo
This file is part of the documentation for kdeui Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed May 5 07:16:11 2004 by doxygen 1.3.6 written by Dimitri van Heesch, © 1997-2003