macOS: как запустить gui QProcess и вывести его на передний план?

#c #macos #qt #cocoa

#c #macos #qt #cocoa

Вопрос:

Я пытаюсь запустить приложение с графическим интерфейсом с помощью QProcess, но по умолчанию оно неактивно:

 qint64 pid = 0;
QProcess::startDetached(executable, args, wd, amp;pid); //The app is in background
  

Я пробовал activateWithOptions , и это не помогает:

 qint64 pid = 0;
QProcess::startDetached(executable, args, wd, amp;pid);

NSRunningApplication *app = [NSRunningApplication runningApplicationWithProcessIdentifier:static_cast<pid_t>(pid)];
[app activateWithOptions: NSApplicationActivateIgnoringOtherApps]; //The app is still in background
  

Но если я добавлю небольшую задержку activateWithOptions , все будет работать так, как ожидалось:

 qint64 pid = 0;
QProcess::startDetached(executable, args, wd, amp;pid);

QThread::msleep(2000);
NSRunningApplication *app = [NSRunningApplication runningApplicationWithProcessIdentifier:static_cast<pid_t>(pid)];
[app activateWithOptions: NSApplicationActivateIgnoringOtherApps]; //The app is in foreground!
  

Но QThread::msleep(2000) выглядит как грязный взлом и не собирается проходить проверку кода 🙂

Итак, мой вопрос: как запустить процесс с графическим интерфейсом и запустить его без взломов?

PS: Я знаю, что QProcess::startDetached("open", "-a " executable); это может сработать, но это не позволяет указать рабочий каталог, поэтому мне это не подходит

UPD: Похоже, мне нужно подождать, пока приложение завершит запуск, и тогда я смогу его активировать.

Комментарии:

1. Что произойдет, если вы используете, open -a script.sh где script.sh находится скрипт bash, который затем запускает желаемый исполняемый файл? Сработает ли это? В противном случае вы могли бы захотеть посмотреть на, QTimer::singleShot а не QThread::msleep(2000) .

2. @G.M., насколько я понимаю, open всегда использует путь к исполняемому файлу в качестве рабочего каталога. Таким образом, запуск его из script на самом деле ничего не меняет

Ответ №1:

Мое решение:

     NSRunningApplication *waitForAppHandle(pid_t pid) const
    {
        forever {
            NSRunningApplication *app  = [NSRunningApplication runningApplicationWithProcessIdentifier: pid];
            if (app) 
                return app;
            }

            QThread::yieldCurrentThread();
        }
    }

    bool waitForLaunched(NSRunningApplication *app) const
    {

        forever {
            if ([app isFinishedLaunching]) {
                return;
            }

            QThread::yieldCurrentThread();
        }
    }

    void activate(pid_t pid)
    {
        NSRunningApplication *app = waitForAppHandle();
        waitForLaunched(app);

        [app activateWithOptions : NSApplicationActivateIgnoringOtherApps];
    }

    //...
    
    QProcess p;
    //...
    activate(p.processId());