@@ -252,6 +252,20 @@ - (BOOL)acceptsFirstResponder;
252252
253253/* ---------------------------- Python classes ---------------------------- */
254254
255+ // Acquire the GIL, call a method with no args, discarding the result and
256+ // printing any exception.
257+ static void gil_call_method (PyObject* obj, const char * name)
258+ {
259+ PyGILState_STATE gstate = PyGILState_Ensure ();
260+ PyObject* result = PyObject_CallMethod (obj, name, NULL );
261+ if (result) {
262+ Py_DECREF (result);
263+ } else {
264+ PyErr_Print ();
265+ }
266+ PyGILState_Release (gstate);
267+ }
268+
255269static bool backend_inited = false ;
256270
257271static void lazy_init (void ) {
@@ -837,13 +851,13 @@ static CGFloat _get_device_scale(CGContextRef cr)
837851 FigureManager_new, /* tp_new */
838852};
839853
840- @interface NavigationToolbar2Handler : NSObject
841- { PyObject* toolbar;
854+ @interface NavigationToolbar2Handler : NSObject {
855+ PyObject* toolbar;
842856 NSButton * panbutton;
843857 NSButton * zoombutton;
844858}
845859- (NavigationToolbar2Handler*)initWithToolbar : (PyObject*)toolbar ;
846- - (void )installCallbacks : (SEL [7 ])actions forButtons : (NSButton *[7 ])buttons ;
860+ - (void )installCallbacks : (SEL [7 ])actions forButtons : (NSButton *[7 ])buttons ;
847861- (void )home : (id )sender ;
848862- (void )back : (id )sender ;
849863- (void )forward : (id )sender ;
@@ -863,118 +877,43 @@ - (void)save_figure:(id)sender;
863877
864878@implementation NavigationToolbar2Handler
865879- (NavigationToolbar2Handler*)initWithToolbar : (PyObject*)theToolbar
866- { [self init ];
880+ {
881+ [self init ];
867882 toolbar = theToolbar;
868883 return self;
869884}
870885
871- - (void )installCallbacks : (SEL [7 ])actions forButtons : (NSButton *[7 ])buttons
886+ - (void )installCallbacks : (SEL [7 ])actions forButtons : (NSButton *[7 ])buttons
872887{
873888 int i;
874- for (i = 0 ; i < 7 ; i++)
875- {
889+ for (i = 0 ; i < 7 ; i++) {
876890 SEL action = actions[i];
877891 NSButton * button = buttons[i];
878892 [button setTarget: self ];
879893 [button setAction: action];
880- if (action== @selector (pan: )) { panbutton = button; }
881- if (action== @selector (zoom: )) { zoombutton = button; }
894+ if (action == @selector (pan: )) { panbutton = button; }
895+ if (action == @selector (zoom: )) { zoombutton = button; }
882896 }
883897}
884898
885- -(void )home : (id )sender
886- { PyObject* result;
887- PyGILState_STATE gstate;
888- gstate = PyGILState_Ensure ();
889- result = PyObject_CallMethod (toolbar, " home" , " " );
890- if (result)
891- Py_DECREF (result);
892- else
893- PyErr_Print ();
894- PyGILState_Release (gstate);
895- }
896-
897- -(void )back : (id )sender
898- { PyObject* result;
899- PyGILState_STATE gstate;
900- gstate = PyGILState_Ensure ();
901- result = PyObject_CallMethod (toolbar, " back" , " " );
902- if (result)
903- Py_DECREF (result);
904- else
905- PyErr_Print ();
906- PyGILState_Release (gstate);
907- }
908-
909- -(void )forward : (id )sender
910- { PyObject* result;
911- PyGILState_STATE gstate;
912- gstate = PyGILState_Ensure ();
913- result = PyObject_CallMethod (toolbar, " forward" , " " );
914- if (result)
915- Py_DECREF (result);
916- else
917- PyErr_Print ();
918- PyGILState_Release (gstate);
919- }
899+ -(void )home : (id )sender { gil_call_method (toolbar, " home" ); }
900+ -(void )back : (id )sender { gil_call_method (toolbar, " back" ); }
901+ -(void )forward : (id )sender { gil_call_method (toolbar, " forward" ); }
920902
921903-(void )pan : (id )sender
922- { PyObject* result;
923- PyGILState_STATE gstate;
924- if ([sender state ])
925- {
926- if (zoombutton) [zoombutton setState: NO ];
927- }
928- gstate = PyGILState_Ensure ();
929- result = PyObject_CallMethod (toolbar, " pan" , " " );
930- if (result)
931- Py_DECREF (result);
932- else
933- PyErr_Print ();
934- PyGILState_Release (gstate);
904+ {
905+ if ([sender state ]) { [zoombutton setState: NO ]; }
906+ gil_call_method (toolbar, " pan" );
935907}
936908
937909-(void )zoom : (id )sender
938- { PyObject* result;
939- PyGILState_STATE gstate;
940- if ([sender state ])
941- {
942- if (panbutton) [panbutton setState: NO ];
943- }
944- gstate = PyGILState_Ensure ();
945- result = PyObject_CallMethod (toolbar, " zoom" , " " );
946- if (result)
947- Py_DECREF (result);
948- else
949- PyErr_Print ();
950- PyGILState_Release (gstate);
951- }
952-
953- -(void )configure_subplots : (id )sender
954910{
955- PyObject* result;
956- PyGILState_STATE gstate;
957- gstate = PyGILState_Ensure ();
958- result = PyObject_CallMethod (toolbar, " configure_subplots" , NULL );
959- if (result) {
960- Py_DECREF (result);
961- } else {
962- PyErr_Print ();
963- }
964- PyGILState_Release (gstate);
911+ if ([sender state ]) { [panbutton setState: NO ]; }
912+ gil_call_method (toolbar, " zoom" );
965913}
966914
967- -(void )save_figure : (id )sender
968- { PyObject* result;
969- PyGILState_STATE gstate;
970- gstate = PyGILState_Ensure ();
971- result = PyObject_CallMethod (toolbar, " save_figure" , " " );
972- if (result)
973- Py_DECREF (result);
974- else
975- PyErr_Print ();
976- PyGILState_Release (gstate);
977- }
915+ -(void )configure_subplots : (id )sender { gil_call_method (toolbar, " configure_subplots" ); }
916+ -(void )save_figure : (id )sender { gil_call_method (toolbar, " save_figure" ); }
978917@end
979918
980919static PyObject*
@@ -1352,19 +1291,7 @@ - (NSRect)constrainFrameRect:(NSRect)rect toScreen:(NSScreen*)screen
13521291 return suggested;
13531292}
13541293
1355- - (BOOL )closeButtonPressed
1356- {
1357- PyObject* result;
1358- PyGILState_STATE gstate;
1359- gstate = PyGILState_Ensure ();
1360- result = PyObject_CallMethod (manager, " close" , " " );
1361- if (result)
1362- Py_DECREF (result);
1363- else
1364- PyErr_Print ();
1365- PyGILState_Release (gstate);
1366- return YES ;
1367- }
1294+ - (BOOL )closeButtonPressed { gil_call_method (manager, " close" ); }
13681295
13691296- (void )close
13701297{
@@ -1966,15 +1893,7 @@ - (void)flagsChanged:(NSEvent*)event
19661893
19671894static void timer_callback (CFRunLoopTimerRef timer, void * info)
19681895{
1969- PyObject* method = info;
1970- PyGILState_STATE gstate = PyGILState_Ensure ();
1971- PyObject* result = PyObject_CallFunction (method, NULL );
1972- if (result) {
1973- Py_DECREF (result);
1974- } else {
1975- PyErr_Print ();
1976- }
1977- PyGILState_Release (gstate);
1896+ gil_call_method (info, " _on_timer" );
19781897}
19791898
19801899static void context_cleanup (const void * info)
@@ -2013,12 +1932,12 @@ static void context_cleanup(const void* info)
20131932 PyErr_SetString (PyExc_RuntimeError, " _on_timer should be a Python method" );
20141933 goto exit;
20151934 }
2016- Py_INCREF (py_on_timer );
1935+ Py_INCREF (self );
20171936 context.version = 0 ;
20181937 context.retain = NULL ;
20191938 context.release = context_cleanup;
20201939 context.copyDescription = NULL ;
2021- context.info = py_on_timer ;
1940+ context.info = self ;
20221941 timer = CFRunLoopTimerCreate (kCFAllocatorDefault ,
20231942 firstFire,
20241943 interval,
0 commit comments