This repository was archived by the owner on May 3, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 82
Expand file tree
/
Copy pathdata.go
More file actions
179 lines (158 loc) · 4.64 KB
/
data.go
File metadata and controls
179 lines (158 loc) · 4.64 KB
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package thyme
import (
"bytes"
"fmt"
"strings"
"time"
)
// Tracker tracks application usage. An implementation that satisfies
// this interface is required for each OS windowing system Thyme
// supports.
type Tracker interface {
// Snap returns a Snapshot reflecting the currently in-use windows
// at the current time.
Snap() (*Snapshot, error)
// Deps returns a string listing the dependencies that still need
// to be installed with instructions for how to install them.
Deps() string
}
// Stream represents all the sampling data gathered by Thyme.
type Stream struct {
// Snapshots is a list of window snapshots ordered by time.
Snapshots []*Snapshot
}
// Print returns a pretty-printed representation of the snapshot.
func (s Stream) Print() string {
var b bytes.Buffer
for _, snap := range s.Snapshots {
fmt.Fprintf(&b, "%s", snap.Print())
}
return string(b.Bytes())
}
// Snapshot represents the current state of all in-use application
// windows at a moment in time.
type Snapshot struct {
Time time.Time
Windows []*Window
Active int64
Visible []int64
}
// Print returns a pretty-printed representation of the snapshot.
func (s Snapshot) Print() string {
var b bytes.Buffer
var active *Window
visible := make([]*Window, 0, len(s.Windows))
other := make([]*Window, 0, len(s.Windows))
s_Windows:
for _, w := range s.Windows {
if w.ID == s.Active {
active = w
continue s_Windows
}
for _, v := range s.Visible {
if w.ID == v {
visible = append(visible, w)
continue s_Windows
}
}
other = append(other, w)
}
fmt.Fprintf(&b, "%s\n", s.Time.Format("Mon Jan 2 15:04:05 -0700 MST 2006"))
if active != nil {
fmt.Fprintf(&b, "\tActive: %s\n", active.Info().Print())
}
if len(visible) > 0 {
fmt.Fprintf(&b, "\tVisible: ")
for _, v := range visible {
fmt.Fprintf(&b, "%s, ", v.Info().Print())
}
fmt.Fprintf(&b, "\n")
}
if len(other) > 0 {
fmt.Fprintf(&b, "\tOther: ")
for _, w := range other {
fmt.Fprintf(&b, "%s, ", w.Info().Print())
}
fmt.Fprintf(&b, "\n")
}
return string(b.Bytes())
}
// Window represents an application window.
type Window struct {
// ID is the numerical identifier of the window.
ID int64
// Desktop is the numerical identifier of the desktop the
// window belongs to. Equal to -1 if the window is sticky.
Desktop int64
// Name is the display name of the window (typically what the
// windowing system shows in the top bar of the window).
Name string
}
// systemNames is a set of blacklisted window names that are known to
// be used by system windows that aren't visible to the user.
var systemNames = map[string]struct{}{
"XdndCollectionWindowImp": {},
"unity-launcher": {},
"unity-panel": {},
"unity-dash": {},
"Hud": {},
"Desktop": {},
}
// IsSystem returns true if the window is a system window (like
// "unity-panel" and thus shouldn't be considered an application
// visible to the end-users)
func (w *Window) IsSystem() bool {
if _, is := systemNames[w.Name]; is {
return true
}
return false
}
// IsSticky returns true if the window is a sticky window (i.e.
// present on all desktops)
func (w *Window) IsSticky() bool {
return w.Desktop == -1
}
// IsOnDesktop returns true if the window is present on the specified
// desktop
func (w *Window) IsOnDesktop(desktop int64) bool {
return w.IsSticky() || w.Desktop == desktop
}
// Info returns more structured metadata about a window. The metadata
// is extracted using heuristics.
func (w *Window) Info() *Winfo {
fields := strings.Split(w.Name, " - ")
first := strings.TrimSpace(fields[0])
last := strings.TrimSpace(fields[len(fields)-1])
if last == "Google Chrome" {
return &Winfo{
App: "Google Chrome",
SubApp: strings.TrimSpace(fields[len(fields)-2]),
Title: strings.Join(fields[0:len(fields)-2], " - "),
}
} else if first == "Slack" {
return &Winfo{
App: "Slack",
SubApp: strings.TrimSpace(strings.Join(fields[1:], " - ")),
}
}
return &Winfo{
Title: w.Name,
}
}
// Winfo is structured metadata info about a window.
type Winfo struct {
// App is the application that controls the window.
App string
// SubApp is the sub-application that controls the window. An
// example is a web app (e.g., Sourcegraph) that runs
// inside a Chrome tab. In this case, the App field would be
// "Google Chrome" and the SubApp field would be "Sourcegraph".
SubApp string
// Title is the title of the window after the App and SubApp name
// have been stripped.
Title string
}
// Print returns a pretty-printed representation of the snapshot.
func (w Winfo) Print() string {
return fmt.Sprintf("[%s|%s|%s]", w.App, w.SubApp, w.Title)
}