Only enforce single instance if launched with arguments.

Took 5 minutes
This commit is contained in:
Lukas Brübach 2026-04-05 22:32:58 +02:00
parent 04665e4dd8
commit 3b3a563cfc
2 changed files with 43 additions and 41 deletions

View file

@ -277,18 +277,31 @@ int main(int argc, char *argv[])
SpoilerBackgroundUpdater spoilerBackgroundUpdater;
// --- Handle files or URLs passed at startup ---
SingleInstanceManager instance;
QStringList startupFiles;
// Collect command-line files/URLs
for (int i = 1; i < argc; ++i) {
QString arg = QString::fromLocal8Bit(argv[i]);
startupFiles.append(arg);
startupFiles.append(QString::fromLocal8Bit(argv[i]));
}
if (!instance.tryRun(startupFiles)) {
// Another instance received our files, exit
return 0;
bool hasActivationFiles = !startupFiles.isEmpty();
SingleInstanceManager instance;
if (hasActivationFiles) {
// Activation launch: try to forward
if (!instance.tryRun(startupFiles)) {
// Sent successfully → exit
return 0;
}
// No primary instance → become server
qInfo() << "No existing instance found, becoming primary instance";
} else {
// Plain launch: try to start server, but do not connect to any existing
if (!instance.tryRun(QStringList())) {
// Server already exists → just run independently
qInfo() << "Another instance exists, running independently";
} else {
qInfo() << "No existing instance found, starting server";
}
}
ui.show();
@ -328,18 +341,6 @@ int main(int argc, char *argv[])
}
});
#ifdef Q_OS_MAC
// macOS: handle files opened via Finder after startup
QObject::connect(&app, &QApplication::fileOpen, [&ui](const QString &filePath) {
qDebug() << "macOS opened file:" << filePath;
std::optional<LoadedDeck> deckOpt =
DeckLoader::loadFromFile(filePath, DeckFileFormat::getFormatFromName(filePath), true);
if (deckOpt) {
ui.getTabSupervisor()->openDeckInNewTab(deckOpt.value());
}
});
#endif
int ret = app.exec();
qCInfo(MainLog) << "Event loop finished, terminating...";

View file

@ -4,35 +4,35 @@ SingleInstanceManager::SingleInstanceManager(QObject *parent) : QObject(parent)
{
}
bool SingleInstanceManager::tryRun(const QStringList &initialFiles)
bool SingleInstanceManager::tryRun(const QStringList &filesToSend)
{
serverName = "CockatriceSingleInstance";
QLocalSocket socket;
socket.connectToServer(serverName);
// Attempt to connect only if we have files to send
if (!filesToSend.isEmpty()) {
QLocalSocket socket;
socket.connectToServer(serverName);
if (socket.waitForConnected(200)) {
// Serialize payload with length prefix
QByteArray payload;
QDataStream out(&payload, QIODevice::WriteOnly);
out << filesToSend;
if (socket.waitForConnected(200)) {
// Serialize into buffer first
QByteArray payload;
QDataStream out(&payload, QIODevice::WriteOnly);
out << initialFiles;
QByteArray message;
QDataStream msgStream(&message, QIODevice::WriteOnly);
msgStream << quint32(payload.size());
message.append(payload);
// Prefix with size
QByteArray message;
QDataStream msgStream(&message, QIODevice::WriteOnly);
msgStream << quint32(payload.size());
message.append(payload);
socket.write(message);
socket.flush();
socket.waitForBytesWritten(1000);
socket.write(message);
socket.flush();
socket.waitForBytesWritten(1000);
return false; // Another instance is running
return false; // Sent successfully → exit
}
}
// No other instance → start server
// Otherwise, start server
server = new QLocalServer(this);
connect(server, &QLocalServer::newConnection, this, &SingleInstanceManager::handleNewConnection);
if (!server->listen(serverName)) {
@ -40,8 +40,9 @@ bool SingleInstanceManager::tryRun(const QStringList &initialFiles)
server->listen(serverName);
}
return true;
return true; // This process is now primary server
}
void SingleInstanceManager::handleNewConnection()
{
QLocalSocket *socket = server->nextPendingConnection();