rewrite
This commit is contained in:
commit
8edaa9d713
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
hypr_test.go
|
24
dispatch.go
Normal file
24
dispatch.go
Normal file
@ -0,0 +1,24 @@
|
||||
package hypr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (i *Instance) Dispatch(cmd string) (io.ReadCloser, error) {
|
||||
return readSocketRaw(i.SocketPath(), strings.NewReader(cmd))
|
||||
}
|
||||
|
||||
func (i *Instance) DispatchExpectOK(cmd string) error {
|
||||
str, err := readSocketString(i.SocketPath(), strings.NewReader(cmd))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if strings.ToLower(strings.TrimSpace(str)) != "ok" {
|
||||
return fmt.Errorf("dispatcher '%s' returned an error: %s", cmd, str)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
70
get_instances.go
Normal file
70
get_instances.go
Normal file
@ -0,0 +1,70 @@
|
||||
package hypr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.milar.in/milarin/slices"
|
||||
)
|
||||
|
||||
func GetInstance(signature string) (*Instance, error) {
|
||||
lockFilePath := fmt.Sprintf("/tmp/hypr/%s.lock", signature)
|
||||
|
||||
file, err := os.Open(lockFilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
data, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lines := strings.Split(string(data), "\n")
|
||||
|
||||
pid, err := strconv.Atoi(lines[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Instance{
|
||||
Signature: signature,
|
||||
PID: pid,
|
||||
WaylandSocket: lines[1],
|
||||
}, nil
|
||||
}
|
||||
|
||||
func GetDefaultInstance() (*Instance, error) {
|
||||
signature, ok := os.LookupEnv("HYPRLAND_INSTANCE_SIGNATURE")
|
||||
if !ok {
|
||||
return nil, errors.New("default instance not found because HYPRLAND_INSTANCE_SIGNATURE is not set")
|
||||
}
|
||||
|
||||
return GetInstance(signature)
|
||||
}
|
||||
|
||||
func GetInstances() ([]*Instance, error) {
|
||||
entries, err := os.ReadDir("/tmp/hypr")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
entries = slices.Filter(entries, fs.DirEntry.IsDir)
|
||||
instances := make([]*Instance, 0, len(entries))
|
||||
for _, entry := range entries {
|
||||
instance, err := GetInstance(entry.Name())
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
instances = append(instances, instance)
|
||||
}
|
||||
|
||||
return instances, nil
|
||||
}
|
33
getters.go
Normal file
33
getters.go
Normal file
@ -0,0 +1,33 @@
|
||||
package hypr
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (i *Instance) GetActiveWindow() (*Window, error) {
|
||||
return readSocket[*Window](i.SocketPath(), strings.NewReader("j/activewindow"))
|
||||
}
|
||||
|
||||
func (i *Instance) GetActiveWorkspace() (*Workspace, error) {
|
||||
return readSocket[*Workspace](i.SocketPath(), strings.NewReader("j/activeworkspace"))
|
||||
}
|
||||
|
||||
func (i *Instance) GetBinds() ([]*Bind, error) {
|
||||
return readSocket[[]*Bind](i.SocketPath(), strings.NewReader("j/binds"))
|
||||
}
|
||||
|
||||
func (i *Instance) GetWindows() ([]*Window, error) {
|
||||
return readSocket[[]*Window](i.SocketPath(), strings.NewReader("j/clients"))
|
||||
}
|
||||
|
||||
func (i *Instance) GetCursorPos() (Point, error) {
|
||||
return readSocket[Point](i.SocketPath(), strings.NewReader("j/cursorpos"))
|
||||
}
|
||||
|
||||
func (i *Instance) GetMonitors() ([]*Monitor, error) {
|
||||
return readSocket[[]*Monitor](i.SocketPath(), strings.NewReader("j/monitors"))
|
||||
}
|
||||
|
||||
func (i *Instance) GetWorkspaces() ([]*Workspace, error) {
|
||||
return readSocket[[]*Workspace](i.SocketPath(), strings.NewReader("j/workspaces"))
|
||||
}
|
7
go.mod
Normal file
7
go.mod
Normal file
@ -0,0 +1,7 @@
|
||||
module git.milar.in/milarin/hypr
|
||||
|
||||
go 1.21.6
|
||||
|
||||
require git.milar.in/milarin/slices v0.0.8
|
||||
|
||||
require git.milar.in/milarin/gmath v0.0.3 // indirect
|
4
go.sum
Normal file
4
go.sum
Normal file
@ -0,0 +1,4 @@
|
||||
git.milar.in/milarin/gmath v0.0.3 h1:ii6rKNItS55O/wtIFhD1cTN2BMwDZjTBmiOocKURvxM=
|
||||
git.milar.in/milarin/gmath v0.0.3/go.mod h1:HDLftG5RLpiNGKiIWh+O2G1PYkNzyLDADO8Cd/1abiE=
|
||||
git.milar.in/milarin/slices v0.0.8 h1:qN9TE3tkArdTixMKSnwvNPcApwAjxpLVwA5a9k1rm2s=
|
||||
git.milar.in/milarin/slices v0.0.8/go.mod h1:qMhdtMnfWswc1rHpwgNw33lB84aNEkdBn5BDiYA+G3k=
|
22
model_bind.go
Normal file
22
model_bind.go
Normal file
@ -0,0 +1,22 @@
|
||||
package hypr
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type Bind struct {
|
||||
Locked bool `json:"locked"`
|
||||
Mouse bool `json:"mouse"`
|
||||
Release bool `json:"release"`
|
||||
Repeat bool `json:"repeat"`
|
||||
NonConsuming bool `json:"non_consuming"`
|
||||
ModMask int `json:"modmask"`
|
||||
Submap string `json:"submap"`
|
||||
Key string `json:"key"`
|
||||
KeyCode int `json:"keycode"`
|
||||
Dispatcher string `json:"dispatcher"`
|
||||
Arg string `json:"arg"`
|
||||
}
|
||||
|
||||
func (b Bind) String() string {
|
||||
data, _ := json.MarshalIndent(b, "", "\t")
|
||||
return string(data)
|
||||
}
|
25
model_instance.go
Normal file
25
model_instance.go
Normal file
@ -0,0 +1,25 @@
|
||||
package hypr
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Instance struct {
|
||||
Signature string `json:"instance"`
|
||||
PID int `json:"pid"`
|
||||
WaylandSocket string `json:"wl_socket"`
|
||||
}
|
||||
|
||||
func (i Instance) String() string {
|
||||
data, _ := json.MarshalIndent(i, "", "\t")
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func (i Instance) SocketPath() string {
|
||||
return fmt.Sprintf("/tmp/hypr/%s/.socket.sock", i.Signature)
|
||||
}
|
||||
|
||||
func (i Instance) EventSocketPath() string {
|
||||
return fmt.Sprintf("/tmp/hypr/%s/.socket2.sock", i.Signature)
|
||||
}
|
13
model_misc.go
Normal file
13
model_misc.go
Normal file
@ -0,0 +1,13 @@
|
||||
package hypr
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type Point struct {
|
||||
X int `json:"x"`
|
||||
Y int `json:"y"`
|
||||
}
|
||||
|
||||
func (p Point) String() string {
|
||||
data, _ := json.MarshalIndent(p, "", "\t")
|
||||
return string(data)
|
||||
}
|
31
model_monitor.go
Normal file
31
model_monitor.go
Normal file
@ -0,0 +1,31 @@
|
||||
package hypr
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type Monitor struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Make string `json:"make"`
|
||||
Model string `json:"model"`
|
||||
Serial string `json:"serial"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
RefreshRate float64 `json:"refreshRate"`
|
||||
X int `json:"x"`
|
||||
Y int `json:"y"`
|
||||
ActiveWorkspace WorkspaceIdent `json:"activeWorkspace"`
|
||||
SpecialWorkspace WorkspaceIdent `json:"specialWorkspace"`
|
||||
Reserved [4]int `json:"reserved"`
|
||||
Scale float64 `json:"scale"`
|
||||
Transform int `json:"transform"`
|
||||
Focused bool `json:"focused"`
|
||||
DPMSStatus bool `json:"dpmsStatus"`
|
||||
VRR bool `json:"vrr"`
|
||||
ActivelyTearing bool `json:"activelyTearing"`
|
||||
}
|
||||
|
||||
func (m Monitor) String() string {
|
||||
data, _ := json.MarshalIndent(m, "", "\t")
|
||||
return string(data)
|
||||
}
|
32
model_window.go
Normal file
32
model_window.go
Normal file
@ -0,0 +1,32 @@
|
||||
package hypr
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type Window struct {
|
||||
Address string `json:"address"`
|
||||
Mapped bool `json:"mapped"`
|
||||
Hidden bool `json:"hidden"`
|
||||
At [2]int `json:"at"`
|
||||
Size [2]int `json:"size"`
|
||||
Workspace WorkspaceIdent `json:"workspace"`
|
||||
Floating bool `json:"floating"`
|
||||
MonitorID int `json:"monitor"`
|
||||
Class string `json:"class"`
|
||||
Title string `json:"title"`
|
||||
InitialClass string `json:"initialClass"`
|
||||
InitialTitle string `json:"initialTitle"`
|
||||
PID int `json:"pid"`
|
||||
Xwayland bool `json:"xwayland"`
|
||||
Pinned bool `json:"pinned"`
|
||||
Fullscreen bool `json:"fullscreen"`
|
||||
FullscreenMode int `json:"fullscreenMode"`
|
||||
FakeFullscreen bool `json:"fakeFullscreen"`
|
||||
Grouped []interface{} `json:"grouped"` // TODO
|
||||
Swallowing string `json:"swallowing"`
|
||||
FocusHistoryID int `json:"focusHistoryID"`
|
||||
}
|
||||
|
||||
func (w Window) String() string {
|
||||
data, _ := json.MarshalIndent(w, "", "\t")
|
||||
return string(data)
|
||||
}
|
24
model_workspace.go
Normal file
24
model_workspace.go
Normal file
@ -0,0 +1,24 @@
|
||||
package hypr
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type WorkspaceIdent struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type Workspace struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Monitor string `json:"monitor"`
|
||||
MonitorID int `json:"monitorID"`
|
||||
Windows int `json:"windows"`
|
||||
HasFullscreen bool `json:"hasfullscreen"`
|
||||
LastWindow string `json:"lastwindow"`
|
||||
LastWindowTitle string `json:"lastwindowtitle"`
|
||||
}
|
||||
|
||||
func (w Workspace) String() string {
|
||||
data, _ := json.MarshalIndent(w, "", "\t")
|
||||
return string(data)
|
||||
}
|
51
utils.go
Normal file
51
utils.go
Normal file
@ -0,0 +1,51 @@
|
||||
package hypr
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net"
|
||||
)
|
||||
|
||||
func readSocketRaw(socket string, body io.Reader) (io.ReadCloser, error) {
|
||||
conn, err := net.Dial("unix", socket)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := io.Copy(conn, body); err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func readSocketString(socket string, body io.Reader) (string, error) {
|
||||
r, err := readSocketRaw(socket, body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
data, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(data), nil
|
||||
}
|
||||
|
||||
func readSocket[T any](socket string, body io.Reader) (T, error) {
|
||||
r, err := readSocketRaw(socket, body)
|
||||
if err != nil {
|
||||
return *new(T), err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
value := new(T)
|
||||
if err := json.NewDecoder(r).Decode(value); err != nil {
|
||||
return *new(T), err
|
||||
}
|
||||
|
||||
return *value, nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user