Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit 56b7a57

Browse files
committed
[[ WidgetContext ]] Update widget context on entry/exit to widget handlers
This patch moves the code which stacks up the current widget state from widget-ref.cpp to callbacks invoked by libscript. Before a widget handler is called, the Entry callback is called allowing MCcurrentwidget and the execution lock to be taken. After a widget handler is called, the Leave callback is called allowing MCcurrentwidget to be reset and execution lock to be removed.
1 parent cc69e64 commit 56b7a57

6 files changed

Lines changed: 106 additions & 54 deletions

File tree

engine/src/widget-ref.cpp

Lines changed: 38 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ bool MCWidgetBase::Create(MCNameRef p_kind)
8484
if (!MCScriptCreateInstanceOfModule(t_module, m_instance))
8585
return false;
8686

87+
MCScriptSetInstanceHostPtr(m_instance, AsWidget());
88+
8789
if (!DispatchRestricted(MCNAME("OnCreate")))
8890
{
8991
MCScriptReleaseInstance(m_instance);
@@ -153,46 +155,12 @@ bool MCWidgetBase::HasHandler(MCNameRef p_handler)
153155

154156
bool MCWidgetBase::SetProperty(MCNameRef p_property, MCValueRef p_value)
155157
{
156-
MCWidgetRef t_old_widget;
157-
t_old_widget = MCcurrentwidget;
158-
MCcurrentwidget = AsWidget();
159-
160-
MCWidget *t_host;
161-
t_host = GetHost();
162-
if (t_host != nil)
163-
t_host -> lockforexecution();
164-
165-
bool t_success;
166-
t_success = MCScriptSetPropertyInInstance(m_instance, p_property, p_value);
167-
168-
if (t_host != nil)
169-
t_host -> unlockforexecution();
170-
171-
MCcurrentwidget = t_old_widget;
172-
173-
return t_success;
158+
return MCScriptSetPropertyInInstance(m_instance, p_property, p_value);
174159
}
175160

176161
bool MCWidgetBase::GetProperty(MCNameRef p_property, MCValueRef& r_value)
177162
{
178-
MCWidgetRef t_old_widget;
179-
t_old_widget = MCcurrentwidget;
180-
MCcurrentwidget = AsWidget();
181-
182-
MCWidget *t_host;
183-
t_host = GetHost();
184-
if (t_host != nil)
185-
t_host -> lockforexecution();
186-
187-
bool t_success;
188-
t_success = MCScriptGetPropertyInInstance(m_instance, p_property, r_value);
189-
190-
if (t_host != nil)
191-
t_host -> unlockforexecution();
192-
193-
MCcurrentwidget = t_old_widget;
194-
195-
return t_success;
163+
return MCScriptGetPropertyInInstance(m_instance, p_property, r_value);
196164
}
197165

198166
static bool chunk_property_handler(MCNameRef p_property, MCNameRef p_chunk_name, bool p_is_get_operation, MCNameRef& r_handler)
@@ -848,34 +816,16 @@ MCGRectangle MCWidgetBase::MapRectFromGlobal(MCGRectangle rect)
848816

849817
bool MCWidgetBase::DoDispatch(MCNameRef p_event, MCValueRef *x_args, uindex_t p_arg_count, MCValueRef *r_result)
850818
{
851-
MCWidgetRef t_old_widget_object;
852-
t_old_widget_object = MCcurrentwidget;
853-
MCcurrentwidget = AsWidget();
854-
855-
// Make sure the host object's 'scriptdepth' is incremented and
856-
// decremented appropriately. This prevents script from deleting
857-
// a widget which has its LCB code on the stack (just as it would if
858-
// it had its LCS code on the stack).
859-
MCWidget *t_host;
860-
t_host = GetHost();
861-
if (t_host != nil)
862-
t_host -> lockforexecution();
863-
864819
bool t_success;
865820
MCAutoValueRef t_retval;
866821
t_success = MCScriptCallHandlerInInstanceIfFound(m_instance, p_event, x_args, p_arg_count, &t_retval);
867822

868-
if (t_host != nil)
869-
t_host -> unlockforexecution();
870-
871823
if (t_success)
872824
{
873825
if (r_result != NULL)
874826
*r_result = t_retval . Take();
875827
}
876828

877-
MCcurrentwidget = t_old_widget_object;
878-
879829
return t_success;
880830

881831
}
@@ -1501,3 +1451,37 @@ MCWidgetRoot *MCWidgetAsRoot(MCWidgetRef self)
15011451
}
15021452

