@@ -107,7 +107,8 @@ extern FSSpec *mfs_GetFSSpecFSSpec();
107107static int interrupted ; /* Set to true when cmd-. seen */
108108static RETSIGTYPE intcatcher Py_PROTO ((int ));
109109
110- static void PyMac_DoYield Py_PROTO ((int , int ));
110+ static int PyMac_DoYield Py_PROTO ((int , int ));
111+ static int PyMac_Yield Py_PROTO ((void ));
111112
112113/*
113114** These are the real scheduling parameters that control what we check
@@ -129,32 +130,6 @@ struct real_sched_param_struct {
129130static struct real_sched_param_struct schedparams =
130131 { 1 , MAINLOOP_EVENTMASK , 1 , 15 , 15 , 1 , 0 };
131132
132- #if 0
133- /*
134- ** We attempt to be a good citizen by giving up the CPU periodically.
135- ** When in the foreground we do this less often and for shorter periods
136- ** than when in the background. At this time we also check for events and
137- ** pass them off to SIOUX, if compiling with mwerks.
138- ** The counts here are in ticks of 1/60th second.
139- ** XXXX The initial values here are not based on anything.
140- ** FG-python gives up the cpu for 1/60th 5 times per second,
141- ** BG-python for .2 second 10 times per second.
142- */
143- static long interval_fg = 12 ;
144- static long interval_bg = 6 ;
145- static long yield_fg = 1 ;
146- static long yield_bg = 2 ;
147- static unsigned long lastyield ;
148- static int in_foreground ;
149-
150- /*
151- ** When > 0, do full scanning for events (program is not event aware)
152- ** when == 0, only scan for Command-period
153- ** when < 0, don't do any event scanning
154- */
155- int PyMac_DoYieldEnabled = 1 ;
156- #endif
157-
158133/*
159134** Workaround for sioux/gusi combo: set when we are exiting
160135*/
@@ -175,6 +150,11 @@ struct hook_args {
175150static DlgHookYDUPP myhook_upp ;
176151static int upp_inited = 0 ;
177152
153+ /*
154+ ** The python-code event handler
155+ */
156+ static PyObject * python_event_handler ;
157+
178158#ifdef USE_GUSI
179159/*
180160** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
@@ -422,23 +402,31 @@ scan_event_queue(flush)
422402}
423403
424404int
425- PyOS_InterruptOccurred ()
405+ PyErr_CheckSignals ()
426406{
427407 if (schedparams .enabled ) {
428408 if ( (unsigned long )LMGetTicks () > schedparams .next_check ) {
429- PyMac_Yield ();
409+ if ( PyMac_Yield () < 0 )
410+ return -1 ;
430411 schedparams .next_check = (unsigned long )LMGetTicks ()
431412 + schedparams .check_interval ;
432413 if (interrupted ) {
433414 scan_event_queue (1 ); /* Eat events up to cmd-. */
434415 interrupted = 0 ;
435- return 1 ;
416+ PyErr_SetNone (PyExc_KeyboardInterrupt );
417+ return -1 ;
436418 }
437419 }
438420 }
439421 return 0 ;
440422}
441423
424+ int
425+ PyOS_InterruptOccurred ()
426+ {
427+ scan_event_queue (1 );
428+ return interrupted ;
429+ }
442430/* Check whether we are in the foreground */
443431int
444432PyMac_InForeground ()
@@ -460,19 +448,29 @@ PyMac_InForeground()
460448
461449}
462450
451+ int
452+ PyMac_SetEventHandler (PyObject * evh )
453+ {
454+ if ( evh && python_event_handler ) {
455+ PyErr_SetString (PyExc_RuntimeError , "Python event handler already set" );
456+ return 0 ;
457+ }
458+ if ( python_event_handler )
459+ Py_DECREF (python_event_handler );
460+ if ( evh )
461+ Py_INCREF (evh );
462+ python_event_handler = evh ;
463+ return 1 ;
464+ }
465+
463466/*
464467** Handle an event, either one found in the mainloop eventhandler or
465468** one passed back from the python program.
466469*/
467470void
468- PyMac_HandleEvent (evp , maycallpython )
471+ PyMac_HandleEventIntern (evp )
469472 EventRecord * evp ;
470- int maycallpython ;
471473{
472-
473- if ( maycallpython ) {
474- /* To be implemented */
475- }
476474#ifdef __MWERKS__
477475 {
478476 int siouxdidit ;
@@ -493,19 +491,43 @@ PyMac_HandleEvent(evp, maycallpython)
493491 }
494492 }
495493#endif /* !__MWERKS__ */
496- printf ("not handled\n" );
494+ }
495+
496+ /*
497+ ** Handle an event, either through HandleEvent or by passing it to the Python
498+ ** event handler.
499+ */
500+ int
501+ PyMac_HandleEvent (evp )
502+ EventRecord * evp ;
503+ {
504+ PyObject * rv ;
505+
506+ if ( python_event_handler ) {
507+ rv = PyObject_CallFunction (python_event_handler , "(O&)" ,
508+ PyMac_BuildEventRecord , evp );
509+ if ( rv )
510+ Py_DECREF (rv );
511+ else
512+ return -1 ; /* Propagate exception */
513+ } else {
514+ PyMac_HandleEventIntern (evp );
515+ }
516+ return 0 ;
497517}
498518
499519/*
500520** Yield the CPU to other tasks without processing events.
501521*/
502- static void
522+ static int
503523PyMac_DoYield (int maxsleep , int maycallpython )
504524{
505525 EventRecord ev ;
506526 int gotone ;
507527 long latest_time_ready ;
528+ static int in_here = 0 ;
508529
530+ in_here ++ ;
509531 /*
510532 ** First check for interrupts, if wanted.
511533 ** This sets a flag that will be picked up at an appropriate
@@ -522,27 +544,33 @@ PyMac_DoYield(int maxsleep, int maycallpython)
522544 ** - don't process events but do yield
523545 ** - do neither
524546 */
525- if ( !schedparams .process_events ) {
547+ if ( in_here > 1 || !schedparams .process_events ||
548+ (python_event_handler && !maycallpython ) ) {
526549 if ( maxsleep >= 0 ) {
527550 SystemTask ();
528551 }
529552 } else {
530553 latest_time_ready = LMGetTicks () + maxsleep ;
531554 while ( maxsleep >= 0 ) {
532- gotone = WaitNextEvent (schedparams .process_events , & ev , 0 /* maxsleep*/ , NULL );
555+ gotone = WaitNextEvent (schedparams .process_events , & ev , maxsleep , NULL );
533556 /* Get out quickly if nothing interesting is happening */
534557 if ( !gotone || ev .what == nullEvent )
535558 break ;
536- PyMac_HandleEvent (& ev , maycallpython );
559+ if ( PyMac_HandleEvent (& ev ) < 0 ) {
560+ in_here -- ;
561+ return -1 ;
562+ }
537563 maxsleep = latest_time_ready - LMGetTicks ();
538564 }
539565 }
566+ in_here -- ;
567+ return 0 ;
540568}
541569
542570/*
543571** Process events and/or yield the CPU to other tasks if opportune
544572*/
545- void
573+ int
546574PyMac_Yield () {
547575 unsigned long maxsleep ;
548576
@@ -551,7 +579,7 @@ PyMac_Yield() {
551579 else
552580 maxsleep = schedparams .bg_yield ;
553581
554- PyMac_DoYield (maxsleep , 1 );
582+ return PyMac_DoYield (maxsleep , 1 );
555583}
556584
557585/*
0 commit comments