-
Notifications
You must be signed in to change notification settings - Fork 0
/
grab_screen_info.go
135 lines (119 loc) · 4.13 KB
/
grab_screen_info.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package main
/*
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -framework Foundation -framework AppKit
#import <Foundation/Foundation.h>
#import <Appkit/Appkit.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void processWindowInfo(const char** returnValue) {
NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
NSArray<NSDictionary *> *info = CFBridgingRelease(CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID));
NSArray<NSRunningApplication *> *apps = [[workspace runningApplications] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSRunningApplication *app, NSDictionary<NSString *,id> *bindings) {
return (app.activationPolicy == NSApplicationActivationPolicyRegular);
}]];
int order = 0;
NSString *str = [[NSString alloc] initWithString:@""];
for (NSDictionary *dict in info) {
NSNumber *pid = dict[(__bridge NSString *)kCGWindowOwnerPID];
if (pid != nil) {
for (NSRunningApplication *app in apps) {
if ([pid isEqualToNumber:@(app.processIdentifier)] && app.localizedName != nil) {
order += 10;
str = [str stringByAppendingFormat:@"\n\n ---- \n\n AppName = %s; \n pid = %d; \n WindowIsOnScreen = %@; \n Layer = %d \n %@;",
[app.localizedName UTF8String],
app.processIdentifier,
dict[(__bridge NSString *)kCGWindowIsOnscreen] ? @"true" : @"false",
order,
dict[(__bridge NSString *)kCGWindowBounds]
];
}
}
}
}
*returnValue = strdup([str UTF8String]);
[str release];
[info release];
[apps release];
}
*/
import "C"
import (
"bufio"
"encoding/json"
"strconv"
"strings"
"unsafe"
"github.com/sirupsen/logrus"
)
func grabScreenInfo() ([]*ScreenWindow, error) {
cRetValue := C.CString("")
defer C.free(unsafe.Pointer(cRetValue))
C.processWindowInfo(&cRetValue)
str := C.GoString(cRetValue)
scanner := bufio.NewScanner(strings.NewReader(str))
screenWindows := make([]*ScreenWindow, 0)
lineAt := 0
currentSw := &ScreenWindow{}
for scanner.Scan() {
curLine := strings.TrimSpace(scanner.Text())
if strings.Contains(curLine, "----") {
// BREAK and start new
if currentSw.AppName != "" {
screenWindows = append(screenWindows, currentSw)
}
lineAt = 0
currentSw = &ScreenWindow{
Bounds: ScreenWindowBounds{},
}
}
spl := strings.Split(curLine, " = ")
if len(spl) > 1 {
value := strings.TrimRight(strings.TrimSpace(spl[1]), ";")
value = strings.TrimRight(value, "\"") // sometimes ints are in this format "-1250" note -1250
value = strings.TrimLeft(value, "\"")
// this could be a case statement, but i dont know what wierdness might occur, best to check line number and "key"
if lineAt == 2 && strings.TrimSpace(spl[0]) == "AppName" {
currentSw.AppName = value
} else if lineAt == 3 && strings.TrimSpace(spl[0]) == "pid" {
if i, err := strconv.Atoi(value); err == nil {
currentSw.Pid = i
}
} else if lineAt == 5 && strings.TrimSpace(spl[0]) == "Layer" {
if i, err := strconv.Atoi(value); err == nil {
currentSw.Layer = i
}
} else if lineAt == 7 && strings.TrimSpace(spl[0]) == "Height" {
if i, err := strconv.Atoi(value); err == nil {
currentSw.Bounds.Height = i
}
} else if lineAt == 8 && strings.TrimSpace(spl[0]) == "Width" {
if i, err := strconv.Atoi(value); err == nil {
currentSw.Bounds.Width = i
}
} else if lineAt == 9 && strings.TrimSpace(spl[0]) == "X" {
if i, err := strconv.Atoi(value); err == nil {
currentSw.Bounds.X = i
}
} else if lineAt == 10 && strings.TrimSpace(spl[0]) == "Y" {
if i, err := strconv.Atoi(value); err == nil {
currentSw.Bounds.Y = i
}
} else if lineAt == 4 && strings.TrimSpace(spl[0]) == "WindowIsOnScreen" {
currentSw.IsOnScreen = (value == "true")
}
}
lineAt++
}
// grab the last guy
if currentSw.AppName != "" {
screenWindows = append(screenWindows, currentSw)
}
b, err := json.Marshal(screenWindows)
if err != nil {
return nil, err
}
logrus.Info(string(b))
return screenWindows, nil
}