diff --git a/qrenderdoc/Code/Interface/Extensions.h b/qrenderdoc/Code/Interface/Extensions.h index 2ed300b86..ee81d97b9 100644 --- a/qrenderdoc/Code/Interface/Extensions.h +++ b/qrenderdoc/Code/Interface/Extensions.h @@ -338,6 +338,21 @@ struct IMiniQtHelper { typedef std::function WidgetCallback; + DOCUMENT(R"(Invoke a callback on the UI thread. All widget accesses must come from the UI thread, +so if work has been done on the render thread then this function can be used to asynchronously and +safely go back to the UI thread. + +This function is safe to call on the UI thread, but it will synchronously call the callback +immediately before returning. + +.. note:: + No parameters are provided to the callback, it is assumed that the callback will maintain its own + context as needed. + +:param function callback: The callback to invoke on the UI thread. +)"); + virtual void InvokeOntoUIThread(std::function callback) = 0; + // top level widgets DOCUMENT(R"(Creates and returns a top-level widget for creating layouts. diff --git a/qrenderdoc/Code/MiniQtHelper.cpp b/qrenderdoc/Code/MiniQtHelper.cpp index adf9bb301..4d84ec44b 100644 --- a/qrenderdoc/Code/MiniQtHelper.cpp +++ b/qrenderdoc/Code/MiniQtHelper.cpp @@ -58,6 +58,11 @@ MiniQtHelper::~MiniQtHelper() }); } +void MiniQtHelper::InvokeOntoUIThread(std::function callback) +{ + GUIInvoke::call(m_Ctx.GetMainWindow()->Widget(), callback); +} + void MiniQtHelper::AddWidgetCallback(QWidget *widget, QMetaObject::Connection connection) { // remember the connection and delete it python-safely at shutdown if it's still there diff --git a/qrenderdoc/Code/MiniQtHelper.h b/qrenderdoc/Code/MiniQtHelper.h index ca07a6f1c..948b2f0c1 100644 --- a/qrenderdoc/Code/MiniQtHelper.h +++ b/qrenderdoc/Code/MiniQtHelper.h @@ -35,6 +35,8 @@ public: MiniQtHelper(ICaptureContext &ctx); virtual ~MiniQtHelper(); + void InvokeOntoUIThread(std::function callback) override; + QWidget *CreateToplevelWidget(const rdcstr &windowTitle, WidgetCallback closed) override; // widget hierarchy diff --git a/qrenderdoc/Windows/PythonShell.cpp b/qrenderdoc/Windows/PythonShell.cpp index 023c00818..e5ae9ce2e 100644 --- a/qrenderdoc/Windows/PythonShell.cpp +++ b/qrenderdoc/Windows/PythonShell.cpp @@ -85,6 +85,12 @@ struct MiniQtInvoker : ObjectForwarder { MiniQtInvoker(PythonShell *shell, IMiniQtHelper &obj) : ObjectForwarder(shell, obj) {} virtual ~MiniQtInvoker() {} + void InvokeOntoUIThread(std::function callback) + { + // this function is already thread safe since it's invoking, so just call it directly + m_Obj.InvokeOntoUIThread(callback); + } + /////////////////////////////////////////////////////////////////////// // all functions invoke onto the UI thread since they deal with widgets! ///////////////////////////////////////////////////////////////////////