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. Integrating GLib event processing in a Qt/Cocoa Mac application
Forum Update on Monday, May 27th 2025

Integrating GLib event processing in a Qt/Cocoa Mac application

Scheduled Pinned Locked Moved Unsolved General and Desktop
9 Posts 3 Posters 455 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.
  • R Offline
    R Offline
    RJV B
    wrote on 3 Aug 2024, 11:34 last edited by
    #1

    Hi,

    I'm trying to get a Unix desktop Qt application to function properly as a "native" Mac application. Long story short: AFAICT it relies on Qt using a GLib-based event loop.

    The qtbase code suggests that event processing never uses GLib on Q_OS_DARWIN, even when GLib support is built in. Yet the application does work correctly when I start it using the XCB QPA (which can be built on Mac with a little bit of build system tweaking). I have yet to figure out how and why that is (via QGenericUnixEventDispatcher?) but it does show that the application can be functional on the platform.

    From what I gather I will need to make certain that g_main_context_iteration is being called regularly, preferably linked to Qt's own message pump.

    I did find this topic
    https://forum.qt.io/topic/132556/use-gstreamer-gtk-signaling-in-qt-application/3

    that suggests using QEventDispatcherGlib but fails to give examples how to do this. I cannot seem to find a way to obtain a reference to the qApp's QEventLoop.

    Would overloading QApplication::processEvents() with a version that integrates the code from QEventDispatcherGlib::processEvents be a plausible solution, or should I simply follow this QTimer approach (from
    Qt 5.9)?

        QGstreamerBusHelperPrivate(QGstreamerBusHelper *parent, GstBus* bus) :
    [...]
        {
            // glib event loop can be disabled either by env variable or QT_NO_GLIB define, so check the dispacher
            QAbstractEventDispatcher *dispatcher = QCoreApplication::eventDispatcher();
            const bool hasGlib = dispatcher && dispatcher->inherits("QEventDispatcherGlib");
            if (!hasGlib) {
                m_intervalTimer = new QTimer(this);
                m_intervalTimer->setInterval(250);
                connect(m_intervalTimer, SIGNAL(timeout()), SLOT(interval()));
                m_intervalTimer->start();
    

    Other potential mechanisms I can see:

    • QApplication::eventDispatcher::registerTimer() if one exists (but what should the QObject be?)
    • Force the use of a QEventDispatcherGlib eventDispatcher by calling QApplication::setEventDispatcher(new QEventDispatcherGlib) before QApplication app(argc, argv) (?)

    Pointers and suggestions appreciated, thanks!

    NB: I'm using Qt5 in this "retro-computing" project.

    R 2 Replies Last reply 3 Aug 2024, 12:03
    0
    • R RJV B
      3 Aug 2024, 11:34

      Hi,

      I'm trying to get a Unix desktop Qt application to function properly as a "native" Mac application. Long story short: AFAICT it relies on Qt using a GLib-based event loop.

      The qtbase code suggests that event processing never uses GLib on Q_OS_DARWIN, even when GLib support is built in. Yet the application does work correctly when I start it using the XCB QPA (which can be built on Mac with a little bit of build system tweaking). I have yet to figure out how and why that is (via QGenericUnixEventDispatcher?) but it does show that the application can be functional on the platform.

      From what I gather I will need to make certain that g_main_context_iteration is being called regularly, preferably linked to Qt's own message pump.

      I did find this topic
      https://forum.qt.io/topic/132556/use-gstreamer-gtk-signaling-in-qt-application/3

      that suggests using QEventDispatcherGlib but fails to give examples how to do this. I cannot seem to find a way to obtain a reference to the qApp's QEventLoop.

      Would overloading QApplication::processEvents() with a version that integrates the code from QEventDispatcherGlib::processEvents be a plausible solution, or should I simply follow this QTimer approach (from
      Qt 5.9)?

          QGstreamerBusHelperPrivate(QGstreamerBusHelper *parent, GstBus* bus) :
      [...]
          {
              // glib event loop can be disabled either by env variable or QT_NO_GLIB define, so check the dispacher
              QAbstractEventDispatcher *dispatcher = QCoreApplication::eventDispatcher();
              const bool hasGlib = dispatcher && dispatcher->inherits("QEventDispatcherGlib");
              if (!hasGlib) {
                  m_intervalTimer = new QTimer(this);
                  m_intervalTimer->setInterval(250);
                  connect(m_intervalTimer, SIGNAL(timeout()), SLOT(interval()));
                  m_intervalTimer->start();
      

      Other potential mechanisms I can see:

      • QApplication::eventDispatcher::registerTimer() if one exists (but what should the QObject be?)
      • Force the use of a QEventDispatcherGlib eventDispatcher by calling QApplication::setEventDispatcher(new QEventDispatcherGlib) before QApplication app(argc, argv) (?)

      Pointers and suggestions appreciated, thanks!

      NB: I'm using Qt5 in this "retro-computing" project.

      R Offline
      R Offline
      RJV B
      wrote on 3 Aug 2024, 12:03 last edited by
      #2

      @RJV-B said in Integrating GLib event processing in a Qt/Cocoa Mac application:

      • Force the use of a QEventDispatcherGlib eventDispatcher by calling QApplication::setEventDispatcher(new QEventDispatcherGlib) before QApplication app(argc, argv) (?)

      Well, testing that with the Linux version of the app somehow puts it in a state where it doesn't appear to have an event dispatcher at all, or one that doesn't do anything?!

      Yet from looking at QCoreApplicationPrivate::init() there shouldn't be anything different!

      1 Reply Last reply
      0
      • R RJV B
        3 Aug 2024, 11:34

        Hi,

        I'm trying to get a Unix desktop Qt application to function properly as a "native" Mac application. Long story short: AFAICT it relies on Qt using a GLib-based event loop.

        The qtbase code suggests that event processing never uses GLib on Q_OS_DARWIN, even when GLib support is built in. Yet the application does work correctly when I start it using the XCB QPA (which can be built on Mac with a little bit of build system tweaking). I have yet to figure out how and why that is (via QGenericUnixEventDispatcher?) but it does show that the application can be functional on the platform.

        From what I gather I will need to make certain that g_main_context_iteration is being called regularly, preferably linked to Qt's own message pump.

        I did find this topic
        https://forum.qt.io/topic/132556/use-gstreamer-gtk-signaling-in-qt-application/3

        that suggests using QEventDispatcherGlib but fails to give examples how to do this. I cannot seem to find a way to obtain a reference to the qApp's QEventLoop.

        Would overloading QApplication::processEvents() with a version that integrates the code from QEventDispatcherGlib::processEvents be a plausible solution, or should I simply follow this QTimer approach (from
        Qt 5.9)?

            QGstreamerBusHelperPrivate(QGstreamerBusHelper *parent, GstBus* bus) :
        [...]
            {
                // glib event loop can be disabled either by env variable or QT_NO_GLIB define, so check the dispacher
                QAbstractEventDispatcher *dispatcher = QCoreApplication::eventDispatcher();
                const bool hasGlib = dispatcher && dispatcher->inherits("QEventDispatcherGlib");
                if (!hasGlib) {
                    m_intervalTimer = new QTimer(this);
                    m_intervalTimer->setInterval(250);
                    connect(m_intervalTimer, SIGNAL(timeout()), SLOT(interval()));
                    m_intervalTimer->start();
        

        Other potential mechanisms I can see:

        • QApplication::eventDispatcher::registerTimer() if one exists (but what should the QObject be?)
        • Force the use of a QEventDispatcherGlib eventDispatcher by calling QApplication::setEventDispatcher(new QEventDispatcherGlib) before QApplication app(argc, argv) (?)

        Pointers and suggestions appreciated, thanks!

        NB: I'm using Qt5 in this "retro-computing" project.

        R Offline
        R Offline
        RJV B
        wrote on 3 Aug 2024, 13:47 last edited by
        #3

        @RJV-B said in Integrating GLib event processing in a Qt/Cocoa Mac application:

        Would overloading QApplication::processEvents()

        Tried that but my overload doesn't appear to get called?!

        class PVCApplication : public QApplication
        {
            Q_OBJECT
        public:
            PVCApplication(int &argc, char **argv)
                : QApplication(argc, argv)
            {
                gContext = g_main_context_default();
                dispatcher = eventDispatcher();
                qWarning() << Q_FUNC_INFO << "eventDispatcher:" << dispatcher;
                hasGlib = dispatcher && dispatcher->inherits("QEventDispatcherGlib");
            }
        
            static void processEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents)
            {
                qWarning() << Q_FUNC_INFO << hasGlib;
                if (!hasGlib) {
                    g_main_context_iteration(gContext, false);
                }
                QApplication::processEvents(flags);
            }
            static void processEvents(QEventLoop::ProcessEventsFlags flags, int maxtime)
            {
                qWarning() << Q_FUNC_INFO << hasGlib;
                if (!hasGlib) {
                    g_main_context_iteration(gContext, false);
                }
                QApplication::processEvents(flags, maxtime);
            }
        
        private:
            static _GMainContext *gContext;
            QAbstractEventDispatcher *dispatcher = nullptr;
            static bool hasGlib;
        };
        _GMainContext *PVCApplication::gContext = nullptr;
        bool PVCApplication::hasGlib = true;
        
        Christian EhrlicherC 1 Reply Last reply 3 Aug 2024, 14:24
        0
        • R RJV B
          3 Aug 2024, 13:47

          @RJV-B said in Integrating GLib event processing in a Qt/Cocoa Mac application:

          Would overloading QApplication::processEvents()

          Tried that but my overload doesn't appear to get called?!

          class PVCApplication : public QApplication
          {
              Q_OBJECT
          public:
              PVCApplication(int &argc, char **argv)
                  : QApplication(argc, argv)
              {
                  gContext = g_main_context_default();
                  dispatcher = eventDispatcher();
                  qWarning() << Q_FUNC_INFO << "eventDispatcher:" << dispatcher;
                  hasGlib = dispatcher && dispatcher->inherits("QEventDispatcherGlib");
              }
          
              static void processEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents)
              {
                  qWarning() << Q_FUNC_INFO << hasGlib;
                  if (!hasGlib) {
                      g_main_context_iteration(gContext, false);
                  }
                  QApplication::processEvents(flags);
              }
              static void processEvents(QEventLoop::ProcessEventsFlags flags, int maxtime)
              {
                  qWarning() << Q_FUNC_INFO << hasGlib;
                  if (!hasGlib) {
                      g_main_context_iteration(gContext, false);
                  }
                  QApplication::processEvents(flags, maxtime);
              }
          
          private:
              static _GMainContext *gContext;
              QAbstractEventDispatcher *dispatcher = nullptr;
              static bool hasGlib;
          };
          _GMainContext *PVCApplication::gContext = nullptr;
          bool PVCApplication::hasGlib = true;
          
          Christian EhrlicherC Online
          Christian EhrlicherC Online
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on 3 Aug 2024, 14:24 last edited by
          #4

          @RJV-B said in Integrating GLib event processing in a Qt/Cocoa Mac application:

          Tried that but my overload doesn't appear to get called?!

          Because these are static functions - how should they be called from inside the Qt code?

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

          R 1 Reply Last reply 3 Aug 2024, 15:45
          0
          • Christian EhrlicherC Christian Ehrlicher
            3 Aug 2024, 14:24

            @RJV-B said in Integrating GLib event processing in a Qt/Cocoa Mac application:

            Tried that but my overload doesn't appear to get called?!

            Because these are static functions - how should they be called from inside the Qt code?

            R Offline
            R Offline
            RJV B
            wrote on 3 Aug 2024, 15:45 last edited by
            #5

            @Christian-Ehrlicher said in Integrating GLib event processing in a Qt/Cocoa Mac application:

            Because these are static functions - how should they be called from inside the Qt code?

            I'll have to admit that I never tried to overload a static class function before; I simply assumed that C++ had a trick up its sleeve to allow overloading them too.

            I noticed that on Linux the default eventDispatcher is of type QPAEventDispatcherGlib instead of QEventDispatcherGlib. So I tried

                extern QAbstractEventDispatcher *createUnixEventDispatcher();
                QApplication::setEventDispatcher(createUnixEventDispatcher());
                QApplication app(argc, argv);
            

            which does give me a dispatcher of the proper type, but it still doesn't seem to be pumping the GLib event loop at all (Qt's own event processing works).

            I'd really like to avoid using a timer because that will either give too coarse GLib event processing or else burn more CPU than necessary. Plus it's clearly possible to run into race conditions on exit.

            Christian EhrlicherC 1 Reply Last reply 3 Aug 2024, 17:30
            0
            • R RJV B
              3 Aug 2024, 15:45

              @Christian-Ehrlicher said in Integrating GLib event processing in a Qt/Cocoa Mac application:

              Because these are static functions - how should they be called from inside the Qt code?

              I'll have to admit that I never tried to overload a static class function before; I simply assumed that C++ had a trick up its sleeve to allow overloading them too.

              I noticed that on Linux the default eventDispatcher is of type QPAEventDispatcherGlib instead of QEventDispatcherGlib. So I tried

                  extern QAbstractEventDispatcher *createUnixEventDispatcher();
                  QApplication::setEventDispatcher(createUnixEventDispatcher());
                  QApplication app(argc, argv);
              

              which does give me a dispatcher of the proper type, but it still doesn't seem to be pumping the GLib event loop at all (Qt's own event processing works).

              I'd really like to avoid using a timer because that will either give too coarse GLib event processing or else burn more CPU than necessary. Plus it's clearly possible to run into race conditions on exit.

              Christian EhrlicherC Online
              Christian EhrlicherC Online
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on 3 Aug 2024, 17:30 last edited by
              #6

              @RJV-B said in Integrating GLib event processing in a Qt/Cocoa Mac application:

              I'll have to admit that I never tried to overload a static class function before; I simply assumed that C++ had a trick up its sleeve to allow overloading them too.

              You can not overload a static function - basic c++.

              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
              0
              • R Offline
                R Offline
                RJV B
                wrote on 3 Aug 2024, 19:33 last edited by
                #7

                Well, yes. Or rather (I think), a derived class can't override a static member function of a parent class with the same reciprocal effect you get with regular member function. Anyway, now I know, and it's not the topic at hand.

                The sample applications I checked that do work in with PulseAudio in native/Cocoa mode only play or record audio so it's (much) easier for them to use the threaded mainloop mechanism from libpulse.

                I might be able to do that by calling the toplevel GUI functions as slots but it may be easier to just add a "source" (that pumps the glib event loop) to the CoreFoundation main runloop.

                1 Reply Last reply
                0
                • Axel SpoerlA Offline
                  Axel SpoerlA Offline
                  Axel Spoerl
                  Moderators
                  wrote on 4 Aug 2024, 06:21 last edited by Axel Spoerl 8 Apr 2024, 06:22
                  #8

                  While the requirement to have a glib event loop running on macOS feels strange, using a tweaked XCB for that purpose sounds like breaking a butterfly on a wheel.

                  If memory serves well, GStreamer runs an event loop on windows and macOS. You might wanna check their sources and see how it’s done there.

                  Software Engineer
                  The Qt Company, Oslo

                  R 1 Reply Last reply 4 Aug 2024, 10:55
                  0
                  • Axel SpoerlA Axel Spoerl
                    4 Aug 2024, 06:21

                    While the requirement to have a glib event loop running on macOS feels strange, using a tweaked XCB for that purpose sounds like breaking a butterfly on a wheel.

                    If memory serves well, GStreamer runs an event loop on windows and macOS. You might wanna check their sources and see how it’s done there.

                    R Offline
                    R Offline
                    RJV B
                    wrote on 4 Aug 2024, 10:55 last edited by
                    #9

                    @Axel-Spoerl said in Integrating GLib event processing in a Qt/Cocoa Mac application:

                    While the requirement to have a glib event loop running on macOS feels strange, using a tweaked XCB for that purpose sounds like breaking a butterfly on a wheel.

                    Running PulseAudio itself on Mac "feels strange" but this is cross-platform code of course, and Darwin is a Unix so ultimately this software should be more at home there than on MSWin.
                    Who said anything about a tweaked XCB? I had to tweak Qt's build system so it would consider building the X11 components there, but that aside I didn't have to do anything naughty (and at some point the Qt devs were open to incorporating those changes under the principle that any QPA that can build and run on a platform is supported).

                    GStreamer is pure GTk code, and while GTk do offer a "quartz" backend I never experimented with that for various reasons. I'm not expecting to learn much from how they do things. GLib itself has works fine but I get it from MacPorts and haven't looked at how complex their patches are (not very large in any case).

                    After looking at the code of the Cocoa event dispatcher I had hoped I could just add my own CF source and have them be picked up by the observer that has to be in place AFAICT. It's not, so now I'm going to try again to use the threaded GLib mainloop that libpulse also provides and that's used in VLC, QMPlay2 and PortAudio (all those have functional PulseAudio support on Mac). It will mean that I need to modify the "pa callback" functions to execute on the Qt main loop. They do get a userdata pointer of course, current the MainWindow* but I plan to change that to a pointer to a derived QApplication instance with member functions that contain the actual payload. I can't recall doing this before, but I think that a global callback function of the form below should work?

                    void card_cb(const pa_card_info *i, int eol, void *userdata)
                    {
                        if (userdata) {
                            PVCApplication *app = static_cast<PVCApplication*>(userdata);
                            QMetaObject::invokeMethod(app, [=]() { app->card_cb(i, eol); }, Qt::BlockingQueuedConnection);
                        } else {
                            // for being callable on the main thread
                            PVCApplication::instance()->card_cb(i, eol);
                        }
                    }
                    
                    void PVCApplication::card_cb(const pa_card_info *i, int eol)
                    {
                    //    payload code
                    }
                    
                    1 Reply Last reply
                    0

                    1/9

                    3 Aug 2024, 11:34

                    • Login

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