|
|
|
/*
|
|
|
|
* 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 <tqsettings.h>
|
|
|
|
#include <tqpopupmenu.h>
|
|
|
|
#include <tqmessagebox.h>
|
|
|
|
#include <tqfiledialog.h>
|
|
|
|
#include <tqinputdialog.h>
|
|
|
|
#include <tqaction.h>
|
|
|
|
#include <tqtimer.h>
|
|
|
|
#include <tqsize.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#include <kglobal.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
|
|
|
|
#include "trace.h"
|
|
|
|
#include "customtraylabel.h"
|
|
|
|
#include "traylabelmgr.h"
|
|
|
|
#include "kdocker.h"
|
|
|
|
|
|
|
|
CustomTrayLabel::CustomTrayLabel(Window w, TQWidget* p, const TQString& t)
|
|
|
|
: TQTrayLabel(w, p, t), mUndockWhenDead(false)
|
|
|
|
{
|
|
|
|
installMenu();
|
|
|
|
}
|
|
|
|
|
|
|
|
CustomTrayLabel::CustomTrayLabel(const TQStringList& argv, pid_t pid,
|
|
|
|
TQWidget* parent)
|
|
|
|
: TQTrayLabel(argv, pid, parent), mUndockWhenDead(false)
|
|
|
|
{
|
|
|
|
installMenu();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Installs a popup menu on the tray label
|
|
|
|
*/
|
|
|
|
void CustomTrayLabel::installMenu()
|
|
|
|
{
|
|
|
|
TQPixmap kdocker_png(KGlobal::iconLoader()->loadIcon("kdocker", KIcon::NoGroup, KIcon::SizeSmall));
|
|
|
|
setIcon(kdocker_png);
|
|
|
|
TrayLabelMgr *tlMgr = TrayLabelMgr::instance();
|
|
|
|
|
|
|
|
mOptionsMenu = new TQPopupMenu(this);
|
|
|
|
mSessionManagement = new TQAction(i18n("Dock when session restored"), 0, this);
|
|
|
|
mSessionManagement->setToggleAction(true);
|
|
|
|
connect(mSessionManagement, SIGNAL(toggled(bool)),
|
|
|
|
this, SLOT(enableSessionManagement(bool)));
|
|
|
|
mSessionManagement->addTo(mOptionsMenu);
|
|
|
|
|
|
|
|
mAutoLaunch = new TQAction(i18n("Launch on startup"), 0, this);
|
|
|
|
mAutoLaunch->setToggleAction(true);
|
|
|
|
connect(mAutoLaunch, SIGNAL(activated()),
|
|
|
|
this, SLOT(slotSetLaunchOnStartup()));
|
|
|
|
mAutoLaunch->addTo(mOptionsMenu);
|
|
|
|
|
|
|
|
mOptionsMenu->insertItem(i18n("Set Icon"), this, SLOT(setCustomIcon()));
|
|
|
|
|
|
|
|
mBalloonTimeout = new TQAction(i18n("Set balloon timeout"), 0, this);
|
|
|
|
connect(mBalloonTimeout, SIGNAL(activated()),
|
|
|
|
this, SLOT(slotSetBalloonTimeout()));
|
|
|
|
mBalloonTimeout->addTo(mOptionsMenu);
|
|
|
|
|
|
|
|
mDockWhenObscured = new TQAction(i18n("Dock when obscured"), 0, this);
|
|
|
|
mDockWhenObscured->setToggleAction(true);
|
|
|
|
connect(mDockWhenObscured, SIGNAL(toggled(bool)),
|
|
|
|
this, SLOT(setDockWhenObscured(bool)));
|
|
|
|
mDockWhenObscured->addTo(mOptionsMenu);
|
|
|
|
|
|
|
|
mDockWhenMinimized = new TQAction(i18n("Dock when minimized"), 0, this);
|
|
|
|
mDockWhenMinimized->setToggleAction(true);
|
|
|
|
connect(mDockWhenMinimized, SIGNAL(toggled(bool)),
|
|
|
|
this, SLOT(setDockWhenMinimized(bool)));
|
|
|
|
mDockWhenMinimized->addTo(mOptionsMenu);
|
|
|
|
|
|
|
|
mDockWhenFocusLost = new TQAction(i18n("Dock when focus lost"), 0, this);
|
|
|
|
mDockWhenFocusLost->setToggleAction(true);
|
|
|
|
connect(mDockWhenFocusLost, SIGNAL(toggled(bool)),
|
|
|
|
this, SLOT(setDockWhenFocusLost(bool)));
|
|
|
|
mDockWhenFocusLost->addTo(mOptionsMenu);
|
|
|
|
|
|
|
|
mSkipTaskbar = new TQAction(i18n("Skip taskbar"), 0, this);
|
|
|
|
mSkipTaskbar->setToggleAction(true);
|
|
|
|
connect(mSkipTaskbar, SIGNAL(toggled(bool)),
|
|
|
|
this, SLOT(setSkipTaskbar(bool)));
|
|
|
|
mSkipTaskbar->addTo(mOptionsMenu);
|
|
|
|
|
|
|
|
mMainMenu = new TQPopupMenu(this);
|
|
|
|
mMainMenu->insertItem(TQIconSet(kdocker_png),
|
|
|
|
i18n("About KDocker"), tlMgr, SLOT(about()));
|
|
|
|
mMainMenu->insertSeparator();
|
|
|
|
mMainMenu->insertItem(i18n("Options"), mOptionsMenu);
|
|
|
|
mMainMenu->insertItem(i18n("Dock Another"), tlMgr, SLOT(dockAnother()));
|
|
|
|
mMainMenu->insertItem(i18n("Undock All"), tlMgr, SLOT(undockAll()));
|
|
|
|
mMainMenu->insertSeparator();
|
|
|
|
|
|
|
|
mShowId = mMainMenu->insertItem(TQString("Show/Hide [untitled]"),
|
|
|
|
this, SLOT(toggleShow()));
|
|
|
|
mMainMenu->insertItem(TQString(i18n("Undock")), this, SLOT(undock()));
|
|
|
|
mMainMenu->insertItem(TQString(i18n("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(TQSettings& settings)
|
|
|
|
{
|
|
|
|
mAutoLaunch->setOn(settings.readBoolEntry("/LaunchOnStartup"));
|
|
|
|
setDockWhenObscured(settings.readBoolEntry("/DockWhenObscured"));
|
|
|
|
TRACE("AutoLaunch=%i DWM=%i DWO=%i", isLaunchOnStartup(),
|
|
|
|
isDockWhenMinimized(), isDockWhenObscured());
|
|
|
|
return TQTrayLabel::restoreState(settings);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CustomTrayLabel::saveState(TQSettings& settings)
|
|
|
|
{
|
|
|
|
if (!mSessionManagement->isOn()) return false;
|
|
|
|
|
|
|
|
TQTrayLabel::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)
|
|
|
|
{
|
|
|
|
TQTrayLabel::setDockWhenMinimized(dwm);
|
|
|
|
mDockWhenMinimized->setOn(isDockWhenMinimized());
|
|
|
|
}
|
|
|
|
|
|
|
|
void CustomTrayLabel::setSkipTaskbar(bool skip)
|
|
|
|
{
|
|
|
|
TQTrayLabel::setSkipTaskbar(skip);
|
|
|
|
mSkipTaskbar->setOn(isSkippingTaskbar());
|
|
|
|
}
|
|
|
|
|
|
|
|
void CustomTrayLabel::setAppName(const TQString& name)
|
|
|
|
{
|
|
|
|
TQTrayLabel::setAppName(name.lower());
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function is called when TQTrayLabel 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)
|
|
|
|
{
|
|
|
|
TQString icon;
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
// Nag the user to give us a valid icon or press cancel
|
|
|
|
icon = TQFileDialog::getOpenFileName();
|
|
|
|
if (icon.isNull()) return; // user cancelled
|
|
|
|
if (!TQPixmap(icon).isNull()) break;
|
|
|
|
TRACE("Attempting to set icon to %s", icon.latin1());
|
|
|
|
TQMessageBox::critical(this, i18n("KDocker"),
|
|
|
|
i18n("%1 is not a valid icon").arg(icon));
|
|
|
|
}
|
|
|
|
|
|
|
|
setTrayIcon(icon);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get balloon timeout from the user
|
|
|
|
void CustomTrayLabel::slotSetBalloonTimeout(void)
|
|
|
|
{
|
|
|
|
bool ok;
|
|
|
|
int timeout = TQInputDialog::getInteger(i18n("KDocker"),
|
|
|
|
i18n("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;
|
|
|
|
TQString 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 (TQMessageBox::critical(NULL, i18n("KDocker"),
|
|
|
|
i18n("\"%1\" is not a valid executable "
|
|
|
|
"or was not found in your $PATH").arg(app),
|
|
|
|
i18n("Select program"), i18n("Cancel")) == 1)
|
|
|
|
{
|
|
|
|
mAutoLaunch->setOn(false);
|
|
|
|
return; // cancelled
|
|
|
|
}
|
|
|
|
|
|
|
|
app = TQFileDialog::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)
|
|
|
|
{
|
|
|
|
TQString title = appClass(); // + "(" + appTitle() + ")";
|
|
|
|
mMainMenu->changeItem(mShowId, TQIconSet(*pixmap()),
|
|
|
|
TQString((isWithdrawn() ? i18n("Show %1") : i18n("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);
|
|
|
|
TQTimer::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(TQMouseEvent * ev)
|
|
|
|
{
|
|
|
|
if (ev->button() == TQt::RightButton)
|
|
|
|
mMainMenu->popup(ev->globalPos());
|
|
|
|
else
|
|
|
|
toggleShow();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CustomTrayLabel::destroyEvent(void)
|
|
|
|
{
|
|
|
|
mUndockWhenDead = true;
|
|
|
|
TQTrayLabel::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(TQDropEvent *)
|
|
|
|
{
|
|
|
|
TQMessageBox::information(NULL, "KDocker",
|
|
|
|
i18n("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"));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include "customtraylabel.moc"
|