summaryrefslogtreecommitdiffstats
path: root/Mac/Python
diff options
context:
space:
mode:
authorJack Jansen <jack.jansen@cwi.nl>1997-06-20 16:18:15 (GMT)
committerJack Jansen <jack.jansen@cwi.nl>1997-06-20 16:18:15 (GMT)
commit36ed506f09b0b73d6d99341541f2dbc4b89ffe99 (patch)
tree2be46594fa36d775da0a492701cc3637912f9c00 /Mac/Python
parentd993648ef6f9e76cf847dfc8f66904f76c621894 (diff)
downloadcpython-36ed506f09b0b73d6d99341541f2dbc4b89ffe99.zip
cpython-36ed506f09b0b73d6d99341541f2dbc4b89ffe99.tar.gz
cpython-36ed506f09b0b73d6d99341541f2dbc4b89ffe99.tar.bz2
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.
Diffstat (limited to 'Mac/Python')
-rw-r--r--Mac/Python/macglue.c114
1 files changed, 71 insertions, 43 deletions
diff --git a/Mac/Python/macglue.c b/Mac/Python/macglue.c
index 2177036..b4db23c 100644
--- a/Mac/Python/macglue.c
+++ b/Mac/Python/macglue.c
@@ -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);
}
/*