+CompositedMonitor *find_monitor_by_name(CompositedScreen *screen, char *name)
+{
+ unsigned i;
+
+ for(i=0; i<screen->nmonitors; ++i)
+ if(!strcmp(screen->monitors[i].name, name))
+ return &screen->monitors[i];
+
+ return NULL;
+}
+
+CompositedMonitor *find_monitor_by_name_global(Compositor *compositor, char *name, CompositedScreen **screen)
+{
+ unsigned i, j;
+
+ for(i=0; i<compositor->nscreens; ++i)
+ for(j=0; j<compositor->screens[i].nmonitors; ++j)
+ if(!strcmp(compositor->screens[i].monitors[j].name, name))
+ {
+ if(screen)
+ *screen = &compositor->screens[i];
+ return &compositor->screens[i].monitors[j];
+ }
+
+ if(screen)
+ *screen = NULL;
+ return NULL;
+}
+
+void update_monitors(Compositor *compositor, CompositedScreen *screen)
+{
+ XRRScreenResources *xrr_res;
+ int i;
+
+ xrr_res = XRRGetScreenResources(compositor->display, screen->root);
+ for(i=0; i<xrr_res->noutput; ++i)
+ {
+ XRROutputInfo *output;
+ CompositedMonitor *monitor;
+ int was_enabled;
+ XRRCrtcInfo *crtc;
+
+ output = XRRGetOutputInfo(compositor->display, xrr_res, xrr_res->outputs[i]);
+ monitor = find_monitor_by_name(screen, output->name);
+ if(!monitor)
+ continue;
+
+ was_enabled = monitor->enabled;
+ monitor->enabled = !!output->crtc;
+ if(!monitor->enabled)
+ {
+ XRRFreeOutputInfo(output);
+ if(was_enabled)
+ free_geometry_correction(monitor);
+ continue;
+ }
+
+ crtc = XRRGetCrtcInfo(compositor->display, xrr_res, output->crtc);
+ monitor->x = crtc->x;
+ monitor->y = crtc->y;
+ monitor->width = crtc->width;
+ monitor->height = crtc->height;
+ XRRFreeCrtcInfo(crtc);
+ XRRFreeOutputInfo(output);
+
+ if(!was_enabled)
+ create_geometry_correction(monitor);
+
+ update_monitor_vertices(screen, monitor);
+ }
+ XRRFreeScreenResources(xrr_res);
+}
+
+void update_geometry_correction(Compositor *compositor, CompositedScreen *screen)
+{
+ Atom prop_type;
+ int prop_format;
+ unsigned long overflow;
+ unsigned long names_length;
+ char *names;
+ unsigned long values_length;
+ short *values;
+ char *name_ptr;
+ unsigned i;
+
+ XGetWindowProperty(compositor->display, screen->root, compositor->monitors_atom, 0, 64, False, XA_STRING,
+ &prop_type, &prop_format, &names_length, &overflow, (unsigned char **)&names);
+ if(prop_type!=XA_STRING || prop_format!=8)
+ return;
+
+ XGetWindowProperty(compositor->display, screen->root, compositor->correction_atom, 0, 64, False, XA_INTEGER,
+ &prop_type, &prop_format, &values_length, &overflow, (unsigned char **)&values);
+ if(prop_type!=XA_INTEGER || prop_format!=16)
+ {
+ XFree(names);
+ return;
+ }
+
+ use_gl(compositor, screen);
+
+ name_ptr = names;
+ for(i=0; i*5+4<values_length; ++i)
+ {
+ CompositedMonitor *monitor;
+
+ if(name_ptr>=names+names_length)
+ break;
+
+ monitor = find_monitor_by_name(screen, name_ptr);
+ if(monitor)
+ {
+ monitor->keystone_vertical = values[i*5]/4096.0f;
+ monitor->curvature_type = values[i*5+1];
+ monitor->curvature_depth = values[i*5+2]/4096.0f;
+ monitor->vertical_center = values[i*5+3]/4096.0f;
+ monitor->perspective = values[i*5+4]/4096.0f;
+
+ if(monitor->enabled)
+ update_monitor_vertices(screen, monitor);
+ }
+
+ name_ptr += strlen(name_ptr)+1;
+ }
+
+ XFree(names);
+ XFree(values);
+}
+
+void update_root_pixmap(Compositor *compositor, CompositedScreen *screen)
+{
+ Atom prop_type;
+ int prop_format;
+ unsigned long overflow;
+ unsigned long length;
+ long *pixmap;
+ Window root;
+ int x, y;
+ unsigned width;
+ unsigned height;
+ unsigned border;
+ unsigned depth;
+
+ use_gl(compositor, screen);
+
+ if(screen->root_glx_pixmap)
+ {
+ glXDestroyPixmap(compositor->display, screen->root_glx_pixmap);
+ screen->root_glx_pixmap = None;
+ }
+
+ XGetWindowProperty(compositor->display, screen->root, compositor->root_pmap_atom, 0, 1, False, XA_PIXMAP,
+ &prop_type, &prop_format, &length, &overflow, (unsigned char **)&pixmap);
+ if(prop_type!=XA_PIXMAP || prop_format!=32)
+ {
+ screen->root_pixmap = None;
+ return;
+ }
+
+ screen->root_pixmap = pixmap[0];
+ if(XGetGeometry(compositor->display, screen->root_pixmap, &root, &x, &y, &width, &height, &border, &depth))
+ screen->root_glx_pixmap = pixmap_to_glx_pixmap(compositor, screen, screen->root_pixmap);
+ else
+ screen->root_pixmap = None;
+
+ XFree(pixmap);
+}
+