summaryrefslogtreecommitdiffstats
path: root/src/tdedocker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tdedocker.cpp')
-rw-r--r--src/tdedocker.cpp233
1 files changed, 233 insertions, 0 deletions
diff --git a/src/tdedocker.cpp b/src/tdedocker.cpp
new file mode 100644
index 0000000..2b404c7
--- /dev/null
+++ b/src/tdedocker.cpp
@@ -0,0 +1,233 @@
+/*
+ * 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: tdedocker.cpp,v 1.24 2005/02/04 10:25:46 cs19713 Exp $
+
+#include <tqsessionmanager.h>
+#include <tqdir.h>
+#include <tqfile.h>
+#include <tqtextcodec.h>
+#include <tqtextstream.h>
+#include <tqtimer.h>
+#include <tqstring.h>
+
+#include <tdelocale.h>
+
+#include "trace.h"
+#include "traylabelmgr.h"
+#include "tdedocker.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+// #define TMPFILE_PREFIX TQString("/tmp/tdedocker.")
+#define TMPFILE_PREFIX TQDir::homeDirPath() + "/.tdedocker."
+
+TDEDocker::TDEDocker(int& argc, char** argv)
+ :TQApplication(argc, argv), mTrayLabelMgr(0)
+{
+ INIT_TRACE();
+
+ // Attempt doing anything only if the CLI arguments were good
+ opterr = 0; // suppress the warning
+ int option;
+ while ((option = getopt(argc, argv, TrayLabelMgr::options().latin1())) != EOF)
+ {
+ if (option == '?')
+ {
+ if (optopt == 'v') printVersion(); else printUsage(optopt);
+ ::exit(0);
+ }
+ }
+
+ /*
+ * Detect and transfer control to previous instance (if one exists)
+ * _KDOCKER_RUNNING is a X Selection. We start out by trying to locate the
+ * selection owner. If someone else owns it, transfer control to that
+ * instance of TDEDocker
+ */
+ Display *display = TQPaintDevice::x11AppDisplay();
+ Atom tdedocker = XInternAtom(display, "_KDOCKER_RUNNING", False);
+ Window prev_instance = XGetSelectionOwner(display, tdedocker);
+
+ if (prev_instance == None)
+ {
+ 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);
+ mTrayLabelMgr = TrayLabelMgr::instance();
+ }
+ else
+ notifyPreviousInstance(prev_instance); // does not return
+}
+
+void TDEDocker::printVersion(void)
+{
+ tqDebug("TQt: %s", tqVersion());
+ tqDebug("TDEDocker: %s", KDOCKER_APP_VERSION);
+}
+
+// Prints the CLI arguments. Does not return
+void TDEDocker::printUsage(char optopt)
+{
+ if (optopt != 'h') tqDebug("%s", i18n("tdedocker: invalid option -- %1").arg(optopt).local8Bit().data());
+
+ tqDebug("%s", i18n("Usage: TDEDocker [options] command\n").local8Bit().data());
+ tqDebug("%s", i18n("Docks any application into the system tray\n").local8Bit().data());
+ tqDebug("%s", i18n("command \tCommand to execute\n").local8Bit().data());
+ tqDebug("%s", i18n("Options").local8Bit().data());
+ tqDebug("%s", i18n("-a \tShow author information").local8Bit().data());
+ tqDebug("%s", i18n("-b \tDont warn about non-normal windows (blind mode)").local8Bit().data());
+ tqDebug("%s", i18n("-d \tDisable session management").local8Bit().data());
+ tqDebug("%s", i18n("-e \tEnable session management").local8Bit().data());
+ tqDebug("%s", i18n("-f \tDock window that has the focus(active window)").local8Bit().data());
+ tqDebug("%s", i18n("-h \tDisplay this help").local8Bit().data());
+ tqDebug("%s", i18n("-i icon\tCustom dock Icon").local8Bit().data());
+ tqDebug("%s", i18n("-l \tLaunch on startup").local8Bit().data());
+ tqDebug("%s", i18n("-m \tKeep application window mapped (dont hide on dock)").local8Bit().data());
+ tqDebug("%s", i18n("-o \tDock when obscured").local8Bit().data());
+ tqDebug("%s", i18n("-p secs\tSet ballooning timeout (popup time)").local8Bit().data());
+ tqDebug("%s", i18n("-q \tDisable ballooning title changes (quiet)").local8Bit().data());
+ tqDebug("%s", i18n("-t \tRemove this application from the task bar").local8Bit().data());
+ tqDebug("%s", i18n("-v \tDisplay version").local8Bit().data());
+ tqDebug("%s", i18n("-w wid \tWindow id of the application to dock\n").local8Bit().data());
+
+ tqDebug("%s", i18n("NOTE: Use -d for all startup scripts.\n").local8Bit().data());
+
+ tqDebug("%s", i18n("Bugs and wishes to gramakri@uiuc.edu").local8Bit().data());
+ tqDebug("%s", i18n("Project information at http://tdedocker.sourceforge.net").local8Bit().data());
+}
+
+void TDEDocker::notifyPreviousInstance(Window prevInstance)
+{
+ Display *display = TQPaintDevice::x11AppDisplay();
+
+ TRACE("Notifying previous instance [%x]", (unsigned) prevInstance);
+
+ // Dump all arguments in temporary file
+ TQFile f(TMPFILE_PREFIX + TQString().setNum(getpid()));
+ if (!f.open(IO_WriteOnly)) return;
+ TQTextStream s(&f);
+
+ /*
+ * Its normal to use TDEDocker in startup scripts. We could be getting restored
+ * from a session at the same time. So, if we were getting restored and
+ * another instance already exists, send across the session id. Remember, qt
+ * strips out all the arguments that it understands. So need to do it by hand.
+ */
+ if (isSessionRestored())
+ s << argv()[0] << " " << "-session" << " " << sessionId();
+ else
+ for (int i = 0; i < argc(); i++) s << argv()[i] << " ";
+
+ f.close();
+
+ /*
+ * Now tell our previous instance that we came to pass. Actually, it can
+ * figure it out itself using PropertyNotify events but this is a lot nicer
+ */
+ XClientMessageEvent dock_event;
+ memset(&dock_event, 0, sizeof(XClientMessageEvent));
+ dock_event.display = display;
+ dock_event.window = prevInstance;
+ dock_event.send_event = True;
+ dock_event.type = ClientMessage;
+ dock_event.message_type = 0x220679; // it all started this day
+ dock_event.format = 8;
+ dock_event.data.l[0] = 0xBABE; // love letter ;)
+ dock_event.data.l[1] = getpid();
+ XSendEvent(display, prevInstance, False, 0, (XEvent *) &dock_event);
+ XSync(display, False);
+
+ ::exit(0);
+}
+
+/*
+ * The X11 Event filter called by TQt. Look out for ClientMessage events from
+ * our new instance
+ */
+bool TDEDocker::x11EventFilter(XEvent * event)
+{
+ if (event->type == ClientMessage)
+ {
+ // look for requests from a new instance of tdedocker
+ XClientMessageEvent *client = (XClientMessageEvent *) event;
+ if (!(client->message_type == 0x220679 && client->data.l[0] == 0xBABE))
+ return FALSE;
+
+ TRACE("ClientMessage from PID=%ld. SelOwn=0x%x",
+ client->data.l[1], (unsigned) mSelectionOwner);
+ char tmp[50];
+ struct stat buf;
+ sprintf(tmp, TQString(TMPFILE_PREFIX "%ld").local8Bit(), client->data.l[1]);
+ if (stat(tmp, &buf) || (getuid()!=buf.st_uid))
+ {
+ /*
+ * We make sure that the owner of this process and the owner of the file
+ * are the same. This will prevent someone from executing arbitrary
+ * programs by sending client message. Of course, you can send a message
+ * only if you are authenticated to the X session and have permission to
+ * create files in TMPFILE_PREFIX. So this code is there just for the
+ * heck of it.
+ */
+ TRACE("User %i is trying something fishy...", buf.st_uid);
+ unlink(tmp);
+ return TRUE;
+ }
+ TQFile f(tmp);
+ if (!f.open(IO_ReadOnly)) return TRUE;
+ TQTextStream s(&f);
+ TQStringList argv;
+ while (!s.atEnd()) { TQString x; s >> x; argv += x; }
+ f.close();
+ unlink(tmp); // delete the tmp file
+ mTrayLabelMgr->processCommand(argv);
+ return TRUE;
+ }
+ else return mTrayLabelMgr->x11EventFilter(event);
+}
+
+/*
+ * XSMP Support
+ */
+void TDEDocker::saveState(TQSessionManager &sm)
+{
+ TQString sf = mTrayLabelMgr->saveSession();
+
+ TQStringList discard_command;
+ discard_command << "rm" << sf;
+ sm.setDiscardCommand(discard_command);
+
+ sm.setRestartHint(TQSessionManager::RestartIfRunning);
+ TQStringList restart_command;
+ restart_command << this->argv()[0]
+ << "-session" << sm.sessionId();
+ sm.setRestartCommand(restart_command);
+
+ TRACE("SessionFile=%s AppName=%s", sf.latin1(), this->argv()[0]);
+ DUMP_TRACE(TQDir::homeDirPath() + "/tdedocker.trace");
+ // sm.setRestartCommand(applicationFilePath());
+}
+
+
+#include "tdedocker.moc"