-
Notifications
You must be signed in to change notification settings - Fork 17
/
wayinfo.go
110 lines (102 loc) · 3.01 KB
/
wayinfo.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
package wallutils
// #cgo pkg-config: wayland-client
//#include "include/wayinfo.h"
import "C"
import (
"errors"
"log"
"strconv"
"strings"
)
// WaylandCanConnect checks if a Wayland server is up and running
func WaylandCanConnect() bool {
return bool(C.WaylandRunning())
}
// WaylandInfo returns a long info string about the current Wayland setup
func WaylandInfo() (string, error) {
if !WaylandCanConnect() {
return "", errors.New("WaylandInfo(): not connected over Wayland")
}
infoString := C.GoString(C.WaylandInfoString())
return infoString, nil
}
// WaylandMonitors returns information about the available monitors.
// The given slices are filled with data about resolution and DPI.
func WaylandMonitors(IDs, widths, heights, wDPIs, hDPIs *[]uint) error {
if !WaylandCanConnect() {
return errors.New("WaylandMonitors(): not connected over Wayland")
}
info, err := WaylandInfo()
if err != nil {
return err
}
var (
counter uint
physCounter uint
physW uint
physH uint
wDPI uint
hDPI uint
)
// TODO: Write a C implementation instead of parsing the string output
lines := strings.Split(info, "\n")
// The physical width and height of the last encountered monitor, in millimeters
for i, line := range lines {
// Example output from Wayland Info:
// width: 1920 px, height: 1200 px, refresh: 60 Hz,
// flags: current
if strings.Contains(line, "flags: current") {
prevline := lines[i-1]
fields := strings.Fields(prevline)
if len(fields) > 4 {
w, err := strconv.Atoi(fields[1])
if err != nil {
return err
}
h, err := strconv.Atoi(fields[4])
if err != nil {
return err
}
*IDs = append(*IDs, counter)
*widths = append(*widths, uint(w))
*heights = append(*heights, uint(h))
if physW == 0 || physH == 0 {
wDPI = 96 // default DPI value, if no physical size is given
hDPI = 96 // default DPI value, if no physical size is given
log.Println("WARN: No physical monitor size detected!")
// return errors.New("no physical monitor size detected")
}
if physW > 0 && physH > 0 {
// Calculate DPI, from the monitor size (in mm) and the pixel size
wDPI = uint(float64(w) / (float64(physW) / 25.4))
hDPI = uint(float64(h) / (float64(physH) / 25.4))
}
*wDPIs = append(*wDPIs, wDPI)
*hDPIs = append(*hDPIs, hDPI)
counter++
}
} else if strings.Contains(line, "physical_width:") {
// Example output from Wayland Info:
// physical_width: 518 mm, physical_height: 324 mm,
fields := strings.Fields(line)
if len(fields) > 5 {
w, err := strconv.Atoi(fields[1])
if err != nil {
return err
}
h, err := strconv.Atoi(fields[4])
if err != nil {
return err
}
physW = uint(w)
physH = uint(h)
physCounter++
}
}
}
if 0 < physCounter && physCounter < counter {
log.Println("WARN: Some monitors contains a physical size, but not all of them")
// return errors.New("some monitors contains a physical size, but not all of them")
}
return nil
}