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:
Jack Jansen 1997-06-20 16:18:15 +00:00
parent d993648ef6
commit 36ed506f09

View file

@ -107,7 +107,8 @@ extern FSSpec *mfs_GetFSSpecFSSpec();
static int interrupted; /* Set to true when cmd-. seen */ static int interrupted; /* Set to true when cmd-. seen */
static RETSIGTYPE intcatcher Py_PROTO((int)); 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 ** 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 = static struct real_sched_param_struct schedparams =
{ 1, MAINLOOP_EVENTMASK, 1, 15, 15, 1, 0}; { 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 ** Workaround for sioux/gusi combo: set when we are exiting
*/ */
@ -175,6 +150,11 @@ struct hook_args {
static DlgHookYDUPP myhook_upp; static DlgHookYDUPP myhook_upp;
static int upp_inited = 0; static int upp_inited = 0;
/*
** The python-code event handler
*/
static PyObject *python_event_handler;
#ifdef USE_GUSI #ifdef USE_GUSI
/* /*
** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of ** 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 int
PyOS_InterruptOccurred() PyErr_CheckSignals()
{ {
if (schedparams.enabled) { if (schedparams.enabled) {
if ( (unsigned long)LMGetTicks() > schedparams.next_check ) { if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
PyMac_Yield(); if ( PyMac_Yield() < 0)
return -1;
schedparams.next_check = (unsigned long)LMGetTicks() schedparams.next_check = (unsigned long)LMGetTicks()
+ schedparams.check_interval; + schedparams.check_interval;
if (interrupted) { if (interrupted) {
scan_event_queue(1); /* Eat events up to cmd-. */ scan_event_queue(1); /* Eat events up to cmd-. */
interrupted = 0; interrupted = 0;
return 1; PyErr_SetNone(PyExc_KeyboardInterrupt);
return -1;
} }
} }
} }
return 0; return 0;
} }
int
PyOS_InterruptOccurred()
{
scan_event_queue(1);
return interrupted;
}
/* Check whether we are in the foreground */ /* Check whether we are in the foreground */
int int
PyMac_InForeground() 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 ** Handle an event, either one found in the mainloop eventhandler or
** one passed back from the python program. ** one passed back from the python program.
*/ */
void void
PyMac_HandleEvent(evp, maycallpython) PyMac_HandleEventIntern(evp)
EventRecord *evp; EventRecord *evp;
int maycallpython;
{ {
if ( maycallpython ) {
/* To be implemented */
}
#ifdef __MWERKS__ #ifdef __MWERKS__
{ {
int siouxdidit; int siouxdidit;
@ -493,19 +491,43 @@ PyMac_HandleEvent(evp, maycallpython)
} }
} }
#endif /* !__MWERKS__ */ #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. ** Yield the CPU to other tasks without processing events.
*/ */
static void static int
PyMac_DoYield(int maxsleep, int maycallpython) PyMac_DoYield(int maxsleep, int maycallpython)
{ {
EventRecord ev; EventRecord ev;
int gotone; int gotone;
long latest_time_ready; long latest_time_ready;
static int in_here = 0;
in_here++;
/* /*
** First check for interrupts, if wanted. ** First check for interrupts, if wanted.
** This sets a flag that will be picked up at an appropriate ** 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 ** - don't process events but do yield
** - do neither ** - do neither
*/ */
if( !schedparams.process_events ) { if( in_here > 1 || !schedparams.process_events ||
(python_event_handler && !maycallpython) ) {
if ( maxsleep >= 0 ) { if ( maxsleep >= 0 ) {
SystemTask(); SystemTask();
} }
} else { } else {
latest_time_ready = LMGetTicks() + maxsleep; latest_time_ready = LMGetTicks() + maxsleep;
while ( maxsleep >= 0 ) { 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 */ /* Get out quickly if nothing interesting is happening */
if ( !gotone || ev.what == nullEvent ) if ( !gotone || ev.what == nullEvent )
break; break;
PyMac_HandleEvent(&ev, maycallpython); if ( PyMac_HandleEvent(&ev) < 0 ) {
in_here--;
return -1;
}
maxsleep = latest_time_ready - LMGetTicks(); maxsleep = latest_time_ready - LMGetTicks();
} }
} }
in_here--;
return 0;
} }
/* /*
** Process events and/or yield the CPU to other tasks if opportune ** Process events and/or yield the CPU to other tasks if opportune
*/ */
void int
PyMac_Yield() { PyMac_Yield() {
unsigned long maxsleep; unsigned long maxsleep;
@ -551,7 +579,7 @@ PyMac_Yield() {
else else
maxsleep = schedparams.bg_yield; maxsleep = schedparams.bg_yield;
PyMac_DoYield(maxsleep, 1); return PyMac_DoYield(maxsleep, 1);
} }
/* /*