+ int major, minor;
+ XRRQueryVersion(priv->display, &major, &minor);
+ if(major>1 || (major==1 && minor>=2))
+ {
+ XRRScreenResources *res = XRRGetScreenResources(priv->display, priv->root_window);
+ RROutput primary = XRRGetOutputPrimary(priv->display, priv->root_window);
+ Atom edid_prop = XInternAtom(priv->display, RR_PROPERTY_RANDR_EDID, true);
+
+ map<RRMode, XRRModeInfo *> modes_by_id;
+ for(int i=0; i<res->nmode; ++i)
+ modes_by_id[res->modes[i].id] = &res->modes[i];
+
+ int primary_index = -1;
+ vector<unsigned> mode_monitor_indices;
+ vector<int> desktop_mode_indices;
+ for(int i=0; i<res->noutput; ++i)
+ {
+ XRROutputInfo *output = XRRGetOutputInfo(priv->display, res, res->outputs[i]);
+ XRRCrtcInfo *crtc = (output->crtc ? XRRGetCrtcInfo(priv->display, res, output->crtc) : nullptr);
+
+ monitors.push_back(Monitor());
+ Monitor &monitor = monitors.back();
+ monitor.index = monitors.size()-1;
+ monitor.name.assign(output->name, output->nameLen);
+ priv->monitors.push_back(res->outputs[i]);
+
+ if(edid_prop)
+ {
+ Atom prop_type;
+ int prop_format;
+ unsigned long length;
+ unsigned long overflow;
+ unsigned char *edid = nullptr;
+ XRRGetOutputProperty(priv->display, res->outputs[i], edid_prop, 0, 32, false, false, XA_INTEGER, &prop_type, &prop_format, &length, &overflow, &edid);
+ if(prop_type==XA_INTEGER && prop_format==8)
+ {
+ for(unsigned j=0; j<4; ++j)
+ {
+ unsigned offset = 54+j*18;
+ if(edid[offset]==0 && edid[offset+1]==0 && edid[offset+3]==0xFC)
+ {
+ unsigned k;
+ for(k=0; (k<13 && edid[offset+5+k]!=0x0A); ++k) ;
+ monitor.name.assign(reinterpret_cast<char *>(edid+offset+5), k);
+ }
+ }
+ }
+ XFree(edid);
+ }
+
+ if(crtc)
+ {
+ monitor.desktop_settings.rotation = rotation_from_sys(crtc->rotation);
+ monitor.desktop_settings.x = crtc->x;
+ monitor.desktop_settings.y = crtc->y;
+ }
+
+ if(res->outputs[i]==primary)
+ primary_index = monitor.index;
+
+ unsigned first_mode = modes.size();
+ int desktop_mode_index = -1;
+ for(int j=0; j<output->nmode; ++j)
+ {
+ auto k = modes_by_id.find(output->modes[j]);
+ if(k==modes_by_id.end())
+ continue;
+
+ XRRModeInfo *info = k->second;
+ float rate = static_cast<float>(info->dotClock)/(info->hTotal*info->vTotal);
+
+ if(any_of(modes.begin()+first_mode, modes.end(), [&info, rate](const VideoMode &m){
+ return (m.width==info->width && m.height==info->height && abs(m.rate-rate)<0.01f);
+ }))
+ continue;
+
+ VideoMode mode(info->width, info->height);
+ mode.index = modes.size();
+ mode.rate = rate;