From 88fbf7e81a6ab317262bd97875a0296f59287586 Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Thu, 26 Mar 2020 15:10:12 +0900 Subject: [PATCH] 1) Additional work on tq app -> tde app translation. 2) Make sure to exit app after restore if no app window can be grabbed 3) Save state only for known applications (app with empty name will not be saved and restored) Signed-off-by: Michele Calgaro --- src/customtraylabel.cpp | 24 +++++++++---- src/customtraylabel.h | 4 +-- src/main.cpp | 20 +++++------ src/qtraylabel.cpp | 41 +++++++++++++++++----- src/qtraylabel.h | 6 ++-- src/tdedocker.cpp | 25 ++++++++----- src/tdedocker.h | 6 +++- src/trace.cpp | 2 +- src/traylabelmgr.cpp | 78 ++++++++++++++++++++++++++++------------- src/traylabelmgr.h | 2 -- 10 files changed, 141 insertions(+), 67 deletions(-) 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; };