| 161 | #include <X11/Xlib.h> |
| 162 | |
| 163 | static std::optional<float> GetRefreshRateFromXRandR(const WindowInfo& wi) |
| 164 | { |
| 165 | Display* display = static_cast<Display*>(wi.display_connection); |
| 166 | Window window = static_cast<Window>(reinterpret_cast<uintptr_t>(wi.window_handle)); |
| 167 | if (!display || !window) |
| 168 | return std::nullopt; |
| 169 | |
| 170 | XRRScreenResources* res = XRRGetScreenResources(display, window); |
| 171 | if (!res) |
| 172 | { |
| 173 | Console.Error("(GetRefreshRateFromXRandR) XRRGetScreenResources() failed"); |
| 174 | return std::nullopt; |
| 175 | } |
| 176 | |
| 177 | ScopedGuard res_guard([res]() { XRRFreeScreenResources(res); }); |
| 178 | |
| 179 | int num_monitors; |
| 180 | XRRMonitorInfo* mi = XRRGetMonitors(display, window, True, &num_monitors); |
| 181 | if (num_monitors < 0) |
| 182 | { |
| 183 | Console.Error("(GetRefreshRateFromXRandR) XRRGetMonitors() failed"); |
| 184 | return std::nullopt; |
| 185 | } |
| 186 | else if (num_monitors > 1) |
| 187 | { |
| 188 | Console.Warning("(GetRefreshRateFromXRandR) XRRGetMonitors() returned %d monitors, using first", num_monitors); |
| 189 | } |
| 190 | |
| 191 | ScopedGuard mi_guard([mi]() { XRRFreeMonitors(mi); }); |
| 192 | if (mi->noutput <= 0) |
| 193 | { |
| 194 | Console.Error("(GetRefreshRateFromXRandR) Monitor has no outputs"); |
| 195 | return std::nullopt; |
| 196 | } |
| 197 | else if (mi->noutput > 1) |
| 198 | { |
| 199 | Console.Warning("(GetRefreshRateFromXRandR) Monitor has %d outputs, using first", mi->noutput); |
| 200 | } |
| 201 | |
| 202 | XRROutputInfo* oi = XRRGetOutputInfo(display, res, mi->outputs[0]); |
| 203 | if (!oi) |
| 204 | { |
| 205 | Console.Error("(GetRefreshRateFromXRandR) XRRGetOutputInfo() failed"); |
| 206 | return std::nullopt; |
| 207 | } |
| 208 | |
| 209 | ScopedGuard oi_guard([oi]() { XRRFreeOutputInfo(oi); }); |
| 210 | |
| 211 | XRRCrtcInfo* ci = XRRGetCrtcInfo(display, res, oi->crtc); |
| 212 | if (!ci) |
| 213 | { |
| 214 | Console.Error("(GetRefreshRateFromXRandR) XRRGetCrtcInfo() failed"); |
| 215 | return std::nullopt; |
| 216 | } |
| 217 | |
| 218 | ScopedGuard ci_guard([ci]() { XRRFreeCrtcInfo(ci); }); |
| 219 | |
| 220 | XRRModeInfo* mode = nullptr; |
no test coverage detected