Added PyMac_SetEventHandler which allows you to replace complete event
handling in inner loop with python code. Also move (previously machine independent) PyErr_CheckSignals here, so we can propagate exceptions in event handling code.
This commit is contained in:
parent
d993648ef6
commit
36ed506f09
|
@ -107,7 +107,8 @@ extern FSSpec *mfs_GetFSSpecFSSpec();
|
|||
static int interrupted; /* Set to true when cmd-. seen */
|
||||
static RETSIGTYPE intcatcher Py_PROTO((int));
|
||||
|
||||
static void PyMac_DoYield Py_PROTO((int, int));
|
||||
static int PyMac_DoYield Py_PROTO((int, int));
|
||||
static int PyMac_Yield Py_PROTO((void));
|
||||
|
||||
/*
|
||||
** These are the real scheduling parameters that control what we check
|
||||
|
@ -129,32 +130,6 @@ struct real_sched_param_struct {
|
|||
static struct real_sched_param_struct schedparams =
|
||||
{ 1, MAINLOOP_EVENTMASK, 1, 15, 15, 1, 0};
|
||||
|
||||
#if 0
|
||||
/*
|
||||
** We attempt to be a good citizen by giving up the CPU periodically.
|
||||
** When in the foreground we do this less often and for shorter periods
|
||||
** than when in the background. At this time we also check for events and
|
||||
** pass them off to SIOUX, if compiling with mwerks.
|
||||
** The counts here are in ticks of 1/60th second.
|
||||
** XXXX The initial values here are not based on anything.
|
||||
** FG-python gives up the cpu for 1/60th 5 times per second,
|
||||
** BG-python for .2 second 10 times per second.
|
||||
*/
|
||||
static long interval_fg = 12;
|
||||
static long interval_bg = 6;
|
||||
static long yield_fg = 1;
|
||||
static long yield_bg = 2;
|
||||
static unsigned long lastyield;
|
||||
static int in_foreground;
|
||||
|
||||
/*
|
||||
** When > 0, do full scanning for events (program is not event aware)
|
||||
** when == 0, only scan for Command-period
|
||||
** when < 0, don't do any event scanning
|
||||
*/
|
||||
int PyMac_DoYieldEnabled = 1;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Workaround for sioux/gusi combo: set when we are exiting
|
||||
*/
|
||||
|
@ -175,6 +150,11 @@ struct hook_args {
|
|||
static DlgHookYDUPP myhook_upp;
|
||||
static int upp_inited = 0;
|
||||
|
||||
/*
|
||||
** The python-code event handler
|
||||
*/
|
||||
static PyObject *python_event_handler;
|
||||
|
||||
#ifdef USE_GUSI
|
||||
/*
|
||||
** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
|
||||
|
@ -422,23 +402,31 @@ scan_event_queue(flush)
|
|||
}
|
||||
|
||||
int
|
||||
PyOS_InterruptOccurred()
|
||||
PyErr_CheckSignals()
|
||||
{
|
||||
if (schedparams.enabled) {
|
||||
if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
|
||||
PyMac_Yield();
|
||||
if ( PyMac_Yield() < 0)
|
||||
return -1;
|
||||
schedparams.next_check = (unsigned long)LMGetTicks()
|
||||
+ schedparams.check_interval;
|
||||
if (interrupted) {
|
||||
scan_event_queue(1); /* Eat events up to cmd-. */
|
||||
interrupted = 0;
|
||||
return 1;
|
||||
PyErr_SetNone(PyExc_KeyboardInterrupt);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PyOS_InterruptOccurred()
|
||||
{
|
||||
scan_event_queue(1);
|
||||
return interrupted;
|
||||
}
|
||||
/* Check whether we are in the foreground */
|
||||
int
|
||||
PyMac_InForeground()
|
||||
|
@ -460,19 +448,29 @@ PyMac_InForeground()
|
|||
|
||||
}
|
||||
|
||||
int
|
||||
PyMac_SetEventHandler(PyObject *evh)
|
||||
{
|
||||
if ( evh && python_event_handler ) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
|
||||
return 0;
|
||||
}
|
||||
if ( python_event_handler )
|
||||
Py_DECREF(python_event_handler);
|
||||
if ( evh )
|
||||
Py_INCREF(evh);
|
||||
python_event_handler = evh;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Handle an event, either one found in the mainloop eventhandler or
|
||||
** one passed back from the python program.
|
||||
*/
|
||||
void
|
||||
PyMac_HandleEvent(evp, maycallpython)
|
||||
PyMac_HandleEventIntern(evp)
|
||||
EventRecord *evp;
|
||||
int maycallpython;
|
||||
{
|
||||
|
||||
if ( maycallpython ) {
|
||||
/* To be implemented */
|
||||
}
|
||||
#ifdef __MWERKS__
|
||||
{
|
||||
int siouxdidit;
|
||||
|
@ -493,19 +491,43 @@ PyMac_HandleEvent(evp, maycallpython)
|
|||
}
|
||||
}
|
||||
#endif /* !__MWERKS__ */
|
||||
printf("not handled\n");
|
||||
}
|
||||
|
||||
/*
|
||||
** Handle an event, either through HandleEvent or by passing it to the Python
|
||||
** event handler.
|
||||
*/
|
||||
int
|
||||
PyMac_HandleEvent(evp)
|
||||
EventRecord *evp;
|
||||
{
|
||||
PyObject *rv;
|
||||
|
||||
if ( python_event_handler ) {
|
||||
rv = PyObject_CallFunction(python_event_handler, "(O&)",
|
||||
PyMac_BuildEventRecord, evp);
|
||||
if ( rv )
|
||||
Py_DECREF(rv);
|
||||
else
|
||||
return -1; /* Propagate exception */
|
||||
} else {
|
||||
PyMac_HandleEventIntern(evp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Yield the CPU to other tasks without processing events.
|
||||
*/
|
||||
static void
|
||||
static int
|
||||
PyMac_DoYield(int maxsleep, int maycallpython)
|
||||
{
|
||||
EventRecord ev;
|
||||
int gotone;
|
||||
long latest_time_ready;
|
||||
static int in_here = 0;
|
||||
|
||||
in_here++;
|
||||
/*
|
||||
** First check for interrupts, if wanted.
|
||||
** This sets a flag that will be picked up at an appropriate
|
||||
|
@ -522,27 +544,33 @@ PyMac_DoYield(int maxsleep, int maycallpython)
|
|||
** - don't process events but do yield
|
||||
** - do neither
|
||||
*/
|
||||
if( !schedparams.process_events ) {
|
||||
if( in_here > 1 || !schedparams.process_events ||
|
||||
(python_event_handler && !maycallpython) ) {
|
||||
if ( maxsleep >= 0 ) {
|
||||
SystemTask();
|
||||
}
|
||||
} else {
|
||||
latest_time_ready = LMGetTicks() + maxsleep;
|
||||
while ( maxsleep >= 0 ) {
|
||||
gotone = WaitNextEvent(schedparams.process_events, &ev, 0 /*maxsleep*/, NULL);
|
||||
gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
|
||||
/* Get out quickly if nothing interesting is happening */
|
||||
if ( !gotone || ev.what == nullEvent )
|
||||
break;
|
||||
PyMac_HandleEvent(&ev, maycallpython);
|
||||
if ( PyMac_HandleEvent(&ev) < 0 ) {
|
||||
in_here--;
|
||||
return -1;
|
||||
}
|
||||
maxsleep = latest_time_ready - LMGetTicks();
|
||||
}
|
||||
}
|
||||
in_here--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Process events and/or yield the CPU to other tasks if opportune
|
||||
*/
|
||||
void
|
||||
int
|
||||
PyMac_Yield() {
|
||||
unsigned long maxsleep;
|
||||
|
||||
|
@ -551,7 +579,7 @@ PyMac_Yield() {
|
|||
else
|
||||
maxsleep = schedparams.bg_yield;
|
||||
|
||||
PyMac_DoYield(maxsleep, 1);
|
||||
return PyMac_DoYield(maxsleep, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue