IPC.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. package main
  2. import (
  3. "os"
  4. "fmt"
  5. "net"
  6. "strings"
  7. "errors"
  8. "path/filepath"
  9. "github.com/goccy/go-json"
  10. // "github.com/dlasky/gotk3-layershell/layershell"
  11. )
  12. type workspace struct {
  13. Id int `json:"id"`
  14. Name string `json:"name"`
  15. Monitor string `json:"monitor"`
  16. Windows int `json:"windows"`
  17. Hasfullscreen bool `json:"hasfullscreen"`
  18. Lastwindow string `json:"lastwindow"`
  19. Lastwindowtitle string `json:"lastwindowtitle"`
  20. }
  21. type monitor struct {
  22. Id int `json:"id"`
  23. Name string `json:"name"`
  24. Description string `json:"description"`
  25. Make string `json:"make"`
  26. Model string `json:"model"`
  27. Serial string `json:"serial"`
  28. Width int `json:"width"`
  29. Height int `json:"height"`
  30. RefreshRate float64 `json:"refreshRate"`
  31. X int `json:"x"`
  32. Y int `json:"y"`
  33. ActiveWorkspace struct {
  34. Id int `json:"id"`
  35. Name string `json:"name"`
  36. } `json:"activeWorkspace"`
  37. Reserved []int `json:"reserved"`
  38. Scale float64 `json:"scale"`
  39. Transform int `json:"transform"`
  40. Focused bool `json:"focused"`
  41. DpmsStatus bool `json:"dpmsStatus"`
  42. Vrr bool `json:"vrr"`
  43. }
  44. type client struct {
  45. Address string `json:"address"`
  46. Mapped bool `json:"mapped"`
  47. Hidden bool `json:"hidden"`
  48. At []int `json:"at"`
  49. Size []int `json:"size"`
  50. Workspace struct {
  51. Id int `json:"id"`
  52. Name string `json:"name"`
  53. } `json:"workspace"`
  54. Floating bool `json:"floating"`
  55. Monitor int `json:"monitor"`
  56. Class string `json:"class"`
  57. Title string `json:"title"`
  58. InitialClass string `json:"initialClass"`
  59. InitialTitle string `json:"initialTitle"`
  60. Pid int `json:"pid"`
  61. Xwayland bool `json:"xwayland"`
  62. Pinned bool `json:"pinned"`
  63. Fullscreen bool `json:"fullscreen"`
  64. FullscreenMode int `json:"fullscreenMode"`
  65. FakeFullscreen bool `json:"fakeFullscreen"`
  66. Grouped []interface{} `json:"grouped"`
  67. Swallowing interface{} `json:"swallowing"`
  68. }
  69. var monitors []monitor
  70. var clients []client
  71. var activeClient *client
  72. var lastWinAddr string
  73. var hyprDir = filepath.Join(os.Getenv("XDG_RUNTIME_DIR"), "hypr")
  74. var his = os.Getenv("HYPRLAND_INSTANCE_SIGNATURE")
  75. var unixSockAdress = fmt.Sprintf("%s/%s/.socket.sock", hyprDir, his)
  76. var unixSock2Adress = &net.UnixAddr {
  77. Name: fmt.Sprintf("%s/%s/.socket2.sock", hyprDir, his),
  78. Net: "unix",
  79. }
  80. var special = false
  81. func hyprctl(cmd string) ([]byte, error) {
  82. conn, err := net.Dial("unix", unixSockAdress)
  83. if err != nil {
  84. return nil, err
  85. }
  86. message := []byte(cmd)
  87. _, err = conn.Write(message)
  88. if err != nil {
  89. return nil, err
  90. }
  91. response := make([]byte, 102400)
  92. n, err := conn.Read(response)
  93. if err != nil {
  94. return nil, err
  95. }
  96. defer conn.Close()
  97. return response[:n], nil
  98. }
  99. func listMonitors() error {
  100. response, err := hyprctl("j/monitors")
  101. if err != nil {
  102. return err
  103. } else {
  104. err = json.Unmarshal([]byte(response), &monitors)
  105. }
  106. return err
  107. }
  108. func listClients() error {
  109. response, err := hyprctl("j/clients")
  110. if err != nil {
  111. return err
  112. } else {
  113. err = json.Unmarshal([]byte(response), &clients)
  114. }
  115. activeClient, _ = getActiveWindow()
  116. return err
  117. }
  118. func getActiveWindow() (*client, error) {
  119. var activeWindow client
  120. response, err := hyprctl("j/activewindow")
  121. err = json.Unmarshal([]byte(response), &activeWindow)
  122. if err == nil {
  123. return &activeWindow, nil
  124. }
  125. return nil, err
  126. }
  127. func initHyprEvents() {
  128. unixConnect, _ := net.DialUnix("unix", nil, unixSock2Adress)
  129. defer unixConnect.Close()
  130. for {
  131. bufer := make([]byte, 10240)
  132. unixNumber, err := unixConnect.Read(bufer)
  133. if err != nil {fmt.Println(err)}
  134. hyprEvent := string(bufer[:unixNumber])
  135. // fmt.Println(hyprEvent)
  136. if strings.Contains(hyprEvent, "configreloaded") {
  137. addLayerRule()
  138. }
  139. if strings.Contains(hyprEvent, "openwindow>>") {
  140. windowData := strings.TrimSpace(strings.Split(hyprEvent, "openwindow>>")[1])
  141. windowAddressGrange := "0x" + strings.Split(windowData, ",")[0]
  142. windowAddress := strings.Split(windowAddressGrange, "\n")[0]
  143. windowClient, err := searchClientByAddress(windowAddress)
  144. if err != nil {
  145. fmt.Println(err)
  146. } else {
  147. go addApp(windowClient)
  148. }
  149. }
  150. if strings.Contains(hyprEvent, "closewindow>>") {
  151. windowData := strings.TrimSpace(strings.Split(hyprEvent, "closewindow>>")[1])
  152. windowAddressGrange := "0x" + strings.Split(windowData, ",")[0]
  153. windowAddress := strings.Split(windowAddressGrange, "\n")[0]
  154. go removeApp(windowAddress)
  155. }
  156. if strings.Contains(hyprEvent, "activespecial>>") {
  157. // fmt.Println(hyprEvent)
  158. specialData := strings.TrimSpace(strings.Split(hyprEvent, "activespecial>>")[1])
  159. specialDataArr := strings.Split(specialData, ",")
  160. if specialDataArr[0] == "special:special" {
  161. // fmt.Println("Open")
  162. special = true
  163. }
  164. if specialDataArr[0] != "special:special" {
  165. // fmt.Println("Close")
  166. special = false
  167. }
  168. }
  169. }
  170. }
  171. func searchClientByAddress(address string) (client, error) {
  172. listClients()
  173. for _, ipcClient := range clients {
  174. if ipcClient.Address == address {
  175. return ipcClient, nil
  176. }
  177. }
  178. err := errors.New("Client non found by address: " + address)
  179. return client{}, err
  180. }
  181. func addLayerRule() {
  182. if config.Blur == "on" {
  183. hyprctl("keyword layerrule blur,hypr-dock")
  184. hyprctl("keyword layerrule ignorealpha 0.4,hypr-dock")
  185. }
  186. }