Skip to content

Commit

Permalink
Implement "Start on window system startup" on Win32 + Linux.
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt Corallo committed Dec 20, 2011
1 parent 8214620 commit f18a119
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 3 deletions.
6 changes: 5 additions & 1 deletion bitcoin-qt.pro
Original file line number Diff line number Diff line change
Expand Up @@ -251,10 +251,14 @@ isEmpty(BOOST_INCLUDE_PATH) {
macx:BOOST_INCLUDE_PATH = /opt/local/include
}

windows:LIBS += -lws2_32
windows:LIBS += -lws2_32 -lshlwapi
windows:DEFINES += WIN32
windows:RC_FILE = src/qt/res/bitcoin-qt.rc

!windows:!mac {
DEFINES += LINUX
}

macx:HEADERS += src/qt/macdockiconhandler.h
macx:OBJECTIVE_SOURCES += src/qt/macdockiconhandler.mm
macx:LIBS += -framework Foundation -framework ApplicationServices -framework AppKit
Expand Down
155 changes: 155 additions & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "strlcpy.h"
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/convenience.hpp>
#include <boost/interprocess/sync/file_lock.hpp>

#if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
Expand Down Expand Up @@ -523,10 +524,164 @@ bool AppInit2(int argc, char* argv[])
if (fServer)
CreateThread(ThreadRPCServer, NULL);

#ifdef QT_GUI
if(GetStartOnSystemStartup())
SetStartOnSystemStartup(true); // Remove startup links to bitcoin-wx
#endif

#if !defined(QT_GUI)
while (1)
Sleep(5000);
#endif

return true;
}

#ifdef WIN32
string StartupShortcutPath()
{
return MyGetSpecialFolderPath(CSIDL_STARTUP, true) + "\\Bitcoin.lnk";
}

bool GetStartOnSystemStartup()
{
return filesystem::exists(StartupShortcutPath().c_str());
}

bool SetStartOnSystemStartup(bool fAutoStart)
{
// If the shortcut exists already, remove it for updating
remove(StartupShortcutPath().c_str());

if (fAutoStart)
{
CoInitialize(NULL);

// Get a pointer to the IShellLink interface.
IShellLink* psl = NULL;
HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, IID_IShellLink,
reinterpret_cast<void**>(&psl));

if (SUCCEEDED(hres))
{
// Get the current executable path
TCHAR pszExePath[MAX_PATH];
GetModuleFileName(NULL, pszExePath, sizeof(pszExePath));

TCHAR pszArgs[5] = TEXT("-min");

// Set the path to the shortcut target
psl->SetPath(pszExePath);
PathRemoveFileSpec(pszExePath);
psl->SetWorkingDirectory(pszExePath);
psl->SetShowCmd(SW_SHOWMINNOACTIVE);
psl->SetArguments(pszArgs);

// Query IShellLink for the IPersistFile interface for
// saving the shortcut in persistent storage.
IPersistFile* ppf = NULL;
hres = psl->QueryInterface(IID_IPersistFile,
reinterpret_cast<void**>(&ppf));
if (SUCCEEDED(hres))
{
WCHAR pwsz[MAX_PATH];
// Ensure that the string is ANSI.
MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().c_str(), -1, pwsz, MAX_PATH);
// Save the link by calling IPersistFile::Save.
hres = ppf->Save(pwsz, TRUE);
ppf->Release();
psl->Release();
CoUninitialize();
return true;
}
psl->Release();
}
CoUninitialize();
return false;
}
return true;
}

#elif defined(LINUX)

// Follow the Desktop Application Autostart Spec:
// http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html

boost::filesystem::path GetAutostartDir()
{
namespace fs = boost::filesystem;

char* pszConfigHome = getenv("XDG_CONFIG_HOME");
if (pszConfigHome) return fs::path(pszConfigHome) / fs::path("autostart");
char* pszHome = getenv("HOME");
if (pszHome) return fs::path(pszHome) / fs::path(".config/autostart");
return fs::path();
}

boost::filesystem::path GetAutostartFilePath()
{
return GetAutostartDir() / boost::filesystem::path("bitcoin.desktop");
}

bool GetStartOnSystemStartup()
{
boost::filesystem::ifstream optionFile(GetAutostartFilePath());
if (!optionFile.good())
return false;
// Scan through file for "Hidden=true":
string line;
while (!optionFile.eof())
{
getline(optionFile, line);
if (line.find("Hidden") != string::npos &&
line.find("true") != string::npos)
return false;
}
optionFile.close();

return true;
}

bool SetStartOnSystemStartup(bool fAutoStart)
{
if (!fAutoStart)
{
#if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3
unlink(GetAutostartFilePath().string().c_str());
#else
unlink(GetAutostartFilePath().native_file_string().c_str());
#endif
}
else
{
char pszExePath[MAX_PATH+1];
memset(pszExePath, 0, sizeof(pszExePath));
if (readlink("/proc/self/exe", pszExePath, sizeof(pszExePath)-1) == -1)
return false;

boost::filesystem::create_directories(GetAutostartDir());

boost::filesystem::ofstream optionFile(GetAutostartFilePath(), ios_base::out|ios_base::trunc);
if (!optionFile.good())
return false;
// Write a bitcoin.desktop file to the autostart directory:
optionFile << "[Desktop Entry]\n";
optionFile << "Type=Application\n";
optionFile << "Name=Bitcoin\n";
optionFile << "Exec=" << pszExePath << " -min\n";
optionFile << "Terminal=false\n";
optionFile << "Hidden=false\n";
optionFile.close();
}
return true;
}
#else

// TODO: OSX startup stuff; see:
// http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/CustomLogin.html

bool GetStartOnSystemStartup() { return false; }
bool SetStartOnSystemStartup(bool fAutoStart) { return false; }

#endif
3 changes: 3 additions & 0 deletions src/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ void Shutdown(void* parg);
bool AppInit(int argc, char* argv[]);
bool AppInit2(int argc, char* argv[]);

bool GetStartOnSystemStartup();
bool SetStartOnSystemStartup(bool fAutoStart);

#endif
5 changes: 3 additions & 2 deletions src/qt/optionsmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "bitcoinunits.h"

#include "headers.h"
#include "init.h"

OptionsModel::OptionsModel(CWallet *wallet, QObject *parent) :
QAbstractListModel(parent),
Expand All @@ -27,7 +28,7 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
switch(index.row())
{
case StartAtStartup:
return QVariant();
return QVariant(GetStartOnSystemStartup());
case MinimizeToTray:
return QVariant(fMinimizeToTray);
case MapPortUPnP:
Expand Down Expand Up @@ -62,7 +63,7 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
switch(index.row())
{
case StartAtStartup:
successful = false; /*TODO*/
successful = SetStartOnSystemStartup(value.toBool());
break;
case MinimizeToTray:
fMinimizeToTray = value.toBool();
Expand Down

0 comments on commit f18a119

Please sign in to comment.