Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 36ed506

Browse files
committed
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.
1 parent d993648 commit 36ed506

1 file changed

Lines changed: 71 additions & 43 deletions

File tree

Mac/Python/macglue.c

Lines changed: 71 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ extern FSSpec *mfs_GetFSSpecFSSpec();
107107
static int interrupted; /* Set to true when cmd-. seen */
108108
static 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 {
129130
static 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 {
175150
static DlgHookYDUPP myhook_upp;
176151
static 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

424404
int
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 */
443431
int
444432
PyMac_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
*/
467470
void
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
503523
PyMac_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
546574
PyMac_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

Comments
 (0)