]> granicus.if.org Git - python/commitdiff
Added PyMac_SetEventHandler which allows you to replace complete event
authorJack Jansen <jack.jansen@cwi.nl>
Fri, 20 Jun 1997 16:18:15 +0000 (16:18 +0000)
committerJack Jansen <jack.jansen@cwi.nl>
Fri, 20 Jun 1997 16:18:15 +0000 (16:18 +0000)
handling in inner loop with python code. Also move (previously
machine independent) PyErr_CheckSignals here, so we can propagate
exceptions in event handling code.

Mac/Python/macglue.c

index 217703627e76e511e80ec7b52ecde6ee2215c4e4..b4db23c4cfde29f4f561c4ded80983c0d209c7de 100644 (file)
@@ -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);
 }
 
 /*