]> git.tdb.fi Git - libs/gui.git/blobdiff - source/graphics/x11/display.cpp
Get monitor names from EDID if available
[libs/gui.git] / source / graphics / x11 / display.cpp
index 70b77c60ff6239c46041b2821a9c39777f6f0628..a48f3f874f1a3600da402f9fd88a1138b7f80c89 100644 (file)
@@ -1,5 +1,5 @@
-#include <iostream>
 #include <X11/Xlib.h>
+#include <X11/Xatom.h>
 #ifdef WITH_XRANDR
 #include <X11/extensions/Xrandr.h>
 #endif
@@ -38,6 +38,7 @@ int x_error_handler(Display *display, XErrorEvent *event)
        return 0;
 }
 
+#ifdef WITH_XRANDR
 inline Msp::Graphics::VideoRotation rotation_from_sys(Rotation r)
 {
        switch(r)
@@ -60,12 +61,13 @@ inline Rotation rotation_to_sys(Msp::Graphics::VideoRotation r)
        }
 }
 
-bool monitor_x_compare(const Msp::Graphics::Monitor &m1, const Msp::Graphics::Monitor &m2)
+inline bool monitor_x_compare(const Msp::Graphics::Monitor &m1, const Msp::Graphics::Monitor &m2)
 {
        if(m1.desktop_mode && !m2.desktop_mode)
                return true;
        return m1.x<m2.x;
 }
+#endif
 
 inline unsigned mode_width(const Msp::Graphics::VideoMode &m, Msp::Graphics::VideoRotation r)
 {
@@ -83,7 +85,8 @@ namespace Graphics {
 
 Display::Display(const string &disp_name):
        primary_monitor(0),
-       priv(new Private)
+       priv(new Private),
+       focus_window(0)
 {
        if(disp_name.empty())
                priv->display = XOpenDisplay(0);
@@ -94,6 +97,8 @@ Display::Display(const string &disp_name):
 
        XSetErrorHandler(x_error_handler);
 
+       priv->root_window = DefaultRootWindow(priv->display);
+
        err_dialog = new ErrorDialog(this);
 
 #ifdef WITH_XRANDR
@@ -105,9 +110,9 @@ Display::Display(const string &disp_name):
                XRRQueryVersion(priv->display, &major, &minor);
                if(major>1 || (major==1 && minor>=2))
                {
-                       WindowHandle root = DefaultRootWindow(priv->display);
-                       XRRScreenResources *res = XRRGetScreenResources(priv->display, root);
-                       RROutput primary = XRRGetOutputPrimary(priv->display, root);
+                       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)
@@ -121,8 +126,33 @@ Display::Display(const string &disp_name):
                                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 = 0;
+                                       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_rotation = rotation_from_sys(crtc->rotation);
@@ -145,8 +175,8 @@ Display::Display(const string &disp_name):
                                        VideoMode mode(info->width, info->height);
                                        mode.index = modes.size();
                                        mode.monitor = &monitor;
-                                       mode.rate = info->dotClock/(info->hTotal*info->vTotal);
-                                       if(find_matching_mode(mode))
+                                       mode.rate = static_cast<float>(info->dotClock)/(info->hTotal*info->vTotal);
+                                       if(find_mode(mode, 0.01f))
                                                continue;
 
                                        modes.push_back(mode);
@@ -208,7 +238,7 @@ Display::~Display()
 void Display::set_mode(const VideoMode &requested_mode, bool exclusive)
 {
 #ifdef WITH_XRANDR
-       const VideoMode *mode = find_matching_mode(requested_mode);
+       const VideoMode *mode = find_mode(requested_mode);
        if(!mode)
                throw unsupported_video_mode(requested_mode);
 
@@ -216,8 +246,7 @@ void Display::set_mode(const VideoMode &requested_mode, bool exclusive)
        if(requested_rotation==ROTATE_ANY)
                requested_rotation = mode->monitor->desktop_rotation;
 
-       WindowHandle root = DefaultRootWindow(priv->display);
-       XRRScreenResources *res = XRRGetScreenResources(priv->display, root);
+       XRRScreenResources *res = XRRGetScreenResources(priv->display, priv->root_window);
        RROutput output = priv->monitors[mode->monitor->index];
        XRROutputInfo *output_info = XRRGetOutputInfo(priv->display, res, output);
 
@@ -300,6 +329,23 @@ void Display::set_mode(const VideoMode &requested_mode, bool exclusive)
                {
                        XRROutputInfo *o = XRRGetOutputInfo(priv->display, res, priv->monitors[i->index]);
                        XRRSetCrtcConfig(priv->display, res, o->crtc, CurrentTime, x, y, priv->modes[i->current_mode->index], rotation_to_sys(i->current_rotation), &priv->monitors[i->index], 1);
+
+                       XRRPanning panning;
+                       panning.timestamp = CurrentTime;
+                       panning.left = x;
+                       panning.top = y;
+                       panning.width = i->current_mode->width;
+                       panning.height = i->current_mode->height;
+                       panning.track_left = panning.left;
+                       panning.track_top = panning.top;
+                       panning.track_width = panning.width;
+                       panning.track_height = panning.height;
+                       panning.border_left = 0;
+                       panning.border_top = 0;
+                       panning.border_right = 0;
+                       panning.border_bottom = 0;
+                       XRRSetPanning(priv->display, res, o->crtc, &panning);
+
                        XRRFreeOutputInfo(o);
 
                        i->x = x;