summaryrefslogtreecommitdiffstats
path: root/kicker/applets/systemtray
diff options
context:
space:
mode:
Diffstat (limited to 'kicker/applets/systemtray')
-rw-r--r--kicker/applets/systemtray/Makefile.am24
-rw-r--r--kicker/applets/systemtray/systemtrayapplet.cpp1013
-rw-r--r--kicker/applets/systemtray/systemtrayapplet.desktop158
-rw-r--r--kicker/applets/systemtray/systemtrayapplet.h126
4 files changed, 1321 insertions, 0 deletions
diff --git a/kicker/applets/systemtray/Makefile.am b/kicker/applets/systemtray/Makefile.am
new file mode 100644
index 000000000..849795a9e
--- /dev/null
+++ b/kicker/applets/systemtray/Makefile.am
@@ -0,0 +1,24 @@
+
+INCLUDES = -I$(top_srcdir)/kicker/libkicker $(all_includes)
+
+kde_module_LTLIBRARIES = systemtray_panelapplet.la
+
+systemtray_panelapplet_la_SOURCES = systemtrayapplet.cpp systemtrayapplet.skel
+
+systemtray_panelapplet_la_METASOURCES = AUTO
+noinst_HEADERS = systemtrayapplet.h
+
+lnkdir = $(kde_datadir)/kicker/applets
+lnk_DATA = systemtrayapplet.desktop
+
+EXTRA_DIST = $(lnk_DATA)
+
+systemtray_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+systemtray_panelapplet_la_LIBADD = ../../libkicker/libkickermain.la $(LIB_KDEUI) $(LIB_KIO)
+
+
+messages:
+ $(XGETTEXT) *.cpp *.h -o $(podir)/ksystemtrayapplet.pot
+
+srcdoc:
+ kdoc -a -p -H -d $$HOME/web/src/ksystemtrayapplet ksystemtrayapplet *.h -lqt -lkdecore -lkdeui -lkfile
diff --git a/kicker/applets/systemtray/systemtrayapplet.cpp b/kicker/applets/systemtray/systemtrayapplet.cpp
new file mode 100644
index 000000000..8ae502fb4
--- /dev/null
+++ b/kicker/applets/systemtray/systemtrayapplet.cpp
@@ -0,0 +1,1013 @@
+/*****************************************************************
+
+Copyright (c) 2000-2001 Matthias Ettrich <ettrich@kde.org>
+ 2000-2001 Matthias Elter <elter@kde.org>
+ 2001 Carsten Pfeiffer <pfeiffer@kde.org>
+ 2001 Martijn Klingens <mklingens@yahoo.com>
+ 2004 Aaron J. Seigo <aseigo@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qcursor.h>
+#include <qlayout.h>
+#include <qpopupmenu.h>
+#include <qtimer.h>
+#include <qpixmap.h>
+#include <qevent.h>
+#include <qstyle.h>
+#include <qpainter.h>
+
+#include <dcopclient.h>
+#include <kapplication.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <krun.h>
+#include <kwinmodule.h>
+#include <kdialogbase.h>
+#include <kactionselector.h>
+#include <kiconloader.h>
+#include <kwin.h>
+
+#include "simplebutton.h"
+
+#include "systemtrayapplet.h"
+#include "systemtrayapplet.moc"
+
+#include <X11/Xlib.h>
+
+#define ICON_MARGIN 1
+
+extern "C"
+{
+ KDE_EXPORT KPanelApplet* init(QWidget *parent, const QString& configFile)
+ {
+ KGlobal::locale()->insertCatalogue("ksystemtrayapplet");
+ return new SystemTrayApplet(configFile, KPanelApplet::Normal,
+ KPanelApplet::Preferences, parent, "ksystemtrayapplet");
+ }
+}
+
+SystemTrayApplet::SystemTrayApplet(const QString& configFile, Type type, int actions,
+ QWidget *parent, const char *name)
+ : KPanelApplet(configFile, type, actions, parent, name),
+ m_showFrame(false),
+ m_showHidden(false),
+ m_expandButton(0),
+ m_settingsDialog(0),
+ m_iconSelector(0),
+ m_autoRetractTimer(0),
+ m_autoRetract(false),
+ m_iconSize(24),
+ m_layout(0)
+{
+ loadSettings();
+
+ setBackgroundOrigin(AncestorOrigin);
+
+ kwin_module = new KWinModule(this);
+
+ // kApplication notifies us of settings changes. added to support
+ // disabling of frame effect on mouse hover
+ kapp->dcopClient()->setNotifications(true);
+ connectDCOPSignal("kicker", "kicker", "configurationChanged()", "loadSettings()", false);
+
+ QTimer::singleShot(0, this, SLOT(initialize()));
+}
+
+void SystemTrayApplet::initialize()
+{
+ // register existing tray windows
+ const QValueList<WId> systemTrayWindows = kwin_module->systemTrayWindows();
+ bool existing = false;
+ for (QValueList<WId>::ConstIterator it = systemTrayWindows.begin();
+ it != systemTrayWindows.end(); ++it )
+ {
+ embedWindow(*it, true);
+ existing = true;
+ }
+
+ showExpandButton(!m_hiddenWins.isEmpty());
+
+ if (existing)
+ {
+ updateVisibleWins();
+ layoutTray();
+ }
+
+ // the KWinModule notifies us when tray windows are added or removed
+ connect( kwin_module, SIGNAL( systemTrayWindowAdded(WId) ),
+ this, SLOT( systemTrayWindowAdded(WId) ) );
+ connect( kwin_module, SIGNAL( systemTrayWindowRemoved(WId) ),
+ this, SLOT( updateTrayWindows() ) );
+
+ QCString screenstr;
+ screenstr.setNum(qt_xscreen());
+ QCString trayatom = "_NET_SYSTEM_TRAY_S" + screenstr;
+
+ Display *display = qt_xdisplay();
+
+ net_system_tray_selection = XInternAtom(display, trayatom, false);
+ net_system_tray_opcode = XInternAtom(display, "_NET_SYSTEM_TRAY_OPCODE", false);
+
+ // Acquire system tray
+ XSetSelectionOwner(display,
+ net_system_tray_selection,
+ winId(),
+ CurrentTime);
+
+ WId root = qt_xrootwin();
+
+ if (XGetSelectionOwner (display, net_system_tray_selection) == winId())
+ {
+ XClientMessageEvent xev;
+
+ xev.type = ClientMessage;
+ xev.window = root;
+
+ xev.message_type = XInternAtom (display, "MANAGER", False);
+ xev.format = 32;
+ xev.data.l[0] = CurrentTime;
+ xev.data.l[1] = net_system_tray_selection;
+ xev.data.l[2] = winId();
+ xev.data.l[3] = 0; /* manager specific data */
+ xev.data.l[4] = 0; /* manager specific data */
+
+ XSendEvent (display, root, False, StructureNotifyMask, (XEvent *)&xev);
+ }
+
+ setBackground();
+}
+
+SystemTrayApplet::~SystemTrayApplet()
+{
+ for (TrayEmbedList::const_iterator it = m_hiddenWins.constBegin();
+ it != m_hiddenWins.constEnd();
+ ++it)
+ {
+ delete *it;
+ }
+
+ for (TrayEmbedList::const_iterator it = m_shownWins.constBegin();
+ it != m_shownWins.constEnd();
+ ++it)
+ {
+ delete *it;
+ }
+
+ KGlobal::locale()->removeCatalogue("ksystemtrayapplet");
+}
+
+bool SystemTrayApplet::x11Event( XEvent *e )
+{
+#define SYSTEM_TRAY_REQUEST_DOCK 0
+#define SYSTEM_TRAY_BEGIN_MESSAGE 1
+#define SYSTEM_TRAY_CANCEL_MESSAGE 2
+ if ( e->type == ClientMessage ) {
+ if ( e->xclient.message_type == net_system_tray_opcode &&
+ e->xclient.data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
+ if( isWinManaged( (WId)e->xclient.data.l[2] ) ) // we already manage it
+ return true;
+ embedWindow( e->xclient.data.l[2], false );
+ layoutTray();
+ return true;
+ }
+ }
+ return KPanelApplet::x11Event( e ) ;
+}
+
+void SystemTrayApplet::preferences()
+{
+ if (m_settingsDialog)
+ {
+ m_settingsDialog->show();
+ m_settingsDialog->raise();
+ return;
+ }
+
+ m_settingsDialog = new KDialogBase(0, "systrayconfig",
+ false, i18n("Configure System Tray"),
+ KDialogBase::Ok | KDialogBase::Apply | KDialogBase::Cancel,
+ KDialogBase::Ok, true);
+ m_settingsDialog->resize(450, 400);
+ connect(m_settingsDialog, SIGNAL(applyClicked()), this, SLOT(applySettings()));
+ connect(m_settingsDialog, SIGNAL(okClicked()), this, SLOT(applySettings()));
+ connect(m_settingsDialog, SIGNAL(finished()), this, SLOT(settingsDialogFinished()));
+
+ m_iconSelector = new KActionSelector(m_settingsDialog);
+ m_iconSelector->setAvailableLabel(i18n("Visible icons:"));
+ m_iconSelector->setSelectedLabel(i18n("Hidden icons:"));
+ m_iconSelector->setShowUpDownButtons(false);
+ m_settingsDialog->setMainWidget(m_iconSelector);
+
+ QListBox *shownListBox = m_iconSelector->availableListBox();
+ QListBox *hiddenListBox = m_iconSelector->selectedListBox();
+
+ TrayEmbedList::const_iterator it = m_shownWins.begin();
+ TrayEmbedList::const_iterator itEnd = m_shownWins.end();
+ for (; it != itEnd; ++it)
+ {
+ QString name = KWin::windowInfo((*it)->embeddedWinId()).name();
+ if(!shownListBox->findItem(name, Qt::ExactMatch | Qt::CaseSensitive))
+ {
+ shownListBox->insertItem(KWin::icon((*it)->embeddedWinId(), 22, 22, true), name);
+ }
+ }
+
+ it = m_hiddenWins.begin();
+ itEnd = m_hiddenWins.end();
+ for (; it != itEnd; ++it)
+ {
+ QString name = KWin::windowInfo((*it)->embeddedWinId()).name();
+ if(!hiddenListBox->findItem(name, Qt::ExactMatch | Qt::CaseSensitive))
+ {
+ hiddenListBox->insertItem(KWin::icon((*it)->embeddedWinId(), 22, 22, true), name);
+ }
+ }
+
+ m_settingsDialog->show();
+}
+
+void SystemTrayApplet::settingsDialogFinished()
+{
+ m_settingsDialog->delayedDestruct();
+ m_settingsDialog = 0;
+ m_iconSelector = 0;
+}
+
+void SystemTrayApplet::applySettings()
+{
+ if (!m_iconSelector)
+ {
+ return;
+ }
+
+ KConfig *conf = config();
+ conf->setGroup("HiddenTrayIcons");
+ QString name;
+
+ // use the following snippet of code someday to implement ordering
+ // of icons
+ /*
+ m_visibleIconList.clear();
+ QListBoxItem* item = m_iconSelector->availableListBox()->firstItem();
+ for (; item; item = item->next())
+ {
+ m_visibleIconList.append(item->text());
+ }
+ conf->writeEntry("Visible", m_visibleIconList);
+ selection.clear();*/
+
+ m_hiddenIconList.clear();
+ QListBoxItem* item = m_iconSelector->selectedListBox()->firstItem();
+ for (; item; item = item->next())
+ {
+ m_hiddenIconList.append(item->text());
+ }
+ conf->writeEntry("Hidden", m_hiddenIconList);
+ conf->sync();
+
+ TrayEmbedList::iterator it = m_shownWins.begin();
+ while (it != m_shownWins.end())
+ {
+ if (shouldHide((*it)->embeddedWinId()))
+ {
+ m_hiddenWins.append(*it);
+ it = m_shownWins.erase(it);
+ }
+ else
+ {
+ ++it;
+ }
+ }
+
+ it = m_hiddenWins.begin();
+ while (it != m_hiddenWins.end())
+ {
+ if (!shouldHide((*it)->embeddedWinId()))
+ {
+ m_shownWins.append(*it);
+ it = m_hiddenWins.erase(it);
+ }
+ else
+ {
+ ++it;
+ }
+ }
+
+ showExpandButton(!m_hiddenWins.isEmpty());
+
+ updateVisibleWins();
+ layoutTray();
+}
+
+void SystemTrayApplet::checkAutoRetract()
+{
+ if (!m_autoRetractTimer)
+ {
+ return;
+ }
+
+ if (!geometry().contains(mapFromGlobal(QCursor::pos())))
+ {
+ m_autoRetractTimer->stop();
+ if (m_autoRetract)
+ {
+ m_autoRetract = false;
+
+ if (m_showHidden)
+ {
+ retract();
+ }
+ }
+ else
+ {
+ m_autoRetract = true;
+ m_autoRetractTimer->start(2000, true);
+ }
+
+ }
+ else
+ {
+ m_autoRetract = false;
+ m_autoRetractTimer->start(250, true);
+ }
+}
+
+void SystemTrayApplet::showExpandButton(bool show)
+{
+ if (show)
+ {
+ if (!m_expandButton)
+ {
+ m_expandButton = new SimpleArrowButton(this);
+ m_expandButton->installEventFilter(this);
+ refreshExpandButton();
+
+ if (orientation() == Vertical)
+ {
+ m_expandButton->setFixedSize(width() - 4,
+ m_expandButton->sizeHint()
+ .height());
+ }
+ else
+ {
+ m_expandButton->setFixedSize(m_expandButton->sizeHint()
+ .width(),
+ height() - 4);
+ }
+ connect(m_expandButton, SIGNAL(clicked()),
+ this, SLOT(toggleExpanded()));
+
+ m_autoRetractTimer = new QTimer(this);
+ connect(m_autoRetractTimer, SIGNAL(timeout()),
+ this, SLOT(checkAutoRetract()));
+ }
+ else
+ {
+ refreshExpandButton();
+ }
+
+ m_expandButton->show();
+ }
+ else if (m_expandButton)
+ {
+ m_expandButton->hide();
+ }
+}
+
+void SystemTrayApplet::orientationChange( Orientation /*orientation*/ )
+{
+ refreshExpandButton();
+}
+
+void SystemTrayApplet::loadSettings()
+{
+ // set our defaults
+ setFrameStyle(NoFrame);
+ m_showFrame = false;
+
+ KConfig *conf = config();
+ conf->setGroup("General");
+
+ if (conf->readBoolEntry("ShowPanelFrame", false))
+ {
+ setFrameStyle(Panel | Sunken);
+ }
+
+ conf->setGroup("HiddenTrayIcons");
+ m_hiddenIconList = conf->readListEntry("Hidden");
+
+ //Note This setting comes from kdeglobal.
+ conf->setGroup("System Tray");
+ m_iconSize = conf->readNumEntry("systrayIconWidth", 22);
+}
+
+void SystemTrayApplet::systemTrayWindowAdded( WId w )
+{
+ if (isWinManaged(w))
+ {
+ // we already manage it
+ return;
+ }
+
+ embedWindow(w, true);
+ updateVisibleWins();
+ layoutTray();
+
+ if (m_showFrame && frameStyle() == NoFrame)
+ {
+ setFrameStyle(Panel|Sunken);
+ }
+}
+
+void SystemTrayApplet::embedWindow( WId w, bool kde_tray )
+{
+ TrayEmbed* emb = new TrayEmbed(kde_tray, this);
+ emb->setAutoDelete(false);
+
+ if (kde_tray)
+ {
+ static Atom hack_atom = XInternAtom( qt_xdisplay(), "_KDE_SYSTEM_TRAY_EMBEDDING", False );
+ XChangeProperty( qt_xdisplay(), w, hack_atom, hack_atom, 32, PropModeReplace, NULL, 0 );
+ emb->embed(w);
+ XDeleteProperty( qt_xdisplay(), w, hack_atom );
+ }
+ else
+ {
+ emb->embed(w);
+ }
+
+ if (emb->embeddedWinId() == 0) // error embedding
+ {
+ delete emb;
+ return;
+ }
+
+ connect(emb, SIGNAL(embeddedWindowDestroyed()), SLOT(updateTrayWindows()));
+ emb->getIconSize(m_iconSize);
+
+ if (shouldHide(w))
+ {
+ emb->hide();
+ m_hiddenWins.append(emb);
+ showExpandButton(true);
+ }
+ else
+ {
+ //emb->hide();
+ emb->setBackground();
+ emb->show();
+ m_shownWins.append(emb);
+ }
+}
+
+bool SystemTrayApplet::isWinManaged(WId w)
+{
+ TrayEmbedList::const_iterator lastEmb = m_shownWins.end();
+ for (TrayEmbedList::const_iterator emb = m_shownWins.begin(); emb != lastEmb; ++emb)
+ {
+ if ((*emb)->embeddedWinId() == w) // we already manage it
+ {
+ return true;
+ }
+ }
+
+ lastEmb = m_hiddenWins.end();
+ for (TrayEmbedList::const_iterator emb = m_hiddenWins.begin(); emb != lastEmb; ++emb)
+ {
+ if ((*emb)->embeddedWinId() == w) // we already manage it
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool SystemTrayApplet::shouldHide(WId w)
+{
+ return m_hiddenIconList.find(KWin::windowInfo(w).name()) != m_hiddenIconList.end();
+}
+
+void SystemTrayApplet::updateVisibleWins()
+{
+ TrayEmbedList::const_iterator lastEmb = m_hiddenWins.end();
+ TrayEmbedList::const_iterator emb = m_hiddenWins.begin();
+
+ if (m_showHidden)
+ {
+ for (; emb != lastEmb; ++emb)
+ {
+ //(*emb)->hide();
+ (*emb)->setBackground();
+ (*emb)->show();
+ }
+ }
+ else
+ {
+ for (; emb != lastEmb; ++emb)
+ {
+ (*emb)->hide();
+ }
+ }
+}
+
+void SystemTrayApplet::toggleExpanded()
+{
+ if (m_showHidden)
+ {
+ retract();
+ }
+ else
+ {
+ expand();
+ }
+}
+
+void SystemTrayApplet::refreshExpandButton()
+{
+ if (!m_expandButton)
+ {
+ return;
+ }
+
+ Qt::ArrowType a;
+
+ if (orientation() == Vertical)
+ a = m_showHidden ? Qt::DownArrow : Qt::UpArrow;
+ else
+ a = (m_showHidden ^ kapp->reverseLayout()) ? Qt::RightArrow : Qt::LeftArrow;
+
+ m_expandButton->setArrowType(a);
+}
+
+void SystemTrayApplet::expand()
+{
+ m_showHidden = true;
+ refreshExpandButton();
+
+ updateVisibleWins();
+ layoutTray();
+
+ if (m_autoRetractTimer)
+ {
+ m_autoRetractTimer->start(250, true);
+ }
+}
+
+void SystemTrayApplet::retract()
+{
+ if (m_autoRetractTimer)
+ {
+ m_autoRetractTimer->stop();
+ }
+
+ m_showHidden = false;
+ refreshExpandButton();
+
+ updateVisibleWins();
+ layoutTray();
+}
+
+void SystemTrayApplet::updateTrayWindows()
+{
+ TrayEmbedList::iterator emb = m_shownWins.begin();
+ while (emb != m_shownWins.end())
+ {
+ WId wid = (*emb)->embeddedWinId();
+ if ((wid == 0) ||
+ ((*emb)->kdeTray() &&
+ !kwin_module->systemTrayWindows().contains(wid)))
+ {
+ (*emb)->deleteLater();
+ emb = m_shownWins.erase(emb);
+ }
+ else
+ {
+ ++emb;
+ }
+ }
+
+ emb = m_hiddenWins.begin();
+ while (emb != m_hiddenWins.end())
+ {
+ WId wid = (*emb)->embeddedWinId();
+ if ((wid == 0) ||
+ ((*emb)->kdeTray() &&
+ !kwin_module->systemTrayWindows().contains(wid)))
+ {
+ (*emb)->deleteLater();
+ emb = m_hiddenWins.erase(emb);
+ }
+ else
+ {
+ ++emb;
+ }
+ }
+
+ showExpandButton(!m_hiddenWins.isEmpty());
+ updateVisibleWins();
+ layoutTray();
+}
+
+int SystemTrayApplet::maxIconWidth() const
+{
+ int largest = m_iconSize;
+
+ TrayEmbedList::const_iterator lastEmb = m_shownWins.end();
+ for (TrayEmbedList::const_iterator emb = m_shownWins.begin(); emb != lastEmb; ++emb)
+ {
+ if (*emb == 0)
+ {
+ continue;
+ }
+
+ int width = (*emb)->width();
+ if (width > largest)
+ {
+ largest = width;
+ }
+ }
+
+ if (m_showHidden)
+ {
+ lastEmb = m_hiddenWins.end();
+ for (TrayEmbedList::const_iterator emb = m_hiddenWins.begin(); emb != lastEmb; ++emb)
+ {
+ int width = (*emb)->width();
+ if (width > largest)
+ {
+ largest = width;
+ }
+ }
+ }
+
+ return largest;
+}
+
+int SystemTrayApplet::maxIconHeight() const
+{
+ int largest = m_iconSize;
+
+ TrayEmbedList::const_iterator lastEmb = m_shownWins.end();
+ for (TrayEmbedList::const_iterator emb = m_shownWins.begin(); emb != m_shownWins.end(); ++emb)
+ {
+ if (*emb == 0)
+ {
+ continue;
+ }
+
+ int height = (*emb)->height();
+ if (height > largest)
+ {
+ largest = height;
+ }
+ }
+
+ if (m_showHidden)
+ {
+ lastEmb = m_hiddenWins.end();
+ for (TrayEmbedList::const_iterator emb = m_hiddenWins.begin(); emb != m_hiddenWins.end(); ++emb)
+ {
+ if (*emb == 0)
+ {
+ continue;
+ }
+
+ int height = (*emb)->height();
+ if (height > largest)
+ {
+ largest = height;
+ }
+ }
+ }
+
+ return largest;
+}
+
+bool SystemTrayApplet::eventFilter(QObject* watched, QEvent* e)
+{
+ if (watched == m_expandButton)
+ {
+ QPoint p;
+ if (e->type() == QEvent::ContextMenu)
+ {
+ p = static_cast<QContextMenuEvent*>(e)->globalPos();
+ }
+ else if (e->type() == QEvent::MouseButtonPress)
+ {
+ QMouseEvent* me = static_cast<QMouseEvent*>(e);
+ if (me->button() == Qt::RightButton)
+ {
+ p = me->globalPos();
+ }
+ }
+
+ if (!p.isNull())
+ {
+ QPopupMenu* contextMenu = new QPopupMenu(this);
+ contextMenu->insertItem(SmallIcon("configure"), i18n("Configure System Tray..."),
+ this, SLOT(configure()));
+
+ contextMenu->exec(static_cast<QContextMenuEvent*>(e)->globalPos());
+
+ delete contextMenu;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+int SystemTrayApplet::widthForHeight(int h) const
+{
+ if (orientation() == Qt::Vertical)
+ {
+ return width();
+ }
+
+ int currentHeight = height();
+ if (currentHeight != h)
+ {
+ SystemTrayApplet* me = const_cast<SystemTrayApplet*>(this);
+ me->setMinimumSize(0, 0);
+ me->setMaximumSize(32767, 32767);
+ me->setFixedHeight(h);
+ }
+
+ return sizeHint().width();
+}
+
+int SystemTrayApplet::heightForWidth(int w) const
+{
+ if (orientation() == Qt::Horizontal)
+ {
+ return height();
+ }
+
+ int currentWidth = width();
+ if (currentWidth != w)
+ {
+ SystemTrayApplet* me = const_cast<SystemTrayApplet*>(this);
+ me->setMinimumSize(0, 0);
+ me->setMaximumSize(32767, 32767);
+ me->setFixedWidth(w);
+ }
+
+ return sizeHint().height();
+}
+
+void SystemTrayApplet::moveEvent( QMoveEvent* )
+{
+ setBackground();
+}
+
+
+void SystemTrayApplet::resizeEvent( QResizeEvent* )
+{
+ layoutTray();
+ // we need to give ourselves a chance to adjust our size before calling this
+ QTimer::singleShot(0, this, SIGNAL(updateLayout()));
+}
+
+void SystemTrayApplet::layoutTray()
+{
+ setUpdatesEnabled(false);
+
+ int iconCount = m_shownWins.count();
+
+ if (m_showHidden)
+ {
+ iconCount += m_hiddenWins.count();
+ }
+
+ /* heightWidth = height or width in pixels (depends on orientation())
+ * nbrOfLines = number of rows or cols (depends on orientation())
+ * line = what line to draw an icon in */
+ int i = 0, line, nbrOfLines, heightWidth;
+ bool showExpandButton = m_expandButton && m_expandButton->isVisibleTo(this);
+ delete m_layout;
+ m_layout = new QGridLayout(this, 1, 1, ICON_MARGIN, ICON_MARGIN);
+
+ if (m_expandButton)
+ {
+ if (orientation() == Vertical)
+ {
+ m_expandButton->setFixedSize(width() - 4, m_expandButton->sizeHint().height());
+ }
+ else
+ {
+ m_expandButton->setFixedSize(m_expandButton->sizeHint().width(), height() - 4);
+ }
+ }
+
+ // col = column or row, depends on orientation(),
+ // the opposite direction of line
+ int col = 0;
+
+ //
+ // The margin and spacing specified in the layout implies that:
+ // [-- ICON_MARGIN pixels --] [-- first icon --] [-- ICON_MARGIN pixels --] ... [-- ICON_MARGIN pixels --] [-- last icon --] [-- ICON_MARGIN pixels --]
+ //
+ // So, if we say that iconWidth is the icon width plus the ICON_MARGIN pixels spacing, then the available width for the icons
+ // is the widget width minus ICON_MARGIN pixels margin. Forgetting these ICON_MARGIN pixels broke the layout algorithm in KDE <= 3.5.9.
+ //
+ // This fix makes the workarounds in the heightForWidth() and widthForHeight() methods unneeded.
+ //
+
+ if (orientation() == Vertical)
+ {
+ int iconWidth = maxIconWidth() + ICON_MARGIN; // +2 for the margins that implied by the layout
+ heightWidth = width() - ICON_MARGIN;
+ // to avoid nbrOfLines=0 we ensure heightWidth >= iconWidth!
+ heightWidth = heightWidth < iconWidth ? iconWidth : heightWidth;
+ nbrOfLines = heightWidth / iconWidth;
+
+ if (showExpandButton)
+ {
+ m_layout->addMultiCellWidget(m_expandButton,
+ 0, 0,
+ 0, nbrOfLines - 1,
+ Qt::AlignHCenter | Qt::AlignVCenter);
+ col = 1;
+ }
+
+ if (m_showHidden)
+ {
+ TrayEmbedList::const_iterator lastEmb = m_hiddenWins.end();
+ for (TrayEmbedList::const_iterator emb = m_hiddenWins.begin();
+ emb != lastEmb; ++emb)
+ {
+ line = i % nbrOfLines;
+ //(*emb)->hide();
+ (*emb)->show();
+ m_layout->addWidget(*emb, col, line,
+ Qt::AlignHCenter | Qt::AlignVCenter);
+
+ if ((line + 1) == nbrOfLines)
+ {
+ ++col;
+ }
+
+ ++i;
+ }
+ }
+
+ TrayEmbedList::const_iterator lastEmb = m_shownWins.end();
+ for (TrayEmbedList::const_iterator emb = m_shownWins.begin();
+ emb != lastEmb; ++emb)
+ {
+ line = i % nbrOfLines;
+ //(*emb)->hide();
+ (*emb)->show();
+ m_layout->addWidget(*emb, col, line,
+ Qt::AlignHCenter | Qt::AlignVCenter);
+
+ if ((line + 1) == nbrOfLines)
+ {
+ ++col;
+ }
+
+ ++i;
+ }
+ }
+ else // horizontal
+ {
+ int iconHeight = maxIconHeight() + ICON_MARGIN; // +2 for the margins that implied by the layout
+ heightWidth = height() - ICON_MARGIN;
+ heightWidth = heightWidth < iconHeight ? iconHeight : heightWidth; // to avoid nbrOfLines=0
+ nbrOfLines = heightWidth / iconHeight;
+
+ if (showExpandButton)
+ {
+ m_layout->addMultiCellWidget(m_expandButton,
+ 0, nbrOfLines - 1,
+ 0, 0,
+ Qt::AlignHCenter | Qt::AlignVCenter);
+ col = 1;
+ }
+
+ if (m_showHidden)
+ {
+ TrayEmbedList::const_iterator lastEmb = m_hiddenWins.end();
+ for (TrayEmbedList::const_iterator emb = m_hiddenWins.begin(); emb != lastEmb; ++emb)
+ {
+ line = i % nbrOfLines;
+ //(*emb)->hide();
+ (*emb)->show();
+ m_layout->addWidget(*emb, line, col,
+ Qt::AlignHCenter | Qt::AlignVCenter);
+
+ if ((line + 1) == nbrOfLines)
+ {
+ ++col;
+ }
+
+ ++i;
+ }
+ }
+
+ TrayEmbedList::const_iterator lastEmb = m_shownWins.end();
+ for (TrayEmbedList::const_iterator emb = m_shownWins.begin();
+ emb != lastEmb; ++emb)
+ {
+ line = i % nbrOfLines;
+ //(*emb)->hide();
+ (*emb)->show();
+ m_layout->addWidget(*emb, line, col,
+ Qt::AlignHCenter | Qt::AlignVCenter);
+
+ if ((line + 1) == nbrOfLines)
+ {
+ ++col;
+ }
+
+ ++i;
+ }
+ }
+
+ setUpdatesEnabled(true);
+ updateGeometry();
+ setBackground();
+}
+
+void SystemTrayApplet::paletteChange(const QPalette & /* oldPalette */)
+{
+ setBackground();
+}
+
+void SystemTrayApplet::setBackground()
+{
+ TrayEmbedList::const_iterator lastEmb;
+
+ lastEmb = m_shownWins.end();
+ for (TrayEmbedList::const_iterator emb = m_shownWins.begin(); emb != lastEmb; ++emb)
+ (*emb)->setBackground();
+
+ lastEmb = m_hiddenWins.end();
+ for (TrayEmbedList::const_iterator emb = m_hiddenWins.begin(); emb != lastEmb; ++emb)
+ (*emb)->setBackground();
+}
+
+
+TrayEmbed::TrayEmbed( bool kdeTray, QWidget* parent )
+ : QXEmbed( parent ), kde_tray( kdeTray )
+{
+ hide();
+}
+
+void TrayEmbed::getIconSize(int defaultIconSize)
+{
+ QSize minSize = minimumSizeHint();
+
+ int width = minSize.width();
+ int height = minSize.height();
+
+ if (width < 1 || width > defaultIconSize)
+ width = defaultIconSize;
+ if (height < 1 || height > defaultIconSize)
+ height = defaultIconSize;
+
+ setFixedSize(width, height);
+ setBackground();
+}
+
+void TrayEmbed::setBackground()
+{
+ const QPixmap *pbg = parentWidget()->backgroundPixmap();
+
+ if (pbg)
+ {
+ QPixmap bg(width(), height());
+ bg.fill(parentWidget(), pos());
+ setPaletteBackgroundPixmap(bg);
+ setBackgroundOrigin(WidgetOrigin);
+ }
+ else
+ unsetPalette();
+
+ if (!isHidden())
+ {
+ XClearArea(x11Display(), embeddedWinId(), 0, 0, 0, 0, True);
+ }
+}
+
diff --git a/kicker/applets/systemtray/systemtrayapplet.desktop b/kicker/applets/systemtray/systemtrayapplet.desktop
new file mode 100644
index 000000000..ab737d83c
--- /dev/null
+++ b/kicker/applets/systemtray/systemtrayapplet.desktop
@@ -0,0 +1,158 @@
+[Desktop Entry]
+Type=Plugin
+Name=System Tray
+Name[af]=Stelsel Laai
+Name[ar]=لوحة النظام
+Name[az]=Sistem Rəfi
+Name[be]=Сістэмны латок
+Name[bg]=Системен панел
+Name[bn]=সিস্টেম ট্রে
+Name[br]=Barlenn ar reizhiad
+Name[ca]=Safata del sistema
+Name[cs]=Systémová část panelu
+Name[csb]=Systemòwi zabiérnik
+Name[cy]=Bar Tasgau
+Name[da]=Statusfelt
+Name[de]=Systemabschnitt der Kontrollleiste
+Name[el]=Πλαίσιο συστήματος
+Name[eo]=Sistempleto
+Name[es]=Bandeja del sistema
+Name[et]=Süsteemne dokk
+Name[eu]=Sistemaren azpila
+Name[fa]=سینی سیستم
+Name[fi]=Ilmoitusalue
+Name[fr]=Boîte à miniatures
+Name[fy]=Systeemfak
+Name[ga]=Tráidire an Chórais
+Name[gl]=Bandexa do Sistema
+Name[he]=מגש מערכת
+Name[hi]=तंत्र तश्तरी
+Name[hr]=Sistemska traka
+Name[hu]=Rendszertálca
+Name[id]=Tray Sistem
+Name[is]=Smáforritabakki
+Name[it]=Vassoio di sistema
+Name[ja]=システムトレイ
+Name[ka]=სისტემური პანელი
+Name[kk]=Жүйелік сөре
+Name[km]=ថាស​ប្រព័ន្ធ
+Name[ko]=시스템 트레이
+Name[lo]=ຖາດຂອງລະບົບ
+Name[lt]=Sistemos dėklas
+Name[lv]=Sistēmas Tekne
+Name[mk]=Системска лента
+Name[mn]=Удирдах самбарын системийн хэсэг
+Name[ms]=Dulang Sistem
+Name[mt]=Tray tas-Sistema
+Name[nb]=Systemkurv
+Name[nds]=Systeemafsnitt vun't Paneel
+Name[ne]=प्रणाली ट्रे
+Name[nl]=Systeemvak
+Name[nn]=Systemtrau
+Name[nso]=Tray ya System
+Name[oc]=Safata dèu sistemo
+Name[pa]=ਸਿਸਟਮ ਟਰੇ
+Name[pl]=Tacka systemowa
+Name[pt]=Bandeja do Painel
+Name[pt_BR]=Ícones do sistema
+Name[ro]=Tavă de sistem
+Name[ru]=Системный лоток
+Name[rw]=Igitwara cya Sisitemu
+Name[se]=Vuogádatgárcu
+Name[sk]=Systémová lišta
+Name[sl]=Sistemska vrstica
+Name[sr]=Системска касета
+Name[sr@Latn]=Sistemska kaseta
+Name[sv]=Systembricka
+Name[ta]=சாதன தட்டு
+Name[te]=వ్యవస్థ ట్రె
+Name[tg]=Сафҳаи идоракунии система
+Name[th]=ถาดของระบบ
+Name[tr]=Sistem Çekmecesi
+Name[tt]=Sistem Tiräse
+Name[uk]=Системний лоток
+Name[ven]=Thirei ya sistemu
+Name[vi]=Khay Hệ thống
+Name[wa]=Boesse ås imådjetes sistinme
+Name[xh]=Itreyi Yendlela yokusebenza
+Name[zh_CN]=系统托盘
+Name[zh_TW]=系統匣
+Name[zu]=Itreyi lesistimu
+
+Comment=The system tray panel applet
+Comment[af]=Die stelsel laai paneel miniprogram
+Comment[ar]=بريمج لوحة النظام
+Comment[az]=Bildiriş sahəsi panel appleti
+Comment[be]=Аплет сістэмнага латка
+Comment[bg]=Системен аплет за регистрация на програми и поддържане на иконите им
+Comment[bn]=সিস্টেম ট্রে প্যানেল অ্যাপলেট
+Comment[br]=Arloadig banell barlenn ar reizhiad
+Comment[bs]=Applet za system tray
+Comment[ca]=L'applet per al plafó de la safata del sistema
+Comment[cs]=Systémová část panelu určená pro applety
+Comment[csb]=Aplet systemòwégò zabiérnika dlô panelu
+Comment[cy]=Rhaglennig bar tasgau i'r panel
+Comment[da]=Statusfelt-panelprogrammet
+Comment[de]=Systemabschnitt der Kontrollleiste
+Comment[el]=Μικροεφαρμογή του πίνακα για το πλαίσιο συστήματος
+Comment[eo]=La sistempleta panelaplikaĵeto
+Comment[es]=La bandeja del sistema (miniaplicación del panel)
+Comment[et]=Paneelil töötav süsteemse doki aplett
+Comment[eu]=Sistemaren azpila (paneleko appleta)
+Comment[fa]=برنامک تابلوی سینی سیستم
+Comment[fi]=Paneelin ilmoitusalue
+Comment[fr]=L'applet de boîte à miniatures du tableau de bord
+Comment[fy]=It systeemfak panielapplet
+Comment[gl]=A applet do painel coa bandexa do sistema
+Comment[he]=יישומון מגש המערכת ללוח
+Comment[hi]=तंत्र तश्तरी फलक ऐपलेट
+Comment[hr]=Aplet ploče za sistemsku traku
+Comment[hu]=A rendszertálca alkalmazás
+Comment[id]=Applet panel tray sistem
+Comment[is]=Íforrit sem birtir lista yfir forrit sem eru í gangi
+Comment[it]=Applet del pannello per il vassoio di sistema
+Comment[ja]=システムトレイパネルアプレット
+Comment[ka]=სისტემური პანელის აპლეტი
+Comment[kk]=Жүйелік сөре панель апплеті
+Comment[km]=អាប់ភ្លេត​បន្ទះ​ថាស​ប្រព័ន្ធ
+Comment[lo]=ແອບແພັດຖາດຂອງລະບົບພາເນລ
+Comment[lt]=Sistemos dėklo pulto priemonė
+Comment[lv]=Sistēmas teknes paneļa aplets
+Comment[mk]=Панелски аплет од системската лента
+Comment[mn]=Удирдах самбарын системийн хэсэг
+Comment[ms]=Aplet panel dulang sistem
+Comment[mt]=Applet għat-tray tas-sistema
+Comment[nb]=Panelprogram for systemkurven
+Comment[nds]=Lüttprogramm för den Systeemafsnitt vun't Paneel
+Comment[ne]=प्रणाली ट्रे प्यानल एप्लेट
+Comment[nl]=De systeemvak paneelapplet
+Comment[nn]=Systemtrau-panelapplet
+Comment[nso]=Applet ya panel ya tray ya system
+Comment[oc]=L'aplet de plafon de la safata dèu sistemo
+Comment[pa]=ਸਿਸਟਮ ਟਰੇ ਪੈਨਲ ਐਪਲਿਟ
+Comment[pl]=Programik tacki systemowej dla panelu
+Comment[pt]=Uma 'applet' com a bandeja do painel
+Comment[pt_BR]=Mini-aplicativo de ícones do sistema
+Comment[ro]=Miniaplicația tavă de sistem pentru panou
+Comment[ru]=Аплет панели системного лотка
+Comment[rw]=Apuleti y'umwanya w'igitwara sisitemu
+Comment[se]=Vuogádatgárcu-panelprográmmaš
+Comment[sk]=Applet Systémová lišta
+Comment[sl]=Vstavek za sistemsko vrstico v pultu
+Comment[sr]=Аплет системске касете за панел
+Comment[sr@Latn]=Aplet sistemske kasete za panel
+Comment[sv]=Panelminiprogram för systembricka
+Comment[ta]=சாதன தட்டு பலக சிறுநிரல்
+Comment[tg]=Барномаи сафҳаи идоракунии системаи сафҳа
+Comment[th]=แอพเพล็ตถาดของระบบบนพาเนล
+Comment[tr]=Sistem çekmece paneli
+Comment[uk]=Аплет системного лотку панелі
+Comment[vi]=Tiểu ứng dụng có bảng điều khiển chứa khay hệ thống
+Comment[wa]=L' aplikete boesse ås imådjetes sistinme do scriftôr
+Comment[xh]=I applet yeqela lenjongo ethile yendlela yetreyi yokusebenza
+Comment[zh_CN]=系统托盘小程序
+Comment[zh_TW]=系統匣 (system tray) 面板小程式
+Comment[zu]=I-applet yewindi lemininingwane yetreyi lesistimu
+Icon=systemtray
+X-KDE-Library=systemtray_panelapplet
+X-KDE-UniqueApplet=true
diff --git a/kicker/applets/systemtray/systemtrayapplet.h b/kicker/applets/systemtray/systemtrayapplet.h
new file mode 100644
index 000000000..7afc18bf9
--- /dev/null
+++ b/kicker/applets/systemtray/systemtrayapplet.h
@@ -0,0 +1,126 @@
+/*****************************************************************
+
+Copyright (c) 1996-2001 the kicker authors. See file AUTHORS.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __systemtrayapplet_h__
+#define __systemtrayapplet_h__
+
+#include <qvaluevector.h>
+#include <qstringlist.h>
+#include <qevent.h>
+#include <qxembed.h>
+
+#include <dcopobject.h>
+#include <kapplication.h>
+#include <kpanelapplet.h>
+
+#include "simplebutton.h"
+
+class QGridLayout;
+class QTimer;
+class KWinModule;
+class TrayEmbed;
+class KDialogBase;
+class KActionSelector;
+
+class SystemTrayApplet : public KPanelApplet, public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+ typedef QValueVector<TrayEmbed*> TrayEmbedList;
+
+public:
+
+ SystemTrayApplet(const QString& configFile, Type t = Normal, int actions = 0,
+ QWidget *parent = 0, const char *name = 0);
+ ~SystemTrayApplet();
+
+ int widthForHeight(int h) const;
+ int heightForWidth(int w) const;
+ int maxIconWidth() const;
+ int maxIconHeight() const;
+
+ bool eventFilter(QObject* watched, QEvent* e);
+
+k_dcop:
+ void loadSettings();
+
+protected:
+ void resizeEvent(QResizeEvent*);
+ void moveEvent(QMoveEvent *);
+ bool x11Event( XEvent *e );
+ void preferences();
+ void orientationChange( Orientation );
+
+protected slots:
+ void initialize();
+ void systemTrayWindowAdded( WId );
+ void updateTrayWindows();
+ void layoutTray();
+ void paletteChange(const QPalette & /* oldPalette */);
+ void toggleExpanded();
+ void settingsDialogFinished();
+ void applySettings();
+ void checkAutoRetract();
+ void configure() { preferences(); }
+ void setBackground();
+
+private:
+ void embedWindow( WId w, bool kde_tray );
+ bool isWinManaged( WId w);
+ bool shouldHide( WId w);
+ void updateVisibleWins();
+ void expand();
+ void retract();
+ void showExpandButton(bool show);
+ void refreshExpandButton();
+
+ TrayEmbedList m_shownWins;
+ TrayEmbedList m_hiddenWins;
+ QStringList m_hiddenIconList;
+ KWinModule *kwin_module;
+ Atom net_system_tray_selection;
+ Atom net_system_tray_opcode;
+ bool m_showFrame;
+ bool m_showHidden;
+ SimpleArrowButton *m_expandButton;
+ KDialogBase* m_settingsDialog;
+ KActionSelector* m_iconSelector;
+ QTimer* m_autoRetractTimer;
+ bool m_autoRetract;
+ int m_iconSize;
+ QGridLayout* m_layout;
+};
+
+class TrayEmbed : public QXEmbed
+{
+ Q_OBJECT
+public:
+ TrayEmbed( bool kdeTray, QWidget* parent = NULL );
+ bool kdeTray() const { return kde_tray; }
+ void setBackground();
+ void getIconSize(int defaultIconSize);
+private:
+ bool kde_tray;
+};
+
+#endif