Qt Assistant window on mac starts behind caller window

439 views Asked by At

I am running a Qt app that launches a process (Qt Assistant)

The window of the process shows up behind the window of the caller, when the app runs on OSX...

How can I bring it in front ?

Code from Qt documentation:

QProcess *process = new QProcess();
QStringList args;
args << QLatin1String("-collectionFile")
     << QLatin1String("mycollection.qhc");
     //<< QLatin1String("-enableRemoteControl");  // can't use this, help freezes... but still starts in background! ... this is apparently a bug in Qt solved in Qt 5.4 (see Note) which I cannot use, but not relevant for current problem 
process->start(QLatin1String("Assistant.app"), args);
if (!process->waitForStarted())
    return;

enter image description here

Note about not using "-enableRemoteControl"- see question

The marked as duplicate/vote for closed points to an example that starts the process as detached. Trying it did not solve the problem - also, the help must be a child process for the app.

Update based on comments/posted answer:

Trying

QString app = "path/to/Assistant";   // since I use the copy from inside bundle
QString helpfile = "path/to/helpfile";
QString cmd = QString("open -a '%1' --args '-collectionFile' '%2'").arg(app).arg(helpFile);
qDebug()<<cmd;
m_helpProcess->start(cmd);
m_helpProcess->waitForStarted();
if (m_helpProcess->state() == QProcess::Running)
    qDebug()<<"help started";
else
    qDebug()<<m_helpProcess->errorString();

Result:

help started (but the window doesn't show at all, I think it gives an error and closes)

(If I copy the path from cmd to Terminal, runs perfectly so the arguments seem to be correct...)

Update after trying to play with osascript:

After the code above to start Assistant, I added (one of the many versions of activateScript)

Q_PID pid = m_helpProcess->pid();

QString activateScript = "tell application System Events to perform action \"AXRaise\" of application " + app + "\n";
QString activateScript = "tell application System Events to perform action \"AXRaise\" of window with title \"My App Help\"\n";
QString activateScript = "tell application " + app + " to activate\n";
QString activateScript = "tell application Assistant activate\n";

QString activateScript = QString("tell application \"System Events\" \n") +
        QString("set (frontmost of processes whose id is ") + QString::number(pid) + QString(") to true\n") +
        QString("end tell\n");

QString activateScript = QString("tell application \"System Events\" \n") +
        QString("tell process whose id is ") + QString::number(pid) + QString(") to activate\n") +
        QString("end tell\n") + QString("end tell\n");

QString activateScript = QString("tell application \"System Events\" to perform action \"AXRaise\"") +
        QString("of application whose id is ") + QString::number(pid) +
        QString("end tell\n");

QString activateScript = QString("tell process whose id is ") + QString::number(pid) + QString(") to activate\n") +
        QString("end tell\n");

QString osaScript = "/usr/bin/osascript";
QStringList osaArguments;
osaArguments << "-l" << "AppleScript";

QProcess p;
p.start(osaScript, osaArguments);
p.write(activateScript.toUtf8());
p.closeWriteChannel();
p.waitForStarted(-1);

None of the above versions of script had any effect.

(A possibility for the scripts that use pid to ignore me is that osascript may be using the window id, which may be different from process id - I have searched for ways to acquire the windows id but found nothing I can use from inside Qt.)

Additional Update:

I created a signal, and sent an "emit" to the caller, after the start, so that perhaps I can do something to hide the caller window. An attempt to minimize then restore the caller looked horrible, especially due to animation. But it would be better than nothing... at least it can notify the user that something has happened, and, if the caller is maximized and the dock is hidden, to show caller that there may be help in the background... Something. (this is not really a solution though)

Well even that horrible attempt does not work. If the help is already running, then minimizing and restoring the caller window will result in the background help window being visible for an instant, and of course the restored caller will show above it. But... If the Assistant is starting for the first time, there is NOTHING in the back !!! waitForStarted() is already true yet the Assistant takes much longer to show.... probably takes too long to load its help database ?

Could this be the reason why the process always starts in the background though (not background process, but as a window behind the caller window) ? It doesn't display itself fast enough so it doesn't receive focus ? And if something like that is going on, how do I fix it ?

...... I tried adding a timer and then calling the above actionscript commands, I could clearly see the wait cursor while the Assistant window showed behind the app window - but saw no effect when the actionscript items were running - so they must all be wrong.

This is incredibly frustrating !

Seems that there are solutions for this issue in Windows (linking a couple, for ideas):

(1) Bring to front window application managed with QProcess

(2) qt-assistant-how-to-maximize-help-window-when-qt-assistent-is-started-as-proces

But I have not seen this weird behavior in Linux or Windows. It only seems to happen on OSX, for my app. Since the process behavior is system dependent, I need some solution for OSX... Please help !

0

There are 0 answers