packages feed

hsqml 0.3.2.0 → 0.3.2.1

raw patch · 9 files changed

+112/−21 lines, 9 files

Files

CHANGELOG view
@@ -1,5 +1,12 @@ HsQML - Release History +release-0.3.2.1 - 2014.11.29++  * Added function to shutdown the Qt framework.+  * Fixed intermittent crash on exit under Linux.+  * Fixed reanimated objects being passed to QML as undefined.+  * Fixed typo in the names of implicit property signals.+ release-0.3.2.0 - 2014.11.13    * Added OpenGL canvas support.
cbits/Manager.cpp view
@@ -28,8 +28,20 @@     "ObjectSerial" }; -extern "C" void hsqml_dump_counters()+// This definition overrides a symbol in the GHC RTS+#ifdef HSQML_USE_EXIT_HOOK+#ifdef Q_OS_LINUX // TODO: Test on other platforms.+extern "C" void OnExitHook() {+    if (gManager) {+        gManager->shutdown();+    }+}+#endif+#endif++static void dump_counters()+{     Q_ASSERT (gManager);     if (gManager->checkLogLevel(1)) {         for (int i=0; i<HsQMLManager::TotalCounters; i++) {@@ -60,11 +72,11 @@     , mFreeFun(freeFun)     , mFreeStable(freeStable)     , mOriginalHandler(qcoreVariantHandler())-    , mHookedHandler(*mOriginalHandler)     , mApp(NULL)     , mLock(QMutex::Recursive)     , mRunning(false)     , mRunCount(0)+    , mShutdown(false)     , mStackBase(NULL)     , mStartCb(NULL)     , mJobsCb(NULL)@@ -76,17 +88,13 @@     if (env) {         setLogLevel(QString(env).toInt());     }--    // Set hooked handler functions-    mHookedHandler.construct = &hooked_construct;-    mHookedHandler.clear = &hooked_clear; }  void HsQMLManager::setLogLevel(int ll) {     mLogLevel = ll;     if (ll > 0 && !mAtExit) {-        if (atexit(&hsqml_dump_counters) == 0) {+        if (atexit(&dump_counters) == 0) {             mAtExit = true;         }         else {@@ -183,10 +191,13 @@ {     QMutexLocker locker(&mLock); -    // Check if already running+    // Check for invalid state     if (mRunning) {         return HSQML_EVLOOP_ALREADY_RUNNING;     }+    else if (mShutdown) {+        return HSQML_EVLOOP_POST_SHUTDOWN;+    }      // Check if event loop bound to a different thread     if (mApp && !isEventThread()) {@@ -207,16 +218,8 @@             "Warning: CPU cannot idle when using the non-threaded RTS.");     } -    // Perform one-time initialisation+    // Create application object     if (!mApp) {-        // Install hooked handler for QVariants-        QVariantPrivate::registerHandler(0, &mHookedHandler);--        // Register custom types-        qRegisterMetaType<HsQMLEngineConfig>("HsQMLEngineConfig");-        qmlRegisterType<HsQMLCanvas>("HsQML.Canvas", 1, 0, "HaskellCanvas");--        // Create application object         mApp = new HsQMLManagerApp();     } @@ -329,13 +332,42 @@     QCoreApplication::postEvent(mApp, ev); } +HsQMLManager::EventLoopStatus HsQMLManager::shutdown()+{+    QMutexLocker locker(&mLock);++    if (mRunning) {+        return HSQML_EVLOOP_ALREADY_RUNNING;+    }+    else if (isEventThread()) {+        HSQML_LOG(1, "Deleting QApplication object.");+        delete mApp;+        mApp = NULL;+        mShutdown = true;+    }+    else if (mApp) {+        return HSQML_EVLOOP_WRONG_THREAD; +    }+    return HSQML_EVLOOP_OK;+}+ HsQMLManagerApp::HsQMLManagerApp()     : mArgC(1)     , mArg0(0)     , mArgV(&mArg0)+    , mHookedHandler(*gManager->mOriginalHandler)     , mApp(mArgC, &mArgV) {     mApp.setQuitOnLastWindowClosed(false);++    // Install hooked handler for QVariants+    mHookedHandler.construct = &hooked_construct;+    mHookedHandler.clear = &hooked_clear;+    QVariantPrivate::registerHandler(0, &mHookedHandler);++    // Register custom types+    qRegisterMetaType<HsQMLEngineConfig>("HsQMLEngineConfig");+    qmlRegisterType<HsQMLCanvas>("HsQML.Canvas", 1, 0, "HaskellCanvas"); }  HsQMLManagerApp::~HsQMLManagerApp()@@ -415,6 +447,14 @@ extern "C" void hsqml_evloop_notify_jobs() {     gManager->notifyJobs();+}++extern "C" HsQMLEventLoopStatus hsqml_evloop_shutdown()+{+    if (gManager) {+        return gManager->shutdown();+    }+    return HSQML_EVLOOP_OK; }  extern "C" void hsqml_set_debug_loglevel(int ll)
cbits/Manager.h view
@@ -54,6 +54,7 @@     void setActiveEngine(HsQMLEngine*);     HsQMLEngine* activeEngine();     void postObjectEvent(HsQMLObjectEvent*);+    EventLoopStatus shutdown();  private:     friend class HsQMLManagerApp;@@ -67,11 +68,11 @@     void (*mFreeStable)(HsStablePtr);     QSet<const QObject*> mObjectSet;     const QVariant::Handler* mOriginalHandler;-    QVariant::Handler mHookedHandler;     HsQMLManagerApp* mApp;     QMutex mLock;     bool mRunning;     int mRunCount;+    bool mShutdown;     void* mStackBase;     HsQMLTrivialCb mStartCb;     HsQMLTrivialCb mJobsCb;@@ -113,6 +114,7 @@     int mArgC;     char mArg0;     char* mArgV;+    QVariant::Handler mHookedHandler;     QApplication mApp; }; 
cbits/Object.cpp view
@@ -57,12 +57,16 @@     Q_ASSERT(engine);     if (!mObject) {         mObject = new HsQMLObject(this, engine);-        tryGCLock();          HSQML_LOG(5,             QString().sprintf("New QObject, class=%s, id=%d, qptr=%p.",             mKlass->name(), mSerial, mObject));     }++    // Old objects may have lost their lock via weak references in addition+    // to new objects needing it.+    tryGCLock();+     return mObject; } 
cbits/hsqml.h view
@@ -21,6 +21,7 @@ typedef enum {     HSQML_EVLOOP_OK = 0,     HSQML_EVLOOP_ALREADY_RUNNING,+    HSQML_EVLOOP_POST_SHUTDOWN,     HSQML_EVLOOP_WRONG_THREAD,     HSQML_EVLOOP_NOT_RUNNING,     HSQML_EVLOOP_OTHER_ERROR@@ -36,6 +37,8 @@ extern void hsqml_evloop_release();  extern void hsqml_evloop_notify_jobs();++extern HsQMLEventLoopStatus hsqml_evloop_shutdown();  /* String */ typedef char HsQMLStringHandle;
hsqml.cabal view
@@ -1,5 +1,5 @@ Name:               hsqml-Version:            0.3.2.0+Version:            0.3.2.1 Cabal-version:      >= 1.14 Build-type:         Custom License:            BSD3@@ -35,6 +35,11 @@         Force enable GHCi workaround library if not using shared libraries.     Default: True +Flag UseExitHook+    Description:+        Override the OnExitHook symbol to shutdown the Qt framework on exit.+    Default: True+ Library     Default-language: Haskell2010     Build-depends:@@ -79,6 +84,8 @@     Build-tools: c2hs     if flag(ForceGHCiLib)         X-force-ghci-lib: True+    if flag(UseExitHook)+        CC-options: -DHSQML_USE_EXIT_HOOK     if os(windows) && !flag(UsePkgConfig)         Include-dirs: /QT_ROOT/include         Extra-libraries:
src/Graphics/QML/Engine.hs view
@@ -22,6 +22,7 @@   RunQML(),   runEventLoop,   requireEventLoop,+  shutdownQt,   EventLoopException(),    -- * Document Paths@@ -168,9 +169,31 @@                 Nothing -> return ()     bracket_ reqFn hsqmlEvloopRelease runFn +-- | Shuts down and frees resources used by the Qt framework, preventing+-- further use of the event loop. The framework is initialised when+-- 'runEventLoop' is first called and remains initialised afterwards so that+-- the event loop can be reentered if desired (e.g. when using GHCi). Once+-- shut down, the framework cannot be reinitialised.+--+-- It is recommended that you call this function at the end of your program as+-- this library will try, but cannot guarantee in all configurations to be able+-- to shut it down for you. Failing to shutdown the framework has been known to+-- intermittently cause crashes on process exit on some platforms.+--+-- This function must be called from the event loop thread and the event loop+-- must not be running at the time otherwise an 'EventLoopException' will be+-- thrown.+shutdownQt :: IO ()+shutdownQt = do+    status <- hsqmlEvloopShutdown+    case statusException status of+        Just ex -> throw ex+        Nothing -> return ()+ statusException :: HsQMLEventLoopStatus -> Maybe EventLoopException statusException HsqmlEvloopOk = Nothing statusException HsqmlEvloopAlreadyRunning = Just EventLoopAlreadyRunning+statusException HsqmlEvloopPostShutdown = Just EventLoopPostShutdown statusException HsqmlEvloopWrongThread = Just EventLoopWrongThread statusException HsqmlEvloopNotRunning = Just EventLoopNotRunning statusException _ = Just EventLoopOtherError@@ -178,6 +201,7 @@ -- | Exception type used to report errors pertaining to the event loop. data EventLoopException     = EventLoopAlreadyRunning+    | EventLoopPostShutdown     | EventLoopWrongThread     | EventLoopNotRunning     | EventLoopOtherError
src/Graphics/QML/Internal/BindCore.chs view
@@ -63,6 +63,10 @@   {} ->   `()' #} +{#fun unsafe hsqml_evloop_shutdown as ^+  {} ->+  `HsQMLEventLoopStatus' cIntToEnum #}+ {#fun hsqml_create_engine as ^   {withMaybeHsQMLObjectHandle* `Maybe HsQMLObjectHandle',    id `HsQMLStringHandle',
src/Graphics/QML/Objects.hs view
@@ -150,7 +150,7 @@         impKeys = filter (flip Set.notMember sigKeys) $ mapMaybe memberKey $             filterMembers PropertyMember ms         impMember i k = Member SignalMember-            ("__implictSignal" ++ show i)+            ("__implicitSignal" ++ show i)             tyVoid             []             (\_ _ -> return ())