From d06730e94320175d40ff6f2bb38dce55312f2e54 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 16 Dec 2014 01:57:45 -0800 Subject: Add monitor support (v2) This adds the ability to query, set and delete monitors v2: [airlied] add list active monitors Reviewed-by: Dave Airlie Signed-off-by: Keith Packard --- configure.ac | 2 +- xrandr.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 222 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 162618c..a357337 100644 --- a/configure.ac +++ b/configure.ac @@ -39,7 +39,7 @@ XORG_DEFAULT_OPTIONS AC_CHECK_LIB(m,floor) # Checks for pkg-config packages -PKG_CHECK_MODULES(XRANDR, xrandr >= 1.4 xrender x11 xproto >= 7.0.17) +PKG_CHECK_MODULES(XRANDR, xrandr >= 1.5 xrender x11 xproto >= 7.0.17) AC_CONFIG_FILES([ Makefile diff --git a/xrandr.c b/xrandr.c index c65fd7e..8a34542 100644 --- a/xrandr.c +++ b/xrandr.c @@ -153,7 +153,11 @@ usage(void) " --delmode \n" " --listproviders\n" " --setprovideroutputsource \n" - " --setprovideroffloadsink \n"); + " --setprovideroffloadsink \n" + " --listmonitors\n" + " --listactivemonitors\n" + " --setmonitor {auto|/x/++} {none|,,...}\n" + " --delmonitor \n"); } static void _X_NORETURN _X_ATTRIBUTE_PRINTF(1,2) @@ -304,6 +308,8 @@ typedef struct _transform transform_t; typedef struct _umode umode_t; typedef struct _output_prop output_prop_t; typedef struct _provider provider_t; +typedef struct _monitors monitors_t; +typedef struct _umonitor umonitor_t; struct _transform { XTransform transform; @@ -397,6 +403,22 @@ struct _provider { XRRProviderInfo *info; }; +struct _monitors { + int n; + XRRMonitorInfo *monitors; +}; + +struct _umonitor { + struct _umonitor *next; + char *name; + Bool set; + Bool primary; + int x, y, width, height; + int mmwidth, mmheight; + int noutput; + name_t *outputs; +}; + static const char *connection[3] = { "connected", "disconnected", @@ -431,7 +453,10 @@ static int minWidth, maxWidth, minHeight, maxHeight; static Bool has_1_2 = False; static Bool has_1_3 = False; static Bool has_1_4 = False; +static Bool has_1_5 = False; static name_t provider_name, output_source_provider_name, offload_sink_provider_name; +static monitors_t *monitors; +static umonitor_t *umonitors; static int mode_height (XRRModeInfo *mode_info, Rotation rotation) @@ -2556,6 +2581,22 @@ find_provider (name_t *name) exit (1); } +static void +get_monitors(Bool get_active) +{ + XRRMonitorInfo *m; + int n; + + if (!has_1_5 || monitors) + return; + + m = XRRGetMonitors(dpy, root, get_active, &n); + if (n == -1) + fatal("get monitors failed\n"); + monitors = calloc(1, sizeof (monitors_t)); + monitors->n = n; + monitors->monitors = m; +} int main (int argc, char **argv) @@ -2595,6 +2636,9 @@ main (int argc, char **argv) Bool list_providers = False; Bool provsetoutsource = False; Bool provsetoffsink = False; + Bool monitorit = False; + Bool list_monitors = False; + Bool list_active_monitors = False; int major, minor; Bool current = False; Bool toggle_x = False; @@ -3130,6 +3174,72 @@ main (int argc, char **argv) provsetoffsink = True; continue; } + if (!strcmp("--listmonitors", argv[i])) + { + list_monitors = True; + action_requested = True; + continue; + } + if (!strcmp("--listactivemonitors", argv[i])) + { + list_active_monitors = True; + action_requested = True; + continue; + } + if (!strcmp("--setmonitor", argv[i])) + { + umonitor_t *m = calloc(1, sizeof (umonitor_t)), **l; + char *t; + char *o; + char *n; + char *geom; + + if (i+3 >= argc) argerr("%s requires three argument\n", argv[i]); + n = argv[++i]; + if (*n == '*') { + m->primary = True; + n++; + } + m->name = n; + m->set = True; + geom = argv[++i]; + + if (strncmp (geom, "auto", 4) != 0) { + if (sscanf(geom, "%d/%dx%d/%d+%d+%d", + &m->width, &m->mmwidth, &m->height, &m->mmheight, &m->x, &m->y) != 6) + argerr ("failed to parse '%s' as monitor geometry\n", argv[i]); + } + + o = argv[++i]; + if (strcmp(o, "none") != 0) { + printf ("output list %s\n", o); + for (; (t = strtok(o, ",")) != NULL; o = NULL) { + m->outputs = realloc(m->outputs, (m->noutput + 1) * sizeof (name_t)); + printf ("add monitor %s\n", t); + set_name(&m->outputs[m->noutput++], t, name_string|name_xid|name_index); + printf ("output name %s\n", m->outputs[m->noutput-1].string); + } + } + for (l = &umonitors; *l; l = &((*l)->next)); + *l = m; + action_requested = True; + monitorit = True; + continue; + } + if (!strcmp("--delmonitor", argv[i])) + { + umonitor_t *m = calloc(1, sizeof (umonitor_t)), **l; + + if (++i >= argc) argerr("%s requires an argument\n", argv[i-1]); + + m->name = argv[i]; + m->set = False; + for (l = &umonitors; *l; l = &((*l)->next)); + *l = m; + action_requested = True; + monitorit = True; + continue; + } argerr ("unrecognized option '%s'\n", argv[i]); } @@ -3172,7 +3282,8 @@ main (int argc, char **argv) has_1_3 = True; if (major > 1 || (major == 1 && minor >= 4)) has_1_4 = True; - + if (major > 1 || (major == 1 && minor >= 5)) + has_1_5 = True; if (has_1_2 && modeit) { umode_t *m; @@ -3216,7 +3327,7 @@ main (int argc, char **argv) break; } } - if (!setit_1_2) + if (!propit && !setit_1_2 && !monitorit) { XSync (dpy, False); exit (0); @@ -3427,6 +3538,73 @@ main (int argc, char **argv) */ apply (); + if (!monitorit) { + XSync (dpy, False); + exit (0); + } + } + if (monitorit) { + umonitor_t *u; + Atom name; + + if (!has_1_5) { + printf("RandR 1.5 not supported\n"); + exit(0); + } + + get_screen(current); + get_monitors(True); + get_crtcs(); + get_outputs(); + + for (u = umonitors; u; u = u->next) { + if (u->set) { + XRRMonitorInfo *m; + int o; + + name = XInternAtom(dpy, u->name, False); + m = XRRAllocateMonitor(dpy, u->noutput); + + m->name = name; + m->primary = u->primary; + m->x = u->x; + m->y = u->y; + m->width = u->width; + m->height = u->height; + m->mwidth = u->mmwidth; + m->mheight = u->mmheight; + for (o = 0; o < u->noutput; o++) { + output_t *output = find_output(&u->outputs[o]); + if (!output) + fatal("cannot find output\n"); + m->outputs[o] = output->output.xid; + } + + XRRSetMonitor(dpy, root, m); + + XRRFreeMonitors(m); + } else { + int m; + + name = XInternAtom(dpy, u->name, True); + if (!name) { + printf("No monitor named '%s'\n", u->name); + } else { + if (!monitors) + printf ("No monitors\n"); + else { + for (m = 0; m < monitors->n; m++) { + if (monitors->monitors[m].name == name) + break; + } + if (m == monitors->n) + printf("No monitor named '%s'\n", u->name); + else + XRRDeleteMonitor(dpy, root, name); + } + } + } + } XSync (dpy, False); exit (0); } @@ -3764,6 +3942,46 @@ main (int argc, char **argv) } } } + if (list_monitors || list_active_monitors) { + + if (!has_1_5) { + printf("RandR 1.5 not supported\n"); + exit(0); + } + + get_screen(current); + get_monitors(list_active_monitors ? True : False); + get_crtcs(); + get_outputs(); + + if (monitors) { + int m, o; + + printf("Monitors: %d\n", monitors->n); + + for (m = 0; m < monitors->n; m++) { + printf (" %d: %s%s%s %d/%dx%d/%d+%d+%d ", + m, + monitors->monitors[m].automatic ? "+" : "", + monitors->monitors[m].primary ? "*" : "", + XGetAtomName(dpy, monitors->monitors[m].name), + monitors->monitors[m].width, + monitors->monitors[m].mwidth, + monitors->monitors[m].height, + monitors->monitors[m].mheight, + monitors->monitors[m].x, + monitors->monitors[m].y); + for (o = 0; o < monitors->monitors[m].noutput; o++) { + output_t *output = find_output_by_xid(monitors->monitors[m].outputs[o]); + if (output) + printf (" %s", output->output.string); + else + printf (" unknown output 0x%x\n", (CARD32) monitors->monitors[m].outputs[o]); + } + printf ("\n"); + } + } + } sc = XRRGetScreenInfo (dpy, root); -- cgit v1.2.3