15031453
////////////////////////////////////////////////////////////////////////////////
1454+
1455+
void *MCWidgetEnter(MCScriptInstanceRef p_instance, void *p_host_ptr)
1456+
{
1457+
void *t_cookie = MCcurrentwidget;
1458+
1459+
auto t_widget = static_cast<MCWidgetRef>(p_host_ptr);
1460+
1461+
// Make sure the host object's 'scriptdepth' is incremented and
1462+
// decremented appropriately. This prevents script from deleting
1463+
// a widget which has its LCB code on the stack (just as it would if
1464+
// it had its LCS code on the stack).
1465+
MCWidget *t_host = MCWidgetAsBase(t_widget)->GetHost();
1466+
if (t_host != nullptr)
1467+
t_host->lockforexecution();
1468+
1469+
// Update the current widget context
1470+
MCcurrentwidget = t_widget;
1471+
1472+
return t_cookie;
1473+
}
1474+
1475+
void MCWidgetLeave(MCScriptInstanceRef p_instance, void *p_host_ptr, void *p_cookie)
1476+
{
1477+
auto t_old_widget = static_cast<MCWidgetRef>(p_cookie);
1478+
MCcurrentwidget = t_old_widget;
1479+
1480+
auto t_widget = static_cast<MCWidgetRef>(p_host_ptr);
1481+
1482+
MCWidget *t_host = MCWidgetAsBase(t_widget)->GetHost();
1483+
if (t_host != nullptr)
1484+
t_host->unlockforexecution();
1485+
}
1486+
1487+
////////////////////////////////////////////////////////////////////////////////

engine/src/widget-ref.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@ MCWidgetBase *MCWidgetAsBase(MCWidgetRef widget);
214214
MCWidgetRoot *MCWidgetAsRoot(MCWidgetRef widget);
215215
MCWidgetChild *MCWidgetAsChild(MCWidgetRef widget);
216216

217+
void *MCWidgetEnter(MCScriptInstanceRef instance, void *host_ptr);
218+
void MCWidgetLeave(MCScriptInstanceRef instance, void *host_ptr, void *cookie);
219+
217220
////////////////////////////////////////////////////////////////////////////////
218221

219222
extern MCWidgetRef MCcurrentwidget;

engine/src/widget.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ void MCWidget::bind(MCNameRef p_kind, MCValueRef p_rep)
111111
bool t_success;
112112
t_success = true;
113113

114+
// Make sure we set the widget barrier callbacks - this should be done in
115+
// module init for 'extension' when we have such a mechanism.
116+
MCScriptSetWidgetBarrierCallbacks(MCWidgetEnter, MCWidgetLeave);
117+
114118
// Create a new root widget.
115119
if (t_success)
116120
t_success = MCWidgetCreateRoot(this, p_kind, m_widget);

