#ifdef WITH_XRANDR
#include <X11/extensions/Xrandr.h>
#endif
+#include <msp/core/algorithm.h>
#include <msp/io/print.h>
#include <msp/strings/format.h>
#include <msp/strings/lexicalcast.h>
namespace {
bool error_flag = false;
-std::string error_msg;
+string error_msg;
int x_error_handler(Display *display, XErrorEvent *event)
{
default: return RR_Rotate_0;
}
}
-
-inline bool monitor_x_compare(const Msp::Graphics::Monitor &m1, const Msp::Graphics::Monitor &m2)
-{
- if(m1.desktop_settings.mode && !m2.desktop_settings.mode)
- return true;
- return m1.desktop_settings.x<m2.desktop_settings.x;
-}
#endif
inline unsigned mode_width(const Msp::Graphics::VideoMode &m, Msp::Graphics::VideoRotation r)
priv(new Private)
{
if(disp_name.empty())
- priv->display = XOpenDisplay(0);
+ priv->display = XOpenDisplay(nullptr);
else
priv->display = XOpenDisplay(disp_name.c_str());
if(!priv->display)
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) : 0);
+ XRRCrtcInfo *crtc = (output->crtc ? XRRGetCrtcInfo(priv->display, res, output->crtc) : nullptr);
monitors.push_back(Monitor());
Monitor &monitor = monitors.back();
int prop_format;
unsigned long length;
unsigned long overflow;
- unsigned char *edid = 0;
+ 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)
{
}
if(res->outputs[i]==primary)
- primary_monitor = &monitor;
+ 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]);
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.monitor = &monitor;
- mode.rate = static_cast<float>(info->dotClock)/(info->hTotal*info->vTotal);
- if(find_mode(mode, 0.01f))
- continue;
+ mode.rate = rate;
modes.push_back(mode);
priv->modes.push_back(info->id);
- monitor.video_modes.push_back(&modes.back());
+ mode_monitor_indices.push_back(monitor.index);
if(crtc && info->id==crtc->mode)
- monitor.desktop_settings.mode = &modes.back();
+ desktop_mode_index = mode.index;
}
-
- monitor.current_settings = monitor.desktop_settings;
+ desktop_mode_indices.push_back(desktop_mode_index);
XRRFreeOutputInfo(output);
if(crtc)
XRRFreeScreenResources(res);
- monitors.sort(monitor_x_compare);
- Monitor *prev_enabled = 0;
+ for(unsigned i=0; i<monitors.size(); ++i)
+ {
+ int j = desktop_mode_indices[i];
+ if(j>=0)
+ monitors[i].desktop_settings.mode = &modes[j];
+ monitors[i].current_settings = monitors[i].desktop_settings;
+ }
+
+ sort(monitors, [](const Msp::Graphics::Monitor &m1, const Msp::Graphics::Monitor &m2){
+ if(m1.desktop_settings.mode && !m2.desktop_settings.mode)
+ return true;
+ if(!m1.desktop_settings.mode && m2.desktop_settings.mode)
+ return false;
+ return m1.desktop_settings.x<m2.desktop_settings.x;
+ });
+
+ for(unsigned i=0; i<modes.size(); ++i)
+ {
+ auto j = find_member(monitors, mode_monitor_indices[i], &Monitor::index);
+ modes[i].monitor = &*j;
+ j->video_modes.push_back(&modes[i]);
+ }
+
+ Monitor *prev_enabled = nullptr;
for(Monitor &m: monitors)
if(m.desktop_settings.mode)
{
prev_enabled = &m;
}
+ if(primary_index>=0)
+ primary_monitor = &*find_member(monitors, static_cast<unsigned>(primary_index), &Monitor::index);
+
if(!primary_monitor || !primary_monitor->desktop_settings.mode)
{
// XRandR didn't give a sensible primary monitor. Try to guess one.
// Check if the output already has a CRTC and find a free one if it doesn't
RRCrtc crtc = output_info->crtc;
- XRRCrtcInfo *crtc_info = 0;
+ XRRCrtcInfo *crtc_info = nullptr;
if(crtc)
crtc_info = XRRGetCrtcInfo(priv->display, res, crtc);
else
{
XRROutputInfo *o = XRRGetOutputInfo(priv->display, res, priv->monitors[m.index]);
if(o->crtc)
- XRRSetCrtcConfig(priv->display, res, o->crtc, CurrentTime, 0, 0, 0, RR_Rotate_0, 0, 0);
+ XRRSetCrtcConfig(priv->display, res, o->crtc, CurrentTime, 0, 0, 0, RR_Rotate_0, nullptr, 0);
XRRFreeOutputInfo(o);
- m.current_settings.mode = 0;
+ m.current_settings.mode = nullptr;
m.current_settings.rotation = ROTATE_NORMAL;
m.current_settings.x = 0;
m.current_settings.y = 0;