Estaba tratando de encontrar todos los monitores y sus coordenadas (width w
, height h
, x origin/top-left-most x
, y y origin/top-left-most y
) y estaba usando este código, funciona bien en algunos sistemas . Pero en otros sistemas obtengo entradas falsas y duplicadas. ¿Sería capaz de evitar estas entradas de monitor duplicadas/falsas si probara si el monitor es un espejo? ¿Cómo probar si es un espejo?
Así que este es mi código:
// start - get all monitor resolutions var screen = XRRGetScreenResources(getXOpenDisplay(), getDefaultRootWindow(getXOpenDisplay())); var noutputs = screen.noutput; for (var i=noutputs-1; i>=0; i--) { var info = XRRGetOutputInfo(getXOpenDisplay(), screen, screen.outputs[i]); if (info.connection == RR_Connected) { var ncrtcs = info.ncrtc; for (var j=ncrtcs-1; j>=0; j--) { var crtc_info = XRRGetCrtcInfo(getXOpenDisplay(), screen, infoCrtcs[j]); console.info('screen #' + i + ' mon#' + j + ' details:', crtc_info.x, crtc_info.y, crtc_info.width, crtc_info.height); collMonInfos.push({ x: crtc_info.x, y: crtc_info.y, w: crtc_info.width, h: crtc_info.height }); XRRFreeCrtcInfo(crtc_info); } } XRRFreeOutputInfo(info); } XRRFreeScreenResources(screen); console.info('JSON:', JSON.stringify(collMonInfos)); // end - get all monitor resolutions
Y esto genera esto para iniciar sesión:
"screen #4 mon#0 details:" 0 0 0 0 "screen #3 mon#1 details:" 0 0 1920 1200 "screen #3 mon#0 details:" 1920 469 1366 768 "screen #2 mon#1 details:" 0 0 1920 1200 "screen #2 mon#0 details:" 1920 469 1366 768 "screen #1 mon#1 details:" 0 0 1920 1200 "screen #1 mon#0 details:" 1920 469 1366 768 "screen #0 mon#1 details:" 0 0 1920 1200 "screen #0 mon#0 details:" 1920 469 1366 768
Esto es todo en formato JSON:
[{ "x": 0, "y": 0, "w": 0, "h": 0 }, { "x": 0, "y": 0, "w": 1920, "h": 1200 }, { "x": 1920, "y": 469, "w": 1366, "h": 768 }, { "x": 0, "y": 0, "w": 1920, "h": 1200 }, { "x": 1920, "y": 469, "w": 1366, "h": 768 }, { "x": 0, "y": 0, "w": 1920, "h": 1200 }, { "x": 1920, "y": 469, "w": 1366, "h": 768 }, { "x": 0, "y": 0, "w": 1920, "h": 1200 }, { "x": 1920, "y": 469, "w": 1366, "h": 768 }]
Realmente solo tengo 2 monitores, el de 1920x1200 y el de 1366x768. ¿Cómo es que todas las demás entradas y cómo probar para evitar (en lugar de filtrar en retrospectiva en función de duplicados o 0 h/w)?
Está iterando innecesariamente sobre cada salida y luego sobre cada monitor . Así que recibe entradas duplicadas. No tiene que llamar a XRRGetOutputInfo
para cada salida, ya que todos los datos que necesita (número de monitores) se pueden encontrar en la estructura devuelta por XRRGetScreenResources
. Aquí está el código C que funciona (al menos para mí):
#include <stdio.h> #include <stdlib.h> #include <X11/Xlib.h> #include <X11/extensions/Xrandr.h> int main(void) { Display *d = XOpenDisplay(getenv("DISPLAY")); Window w = DefaultRootWindow(d); XRRScreenResources *xrrr = XRRGetScreenResources(d, w); XRRCrtcInfo *xrrci; int i; int ncrtc = xrrr->ncrtc; for (i = 0; i < ncrtc; ++i) { xrrci = XRRGetCrtcInfo(d, xrrr, xrrr->crtcs[i]); printf("%dx%d+%d+%d\n", xrrci->width, xrrci->height, xrrci->x, xrrci->y); XRRFreeCrtcInfo(xrrci); } XRRFreeScreenResources(xrrr); return 0; }
La respuesta aceptada no funcionó para mí. La forma correcta que encontré de hacer esto fue esta:
#include <stdio.h> #include <stdlib.h> #include <X11/Xlib.h> #include <X11/extensions/Xrandr.h> int main(void) { Display *display = XOpenDisplay(NULL); if (NULL == display) { perror("No DISPLAY in environment!"); exit(EXIT_FAILURE); } Window window = DefaultRootWindow(display); XRRScreenResources *screenr = XRRGetScreenResources(display, window); // This is the key right here. Use XRRScreenResources::noutput int output = screenr->noutput; for (int i = 0; i < output; ++i) { XRROutputInfo* out_info = XRRGetOutputInfo(display, screenr, screenr->outputs[i]); if (NULL != out_info && out_info->connection == RR_Connected) { XRRCrtcInfo* crt_info = XRRGetCrtcInfo(display, screenr, out_info->crtc); printf("%s\t%dx%d+%d+%d\n", out_info->name, crt_info->width, crt_info->height, crt_info->x, crt_info->y); XRRFreeCrtcInfo(crt_info); } XRRFreeOutputInfo(out_info); } XRRFreeScreenResources(screenr); XCloseDisplay(display); return 0; }
Como dije en el comentario del código, el truco es usar XRRScreenResources::noutput
en lugar de XRRScreenResources::ncrtc