Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions sources/instancemanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include <QPushButton>
#include <QTimer>
#include <QThread>
#include <QEvent>
#include <QFileOpenEvent>

#include <cstring>

Expand Down Expand Up @@ -366,6 +368,36 @@ void InstanceManager::notifyPathChanged(const QStringList& paths) {
}
}

bool InstanceManager::eventFilter(QObject* watched, QEvent* event) {
if (event->type() == QEvent::FileOpen) {
QString path = static_cast<QFileOpenEvent*>(event)->file();
if (!path.isEmpty()) {
if (m_role == Role::Mothership) {
handleOpenRequest(path);
} else if (m_role == Role::Worker) {
// Reuse the persistent mothership connection: from the mothership's
// side this is indistinguishable from a Windows forwarder's
// Command::Open, so it goes through the exact same
// already-open-elsewhere-vs-spawn-a-new-worker logic.
// 既存の母艦への持続的な接続を再利用する: 母艦側から見れば
// これはWindowsの転送プロセスによるCommand::Openと区別が
// つかないため、既存の「他で開いているか・新規ワーカーを
// 起動するか」の判定ロジックがそのまま適用される。
sendFrame(m_workerSocket, Command::Open, path);
}
// Role::Standalone: no mothership exists to route this to (IPC setup
// failed entirely); there is no reasonable fallback, so the request
// is silently dropped, same as it would have been before this filter
// existed.
// Role::Standalone: 転送先の母艦が存在しない(IPCの初期化自体が
// 失敗している)ため、妥当な代替手段がなく、このフィルタ導入前と
// 同様に要求を静かに無視する。
}
return true;
}
return QObject::eventFilter(watched, event);
}

void InstanceManager::requestUnlink() {
if (m_role != Role::Worker || !m_workerSocket) return;
sendFrame(m_workerSocket, Command::Unlink, QString());
Expand Down
17 changes: 17 additions & 0 deletions sources/instancemanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
class QLocalServer;
class QLocalSocket;
class QSharedMemory;
class QEvent;

// Coordinates single-instance behavior for the app: a single hidden
// "mothership" process arbitrates which XDTS file is open in which
Expand Down Expand Up @@ -65,6 +66,22 @@ class InstanceManager : public QObject {
// (以後のCSP同期にのみ影響)なので、呼び出し前の確認は不要。
void requestUnlink();

// macOS only: Finder/`open` file-open requests for a file other than the
// one this process was launched with arrive as a QFileOpenEvent on the
// running QApplication instead of a fresh process with a new argv (macOS's
// Launch Services treats the bundle as already running and does not start
// a second process). Installed as an application-wide event filter by
// main.cpp so it sees these regardless of which existing process (the
// mothership or a worker) macOS happens to deliver them to.
// macOS専用: 起動時に渡されたのとは別のファイルに対するFinder/`open`の
// オープン要求は、新しいargvを持つ新規プロセスとしてではなく、既存の
// QApplicationインスタンスへのQFileOpenEventとして届く(macOSの
// Launch Servicesはバンドルを既に実行中とみなし、2つ目のプロセスを
// 起動しないため)。macOSがどのプロセス(母艦かワーカーか)にこれを
// 配送するかに関わらず受け取れるよう、main.cppからアプリケーション
// 全体のイベントフィルタとしてインストールされる。
bool eventFilter(QObject* watched, QEvent* event) override;

signals:
// Worker role only: emitted when the mothership asks this window to
// reload its XDTS data and come to the foreground, because another
Expand Down
16 changes: 16 additions & 0 deletions sources/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,22 @@ int main(int argc, char* argv[]) {
InstanceManager::Role role =
InstanceManager::instance()->bootstrap(a.arguments(), initialPath);
if (role == InstanceManager::Role::Forwarded) return 0;

#ifdef __MACOS__
// On macOS, Finder/`open` requests for a file other than the one this
// process was launched with don't start a new process (Launch Services
// treats the bundle as already running); they arrive as a
// QFileOpenEvent on whichever process is already running instead. This
// has no effect on Windows, where every launch is a fresh process with
// its own argv.
// macOSでは、起動時に渡されたのとは別のファイルに対するFinder/`open`の
// 要求は新規プロセスを起動しない(Launch Servicesがバンドルを既に
// 実行中とみなすため)。代わりに、既に実行中のいずれかのプロセスへ
// QFileOpenEventとして届く。各起動が固有のargvを持つ新規プロセスと
// なるWindowsでは影響しない。
qApp->installEventFilter(InstanceManager::instance());
#endif

if (role == InstanceManager::Role::Mothership) return a.exec();

MyParams::instance()->initStamps();
Expand Down
Loading