support output assignment on Hyprland
This commit is contained in:
26
main.go
26
main.go
@@ -31,6 +31,7 @@ var (
|
|||||||
id2entry map[string]desktopEntry
|
id2entry map[string]desktopEntry
|
||||||
preferredApps map[string]interface{}
|
preferredApps map[string]interface{}
|
||||||
exclusions []string
|
exclusions []string
|
||||||
|
hyprlandMonitors []monitor
|
||||||
)
|
)
|
||||||
|
|
||||||
var categoryNames = [...]string{
|
var categoryNames = [...]string{
|
||||||
@@ -66,6 +67,30 @@ type desktopEntry struct {
|
|||||||
NoDisplay bool
|
NoDisplay bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 struct {
|
||||||
|
Id int `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"activeWorkspace"`
|
||||||
|
Reserved []int `json:"reserved"`
|
||||||
|
Scale float64 `json:"scale"`
|
||||||
|
Transform int `json:"transform"`
|
||||||
|
Focused bool `json:"focused"`
|
||||||
|
DpmsStatus bool `json:"dpmsStatus"`
|
||||||
|
Vrr bool `json:"vrr"`
|
||||||
|
}
|
||||||
|
|
||||||
// slices below will hold DesktopID strings
|
// slices below will hold DesktopID strings
|
||||||
var (
|
var (
|
||||||
listUtility []string
|
listUtility []string
|
||||||
@@ -372,6 +397,7 @@ func main() {
|
|||||||
if *targetOutput != "" {
|
if *targetOutput != "" {
|
||||||
// We want to assign layershell to a monitor, but we only know the output name!
|
// We want to assign layershell to a monitor, but we only know the output name!
|
||||||
output2mon, err = mapOutputs()
|
output2mon, err = mapOutputs()
|
||||||
|
fmt.Println(">>>", output2mon)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
monitor := output2mon[*targetOutput]
|
monitor := output2mon[*targetOutput]
|
||||||
layershell.SetMonitor(win, monitor)
|
layershell.SetMonitor(win, monitor)
|
||||||
|
|||||||
70
tools.go
70
tools.go
@@ -5,8 +5,11 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/joshuarubin/go-sway"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
@@ -17,11 +20,8 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
|
|
||||||
"github.com/gotk3/gotk3/gdk"
|
"github.com/gotk3/gotk3/gdk"
|
||||||
"github.com/gotk3/gotk3/gtk"
|
"github.com/gotk3/gotk3/gtk"
|
||||||
"github.com/joshuarubin/go-sway"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func wayland() bool {
|
func wayland() bool {
|
||||||
@@ -651,6 +651,31 @@ func open(filePath string, xdgOpen bool) {
|
|||||||
func mapOutputs() (map[string]*gdk.Monitor, error) {
|
func mapOutputs() (map[string]*gdk.Monitor, error) {
|
||||||
result := make(map[string]*gdk.Monitor)
|
result := make(map[string]*gdk.Monitor)
|
||||||
|
|
||||||
|
if os.Getenv("HYPRLAND_INSTANCE_SIGNATURE") != "" {
|
||||||
|
err := listHyprlandMonitors()
|
||||||
|
if err == nil {
|
||||||
|
|
||||||
|
display, err := gdk.DisplayGetDefault()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
num := display.GetNMonitors()
|
||||||
|
for i := 0; i < num; i++ {
|
||||||
|
mon, _ := display.GetMonitor(i)
|
||||||
|
geometry := mon.GetGeometry()
|
||||||
|
// assign output to monitor on the basis of the same x, y coordinates
|
||||||
|
for _, output := range hyprlandMonitors {
|
||||||
|
if int(output.X) == geometry.GetX() && int(output.Y) == geometry.GetY() {
|
||||||
|
result[output.Name] = mon
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if os.Getenv("SWAYSOCK") != "" {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
|
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
@@ -680,6 +705,10 @@ func mapOutputs() (map[string]*gdk.Monitor, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return nil, errors.New("output assignment only supported on sway and Hyprland")
|
||||||
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,3 +727,38 @@ func substring(s string, start int, end int) string {
|
|||||||
}
|
}
|
||||||
return s[startStrIdx:]
|
return s[startStrIdx:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hyprctl(cmd string) ([]byte, error) {
|
||||||
|
his := os.Getenv("HYPRLAND_INSTANCE_SIGNATURE")
|
||||||
|
socketFile := fmt.Sprintf("/tmp/hypr/%s/.socket.sock", his)
|
||||||
|
conn, err := net.Dial("unix", socketFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
message := []byte(cmd)
|
||||||
|
_, err = conn.Write(message)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
reply := make([]byte, 102400)
|
||||||
|
n, err := conn.Read(reply)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
return reply[:n], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func listHyprlandMonitors() error {
|
||||||
|
reply, err := hyprctl("j/monitors")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
err = json.Unmarshal([]byte(reply), &hyprlandMonitors)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user