From 14286a0eb6ec163c90e3d13c27fea147dbb82481 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sl=C3=A1vek=20Banko?= Date: Fri, 5 Jul 2013 19:06:59 +0200 Subject: Initial import --- src/customtraylabel.cpp | 360 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 src/customtraylabel.cpp (limited to 'src/customtraylabel.cpp') diff --git a/src/customtraylabel.cpp b/src/customtraylabel.cpp new file mode 100644 index 0000000..aca36e1 --- /dev/null +++ b/src/customtraylabel.cpp @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2004 Girish Ramakrishnan All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// $Id: customtraylabel.cpp,v 1.14 2005/06/21 10:04:35 cs19713 Exp $ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "trace.h" +#include "customtraylabel.h" +#include "traylabelmgr.h" +#include "kdocker.h" + +CustomTrayLabel::CustomTrayLabel(Window w, QWidget* p, const QString& t) + : QTrayLabel(w, p, t), mUndockWhenDead(false) +{ + installMenu(); +} + +CustomTrayLabel::CustomTrayLabel(const QStringList& argv, pid_t pid, + QWidget* parent) + : QTrayLabel(argv, pid, parent), mUndockWhenDead(false) +{ + installMenu(); +} + +/* + * Installs a popup menu on the tray label + */ +void CustomTrayLabel::installMenu() +{ + QPixmap kdocker_png(QString(ICONS_PATH) + "/kdocker.png"); + if (kdocker_png.isNull()) + kdocker_png.load(qApp->applicationDirPath() + "/icons/kdocker.png"); + setIcon(kdocker_png); + TrayLabelMgr *tlMgr = TrayLabelMgr::instance(); + + mOptionsMenu = new QPopupMenu(this); + mSessionManagement = new QAction(tr("Dock when session restored"), 0, this); + mSessionManagement->setToggleAction(true); + connect(mSessionManagement, SIGNAL(toggled(bool)), + this, SLOT(enableSessionManagement(bool))); + mSessionManagement->addTo(mOptionsMenu); + + mAutoLaunch = new QAction(tr("Launch on startup"), 0, this); + mAutoLaunch->setToggleAction(true); + connect(mAutoLaunch, SIGNAL(activated()), + this, SLOT(slotSetLaunchOnStartup())); + mAutoLaunch->addTo(mOptionsMenu); + + mOptionsMenu->insertItem(tr("Set Icon"), this, SLOT(setCustomIcon())); + + mBalloonTimeout = new QAction(tr("Set balloon timeout"), 0, this); + connect(mBalloonTimeout, SIGNAL(activated()), + this, SLOT(slotSetBalloonTimeout())); + mBalloonTimeout->addTo(mOptionsMenu); + + mDockWhenObscured = new QAction(tr("Dock when obscured"), 0, this); + mDockWhenObscured->setToggleAction(true); + connect(mDockWhenObscured, SIGNAL(toggled(bool)), + this, SLOT(setDockWhenObscured(bool))); + mDockWhenObscured->addTo(mOptionsMenu); + + mDockWhenMinimized = new QAction(tr("Dock when minimized"), 0, this); + mDockWhenMinimized->setToggleAction(true); + connect(mDockWhenMinimized, SIGNAL(toggled(bool)), + this, SLOT(setDockWhenMinimized(bool))); + mDockWhenMinimized->addTo(mOptionsMenu); + + mDockWhenFocusLost = new QAction(tr("Dock when focus lost"), 0, this); + mDockWhenFocusLost->setToggleAction(true); + connect(mDockWhenFocusLost, SIGNAL(toggled(bool)), + this, SLOT(setDockWhenFocusLost(bool))); + mDockWhenFocusLost->addTo(mOptionsMenu); + + mSkipTaskbar = new QAction(tr("Skip taskbar"), 0, this); + mSkipTaskbar->setToggleAction(true); + connect(mSkipTaskbar, SIGNAL(toggled(bool)), + this, SLOT(setSkipTaskbar(bool))); + mSkipTaskbar->addTo(mOptionsMenu); + + mMainMenu = new QPopupMenu(this); + mMainMenu->insertItem(QIconSet(kdocker_png), + tr("About KDocker"), tlMgr, SLOT(about())); + mMainMenu->insertSeparator(); + mMainMenu->insertItem(tr("Options"), mOptionsMenu); + mMainMenu->insertItem(tr("Dock Another"), tlMgr, SLOT(dockAnother())); + mMainMenu->insertItem(tr("Undock All"), tlMgr, SLOT(undockAll())); + mMainMenu->insertSeparator(); + + mShowId = mMainMenu->insertItem(QString("Show/Hide [untitled]"), + this, SLOT(toggleShow())); + mMainMenu->insertItem(QString(tr("Undock")), this, SLOT(undock())); + mMainMenu->insertItem(QString(tr("Close")), this, SLOT(close())); + + connect(mMainMenu, SIGNAL(aboutToShow()), this, SLOT(updateMenu())); + + // Apply defaults here + setLaunchOnStartup(false); + setDockWhenObscured(false); + enableSessionManagement(true); + mDockWhenMinimized->setOn(isDockWhenMinimized()); + mSkipTaskbar->setOn(isSkippingTaskbar()); + setAcceptDrops(true); // and you thought this function only installs the menu +} + +/* + * Session Management + */ +bool CustomTrayLabel::restoreState(QSettings& settings) +{ + mAutoLaunch->setOn(settings.readBoolEntry("/LaunchOnStartup")); + setDockWhenObscured(settings.readBoolEntry("/DockWhenObscured")); + TRACE("AutoLaunch=%i DWM=%i DWO=%i", isLaunchOnStartup(), + isDockWhenMinimized(), isDockWhenObscured()); + return QTrayLabel::restoreState(settings); +} + +bool CustomTrayLabel::saveState(QSettings& settings) +{ + if (!mSessionManagement->isOn()) return false; + + QTrayLabel::saveState(settings); + settings.writeEntry("/LaunchOnStartup", isLaunchOnStartup()); + settings.writeEntry("/DockWhenObscured", isDockWhenObscured()); + TRACE("AutoLaunch=%i DWM=%i DWO=%i", isLaunchOnStartup(), + isDockWhenMinimized(), isDockWhenObscured()); + return true; +} + +static bool which(const char *app) +{ + if (access(app, X_OK) == 0) return true; + + // Check if the program exist in the $PATH + char *path = strdup(getenv("PATH")); + char prog[300]; + if (path == NULL) return false; + TRACE("PATH=%s", path); + char *p = strtok(path, ":"); + while (p != NULL) + { + snprintf(prog, sizeof(prog), "%s/%s", p, app); + if (access(prog, X_OK) == 0) break; + p = strtok(NULL, ":"); + } + free(path); + TRACE("Located at (%s)", p); + return p != NULL; +} + +// Overridden to update our menu +void CustomTrayLabel::setDockWhenMinimized(bool dwm) +{ + QTrayLabel::setDockWhenMinimized(dwm); + mDockWhenMinimized->setOn(isDockWhenMinimized()); +} + +void CustomTrayLabel::setSkipTaskbar(bool skip) +{ + QTrayLabel::setSkipTaskbar(skip); + mSkipTaskbar->setOn(isSkippingTaskbar()); +} + +void CustomTrayLabel::setAppName(const QString& name) +{ + QTrayLabel::setAppName(name.lower()); +} + +/* + * This function is called when QTrayLabel wants to know whether it can + * unsubscribe from root window. This is because it doesnt know if someone + * else is interested in root window events + */ +bool CustomTrayLabel::canUnsubscribeFromRoot(void) +{ + return (TrayLabelMgr::instance())->hiddenLabelsCount() == 0; +} + +// Get icon from user, load it and if successful load it. +void CustomTrayLabel::setCustomIcon(void) +{ + QString icon; + + while (true) + { + // Nag the user to give us a valid icon or press cancel + icon = QFileDialog::getOpenFileName(); + if (icon.isNull()) return; // user cancelled + if (!QPixmap(icon).isNull()) break; + TRACE("Attempting to set icon to %s", icon.latin1()); + QMessageBox::critical(this, tr("KDocker"), + tr("%1 is not a valid icon").arg(icon)); + } + + setTrayIcon(icon); +} + +// Get balloon timeout from the user +void CustomTrayLabel::slotSetBalloonTimeout(void) +{ + bool ok; + int timeout = QInputDialog::getInteger(tr("KDocker"), + tr("Enter balloon timeout (secs). 0 to disable ballooning"), + balloonTimeout()/1000, 0, 60, 1, &ok); + + if (!ok) return; + setBalloonTimeout(timeout * 1000); +} + +void CustomTrayLabel::setLaunchOnStartup(bool launch) +{ + mAutoLaunch->setOn(launch); + slotSetLaunchOnStartup(); // fake an "activated" signal +} + +void CustomTrayLabel::slotSetLaunchOnStartup() +{ + TRACE("%i", mAutoLaunch->isOn()); + if (!mAutoLaunch->isOn()) return; + QString app = appName(); + + TRACE("Validating %s", app.latin1()); + + while (true) + { + if (which(app.latin1())) + { + TRACE("Autolaunch enabled to %s", app.latin1()); + setAppName(app); + mAutoLaunch->setOn(true); + return; + } + + // Request user to provide file name himself + if (QMessageBox::critical(NULL, tr("KDocker"), + tr("\"%1\" is not a valid executable " + "or was not found in your $PATH").arg(app), + tr("Select program"), tr("Cancel")) == 1) + { + mAutoLaunch->setOn(false); + return; // cancelled + } + + app = QFileDialog::getOpenFileName(); + if (app.isNull()) + { + TRACE("Disabling auto launch"); + mAutoLaunch->setOn(false); + return; + } + } +} + +// Called when we are just about to display the menu +void CustomTrayLabel::updateMenu(void) +{ + QString title = appClass(); // + "(" + appTitle() + ")"; + mMainMenu->changeItem(mShowId, QIconSet(*pixmap()), + QString((isWithdrawn() ? tr("Show %1") : tr("Hide %1")).arg(title))); +} + +void CustomTrayLabel::mapEvent(void) +{ + TRACE("mapEvent"); + if (mDockWhenObscured->isOn()) + { + /* + * We get a obscured event for the time between the map and focus in of + * the window. So we disable it for sometime and reanable. + */ + mDockWhenObscured->setOn(false); + QTimer::singleShot(800, mDockWhenObscured, SLOT(toggle())); + TRACE("Turning off DWO for some time"); + } +} + +void CustomTrayLabel::obscureEvent(void) +{ + TRACE("obscureEvent"); + if (mDockWhenObscured->isOn() && !isWithdrawn()) + withdraw(); +} + +void CustomTrayLabel::focusLostEvent() +{ + if (mDockWhenFocusLost->isOn()) withdraw(); +} + +void CustomTrayLabel::mouseReleaseEvent(QMouseEvent * ev) +{ + if (ev->button() == Qt::RightButton) + mMainMenu->popup(ev->globalPos()); + else + toggleShow(); +} + +void CustomTrayLabel::destroyEvent(void) +{ + mUndockWhenDead = true; + QTrayLabel::destroyEvent(); +} + +void CustomTrayLabel::processDead(void) +{ + /* + * This is a ugly hack but worth every but of ugliness IMO ;). + * Lets say, an instance of xmms, already exists. You type kdocker xmms. + * KDocker launches xmms. xmms cowardly exists seeing its previous instance. + * Wouldnt it be nice now to dock the previous instance of xmms automatically. + * This is more common than you think (think of session restoration) + */ + + if (!mUndockWhenDead) + { + scanClients(); + if (dockedWindow() != None) return; + } + undock(); +} + +/* + * Can dock this window iff not docked by another one tray label already + */ +bool CustomTrayLabel::canDockWindow(Window w) +{ + TRACE("Checking if 0x%x is already docked", (unsigned) w); + return !(TrayLabelMgr::instance()->isWindowDocked(w)); +} + +void CustomTrayLabel::dropEvent(QDropEvent *) +{ + QMessageBox::information(NULL, "KDocker", + tr("You cannot drop an item into the tray icon. Drop it on the window\n" + "that is brought in front when you hover the item over the tray icon")); +} + -- cgit v1.2.1