diff --git a/main.go b/main.go index 6a3266c..bcc1832 100644 --- a/main.go +++ b/main.go @@ -24,13 +24,14 @@ import ( const version = "0.4.2" var ( - appDirs []string - configDirectory string - pinnedFile string - pinned []string - id2entry map[string]desktopEntry - preferredApps map[string]interface{} - exclusions []string + appDirs []string + configDirectory string + pinnedFile string + pinned []string + id2entry map[string]desktopEntry + preferredApps map[string]interface{} + exclusions []string + hyprlandMonitors []monitor ) var categoryNames = [...]string{ @@ -66,6 +67,30 @@ type desktopEntry struct { 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 var ( listUtility []string @@ -372,6 +397,7 @@ func main() { if *targetOutput != "" { // We want to assign layershell to a monitor, but we only know the output name! output2mon, err = mapOutputs() + fmt.Println(">>>", output2mon) if err == nil { monitor := output2mon[*targetOutput] layershell.SetMonitor(win, monitor) diff --git a/tools.go b/tools.go index 149c4fd..da615f0 100644 --- a/tools.go +++ b/tools.go @@ -5,8 +5,11 @@ import ( "encoding/json" "errors" "fmt" + "github.com/joshuarubin/go-sway" + log "github.com/sirupsen/logrus" "io" "io/fs" + "net" "os" "os/exec" "path" @@ -17,11 +20,8 @@ import ( "syscall" "time" - log "github.com/sirupsen/logrus" - "github.com/gotk3/gotk3/gdk" "github.com/gotk3/gotk3/gtk" - "github.com/joshuarubin/go-sway" ) func wayland() bool { @@ -651,35 +651,64 @@ func open(filePath string, xdgOpen bool) { func mapOutputs() (map[string]*gdk.Monitor, error) { result := make(map[string]*gdk.Monitor) - ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) - defer cancel() + if os.Getenv("HYPRLAND_INSTANCE_SIGNATURE") != "" { + err := listHyprlandMonitors() + if err == nil { - client, err := sway.New(ctx) - if err != nil { - return nil, err - } + display, err := gdk.DisplayGetDefault() + if err != nil { + return nil, err + } - outputs, err := client.GetOutputs(ctx) - 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 + } - display, err := gdk.DisplayGetDefault() - if err != nil { - return nil, err - } + } else if os.Getenv("SWAYSOCK") != "" { + ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) + defer cancel() - num := display.GetNMonitors() - for i := 0; i < num; i++ { - monitor, _ := display.GetMonitor(i) - geometry := monitor.GetGeometry() - // assign output to monitor on the basis of the same x, y coordinates - for _, output := range outputs { - if int(output.Rect.X) == geometry.GetX() && int(output.Rect.Y) == geometry.GetY() { - result[output.Name] = monitor + client, err := sway.New(ctx) + if err != nil { + return nil, err + } + + outputs, err := client.GetOutputs(ctx) + if err != nil { + return nil, err + } + + display, err := gdk.DisplayGetDefault() + if err != nil { + return nil, err + } + + num := display.GetNMonitors() + for i := 0; i < num; i++ { + monitor, _ := display.GetMonitor(i) + geometry := monitor.GetGeometry() + // assign output to monitor on the basis of the same x, y coordinates + for _, output := range outputs { + if int(output.Rect.X) == geometry.GetX() && int(output.Rect.Y) == geometry.GetY() { + result[output.Name] = monitor + } } } + } else { + return nil, errors.New("output assignment only supported on sway and Hyprland") } + return result, nil } @@ -698,3 +727,38 @@ func substring(s string, start int, end int) string { } 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 +}