summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Moreau <oreaus@gmail.com>2009-10-25 17:35:50 -0600
committerScott Moreau <oreaus@gmail.com>2009-10-25 17:35:50 -0600
commitd259053a6003c81ff762139b1909104c59e47193 (patch)
tree87e77abd58f3cf7362d698187c5f49ffbfe3dde4
parentcfb32dc05e8cc7351de2d3d3a5e18382938dd713 (diff)
downloadstartup-d259053a6003c81ff762139b1909104c59e47193.tar.gz
startup-d259053a6003c81ff762139b1909104c59e47193.tar.bz2
Real initial commit.
-rw-r--r--CMakeLists.txt5
-rw-r--r--src/startup.cpp263
-rw-r--r--src/startup.h71
-rw-r--r--startup.xml.in45
4 files changed, 384 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..b5577fc
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,5 @@
+find_package (Compiz REQUIRED)
+
+include (CompizPlugin)
+
+compiz_plugin (startup PLUGINDEPS composite)
diff --git a/src/startup.cpp b/src/startup.cpp
new file mode 100644
index 0000000..f760645
--- /dev/null
+++ b/src/startup.cpp
@@ -0,0 +1,263 @@
+#include "startup.h"
+
+
+COMPIZ_PLUGIN_20090315 (startup, StartupPluginVTable);
+
+// mkdir_p: Creates a directory making parent directories as needed.
+// (same as mkdir -p)
+
+void
+mkdir_p(CompString &pathname) {
+ if (mkdir(pathname.c_str(), 0777) < 0) {
+ // If we couldn't make the whole directory because of ENOENT (a
+ // parent directory doesn't exist), then try recursively to make
+ // the immediate parent directory.
+ if (errno == ENOENT) {
+
+ size_t slash = pathname.rfind('/');
+ if (slash != CompString::npos) {
+ CompString prefix = pathname.substr(0, slash);
+ mkdir_p(prefix);
+ mkdir(pathname.c_str(), 0777);
+ }
+ }
+ }
+}
+
+void
+StartupScreen::RunCommands()
+{
+ updateOptions();
+
+ for (int i = 0; i < numCommands; i++)
+ {
+ // We're running the commands. FIXME: There may be a neater way to set this bool
+ if ( i == 0)
+ ranCommands = true;
+ // If first time in this session, run all commands except with option 2
+ if ( firstSession && commands[i].interval != 2 )
+ {
+ screen->runCommand ( commands[i].command );
+ continue;
+ }
+ // If we've already run compiz at least once in this session, run all commands with option 1 (Every)
+ if ( firstRun && commands[i].interval == 1 )
+ {
+ screen->runCommand ( commands[i].command );
+ continue;
+ }
+ // Hopefully, these will be all of the commands with option 2 :-P
+ if ( !firstSession && !alreadyRunning && commands[i].interval == 2 )
+ screen->runCommand ( commands[i].command );
+
+ }
+}
+
+void
+StartupScreen::UpdateStatus()
+{
+
+ char* dbus_env_var = getenv("DBUS_SESSION_BUS_ADDRESS");
+ char* dsp = getenv("DISPLAY");
+ char* home = getenv("HOME");
+
+ if( dbus_env_var == NULL )
+ {
+ compLogMessage ("startup", CompLogLevelWarn, "Environment variable DBUS_SESSION_BUS_ADDRESS is not set");
+ return;
+ }
+ if( dsp == NULL )
+ {
+ compLogMessage ("startup", CompLogLevelWarn, "Environment variable DISPLAY is not set");
+ return;
+ }
+ if( home == NULL )
+ {
+ compLogMessage ("startup", CompLogLevelWarn, "Environment variable HOME is not set");
+ return;
+ }
+ // We're only interested in the dbus ID
+ CompString s(dbus_env_var);
+ size_t idx = s.find("guid=");
+ CompString dbus_id = s.substr(idx+5) + "\n";
+
+
+ std::fstream lock;
+ int nCompLock = 0;
+ int nCompPid = getpid();
+ CompString lockdir = "/.compiz/locks/startup/";
+ lockdir.insert (0,home);
+ CompString compLockFile = lockdir + "complock" + dsp;
+ CompString xLockFile = lockdir + "xlock" + dsp;
+
+ lock.open(xLockFile.c_str (), std::ios::in);
+ if (!lock)
+ {
+ compLogMessage ("startup", CompLogLevelWarn, "Could not open %s for reading: %s", xLockFile.c_str (), strerror(errno));
+ compLogMessage ("startup", CompLogLevelWarn, "Perhaps this is the first time using this plugin?");
+ }
+ else
+ {
+ std::stringstream xstrm;
+ xstrm << lock.rdbuf ();
+ lock.close ();
+ lock.open(compLockFile.c_str (), std::ios::in);
+ if (!lock)
+ {
+ compLogMessage ("startup", CompLogLevelWarn, "Could not open %s for reading: %s", compLockFile.c_str (), strerror(errno));
+ compLogMessage ("startup", CompLogLevelWarn, "Perhaps this is the first time using this plugin?");
+ }
+ else
+ {
+ lock >> nCompLock;
+ lock.close ();
+ if (xstrm.str () == dbus_id)
+ {
+ // Compiz has already been run in this X session
+ if (nCompLock == nCompPid)
+ {
+ // Control is reaching this path but compiz is already running
+ // Plugins are most likely being reloaded
+ if (!firstRun)
+ alreadyRunning = true;
+ return;
+ }
+ else
+ {
+ lock.open(compLockFile.c_str (), std::ios::out);
+ if (!lock)
+ {
+ compLogMessage ("startup", CompLogLevelWarn, "Couldn't open %s for writing: %s", compLockFile.c_str (), strerror(errno));
+ }
+ else
+ {
+ // Compiz has just been started. Save it's PID
+ if (!firstSession)
+ firstRun = true;
+ lock << nCompPid;
+ lock.close ();
+ return;
+ }
+ }
+ }
+ }
+ }
+ mkdir_p(lockdir);
+ lock.open (xLockFile.c_str (), std::ios::out);
+ if (!lock)
+ {
+ compLogMessage ("startup", CompLogLevelWarn, "Could not open %s for writing: %s", xLockFile.c_str (), strerror(errno));
+ }
+ else
+ {
+ // First time compiz has been run in this X session
+ firstSession = true;
+ lock << dbus_id;
+ lock.close();
+ }
+ lock.open(compLockFile.c_str (), std::ios::out);
+ if (!lock)
+ {
+ compLogMessage ("startup", CompLogLevelWarn, "Could not open %s for writing: %s", compLockFile.c_str (), strerror(errno));
+ }
+ else
+ {
+ // Save the PID
+ if(firstSession)
+ lock << nCompPid;
+ lock.close ();
+ return;
+ }
+
+ return;
+}
+
+bool
+StartupWindow::damageRect (bool initial,
+ const CompRect &rect)
+{
+ STARTUP_SCREEN (screen);
+
+ if (!ss->ranCommands)
+ ss->RunCommands();
+ else
+ cWindow->damageRectSetEnabled (this, false);
+
+ return cWindow->damageRect (initial, rect);
+}
+
+void
+StartupScreen::updateOptions ()
+{
+
+#define GET_OPTION(opt) CompOption::Value::Vector c##opt = optionGet##opt ();
+ GET_OPTION (PostStartupCommand);
+ GET_OPTION (PostStartupInterval);
+#undef GET_OPTION
+
+ if (cPostStartupCommand.size () != cPostStartupInterval.size ())
+ {
+ compLogMessage ("startup", CompLogLevelWarn, "Malformed option");
+ return;
+ }
+
+ commands.clear ();
+
+ numCommands = 0;
+
+ for (int i = 0; i < cPostStartupCommand.size (); i++, numCommands++)
+ {
+ commands.push_back (StartupCommand ());
+ commands[i].command = cPostStartupCommand[i].s ();
+ commands[i].interval = cPostStartupInterval[i].i ();
+ }
+
+ UpdateStatus ();
+ return;
+}
+
+void
+StartupScreen::optionChanged (CompOption *opt, Options num)
+{
+ updateOptions ();
+}
+
+StartupScreen::StartupScreen (CompScreen *screen) :
+ PluginClassHandler <StartupScreen, CompScreen> (screen),
+ cScreen (CompositeScreen::get (screen)),
+ commands ()
+{
+ optionSetPostStartupCommandNotify (boost::bind (&StartupScreen::
+ optionChanged, this, _1, _2));
+
+ ranCommands = firstRun = firstSession = alreadyRunning = false;
+ updateOptions ();
+}
+
+StartupWindow::StartupWindow (CompWindow *window) :
+ PluginClassHandler <StartupWindow, CompWindow> (window),
+ cWindow (CompositeWindow::get (window))
+{
+ CompositeWindowInterface::setHandler (cWindow);
+}
+
+StartupScreen::~StartupScreen ()
+{
+}
+
+StartupWindow::~StartupWindow ()
+{
+}
+
+bool
+StartupPluginVTable::init ()
+{
+ if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) ||
+ !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI))
+ {
+ compLogMessage ("startup", CompLogLevelError, "Unable to verify core and compositing are present\n");
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/startup.h b/src/startup.h
new file mode 100644
index 0000000..33ce887
--- /dev/null
+++ b/src/startup.h
@@ -0,0 +1,71 @@
+#include <fstream>
+#include <errno.h>
+#include <sstream>
+#include <sys/stat.h>
+#include <core/core.h>
+#include <composite/composite.h>
+
+#include "startup_options.h"
+
+class StartupCommand
+{
+ public:
+
+ CompString command;
+ int interval;
+};
+
+typedef std::vector<StartupCommand> StartupCommands;
+
+class StartupScreen :
+ public PluginClassHandler <StartupScreen, CompScreen>,
+ public StartupOptions
+{
+ public:
+
+ StartupScreen (CompScreen *);
+ ~StartupScreen ();
+
+ CompositeScreen *cScreen;
+
+ bool ranCommands, firstRun, firstSession, alreadyRunning;
+
+ StartupCommands commands;
+
+ int numCommands;
+
+ void updateOptions ();
+
+ void UpdateStatus ();
+
+ void RunCommands ();
+
+ void optionChanged (CompOption*, Options);
+};
+
+class StartupWindow :
+ public PluginClassHandler <StartupWindow, CompWindow>,
+ public CompositeWindowInterface
+{
+ public:
+
+ StartupWindow (CompWindow *);
+ ~StartupWindow ();
+
+ CompWindow *window;
+ CompositeWindow *cWindow;
+
+ bool
+ damageRect (bool, const CompRect&);
+};
+
+#define STARTUP_SCREEN(s) \
+ StartupScreen *ss = StartupScreen::get (s);
+
+class StartupPluginVTable :
+ public CompPlugin::VTableForScreenAndWindow <StartupScreen, StartupWindow>
+{
+ public:
+
+ bool init ();
+};
diff --git a/startup.xml.in b/startup.xml.in
new file mode 100644
index 0000000..e457f93
--- /dev/null
+++ b/startup.xml.in
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<compiz>
+ <plugin name="startup" useBcop="true">
+ <_short>Startup</_short>
+ <_long>Start commands after compiz is loaded properly</_long>
+ <category>Utility</category>
+ <deps>
+ <requirement>
+ <plugin>composite</plugin>
+ </requirement>
+ <relation type="after">
+ <plugin>composite</plugin>
+ </relation>
+ </deps>
+ <options>
+ <subgroup>
+ <option name="post_startup_command" type="list">
+ <_short>Command</_short>
+ <_long>Command to run</_long>
+ <type>string</type>
+ </option>
+ <option name="post_startup_interval" type="list">
+ <_short>Interval</_short>
+ <_long>Interval the command will be run per X session. First Time: First time compiz is started. Every Time: Every time compiz starts. After Frist: Every time execpt the first time.</_long>
+ <type>int</type>
+ <min>0</min>
+ <max>2</max>
+ <desc>
+ <value>0</value>
+ <_name>First Time</_name>
+ </desc>
+ <desc>
+ <value>1</value>
+ <_name>Every Time</_name>
+ </desc>
+ <desc>
+ <value>2</value>
+ <_name>After First</_name>
+ </desc>
+ </option>
+ </subgroup>
+ </options>
+ </plugin>
+</compiz>
+