1
+ #include " modules/hyprland/backend.hpp"
2
+
3
+ #include < ctype.h>
4
+ #include < netdb.h>
5
+ #include < netinet/in.h>
6
+ #include < spdlog/spdlog.h>
7
+ #include < stdio.h>
8
+ #include < stdlib.h>
9
+ #include < string.h>
10
+ #include < sys/socket.h>
11
+ #include < sys/stat.h>
12
+ #include < sys/types.h>
13
+ #include < sys/un.h>
14
+ #include < unistd.h>
15
+
16
+ #include < fstream>
17
+ #include < iostream>
18
+ #include < string>
19
+
20
+ namespace waybar ::modules::hyprland {
21
+
22
+ void IPC::startIPC () {
23
+ // will start IPC and relay events to parseIPC
24
+
25
+ std::thread ([&]() {
26
+ // check for hyprland
27
+ const char * HIS = getenv (" HYPRLAND_INSTANCE_SIGNATURE" );
28
+
29
+ if (!HIS) {
30
+ spdlog::warn (" Hyprland is not running, Hyprland IPC will not be available." );
31
+ return ;
32
+ }
33
+
34
+ if (!modulesReady) return ;
35
+
36
+ spdlog::info (" Hyprland IPC starting" );
37
+
38
+ struct sockaddr_un addr;
39
+ int socketfd = socket (AF_UNIX, SOCK_STREAM, 0 );
40
+
41
+ if (socketfd == -1 ) {
42
+ spdlog::error (" Hyprland IPC: socketfd failed" );
43
+ return ;
44
+ }
45
+
46
+ addr.sun_family = AF_UNIX;
47
+
48
+ // socket path
49
+ std::string socketPath = " /tmp/hypr/" + std::string (HIS) + " /.socket2.sock" ;
50
+
51
+ strncpy (addr.sun_path , socketPath.c_str (), sizeof (addr.sun_path ) - 1 );
52
+
53
+ addr.sun_path [sizeof (addr.sun_path ) - 1 ] = 0 ;
54
+
55
+ int l = sizeof (struct sockaddr_un );
56
+
57
+ if (connect (socketfd, (struct sockaddr *)&addr, l) == -1 ) {
58
+ spdlog::error (" Hyprland IPC: Unable to connect?" );
59
+ return ;
60
+ }
61
+
62
+ auto file = fdopen (socketfd, " r" );
63
+
64
+ while (1 ) {
65
+ // read
66
+
67
+ char buffer[1024 ]; // Hyprland socket2 events are max 1024 bytes
68
+ auto recievedCharPtr = fgets (buffer, 1024 , file);
69
+
70
+ if (!recievedCharPtr) {
71
+ std::this_thread::sleep_for (std::chrono::milliseconds (1 ));
72
+ continue ;
73
+ }
74
+
75
+ callbackMutex.lock ();
76
+
77
+ std::string messageRecieved (buffer);
78
+
79
+ messageRecieved = messageRecieved.substr (0 , messageRecieved.find_first_of (' \n ' ));
80
+
81
+ spdlog::debug (" hyprland IPC received {}" , messageRecieved);
82
+
83
+ parseIPC (messageRecieved);
84
+
85
+ callbackMutex.unlock ();
86
+
87
+ std::this_thread::sleep_for (std::chrono::milliseconds (1 ));
88
+ }
89
+ }).detach ();
90
+ }
91
+
92
+ void IPC::parseIPC (const std::string& ev) {
93
+ // todo
94
+ std::string request = ev.substr (0 , ev.find_first_of (' >' ));
95
+
96
+ for (auto & [eventname, handler] : callbacks) {
97
+ if (eventname == request) {
98
+ handler (ev);
99
+ }
100
+ }
101
+ }
102
+
103
+ void IPC::registerForIPC (const std::string& ev, std::function<void (const std::string&)> fn) {
104
+ callbackMutex.lock ();
105
+
106
+ callbacks.emplace_back (std::make_pair (ev, fn));
107
+
108
+ callbackMutex.unlock ();
109
+ }
110
+
111
+ std::string IPC::getSocket1Reply (const std::string& rq) {
112
+ // basically hyprctl
113
+
114
+ const auto SERVERSOCKET = socket (AF_UNIX, SOCK_STREAM, 0 );
115
+
116
+ if (SERVERSOCKET < 0 ) {
117
+ spdlog::error (" Hyprland IPC: Couldn't open a socket (1)" );
118
+ return " " ;
119
+ }
120
+
121
+ const auto SERVER = gethostbyname (" localhost" );
122
+
123
+ if (!SERVER) {
124
+ spdlog::error (" Hyprland IPC: Couldn't get host (2)" );
125
+ return " " ;
126
+ }
127
+
128
+ // get the instance signature
129
+ auto instanceSig = getenv (" HYPRLAND_INSTANCE_SIGNATURE" );
130
+
131
+ if (!instanceSig) {
132
+ spdlog::error (" Hyprland IPC: HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?)" );
133
+ return " " ;
134
+ }
135
+
136
+ std::string instanceSigStr = std::string (instanceSig);
137
+
138
+ sockaddr_un serverAddress = {0 };
139
+ serverAddress.sun_family = AF_UNIX;
140
+
141
+ std::string socketPath = " /tmp/hypr/" + instanceSigStr + " /.socket.sock" ;
142
+
143
+ strcpy (serverAddress.sun_path , socketPath.c_str ());
144
+
145
+ if (connect (SERVERSOCKET, (sockaddr*)&serverAddress, SUN_LEN (&serverAddress)) < 0 ) {
146
+ spdlog::error (" Hyprland IPC: Couldn't connect to " + socketPath + " . (3)" );
147
+ return " " ;
148
+ }
149
+
150
+ auto sizeWritten = write (SERVERSOCKET, rq.c_str (), rq.length ());
151
+
152
+ if (sizeWritten < 0 ) {
153
+ spdlog::error (" Hyprland IPC: Couldn't write (4)" );
154
+ return " " ;
155
+ }
156
+
157
+ char buffer[8192 ] = {0 };
158
+
159
+ sizeWritten = read (SERVERSOCKET, buffer, 8192 );
160
+
161
+ if (sizeWritten < 0 ) {
162
+ spdlog::error (" Hyprland IPC: Couldn't read (5)" );
163
+ return " " ;
164
+ }
165
+
166
+ close (SERVERSOCKET);
167
+
168
+ return std::string (buffer);
169
+ }
170
+
171
+ } // namespace waybar::modules::hyprland
0 commit comments