@@ -178,76 +178,129 @@ static int wait_for_stdin(void)
178
178
return 1 ;
179
179
}
180
180
181
- static int set_icon (void )
181
+ PyObject* _get_pdf_icon_path (void )
182
182
{
183
183
PyObject* mpl = PyImport_ImportModule (" matplotlib" );
184
184
if (!mpl)
185
185
{
186
- return - 1 ;
186
+ return NULL ;
187
187
}
188
188
189
189
PyObject* get_data_path = PyObject_GetAttrString (mpl, " get_data_path" );
190
190
if (!get_data_path)
191
191
{
192
- Py_DECREF (mpl);
193
- return - 1 ;
192
+ Py_DECREF (mpl);
193
+ return NULL ;
194
194
}
195
195
196
196
PyObject* arg = PyTuple_New (0 );
197
197
if (!arg)
198
198
{
199
- Py_DECREF (mpl);
200
- Py_DECREF (get_data_path);
201
- return - 1 ;
199
+ Py_DECREF (mpl);
200
+ Py_DECREF (get_data_path);
201
+ return NULL ;
202
202
}
203
203
204
204
PyObject* path = PyObject_Call (get_data_path, arg, NULL );
205
205
if (!path)
206
206
{
207
- Py_DECREF (mpl);
208
- Py_DECREF (get_data_path);
209
- Py_DECREF (arg);
210
- return - 1 ;
207
+ Py_DECREF (mpl);
208
+ Py_DECREF (get_data_path);
209
+ Py_DECREF (arg);
210
+ return NULL ;
211
211
}
212
212
213
213
PyObject* pdf_rel = PyUnicode_FromString (" /images/matplotlib.pdf" );
214
+ if (!pdf_rel)
215
+ {
216
+ Py_DECREF (mpl);
217
+ Py_DECREF (get_data_path);
218
+ Py_DECREF (arg);
219
+ Py_DECREF (path);
220
+ return NULL ;
221
+ }
222
+
214
223
PyObject* pdf_absolute = PyUnicode_Concat (path, pdf_rel);
215
- if (!pdf_absolute)
224
+
225
+ Py_DECREF (mpl);
226
+ Py_DECREF (get_data_path);
227
+ Py_DECREF (arg);
228
+ Py_DECREF (path);
229
+ Py_DECREF (pdf_rel);
230
+
231
+ return pdf_absolute;
232
+ }
233
+
234
+ static PyObject* set_icon (PyObject* ignored, PyObject* path)
235
+ {
236
+ if (!path)
216
237
{
217
- Py_DECREF (mpl);
218
- Py_DECREF (get_data_path);
219
- Py_DECREF (arg);
220
- Py_DECREF (path);
221
- Py_DECREF (pdf_rel);
238
+ PyErr_SetString (PyExc_RuntimeError, " No path passed" );
239
+ return NULL ;
222
240
}
223
241
224
242
Py_ssize_t size;
225
- const char * path_string = PyUnicode_AsUTF8AndSize (pdf_absolute, &size);
243
+ // API indicates Python owns path_string; we don't need to free it
244
+ const char * path_string = PyUnicode_AsUTF8AndSize (path, &size);
226
245
if (!path_string)
227
246
{
228
- Py_DECREF (mpl);
229
- Py_DECREF (get_data_path);
230
- Py_DECREF (arg);
231
- Py_DECREF (path);
232
- Py_DECREF (pdf_rel);
233
- Py_DECREF (pdf_absolute);
234
- return -1 ;
247
+ PyErr_SetString (PyExc_TypeError, " bad argument type, must be UTF-8 "
248
+ " path to icon" );
249
+ return NULL ;
235
250
}
236
251
237
- NSString * path_nsstring =
238
- [[NSString alloc ] initWithUTF8String: path_string];
252
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc ] init ];
239
253
240
- NSImage * image = [[NSImage alloc ] initByReferencingFile: path_nsstring];
254
+ NSImage * image;
255
+ @try
256
+ {
257
+ NSString * path_nsstring =
258
+ [[NSString alloc ] initWithUTF8String: path_string];
241
259
242
- NSApplication * app = [NSApplication sharedApplication ];
243
- app.applicationIconImage = image;
260
+ image =
261
+ [[NSImage alloc ] initByReferencingFile: path_nsstring];
262
+ }
263
+ @catch (NSException *e)
264
+ {
244
265
245
- Py_DECREF (mpl);
246
- Py_DECREF (get_data_path);
247
- Py_DECREF (arg);
248
- Py_DECREF (path);
249
- Py_DECREF (pdf_rel);
250
- Py_DECREF (pdf_absolute);
266
+ PyErr_SetString (PyExc_RuntimeError, " could not load icon" );
267
+ [pool drain ];
268
+ return NULL ;
269
+ }
270
+
271
+ @try
272
+ {
273
+ NSApplication * app = [NSApplication sharedApplication ];
274
+ app.applicationIconImage = image;
275
+ }
276
+ @catch (NSException *e)
277
+ {
278
+ PyErr_SetString (PyExc_RuntimeError, " could not set icon" );
279
+ [pool drain ];
280
+ return NULL ;
281
+ }
282
+
283
+ [pool drain ];
284
+ Py_RETURN_NONE;
285
+ }
286
+
287
+ static int _set_icon (void )
288
+ {
289
+ PyObject* pdf_path = _get_pdf_icon_path ();
290
+ if (!pdf_path)
291
+ {
292
+ return -1 ;
293
+ }
294
+
295
+ PyObject* result = set_icon (NULL , pdf_path);
296
+ if (!result)
297
+ {
298
+ Py_DECREF (pdf_path);
299
+ return -1 ;
300
+ }
301
+
302
+ Py_DECREF (pdf_path);
303
+ Py_DECREF (result);
251
304
return 0 ;
252
305
}
253
306
@@ -813,7 +866,10 @@ static CGFloat _get_device_scale(CGContextRef cr)
813
866
814
867
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc ] init ];
815
868
816
- set_icon ();
869
+ if (_set_icon () != 0 )
870
+ {
871
+ return -1 ;
872
+ }
817
873
818
874
self->window = [self ->window initWithContentRect: rect
819
875
styleMask: NSTitledWindowMask
@@ -2702,6 +2758,11 @@ static bool verify_framework(void)
2702
2758
METH_VARARGS,
2703
2759
" Sets the active cursor."
2704
2760
},
2761
+ {" set_icon" ,
2762
+ set_icon,
2763
+ METH_O,
2764
+ " Sets the Dock icon in macOS"
2765
+ },
2705
2766
{NULL , NULL , 0 , NULL } /* sentinel */
2706
2767
};
2707
2768
0 commit comments