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. Focus stealing progress dialog
Forum Update on Monday, May 27th 2025

Focus stealing progress dialog

Scheduled Pinned Locked Moved Solved General and Desktop
31 Posts 4 Posters 742 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.
  • SGaistS Offline
    SGaistS Offline
    SGaist
    Lifetime Qt Champion
    wrote last edited by
    #6

    Nothing obvious jumps to my eyes.

    Would it be possible to have the same dialog but buildable so I can test it on my machine ?

    Interested in AI ? www.idiap.ch
    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

    1 Reply Last reply
    0
    • PerdrixP Offline
      PerdrixP Offline
      Perdrix
      wrote last edited by
      #7

      I thought that I had sent you enough to build it - with judicious removal of pch,h and adding includes for Qt and stdlib stuff.

      1 Reply Last reply
      0
      • PerdrixP Offline
        PerdrixP Offline
        Perdrix
        wrote last edited by
        #8

        Hmmm! Odder and odder the focus stealing doesn't happen on my Windows system but does on many ?? It also happens consistently on both Linux and Mac. It's not related to the QWidget::raise() calls as they only happen when the text of the dlg is updated. The focus is stolen by the progress bar updates.

        1 Reply Last reply
        0
        • PerdrixP Offline
          PerdrixP Offline
          Perdrix
          wrote last edited by Perdrix
          #9

          @SGaist I'm creating a stand-alone Creator project for this problem, and I am almost there, but can't work out how to pass the /openmp:experimental command line flag to MS Visual C++

          How do I configure the project to do this?
          D

          1 Reply Last reply
          0
          • PerdrixP Offline
            PerdrixP Offline
            Perdrix
            wrote last edited by Perdrix
            #10

            @SGaist The Creator Project is here:
            https://www.dropbox.com/scl/fi/h929bym63f2sf1y3904fw/DSS_ProgressDlg.zip?rlkey=vhhntwxapk347ipc6ng2hkf59&dl=0

            It's setup to use MSVC2022_x64 on Windows.

            Focus theft only seems to occur on some Windows systems?? Go figure.

            Moving the dialog - it always snaps back to where it started - commenting the calls to QWidget::show() in applyStart1Text() and applyStart2Text() prevents that problem.

            It is still a focus thief on Linux and MacOS. To build on MacOS you'll need to install:
            https://mac.r-project.org/openmp/openmp-19.1.0-darwin20-Release.tar.gz
            so the files end up in /usr/local/include and /usr/local/lib. For example:

            cd ~/Downloads
            curl -O https://mac.r-project.org/openmp/openmp-19.1.0-darwin20-Release.tar.gz
            sudo tar -zxvf openmp-19.1.0-darwin20-Release.tar.gz -C /
            

            For more details see:
            https://mac.r-project.org/openmp/

            You will likely want to change the .pro file so it looks like (not necessarily 100% correct - I'm not totally familiar with qmake):

            unix:!macx: QMAKE_CXXFLAGS+=-fopenmp
            macx: QMAKE_CXXFLAGS+=-Xclang -fopenmp
            win32: QMAKE_CXXFLAGS+=/openmp:experimental
            
            # Default rules for deployment.
            qnx: target.path = /tmp/$${TARGET}/bin
            else: unix:!android: target.path = /opt/$${TARGET}/bin
            !isEmpty(target.path): INSTALLS += target
            
            unix:!macx: LIBS += -L/usr/lib/x86_64-linux-gnu/ -lomp5
            
            macx: LIBS += -L/usr/local/lib/ -lomp
            
            INCLUDEPATH += /usr/local/include
            DEPENDPATH += /usr/local/include
            
            

            I build for Linux on Lubuntu 22.04 FWIW.

            David

            1 Reply Last reply
            0
            • PerdrixP Offline
              PerdrixP Offline
              Perdrix
              wrote last edited by
              #11

              @Axel-Spoerl This may interest you ...

              1 Reply Last reply
              0
              • Axel SpoerlA Offline
                Axel SpoerlA Offline
                Axel Spoerl
                Moderators
                wrote last edited by
                #12

                Thanks @Perdrix for pinging.
                Generally, a QProgressBar doesn't claim focus. My suspicion is that it happens on Window manager level. So the progress bar is the beneficiary of focus theft, but somebody else does the stealing ;-)
                I also wonder who has told you the lie, that you need to call processEvents() for anything to happen. Unless an application implements blocking code, that's not necessary.

                I wonder if you could isolate the antisocial behaviour into a small reproducer...

                Software Engineer
                The Qt Company, Oslo

                1 Reply Last reply
                0
                • PerdrixP Offline
                  PerdrixP Offline
                  Perdrix
                  wrote last edited by
                  #13

                  This is a small a demo as I can manage. We do need the calls to processEvents()- try commenting the calls out and see what happens - the code we are tracking the progress of is running primarily on the GUI thread with ancillary threads created by openmp.

                  David

                  Christian EhrlicherC 1 Reply Last reply
                  0
                  • PerdrixP Perdrix

                    This is a small a demo as I can manage. We do need the calls to processEvents()- try commenting the calls out and see what happens - the code we are tracking the progress of is running primarily on the GUI thread with ancillary threads created by openmp.

                    David

                    Christian EhrlicherC Online
                    Christian EhrlicherC Online
                    Christian Ehrlicher
                    Lifetime Qt Champion
                    wrote last edited by
                    #14

                    @Perdrix said in Focus stealing progress dialog:

                    This is a small a demo as I can manage.

                    So you tell us that you need openmp to reproduce the issue?
                    provide a minimal, compileable example of the problem so we can take a look on it.

                    Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                    Visit the Qt Academy at https://academy.qt.io/catalog

                    1 Reply Last reply
                    1
                    • PerdrixP Offline
                      PerdrixP Offline
                      Perdrix
                      wrote last edited by Perdrix
                      #15

                      No - you don't need openmp - just comment out the openmp pragma in dialog.cpp and remove references to openmp in the .pro file It will then run single threaded - and display the same problem. I wanted to include a complete example of our dialog in full use just in case...

                      1 Reply Last reply
                      0
                      • Axel SpoerlA Offline
                        Axel SpoerlA Offline
                        Axel Spoerl
                        Moderators
                        wrote last edited by
                        #16
                        namespace DSS
                        {
                        	void ProgressBase::UpdateProcessorsUsed()
                        	{
                                int currentThreadCount = omp_get_num_threads();	// Returns 1 if outside parallel region, else will return threads/cores used!
                                applyProcessorsUsed(currentThreadCount);
                        	}
                        }
                        

                        This doesn't compile without openmp.

                        Please provide a minimal compilable example.
                        It has to be small enough to post it here. I normally don't download stuff from dropbox.

                        Software Engineer
                        The Qt Company, Oslo

                        1 Reply Last reply
                        1
                        • PerdrixP Offline
                          PerdrixP Offline
                          Perdrix
                          wrote last edited by
                          #17

                          I did say a few minor changes to remove openmp - I wanted to be SURE that you guys had all the code
                          Just change that mf to read:

                          	void ProgressBase::UpdateProcessorsUsed()
                          	{
                                         applyProcessorsUsed(1);
                          	}
                          
                          1 Reply Last reply
                          0
                          • PerdrixP Offline
                            PerdrixP Offline
                            Perdrix
                            wrote last edited by
                            #18

                            Believe me I have tried to reduce this to a totally trivial case that causes the focus theft I've burned weeks on this problem which is why I'm passing the code over to minds who have forgotten more about Qt than I ever knew.

                            Axel SpoerlA 1 Reply Last reply
                            0
                            • Axel SpoerlA Offline
                              Axel SpoerlA Offline
                              Axel Spoerl
                              Moderators
                              wrote last edited by Axel Spoerl
                              #19

                              Here's the proof, that focus isn't stolen (tested on Windows, macOS and Linux)

                              #include <QApplication>
                              #include <QThread>
                              #include <QProgressBar>
                              #include <QLineEdit>
                              #include <QTimer>
                              #include <QVBoxLayout>
                              
                              class Updater : public QObject
                              {
                                  Q_OBJECT
                              public:
                                  Updater(QProgressBar *bar, QObject *parent = nullptr) : QObject(parent), bar(bar)
                                  {}
                              
                              public slots:
                                  void update()
                                  {
                                      emit valueChanged(++value);
                                  }
                              
                                  void onValueChanged(int v)
                                  {
                                      value = v;
                                      if (!QThread::currentThread()->isInterruptionRequested())
                                          QTimer::singleShot(400, this, [&]{ update(); });
                                  }
                              
                              signals:
                                  void valueChanged(int value);
                              
                              private:
                                  QProgressBar *bar;
                                  int value = 0;
                              };
                              
                              int main(int argc, char *argv[])
                              {
                                  QApplication a(argc, argv);
                                  QWidget w;
                                  auto *lay = new QVBoxLayout;
                                  auto *edit = new QLineEdit;
                                  auto *bar = new QProgressBar;
                                  lay->addWidget(edit);
                                  lay->addWidget(bar);
                                  w.setLayout(lay);
                                  auto *u = new Updater(bar, &a);
                                  QObject::connect(edit, &QLineEdit::textChanged, u, &Updater::update);
                                  QObject::connect(bar, &QProgressBar::valueChanged, u, &Updater::onValueChanged);
                                  QObject::connect(u, &Updater::valueChanged, bar, &QProgressBar::setValue);
                                  QThread t(&a);
                                  u->moveToThread(&t);
                                  t.start();
                                  w.show();
                                  bar->setValue(1);
                                  const int ret = a.exec();
                                  t.requestInterruption();
                                  t.quit();
                                  t.wait();
                                  return ret;
                              }
                              
                              #include "main.moc"
                              
                              

                              Software Engineer
                              The Qt Company, Oslo

                              1 Reply Last reply
                              1
                              • PerdrixP Offline
                                PerdrixP Offline
                                Perdrix
                                wrote last edited by Perdrix
                                #20

                                Try running the code I pointed you to on Dropbox. The focus IS definitely stolen - that's why I am here - I tried trivial test cases like what you just posted and they caused no problems. I can't see (and I can tell you I have looked until I am blue in the face) what is wrong with the code for DSS::ProgressDlg but something is clearly causing focus to be stolen whenever the progress bars are updated.

                                It's truly dis-heartening when you go somewhere for help and get told that there's no problem, when clearly there is - it's just that neither you nor I yet know what code is causing it.

                                I've now burnt about 7 weeks on this and it's driving me nuts.

                                I have spent quite some time to re-package that dual progress dialog so it would work outside my projects - time well spent I think. But it would be nice if someone would help in trying to work out what the problem is - I am completely out of ideas which I why I came here in the first place.

                                Axel SpoerlA 1 Reply Last reply
                                0
                                • PerdrixP Perdrix

                                  Believe me I have tried to reduce this to a totally trivial case that causes the focus theft I've burned weeks on this problem which is why I'm passing the code over to minds who have forgotten more about Qt than I ever knew.

                                  Axel SpoerlA Offline
                                  Axel SpoerlA Offline
                                  Axel Spoerl
                                  Moderators
                                  wrote last edited by
                                  #21

                                  @Perdrix said in Focus stealing progress dialog:

                                  Believe me I have tried to reduce this to a totally trivial case that causes the focus theft I've burned weeks on this problem which is why I'm passing the code over to minds who have forgotten more about Qt than I ever knew.

                                  You are a seasoned developer who knows a lot about Qt, don't downplay your expertise David!

                                  However, if the use case is too complex to boil down to 10-20 lines and it requires calling processEvents() to function, then there is something wrong in the application. You could do QLoggingCategory::setFilterRules("qt.widgets.focus=true") and/or listen to the QApplication::focusChanged() signal to find out why and where the focus is changed.

                                  Software Engineer
                                  The Qt Company, Oslo

                                  1 Reply Last reply
                                  1
                                  • PerdrixP Perdrix

                                    Try running the code I pointed you to on Dropbox. The focus IS definitely stolen - that's why I am here - I tried trivial test cases like what you just posted and they caused no problems. I can't see (and I can tell you I have looked until I am blue in the face) what is wrong with the code for DSS::ProgressDlg but something is clearly causing focus to be stolen whenever the progress bars are updated.

                                    It's truly dis-heartening when you go somewhere for help and get told that there's no problem, when clearly there is - it's just that neither you nor I yet know what code is causing it.

                                    I've now burnt about 7 weeks on this and it's driving me nuts.

                                    I have spent quite some time to re-package that dual progress dialog so it would work outside my projects - time well spent I think. But it would be nice if someone would help in trying to work out what the problem is - I am completely out of ideas which I why I came here in the first place.

                                    Axel SpoerlA Offline
                                    Axel SpoerlA Offline
                                    Axel Spoerl
                                    Moderators
                                    wrote last edited by Axel Spoerl
                                    #22

                                    @Perdrix said in Focus stealing progress dialog:

                                    Try running the code I pointed you to on Dropbox.

                                    That code doesn't compile without openmp and I don't have the time to re-arrange the code.

                                    Just by code-reading and as a general comment: The progress setters seem to be invoked from different threads, that aren't QThreads, so they have no event loop running. I am not sure, what processEvents() really does in that case.
                                    I don't use openmp. The loop in Dialog::runTask() depends on it and it's not a trivial change to remove that dependency.

                                    As a general question: Why are you struggling to boil the issue down to a simpler reproducer? Have you tried the debugging hints from my previous post?
                                    I'd simply connect a lambda to QApplication::focusChanged(). Call a qFatal() << "Focus thief caught red handed"; inside the lambda, when the old focus object is one of the progress bars. If it crashes too early, use a static int as a counter to crash when focus is stolen. Then you have a perfect stack trace to the point where it happened.

                                    Software Engineer
                                    The Qt Company, Oslo

                                    1 Reply Last reply
                                    1
                                    • PerdrixP Offline
                                      PerdrixP Offline
                                      Perdrix
                                      wrote last edited by Perdrix
                                      #23

                                      I'll post a revised version with openmp removed entirely. Yes it's bad form to do long running processing on the gui thread - but that's what we have so need to call processEvents() from the dlg.

                                      Your suggestions sound good - I wasn't aware of QLoggingCategory stuff and hadn't considered the use of QApplication::focusChanged - that's the advantage you have over me! I'll see what mileage I can get out of those.

                                      D.

                                      1 Reply Last reply
                                      0
                                      • PerdrixP Offline
                                        PerdrixP Offline
                                        Perdrix
                                        wrote last edited by Perdrix
                                        #24

                                        Hmm odder and odder:
                                        I did this:

                                        int main(int argc, char *argv[])
                                        {
                                            QApplication a(argc, argv);
                                        
                                            Dialog w;
                                        
                                            QObject::connect(&a, &QApplication::focusChanged, &a,  [](QWidget* old, QWidget* now){
                                                qDebug() << "Old focus widget: " << old;
                                                qDebug() << "New focus widget: " << now;
                                                    }
                                                );
                                        
                                            w.show();
                                            return a.exec();
                                        }
                                        

                                        As far as Qt is concerned when I click on another application, focus leaves the "StopButton" (the one named "Cancel" and the focus widget goes to nullptr. BUT the Progress dlg still jumps to the front and steals focus from the other application the instant that the progress is updated. No focusChanged signal occurs when that happens.

                                        Old focus widget:  QPushButton(0x55d1c44c14a0, name="StopButton")
                                        New focus widget:  QWidget(0x0)
                                        

                                        What on earth is going on here? The application focus (not the individual Widget focus) IS changed when the progress dlg updates the progress bars.

                                        1 Reply Last reply
                                        0
                                        • PerdrixP Offline
                                          PerdrixP Offline
                                          Perdrix
                                          wrote last edited by
                                          #25

                                          As promised here's the code with openmp stuff removed. It's a tar.gz file setup to build on Linux.

                                          https://www.dropbox.com/scl/fi/ullkvjzhr4qod54wuaako/DSS_ProgressDlg.tar.gz?rlkey=hncz5km5tnxt9vy3axzw3koxy&st=iq8zaagq&dl=0

                                          1 Reply Last reply
                                          0

                                          • Login

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