libscript/include/libscript/script.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,18 @@ typedef bool (*MCScriptForEachBuiltinModuleCallback)(void *p_context, MCScriptMo
4343

4444
typedef bool (*MCScriptLoadLibraryCallback)(MCScriptModuleRef module, MCStringRef name, MCSLibraryRef& r_library);
4545

46+
typedef void *(*MCScriptWidgetEnterCallback)(MCScriptInstanceRef instance, void *host_ptr);
47+
typedef void (*MCScriptWidgetLeaveCallback)(MCScriptInstanceRef instance, void *host_ptr, void* p_cookie);
48+
4649
bool MCScriptInitialize(void);
4750
void MCScriptFinalize(void);
4851

4952
bool MCScriptForEachBuiltinModule(MCScriptForEachBuiltinModuleCallback p_callback, void *p_context);
5053

5154
void MCScriptSetLoadLibraryCallback(MCScriptLoadLibraryCallback callback);
5255

56+
void MCScriptSetWidgetBarrierCallbacks(MCScriptWidgetEnterCallback entry_callback, MCScriptWidgetLeaveCallback leave_callback);
57+
5358
////////////////////////////////////////////////////////////////////////////////
5459

5560
// Packages are a collection of modules which share a common set of foreign
@@ -256,6 +261,13 @@ MCScriptInstanceRef MCScriptRetainInstance(MCScriptInstanceRef instance);
256261
// Release a instance.
257262
void MCScriptReleaseInstance(MCScriptInstanceRef instance);
258263

264+
// Sets a private pointer unused by libscript, but passed to the entry/exit
265+
// callbacks.
266+
void MCScriptSetInstanceHostPtr(MCScriptInstanceRef instance, void *state_ptr);
267+
268+
// Gets the host ptr.
269+
void *MCScriptGetInstanceHostPtr(MCScriptInstanceRef instance);
270+
259271
// Get the module of an instance.
260272
MCScriptModuleRef MCScriptGetModuleOfInstance(MCScriptInstanceRef instance);
261273

libscript/src/script-instance.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@
3131
// code can get some element of context.
3232
static MCScriptModuleRef s_current_module = nil;
3333

34+
static MCScriptWidgetEnterCallback s_widget_enter_callback = nullptr;
35+
static MCScriptWidgetLeaveCallback s_widget_leave_callback = nullptr;
36+
37+
void
38+
MCScriptSetWidgetBarrierCallbacks(MCScriptWidgetEnterCallback p_entry,
39+
MCScriptWidgetLeaveCallback p_leave)
40+
{
41+
s_widget_enter_callback = p_entry;
42+
s_widget_leave_callback = p_leave;
43+
}
44+
3445
////////////////////////////////////////////////////////////////////////////////
3546

3647
bool
@@ -167,6 +178,20 @@ MCScriptReleaseInstance(MCScriptInstanceRef self)
167178

168179
////////////////////////////////////////////////////////////////////////////////
169180

181+
void
182+
MCScriptSetInstanceHostPtr(MCScriptInstanceRef self, void *p_host_ptr)
183+
{
184+
self->host_ptr = p_host_ptr;
185+
}
186+
187+
void *
188+
MCScriptGetInstanceHostPtr(MCScriptInstanceRef self)
189+
{
190+
return self->host_ptr;
191+
}
192+
193+
////////////////////////////////////////////////////////////////////////////////
194+
170195
MCScriptModuleRef
171196
MCScriptGetModuleOfInstance(MCScriptInstanceRef self)
172197
{
@@ -196,6 +221,17 @@ __MCScriptCallHandlerDefinitionInInstance(MCScriptInstanceRef self,
196221
uindex_t p_argument_count,
197222
MCValueRef* r_value)
198223
{
224+
void *t_cookie = nullptr;
225+
226+
if (self->module->module_kind == kMCScriptModuleKindWidget)
227+
{
228+
if (s_widget_enter_callback != nullptr)
229+
{
230+
t_cookie = s_widget_enter_callback(self,
231+
self->host_ptr);
232+
}
233+
}
234+
199235
MCScriptExecuteContext t_execute_ctxt;
200236
t_execute_ctxt.Enter(self,
201237
p_handler_def,
@@ -207,6 +243,16 @@ __MCScriptCallHandlerDefinitionInInstance(MCScriptInstanceRef self,
207243
MCScriptBytecodeExecute(t_execute_ctxt);
208244
}
209245

246+
if (self->module->module_kind == kMCScriptModuleKindWidget)
247+
{
248+
if (s_widget_leave_callback != nullptr)
249+
{
250+
s_widget_leave_callback(self,
251+
self->host_ptr,
252+
t_cookie);
253+
}
254+
}
255+
210256
if (!t_execute_ctxt.Leave())
211257
{
212258
return false;

libscript/src/script-private.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,9 @@ struct MCScriptInstance: public MCScriptObject
504504
// MCHandlerRef. The MCHandlerRefs are freed when the instance is freed.
505505
MCScriptHandlerValue *handlers;
506506
uindex_t handler_count;
507+
508+
// The private host ptr, ignored by libscript but can be used by the host.
509+
void *host_ptr;
507510
};
508511

509512
void

0 commit comments

Comments
 (0)