Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Qt bring QProcess application to the front
QtWS25 Last Chance

Qt bring QProcess application to the front

Scheduled Pinned Locked Moved Solved General and Desktop
8 Posts 4 Posters 1.3k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    lamozg6
    wrote on last edited by
    #1

    Problem arises under the Windows OS.

    I have the main application and I start a new application from that using QProcess (let's call it child application), at first child application just runs in the background, but on click to some button in the main app, child app should be shown. For that purpose (and also for some other reasons) I run a local server and both applications are connected to the server and exchange messages using sockets. When child app gets appropriate message, I call function to display it, which also should raise and bring to the front child application.

    Here is a piece of code related to that part.

    // Case 1 (child app is shown, but not a foreground window)
    
    // Main app
    
    QScopedPointer<QLocalServer> localServer;
    QLocalSocket connection; // connection listens on the same local server as we have in the child application
    
    // this function is called in class constructor and runs process in the background
    void startChildApplication()
    {
      childProcess.reset(new QProcess);
      // args are unimportant here
      childProcess.start(Utilities::getchildProcessLocation(), args);
    }
    
    // this function called onClick of some button to display child process running in the background
    void displayChildApplication()
    {
      const std::string message = "display";
      connection.write(message.data(), message.size());
    }
    
    // Child app
    
    QScopedPointer<QLocalServer> localServer;
    QLocalSocket childConnection; // childConnection listens on the same local server as we have in the main application
    
    void displayApplication()
    {
        appWindow->setWindowState((appWindow->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
        appWindow->show();
        appWindow->activateWindow();
        appWindow->raise();
    }
    
    connect(childConnection, &QLocalSocket::readyRead, this, [this]()
    {
      const auto message = childConnection->readAll();
      if (message == "display")
      {
        displayApplication();
      }
    };
    

    So problem is application is shown, but it's not a foreground window. I also tried Windows specific WINAPI functions (SetForegroundWindow, etc), which also didn't work.

    Funny part of the problem is that if I don't run child app in the background and try to display on button click, but just run QProcess on click and in constructor for child app I call displayApplication function, it works as expected, child application is shown and it's a foreground window.

    // Case 2 (child app is shown and it's a foreground window)
    
    // Main app
    
    // this function is called onClick of some button to start and display child process
    void startChildApplication()
    {
      childProcess.reset(new QProcess);
      // args are unimportant here
      childProcess.start(Utilities::getchildProcessLocation(), args);
    }
    
    // Child app
    
    // this function is called in class constructor
    void displayApplication()
    {
        appWindow->setWindowState((appWindow->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
        appWindow->show();
        appWindow->activateWindow();
        appWindow->raise();
    }
    

    Question is how to get behavior of case 2 in case 1, or at least understand why it doesn't work in the first case and works in the second case.

    P.S. I know that its a Windows specific thing, but as you can see it's possible to get behavior I want.

    JonBJ 1 Reply Last reply
    0
    • Chris KawaC Offline
      Chris KawaC Offline
      Chris Kawa
      Lifetime Qt Champion
      wrote on last edited by Chris Kawa
      #4

      See the Remarks section in the SetForegroundWindow. This also applies to Qt which uses SetForegroundWindow internally.

      To summarize - on Windows you're restricted on when you can bring your window to the foreground. That's to prevent popups and other annoying behavior of some apps. You have to be either the active process, a child of the active process or have input focus.

      The method with a button and QProcess works because it falls under one of the exceptions listed - you're started as a child of the active process and so can raise yourself to the foreground. When you communicate through a server your processes are not related, so the one receiving a message can't raise itself.

      JonBJ 1 Reply Last reply
      4
      • JoeCFDJ Offline
        JoeCFDJ Offline
        JoeCFD
        wrote on last edited by JoeCFD
        #2
        This post is deleted!
        1 Reply Last reply
        0
        • L lamozg6

          Problem arises under the Windows OS.

          I have the main application and I start a new application from that using QProcess (let's call it child application), at first child application just runs in the background, but on click to some button in the main app, child app should be shown. For that purpose (and also for some other reasons) I run a local server and both applications are connected to the server and exchange messages using sockets. When child app gets appropriate message, I call function to display it, which also should raise and bring to the front child application.

          Here is a piece of code related to that part.

          // Case 1 (child app is shown, but not a foreground window)
          
          // Main app
          
          QScopedPointer<QLocalServer> localServer;
          QLocalSocket connection; // connection listens on the same local server as we have in the child application
          
          // this function is called in class constructor and runs process in the background
          void startChildApplication()
          {
            childProcess.reset(new QProcess);
            // args are unimportant here
            childProcess.start(Utilities::getchildProcessLocation(), args);
          }
          
          // this function called onClick of some button to display child process running in the background
          void displayChildApplication()
          {
            const std::string message = "display";
            connection.write(message.data(), message.size());
          }
          
          // Child app
          
          QScopedPointer<QLocalServer> localServer;
          QLocalSocket childConnection; // childConnection listens on the same local server as we have in the main application
          
          void displayApplication()
          {
              appWindow->setWindowState((appWindow->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
              appWindow->show();
              appWindow->activateWindow();
              appWindow->raise();
          }
          
          connect(childConnection, &QLocalSocket::readyRead, this, [this]()
          {
            const auto message = childConnection->readAll();
            if (message == "display")
            {
              displayApplication();
            }
          };
          

          So problem is application is shown, but it's not a foreground window. I also tried Windows specific WINAPI functions (SetForegroundWindow, etc), which also didn't work.

          Funny part of the problem is that if I don't run child app in the background and try to display on button click, but just run QProcess on click and in constructor for child app I call displayApplication function, it works as expected, child application is shown and it's a foreground window.

          // Case 2 (child app is shown and it's a foreground window)
          
          // Main app
          
          // this function is called onClick of some button to start and display child process
          void startChildApplication()
          {
            childProcess.reset(new QProcess);
            // args are unimportant here
            childProcess.start(Utilities::getchildProcessLocation(), args);
          }
          
          // Child app
          
          // this function is called in class constructor
          void displayApplication()
          {
              appWindow->setWindowState((appWindow->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
              appWindow->show();
              appWindow->activateWindow();
              appWindow->raise();
          }
          

          Question is how to get behavior of case 2 in case 1, or at least understand why it doesn't work in the first case and works in the second case.

          P.S. I know that its a Windows specific thing, but as you can see it's possible to get behavior I want.

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by JonB
          #3

          @lamozg6 said in Qt bring QProcess application to the front:

          So problem is application is shown, but it's not a foreground window.

          This is purely a guess/hunch. From your description, you are trying to up-front spawned child from a click in parent. Maybe the order of events is important to the windowing system. Maybe the child is trying to up-front while you're still interacting with the parent window and that's not good?

          In child put in a delay before up-fronting itself. In parent finish the click, releasing the button, then the child up-fronts. Does it now up-front correctly?

          1 Reply Last reply
          0
          • Chris KawaC Offline
            Chris KawaC Offline
            Chris Kawa
            Lifetime Qt Champion
            wrote on last edited by Chris Kawa
            #4

            See the Remarks section in the SetForegroundWindow. This also applies to Qt which uses SetForegroundWindow internally.

            To summarize - on Windows you're restricted on when you can bring your window to the foreground. That's to prevent popups and other annoying behavior of some apps. You have to be either the active process, a child of the active process or have input focus.

            The method with a button and QProcess works because it falls under one of the exceptions listed - you're started as a child of the active process and so can raise yourself to the foreground. When you communicate through a server your processes are not related, so the one receiving a message can't raise itself.

            JonBJ 1 Reply Last reply
            4
            • Chris KawaC Chris Kawa

              See the Remarks section in the SetForegroundWindow. This also applies to Qt which uses SetForegroundWindow internally.

              To summarize - on Windows you're restricted on when you can bring your window to the foreground. That's to prevent popups and other annoying behavior of some apps. You have to be either the active process, a child of the active process or have input focus.

              The method with a button and QProcess works because it falls under one of the exceptions listed - you're started as a child of the active process and so can raise yourself to the foreground. When you communicate through a server your processes are not related, so the one receiving a message can't raise itself.

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by JonB
              #5

              @Chris-Kawa
              An excellent Windows point!

              But I get confused. The OP shows

               childProcess.start(Utilities::getchildProcessLocation(), args);
              

              being run from the program where he clicks the button, not the "server", as I understand it. Which would put the relationship in your

              a child of the active process

              situation. So as I read it, it ought be able to foreground itself when it receives a message from the active parent app? Which I think the OP is saying does not happen.

              Chris KawaC 1 Reply Last reply
              0
              • JonBJ JonB

                @Chris-Kawa
                An excellent Windows point!

                But I get confused. The OP shows

                 childProcess.start(Utilities::getchildProcessLocation(), args);
                

                being run from the program where he clicks the button, not the "server", as I understand it. Which would put the relationship in your

                a child of the active process

                situation. So as I read it, it ought be able to foreground itself when it receives a message from the active parent app? Which I think the OP is saying does not happen.

                Chris KawaC Offline
                Chris KawaC Offline
                Chris Kawa
                Lifetime Qt Champion
                wrote on last edited by
                #6

                @JonB As I understood it the parent is the process which can't raise itself or its child, but now reading the OP again I'm not sure which app gets a message and which tries to raise what window. I guess we need a clarification from @lamozg6 on that, but I believe what I mentioned applies to this problem in some form.

                1 Reply Last reply
                2
                • L Offline
                  L Offline
                  lamozg6
                  wrote on last edited by lamozg6
                  #7

                  @Chris-Kawa said in Qt bring QProcess application to the front:

                  When you communicate through a server your processes are not related, so the one receiving a message can't raise itself.

                  @JonB said in Qt bring QProcess application to the front:

                  being run from the program where he clicks the button, not the "server", as I understand it.

                  Yes, that's the case, child application is run from main application, server is used just for communication (main app sends message to notify child app that it should be displayed now). So processes communicate by server, but that processes are related, child application is a child process of the active process. As I understand this should fall into the same case that @Chris-Kawa mentioned, child process of the active process tries to raise itself, but it can't (I only get that application icon blinking in the toolbar), what did I miss?

                  Also, what I noticed in Task Manager, when that child process is shown, now its a separate process, not a child process of my main application as it was, but that's for both cases.

                  1 Reply Last reply
                  0
                  • L Offline
                    L Offline
                    lamozg6
                    wrote on last edited by
                    #8

                    Problem was solved by adding call to the AllowSetForegroundWindow from main application just before sending message to the child application, not quite sure why it's needed, but anyway problem is gone, so thank you guys.

                    1 Reply Last reply
                    2

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved