Skip to content

Commit 1704573

Browse files
committed
Set the app icon in the MacOsX manager
1 parent 25a54a4 commit 1704573

File tree

2 files changed

+73
-6
lines changed

2 files changed

+73
-6
lines changed

lib/matplotlib/backends/backend_macosx.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ class FigureManagerMac(_macosx.FigureManager, FigureManagerBase):
6666
Wrap everything up into a window for the pylab interface
6767
"""
6868
def __init__(self, canvas, num):
69-
_macosx.FigureManager.__init__(self, canvas)
69+
icon_path = None
70+
if 'com.adobe.pdf' in _macosx.FigureManager._get_image_types():
71+
icon_path = str(cbook._get_data_path('images/matplotlib.pdf'))
72+
_macosx.FigureManager.__init__(self, canvas, icon_path)
7073
FigureManagerBase.__init__(self, canvas, num)
7174
if mpl.rcParams['toolbar'] == 'toolbar2':
7275
self.toolbar = NavigationToolbar2Mac(canvas)

src/_macosx.m

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <objc/NSObjCRuntime.h>
12
#define PY_SSIZE_T_CLEAN
23
#include <Cocoa/Cocoa.h>
34
#include <ApplicationServices/ApplicationServices.h>
@@ -629,6 +630,39 @@ static CGFloat _get_device_scale(CGContextRef cr)
629630
return (PyObject*)self;
630631
}
631632

633+
int set_icon(PyObject* icon_path) {
634+
if (!icon_path) {
635+
return 0;
636+
}
637+
const char* icon_path_ptr = PyUnicode_AsUTF8(icon_path);
638+
if (!icon_path_ptr) {
639+
Py_DECREF(icon_path);
640+
return -1;
641+
}
642+
NSString* ns_icon_path = [NSString stringWithUTF8String: icon_path_ptr];
643+
if (!ns_icon_path) {
644+
Py_DECREF(icon_path);
645+
PyErr_SetString(PyExc_RuntimeError, "Could not convert to NSString*");
646+
return -1;
647+
}
648+
NSImage* image = [[NSImage alloc] initByReferencingFile: ns_icon_path];
649+
[ns_icon_path release];
650+
if (!image) {
651+
PyErr_SetString(PyExc_RuntimeError, "Could not create NSImage*");
652+
[image release];
653+
return -1;
654+
}
655+
if (!image.valid) {
656+
PyErr_SetString(PyExc_RuntimeError, "Image is not valid");
657+
[image release];
658+
return -1;
659+
}
660+
NSApplication* app = [NSApplication sharedApplication];
661+
app.applicationIconImage = image;
662+
[image release];
663+
return 0;
664+
}
665+
632666
static int
633667
FigureManager_init(FigureManager *self, PyObject *args, PyObject *kwds)
634668
{
@@ -637,24 +671,32 @@ static CGFloat _get_device_scale(CGContextRef cr)
637671
View* view;
638672
PyObject* size;
639673
int width, height;
640-
PyObject* obj;
641674
FigureCanvas* canvas;
675+
PyObject* icon_path;
642676

643677
if (!self->window) {
644678
PyErr_SetString(PyExc_RuntimeError, "NSWindow* is NULL");
645679
return -1;
646680
}
681+
static char* kwlist[3] = { "canvas", "icon_path", NULL };
682+
icon_path = NULL;
683+
if (!PyArg_ParseTupleAndKeywords(args, kwds,
684+
"O!|O&", kwlist,
685+
&FigureCanvasType, &canvas,
686+
&PyUnicode_FSDecoder, &icon_path)) {
687+
return -1;
688+
}
689+
if (set_icon(icon_path)) {
690+
return -1;
691+
}
647692

648-
if (!PyArg_ParseTuple(args, "O", &obj)) { return -1; }
649-
650-
canvas = (FigureCanvas*)obj;
651693
view = canvas->view;
652694
if (!view) { /* Something really weird going on */
653695
PyErr_SetString(PyExc_RuntimeError, "NSView* is NULL");
654696
return -1;
655697
}
656698

657-
size = PyObject_CallMethod(obj, "get_width_height", "");
699+
size = PyObject_CallMethod((PyObject*)canvas, "get_width_height", "");
658700
if (!size) { return -1; }
659701
if (!PyArg_ParseTuple(size, "ii", &width, &height)) {
660702
Py_DECREF(size);
@@ -778,6 +820,23 @@ static CGFloat _get_device_scale(CGContextRef cr)
778820
Py_RETURN_NONE;
779821
}
780822

823+
static PyObject*
824+
FigureManager__get_image_types(PyObject* no_self, PyObject* no_args)
825+
{
826+
NSArray<NSString*>* images = NSImage.imageUnfilteredTypes;
827+
const NSUInteger n_images = [images count];
828+
PyObject* out = PyList_New(n_images);
829+
if (!out) {
830+
[images release];
831+
return NULL;
832+
}
833+
for (NSUInteger i=0; i < n_images; ++i) {
834+
const char* string = images[i].UTF8String;
835+
PyList_SET_ITEM(out, i, PyUnicode_FromString(string));
836+
}
837+
return out;
838+
}
839+
781840
static PyMethodDef FigureManager_methods[] = {
782841
{"show",
783842
(PyCFunction)FigureManager_show,
@@ -804,6 +863,11 @@ static CGFloat _get_device_scale(CGContextRef cr)
804863
METH_VARARGS,
805864
NULL, // docstring inherited.
806865
},
866+
{"_get_image_types",
867+
FigureManager__get_image_types,
868+
METH_STATIC | METH_NOARGS,
869+
"Return image types supported by macOS"
870+
},
807871
{NULL} /* Sentinel */
808872
};
809873

0 commit comments

Comments
 (0)