text: #include "monitordetection.h"
  
  #include "globals.h"
  #include "xconnection.h"
  
  #ifdef XINERAMA
  #include <X11/extensions/Xinerama.h>
  #endif /* XINERAMA */
  
  #include <X11/extensions/Xrandr.h>
  
  using std::make_pair;
  using std::string;
  using std::vector;
  
  MonitorDetection::MonitorDetection(string name)
      : name_(name)
      , detect_(nullptr)
  {
  }
  
  #ifdef XINERAMA
  
  // inspired by dwm's updategeom()
  RectangleVec detectMonitorsXinerama(XConnection& X) {
      if (!XineramaIsActive(X.display())) {
          return {};
      }
      int n = 0;
      XineramaScreenInfo* info = XineramaQueryScreens(X.display(), &n);
      if (n == 0 || !info) {
          return {};
      }
      RectangleVec monitor_rects;
      for (int i = 0; i < n; i++) {
          Rectangle r;
          r.x = info[i].x_org;
          r.y = info[i].y_org;
          r.width = info[i].width;
          r.height = info[i].height;
          monitor_rects.push_back(r);
      }
      XFree(info);
      return monitor_rects;
  }
  
  #endif /* XINERAMA */
  
  RectangleVec detectMonitorsXrandr(XConnection& X) {
      // see /usr/share/doc/xorgproto/randrproto.txt for documentation
      int outputs = 0;
      int event_base = 0;
      int error_base = 0;
      if (!XRRQueryExtension(X.display(), &event_base, &error_base)) {
          HSDebug("no xrandr available\n");
          return {};
      }
  
      int major_version = 0, minor_version = 0;
      XRRQueryVersion(X.display(), &major_version, &minor_version);
      if (make_pair(major_version, minor_version) < make_pair(1, 5)) {
          HSDebug("RRGetMonitors only available since RandR 1.5");
          return {};
      }
      // RRGetMonitors was added with randr 1.5
      XRRMonitorInfo* monitorInfo = XRRGetMonitors(X.display(), X.root(), true, &outputs);
      if (outputs <= 0 || !monitorInfo) {
          return {};
      }
      RectangleVec result;
      for (int i = 0; i < outputs; i++) {
          XRRMonitorInfo& cur = monitorInfo[i];
          result.push_back({ cur.x, cur.y, cur.width, cur.height });
      }
      XRRFreeMonitors(monitorInfo);
      return result;
  }
  
  vector<MonitorDetection> MonitorDetection::detectors() {
      MonitorDetection xrandr("xrandr");
      xrandr.detect_ = detectMonitorsXrandr;
      MonitorDetection xinerama("xinerama");
      #ifdef XINERAMA
      xinerama.detect_ = detectMonitorsXinerama;
      #endif
      return { xrandr, xinerama };
  }
  
  