-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgeticon_darwin.go
105 lines (87 loc) · 2.2 KB
/
geticon_darwin.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//go:build darwin
// +build darwin
package geticon
/*
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -framework AppKit
#import <stdlib.h>
#import <AppKit/NSImage.h>
#import <AppKit/NSRunningApplication.h>
int getIcon(NSImage *appIcon, void **img, int *imglen) {
NSData *tiffData = [appIcon TIFFRepresentation];
[appIcon release];
*imglen = (int) [tiffData length];
*img = malloc(*imglen);
if (*img == NULL) {
[tiffData release];
return 1;
}
memcpy(*img, [tiffData bytes], *imglen);
[tiffData release];
return 0;
}
int getIconFromPid(pid_t pid, void **img, int *imglen) {
NSRunningApplication *app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
if (app == nil) {
return 1;
}
NSImage *appIcon = [app icon];
if (appIcon == nil) {
[app release];
return 1;
}
[app release];
return getIcon(appIcon, img, imglen);
}
int getIconFromPath(char* path, void** img, int *imglen) {
NSString *bundlePath = [NSString stringWithUTF8String:path];
NSImage *appIcon = [[NSWorkspace sharedWorkspace] iconForFile:bundlePath];
if (appIcon == nil) {
return 1;
}
return getIcon(appIcon, img, imglen);
}
*/
import "C"
import (
"bytes"
"fmt"
"image"
"unsafe"
"golang.org/x/image/tiff"
)
// FromPath returns the app icon app at the specified path.
func FromPath(appPath string) (image.Image, error) {
var imgLen C.int
var imgPntr unsafe.Pointer
cPath := C.CString(appPath)
defer C.free(unsafe.Pointer(cPath))
errCode := C.getIconFromPath(cPath, &imgPntr, &imgLen)
if errCode != 0 {
return nil, fmt.Errorf("failed to gather icon")
}
defer C.free(imgPntr)
imgData := cToGoSlice(imgPntr, int(imgLen))
img, err := tiff.Decode(bytes.NewReader(imgData))
if err != nil {
return nil, err
}
return img, nil
}
// FromPid returns the app icon of the app currently running
// on the given pid.
func FromPid(pid uint32) (image.Image, error) {
var imgLen C.int
var imgPntr unsafe.Pointer
errCode := C.getIconFromPid(C.pid_t(pid), &imgPntr, &imgLen)
if errCode != 0 {
return nil, fmt.Errorf("failed to gather icon")
}
defer C.free(imgPntr)
imgData := cToGoSlice(imgPntr, int(imgLen))
img, err := tiff.Decode(bytes.NewReader(imgData))
if err != nil {
return nil, err
}
return img, nil
}