diff --git a/src/customtraylabel.cpp b/src/customtraylabel.cpp index 87e50ac..5ad3459 100644 --- a/src/customtraylabel.cpp +++ b/src/customtraylabel.cpp @@ -44,11 +44,10 @@ CustomTrayLabel::CustomTrayLabel(Window w, TQWidget* p, const TQString& t) : TQTrayLabel(w, p, t), mUndockWhenDead(false) { - installMenu(); + installMenu(); } -CustomTrayLabel::CustomTrayLabel(const TQStringList& argv, pid_t pid, - TQWidget* parent) +CustomTrayLabel::CustomTrayLabel(const TQStringList& argv, pid_t pid, TQWidget* parent) : TQTrayLabel(argv, pid, parent), mUndockWhenDead(false) { installMenu(); @@ -124,6 +123,11 @@ void CustomTrayLabel::installMenu() setAcceptDrops(true); // and you thought this function only installs the menu } +void CustomTrayLabel::enableSessionManagement(bool sm) +{ + mSessionManagement->setOn(!appName().isEmpty() && sm); +} + // Session Management bool CustomTrayLabel::restoreState(TDEConfig *config) { @@ -132,13 +136,20 @@ bool CustomTrayLabel::restoreState(TDEConfig *config) return TQTrayLabel::restoreState(config); } -void CustomTrayLabel::saveState(TDEConfig *config) +bool CustomTrayLabel::saveState(TDEConfig *config) { - if (!mSessionManagement->isOn()) return; + if (!mSessionManagement->isOn()) + { + return false; + } - TQTrayLabel::saveState(config); + if (!TQTrayLabel::saveState(config)) + { + return false; + } config->writeEntry("DockWhenObscured", isDockWhenObscured()); TRACE("WM=%i DWO=%i", isDockWhenMinimized(), isDockWhenObscured()); + return true; } static bool which(const char *app) @@ -177,6 +188,7 @@ void CustomTrayLabel::setSkipTaskbar(bool skip) void CustomTrayLabel::setAppName(const TQString& name) { + //FIXME HACK relies on window and application name being the same. TQTrayLabel::setAppName(name.lower()); } diff --git a/src/customtraylabel.h b/src/customtraylabel.h index c022ec4..244ebc2 100644 --- a/src/customtraylabel.h +++ b/src/customtraylabel.h @@ -43,7 +43,7 @@ public: CustomTrayLabel(const TQStringList& argv, pid_t pid, TQWidget* parent = 0); // Session management - void saveState(TDEConfig *config); + bool saveState(TDEConfig *config); bool restoreState(TDEConfig *config); bool isDockWhenObscured(void) const { return mDockWhenObscured->isOn(); } @@ -57,7 +57,7 @@ public slots: void setSkipTaskbar(bool skip); void setDockWhenObscured(bool dock) { mDockWhenObscured->setOn(dock); } - void enableSessionManagement(bool sm) { mSessionManagement->setOn(sm); } + void enableSessionManagement(bool sm); protected: void dropEvent(TQDropEvent *ev); diff --git a/src/main.cpp b/src/main.cpp index b61d52e..dc9bf5e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,13 +40,13 @@ static void sighandler(int sig) { if (sig == SIGUSR1) { - DUMP_TRACE((TQDir::homeDirPath() + "/tdedocker.trace").ascii()); + DUMP_TRACE((TQDir::homeDirPath() + "/tdedocker.trace").local8Bit()); return; } tqDebug("%s", i18n("Caught signal %1. Cleaning up.").arg(sig).local8Bit().data()); - ((TDEDocker *)tqApp)->trayLabelMgr()->undockAll(); - ::exit(0); + ((TDEDocker*)TDEApplication::kApplication())->trayLabelMgr()->undockAll(); + TDEApplication::kApplication()->quit(); } static const TDECmdLineOptions options[] = @@ -69,12 +69,6 @@ static const TDECmdLineOptions options[] = //extern "C" int KDE_EXPORT kdemain(int argc, char* argv[]) int main(int argc, char *argv[]) { - // setup signal handlers that undock and quit - signal(SIGHUP, sighandler); - signal(SIGTERM, sighandler); - signal(SIGINT, sighandler); - signal(SIGUSR1, sighandler); - TDEAboutData about("tdedocker", I18N_NOOP("tdedocker"), "1.3", I18N_NOOP("Docks any application into the system tray\nNOTE: Use -d for all startup scripts."), TDEAboutData::License_GPL); about.addAuthor("John Schember", I18N_NOOP("Original KDocker maintainer"), "john@nachtimwald.com"); @@ -84,8 +78,14 @@ int main(int argc, char *argv[]) TDECmdLineArgs::init(argc, argv, &about); TDECmdLineArgs::addCmdLineOptions(options); - TDEDocker::addCmdLineOptions(); + TDEDocker::addCmdLineOptions(); TDEDocker app; + // setup signal handlers that undock and quit (must be done after the TDEApplication constructor has run) + signal(SIGHUP, sighandler); + signal(SIGTERM, sighandler); + signal(SIGINT, sighandler); + signal(SIGUSR1, sighandler); + return app.exec(); } diff --git a/src/qtraylabel.cpp b/src/qtraylabel.cpp index a74ba48..13c020d 100644 --- a/src/qtraylabel.cpp +++ b/src/qtraylabel.cpp @@ -83,7 +83,7 @@ const char *TQTrayLabel::me(void) const { static char temp[100]; snprintf(temp, sizeof(temp), "(%s,PID=%i,WID=0x%x)", - mProgName[0].local8Bit().data(), mPid, (unsigned) mDockedWindow); + appName().local8Bit().data(), mPid, (unsigned) mDockedWindow); return temp; } @@ -98,8 +98,10 @@ TQTrayLabel::TQTrayLabel(const TQStringList& pname, pid_t pid, TQWidget* parent) :TQLabel(parent, "TrayLabel", WStyle_Customize | WStyle_NoBorder | WStyle_Tool), mDockedWindow(None), mProgName(pname), mPid(pid) { - if (pname[0].at(0) != '/' && pname[0].find('/', 1) > 0) - mProgName[0] = TQFileInfo(pname[0]).absFilePath(); // convert to absolute + if (pname[0].at(0) != '/' && pname[0].find('/', 1) > 0) + { + mProgName.push_front(TQFileInfo(pname[0]).absFilePath()); // convert to absolute + } initialize(); } @@ -113,6 +115,18 @@ TQTrayLabel::~TQTrayLabel() map(); } +void TQTrayLabel::setAppName(const TQString &prog) +{ + if (mProgName.count() == 0) + { + mProgName.push_front(prog); + } + else + { + mProgName[0] = prog; + } +} + /* * Scans the windows in the desktop and checks if a window exists that we might * be interested in @@ -122,7 +136,7 @@ void TQTrayLabel::scanClients() Window r, parent, *children; unsigned nchildren = 0; Display *display = TQPaintDevice::x11AppDisplay(); - TQString ename = TQFileInfo(mProgName[0]).fileName(); // strip out the path + TQString ename = TQFileInfo(appName()).fileName(); // strip out the path XQueryTree(display, tqt_xrootwin(), &r, &parent, &children, &nchildren); TRACE("%s nchildren=%i", me(), nchildren); @@ -671,7 +685,10 @@ bool TQTrayLabel::x11EventFilter(XEvent *ev) if (event->window == mSysTray) { - if (event->type != DestroyNotify) return FALSE; // not interested in others + if (event->type != DestroyNotify) + { + return false; // not interested in others + } emit sysTrayDestroyed(); mSysTray = None; TRACE("%s SystemTray disappeared. Starting timer", me()); @@ -713,8 +730,10 @@ bool TQTrayLabel::x11EventFilter(XEvent *ev) Display *display = TQPaintDevice::x11AppDisplay(); Window w = XmuClientWindow(display, ((XMapEvent *) event)->window); if (!isNormalWindow(display, w)) return FALSE; - if (!analyzeWindow(display, w, mPid, - TQFileInfo(mProgName[0]).fileName().local8Bit())) return FALSE; + if (!analyzeWindow(display, w, mPid, TQFileInfo(appName()).fileName().local8Bit())) + { + return false; + } // All right. Lets dock this baby setDockedWindow(w); return true; @@ -772,8 +791,13 @@ void TQTrayLabel::propertyChangeEvent(Atom property) } // Session Management -void TQTrayLabel::saveState(TDEConfig *config) +bool TQTrayLabel::saveState(TDEConfig *config) { + if (appName().isEmpty()) + { + return false; + } + TRACE("%s saving state", me()); config->writeEntry("Application", mProgName.join(" ")); config->writeEntry("BalloonTimeout", mBalloonTimeout); @@ -781,6 +805,7 @@ void TQTrayLabel::saveState(TDEConfig *config) config->writeEntry("DockWhenMinimized", mDockWhenMinimized); config->writeEntry("SkipTaskbar", mSkippingTaskbar); config->writeEntry("Withdraw", mWithdrawn); + return true; } bool TQTrayLabel::restoreState(TDEConfig *config) diff --git a/src/qtraylabel.h b/src/qtraylabel.h index c0a9e72..27d0ce4 100644 --- a/src/qtraylabel.h +++ b/src/qtraylabel.h @@ -60,8 +60,8 @@ public: bool isWithdrawn(void) const { return mWithdrawn; } bool isDockWhenMinimized(void) const { return mDockWhenMinimized; } - TQString appName(void) const { return mProgName[0]; } - virtual void setAppName(const TQString& prog) { mProgName[0] = prog; } + TQString appName(void) const { return (mProgName.count() > 0) ? mProgName[0] : TQString::null; } + virtual void setAppName(const TQString& prog); TQString appClass(void) const { return mClass; } TQString appTitle(void) const { return mTitle; } TQPixmap appIcon(void) const { return mAppIcon; } @@ -70,7 +70,7 @@ public: bool x11EventFilter(XEvent * event); // Session Management - virtual void saveState(TDEConfig *config); + virtual bool saveState(TDEConfig *config); virtual bool restoreState(TDEConfig *config); public slots: diff --git a/src/tdedocker.cpp b/src/tdedocker.cpp index 2b24cf5..8021e67 100644 --- a/src/tdedocker.cpp +++ b/src/tdedocker.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -43,7 +42,21 @@ #define TMPFILE_PREFIX TQString("/tmp/tdedocker.") TDEDocker::TDEDocker() - : TDEApplication(), mTrayLabelMgr(NULL), firstSaveState(true) + : TDEApplication(), mTrayLabelMgr(NULL) +{ + // Set ourselves up to be called from the application loop + connect(&mInitTimer, SIGNAL(timeout()), this, SLOT(doInit())); + mInitTimer.start(0, true); + + // Required so that the saved config is correctly loaded + // (see TrayLabelMgr::doRestoreSession() for usage) + if (TDEApplication::kApplication()->isRestored()) + { + TDEApplication::kApplication()->sessionConfig(); + } +} + +void TDEDocker::doInit() { INIT_TRACE(); /* @@ -58,12 +71,6 @@ TDEDocker::TDEDocker() if (prev_instance == None) { - if (TDEApplication::kApplication()->isRestored()) - { - // Required so that the saved config is correctly loaded - // (see TrayLabelMgr::doRestoreSession() for usage) - TDEApplication::kApplication()->sessionConfig(); - } mSelectionOwner = XCreateSimpleWindow(display, tqt_xrootwin(), 1, 1, 1, 1, 1, 1, 1); XSetSelectionOwner(display, tdedocker, mSelectionOwner, CurrentTime); TRACE("Selection owner set to 0x%x", (unsigned) mSelectionOwner); @@ -118,7 +125,7 @@ void TDEDocker::notifyPreviousInstance(Window prevInstance) XSendEvent(display, prevInstance, False, 0, (XEvent *) &dock_event); XSync(display, False); - ::exit(0); + quit(); } /* diff --git a/src/tdedocker.h b/src/tdedocker.h index c445a36..a733f75 100644 --- a/src/tdedocker.h +++ b/src/tdedocker.h @@ -22,6 +22,7 @@ #ifndef _TDEDOCKER_H #define _TDEDOCKER_H +#include #include #include @@ -41,12 +42,15 @@ public: protected: bool x11EventFilter(XEvent * event); +private slots: + void doInit(); + private: void notifyPreviousInstance(Window prevInstance); Window mSelectionOwner; TrayLabelMgr *mTrayLabelMgr; - bool firstSaveState; + TQTimer mInitTimer; }; #endif // _TDEDOCKER_H diff --git a/src/trace.cpp b/src/trace.cpp index 9f2d06d..5756a56 100644 --- a/src/trace.cpp +++ b/src/trace.cpp @@ -1,5 +1,4 @@ #ifdef ENABLE_TRACING -#include #include #include #include @@ -38,6 +37,7 @@ void DUMP_TRACE(const char *f) { TQTextStream stream(&file); stream << tracer->text(); + file.close(); } } diff --git a/src/traylabelmgr.cpp b/src/traylabelmgr.cpp index ae32167..29aa0f4 100644 --- a/src/traylabelmgr.cpp +++ b/src/traylabelmgr.cpp @@ -37,7 +37,6 @@ #include TrayLabelMgr* TrayLabelMgr::gTrayLabelMgr = NULL; -const char *TrayLabelMgr::mOptionString = "+bdefi:lmop:qtw:"; TrayLabelMgr* TrayLabelMgr::instance() { @@ -85,7 +84,7 @@ void TrayLabelMgr::startup(void) state == SysTrayAbsent ? i18n("No system tray found") : i18n("System tray appears to be hidden"), i18n("TDEDocker")) == KMessageBox::Cancel) { - tqApp->quit(); + TDEApplication::kApplication()->quit(); return; } } @@ -106,8 +105,13 @@ void TrayLabelMgr::startup(void) // Process the request Q from previous instances TRACE("Request queue has %i requests", mRequestQ.count()); for(unsigned i=0; i < mRequestQ.count(); i++) + { ok |= processCommand(mRequestQ[i]); - if (!ok) tqApp->quit(); + } + if (!ok) + { + TDEApplication::kApplication()->quit(); + } } // Initialize a TQTrayLabel after its creation @@ -258,7 +262,7 @@ bool TrayLabelMgr::processCommand(int argc, char** argv) optind = 0; // initialise the getopt static - while ((option = getopt(argc, argv, mOptionString)) != EOF) + while ((option = getopt(argc, argv, "+bdefi:lmop:qtw:")) != EOF) { switch (option) { @@ -364,7 +368,7 @@ TQTrayLabel *TrayLabelMgr::selectAndDock(Window w, bool checkNormality) if (!isWindowDocked(w)) return new CustomTrayLabel(w); - TRACE("0x%x is not docked", (unsigned) w); + TRACE("0x%x is alredy docked", (unsigned) w); KMessageBox::error(NULL, i18n("This window is already docked.\n" "Click on system tray icon to toggle docking."), i18n("TDEDocker")); @@ -407,7 +411,9 @@ TQTrayLabel *TrayLabelMgr::dockApplication(char *argv[]) if (execvp(argv[0], argv) == -1) { tqDebug("%s", i18n("Failed to exec [%1]: %2").arg(argv[0]).arg(strerror(errno)).local8Bit().data()); - ::exit(0); // will become a zombie in some systems :( + // Exit the forked process only. + // Using TDEApplication::kApplication()->quit() crashes the parent application. + exit(0); return NULL; } } @@ -423,7 +429,7 @@ TQTrayLabel *TrayLabelMgr::dockApplication(char *argv[]) if (argv[i]) cmd_line << argv[i]; else break; TQTrayLabel *label = new CustomTrayLabel(cmd_line, pid); - tqApp->syncX(); + TDEApplication::kApplication()->syncX(); write(filedes[1], buf, sizeof(buf)); close(filedes[0]); close(filedes[1]); @@ -453,7 +459,10 @@ void TrayLabelMgr::trayLabelDestroyed(TQObject *t) { bool reconnect = ((TQObject *)mTrayLabels.getLast() == t); mTrayLabels.removeRef((TQTrayLabel*)t); - if (mTrayLabels.isEmpty()) tqApp->quit(); + if (mTrayLabels.isEmpty()) + { + TDEApplication::kApplication()->quit(); + } else if (reconnect) { TRACE("Reconnecting"); @@ -500,39 +509,58 @@ void TrayLabelMgr::doRestoreSession() TRACE("Restoring session"); TDEConfig *config = TDEApplication::kApplication()->sessionConfig(); - for (int i = 1; ; ++i) + if (config->hasGroup("General")) { - if (!config->hasGroup("Instance" + TQString::number(i))) + config->setGroup("General"); + int count = config->readNumEntry("InstanceCount", 0); + for (int i = 0; i < count; ++i) { - return; - } - config->setGroup("Instance" + TQString::number(i)); - TQString pname = config->readEntry("Application", TQString::null); - if (!pname.isEmpty()) - { - TRACE("Restoring Application[%s]", pname.ascii()); - manageTrayLabel(new CustomTrayLabel(TQStringList::split(" ", pname), 0)); - mTrayLabels.getFirst()->restoreState(config); + if (!config->hasGroup(TQString::number(i))) + { + break; + } + config->setGroup(TQString::number(i)); + TQString pname = config->readEntry("Application", TQString::null); + if (!pname.isEmpty()) + { + TRACE("Restoring Application[%s]", pname.ascii()); + manageTrayLabel(new CustomTrayLabel(TQStringList::split(" ", pname), 0)); + mTrayLabels.getFirst()->restoreState(config); + } } } + // Exit if no application could be restored + if (mTrayLabels.isEmpty()) + { + TDEApplication::kApplication()->quit(); + } } bool TrayLabelMgr::saveState(TQSessionManager &sm) { TRACE("Saving session"); - int i = 1; + int i = 0; TQTrayLabel *t; TDEConfig *config = TDEApplication::kApplication()->sessionConfig(); - TQPtrListIterator it(mTrayLabels); + TQPtrListIterator it(mTrayLabels); for (it.toFirst(); it.current(); ++it) { t = it.current(); - TRACE("Saving instance %i", i); - config->setGroup("Instance" + TQString::number(i)); - t->saveState(config); - ++i; + config->setGroup(TQString::number(i)); + if (t->saveState(config)) + { + TRACE("Saved instance %i", i); + ++i; + } + else + { + config->deleteGroup(TQString::number(i)); + } } + + config->setGroup("General"); + config->writeEntry("InstanceCount", i); return true; } diff --git a/src/traylabelmgr.h b/src/traylabelmgr.h index 90ff1ba..d5fdb9e 100644 --- a/src/traylabelmgr.h +++ b/src/traylabelmgr.h @@ -40,7 +40,6 @@ class TrayLabelMgr : public TQObject, public KSessionManaged public: static TrayLabelMgr* instance(); - static TQString options(void) { return TQString(mOptionString); } ~TrayLabelMgr(); @@ -79,7 +78,6 @@ private: bool mReady; int mHiddenLabelsCount; - static const char *mOptionString; static TrayLabelMgr *gTrayLabelMgr; };