diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 4aed2c8219774f5d797760606b8489a92ddc5163 (patch) | |
tree | 3f8c130f7d269626bf6a9447407ef6c35954426a /kicker/applets/systemtray | |
download | tdebase-4aed2c8219774f5d797760606b8489a92ddc5163.tar.gz tdebase-4aed2c8219774f5d797760606b8489a92ddc5163.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kicker/applets/systemtray')
-rw-r--r-- | kicker/applets/systemtray/Makefile.am | 24 | ||||
-rw-r--r-- | kicker/applets/systemtray/systemtrayapplet.cpp | 1013 | ||||
-rw-r--r-- | kicker/applets/systemtray/systemtrayapplet.desktop | 158 | ||||
-rw-r--r-- | kicker/applets/systemtray/systemtrayapplet.h | 126 |
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 |