/* In the case of multiple outputs of a single crtc (mirroring), we consider one of the
 * outputs the "main". This is the one we consider "owning" the windows, so if
 * the mirroring is changed to a dual monitor setup then the windows are moved to the
 * crtc that now has that main output. If one of the outputs is the primary that is
 * always the main, otherwise we just use the first.
 */
static XID
find_main_output_for_crtc (XRRScreenResources *resources,
                           XRRCrtcInfo        *crtc,
                           Display            *xdisplay,
                           XID                 xroot)
{
    XRROutputInfo *output;
    RROutput primary_output;
    int i;
    XID res;

    primary_output = XRRGetOutputPrimary (xdisplay, xroot);

    res = None;
    for (i = 0; i < crtc->noutput; i++)
    {
        output = XRRGetOutputInfo (xdisplay, resources, crtc->outputs[i]);
        if (output->connection != RR_Disconnected &&
            (res == None || crtc->outputs[i] == primary_output))
        {
            res = crtc->outputs[i];
        }

        XRRFreeOutputInfo (output);
    }

    return res;
}
Exemple #2
0
static void dumpOutput(const char *prefix, Display *dpy, int screen_idx, XRRScreenResources *resources, int outputIdx, RROutput output) {
    int i, j, primIdx=0;
    Window root = RootWindow(dpy, screen_idx);
    RROutput pxid = XRRGetOutputPrimary (dpy, root);
    int isPrim =0;
    if ( None != pxid && pxid == output ) {
        primIdx = i;
        isPrim = 1;
    }
    XRROutputInfo * xrrOutputInfo = XRRGetOutputInfo (dpy, resources, output);
    fprintf(stderr, "%s: Output[%d]: id %#lx, crtx 0x%lX, name %s (%d), %lux%lu, ncrtc %d, nclone %d, nmode %d (preferred %d), primary %d\n", 
        prefix, outputIdx, output, xrrOutputInfo->crtc, SAFE_STRING(xrrOutputInfo->name), xrrOutputInfo->nameLen, 
        xrrOutputInfo->mm_width, xrrOutputInfo->mm_height,
        xrrOutputInfo->ncrtc, xrrOutputInfo->nclone, xrrOutputInfo->nmode, xrrOutputInfo->npreferred, isPrim);
    for(j=0; j<xrrOutputInfo->ncrtc; j++) {
        fprintf(stderr, "%s: Output[%d].Crtc[%d].id %#lx\n", prefix, i, j, xrrOutputInfo->crtcs[j]);
    }
    for(j=0; j<xrrOutputInfo->nclone; j++) {
        fprintf(stderr, "%s: Output[%d].Clones[%d].id %#lx\n", prefix, i, j, xrrOutputInfo->clones[j]);
    }
    for(j=0; j<xrrOutputInfo->nmode; j++) {
        fprintf(stderr, "%s: Output[%d].Mode[%d].id %#lx\n", prefix, i, j, xrrOutputInfo->modes[j]);
    }
    XRRFreeOutputInfo (xrrOutputInfo);
}
Exemple #3
0
MonitorManager *monitor_mgr_create()
{
    Display *display = XOpenDisplay(NULL);
    if (!display)
    {
        fprintf(stderr, "Cannot open display.\n");
        return NULL;
    }

    MonitorManager *mgr = malloc(sizeof(MonitorManager*));
    mgr->monitor_count = 0;
    mgr->monitors = NULL;

    Window root = DefaultRootWindow(display);
    RROutput primary_output = XRRGetOutputPrimary(display, root);

    XRRScreenResources *screen = XRRGetScreenResources(display, root);
    assert(screen);

    for (int i = 0; i < screen->noutput; i++)
    {
        XRROutputInfo *output_info = XRRGetOutputInfo(
            display, screen, screen->outputs[i]);
        assert(output_info);

        if (output_info->connection == RR_Connected)
        {
            XRRCrtcInfo *crtc_info = XRRGetCrtcInfo(
                display, screen, output_info->crtc);
            assert(crtc_info);

            int primary = 0;
            for (int j = 0; j < crtc_info->noutput; j++)
                if (crtc_info->outputs[j] == primary_output)
                    primary = 1;

            Monitor *monitor = monitor_create(
                primary,
                crtc_info->x,
                crtc_info->y,
                crtc_info->width,
                crtc_info->height);
            assert(monitor);

            monitor_mgr_add(mgr, monitor);

            XRRFreeCrtcInfo(crtc_info);
        }

        XRRFreeOutputInfo(output_info);
    }

    XRRFreeScreenResources(screen);
    XCloseDisplay(display);
    return mgr;
}
Exemple #4
0
std::vector<display> display::enumerate()
{
	std::vector<display> result;

	if (randr.is_available)
	{
		RROutput const primary = XRRGetOutputPrimary(g_display, g_root);

		XRRScreenResources* sr = XRRGetScreenResources(g_display, g_root);
		for (int i = 0; i < sr->ncrtc; ++i)
		{
			XRRCrtcInfo* info = XRRGetCrtcInfo(g_display, sr, sr->crtcs[i]);

			if (info->noutput)
			{
				RROutput* output = std::find_if(info->outputs, info->outputs + info->noutput,
					[primary](RROutput output) { return output == primary; });
				if (output == info->outputs + info->noutput)
				{
					output = info->outputs;
				}

				display disp = init(sr, *output);
				if (!disp.name.empty())
				{
					result.emplace_back(disp);
				}
			}
			XRRFreeCrtcInfo(info);
		}
		XRRFreeScreenResources(sr);

		std::vector<display>::iterator it = std::find_if(result.begin(), result.end(),
			[primary](display const& disp) { return disp.output == primary; });
		if (it != result.begin() && it != result.end())
		{
			std::iter_swap(it, result.begin());
		}
	}
	else
	{
		result.push_back(primary());
	}

	return result;
}
Exemple #5
0
display display::from_window(window const* w)
{
	Window root = w? *w : g_root;
	display result;
	if (randr.is_available)
	{
		XRRScreenResources* sr = XRRGetScreenResources(g_display, root);
		RROutput primary = XRRGetOutputPrimary(g_display, g_root);
		result = init(sr, primary);
		XRRFreeScreenResources(sr);
	}
	else
	{
		result.scale = 1;
		result.color_depth = XDefaultDepth(g_display, g_screen);
		result.color_depth_per_component = result.color_depth >= 24? 8 : 0;
		result.rect = result.work_rect = rectangle<int>(0, 0,
			DisplayWidthMM(g_display, g_screen), DisplayHeightMM(g_display, g_screen));
	}
	return result;
}
Exemple #6
0
static gboolean
fill_out_screen_info (Display *xdisplay,
		      Window xroot,
		      ScreenInfo *info,
		      gboolean needs_reprobe,
		      GError **error)
{
#ifdef HAVE_RANDR
    XRRScreenResources *resources;
    
    g_assert (xdisplay != NULL);
    g_assert (info != NULL);

    /* First update the screen resources */

    if (needs_reprobe)
        resources = XRRGetScreenResources (xdisplay, xroot);
    else
    {
	/* XRRGetScreenResourcesCurrent is less expensive than
	 * XRRGetScreenResources, however it is available only
	 * in RandR 1.3 or higher
	 */
#if (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3))
        /* Runtime check for RandR 1.3 or higher */
        if (info->screen->rr_major_version == 1 && info->screen->rr_minor_version >= 3)
            resources = XRRGetScreenResourcesCurrent (xdisplay, xroot);
        else
            resources = XRRGetScreenResources (xdisplay, xroot);
#else
        resources = XRRGetScreenResources (xdisplay, xroot);
#endif
    }

    if (resources)
    {
	if (!fill_screen_info_from_resources (info, resources, error))
	    return FALSE;
    }
    else
    {
	g_set_error (error, MATE_RR_ERROR, MATE_RR_ERROR_RANDR_ERROR,
		     /* Translators: a CRTC is a CRT Controller (this is X terminology). */
		     _("could not get the screen resources (CRTCs, outputs, modes)"));
	return FALSE;
    }

    /* Then update the screen size range.  We do this after XRRGetScreenResources() so that
     * the X server will already have an updated view of the outputs.
     */

    if (needs_reprobe) {
	gboolean success;

        gdk_error_trap_push ();
	success = XRRGetScreenSizeRange (xdisplay, xroot,
					 &(info->min_width),
					 &(info->min_height),
					 &(info->max_width),
					 &(info->max_height));
	gdk_flush ();
	if (gdk_error_trap_pop ()) {
	    g_set_error (error, MATE_RR_ERROR, MATE_RR_ERROR_UNKNOWN,
			 _("unhandled X error while getting the range of screen sizes"));
	    return FALSE;
	}

	if (!success) {
	    g_set_error (error, MATE_RR_ERROR, MATE_RR_ERROR_RANDR_ERROR,
			 _("could not get the range of screen sizes"));
            return FALSE;
        }
    }
    else
    {
        mate_rr_screen_get_ranges (info->screen, 
					 &(info->min_width),
					 &(info->max_width),
					 &(info->min_height),
					 &(info->max_height));
    }

    info->primary = None;
#if (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3))
    /* Runtime check for RandR 1.3 or higher */
    if (info->screen->rr_major_version == 1 && info->screen->rr_minor_version >= 3) {
        gdk_error_trap_push ();
        info->primary = XRRGetOutputPrimary (xdisplay, xroot);
      #if GTK_CHECK_VERSION (3, 0, 0)
	gdk_error_trap_pop_ignored ();
      #else
	gdk_flush ();
	gdk_error_trap_pop (); /* ignore error */
      #endif
    }
#endif

    return TRUE;
#else
    return FALSE;
#endif /* HAVE_RANDR */
}
static void
xfce_randr_populate (XfceRandr *randr,
                     Display   *xdisplay,
                     GdkWindow *root_window)
{
    GPtrArray     *outputs;
    XRROutputInfo *output_info;
    XRRCrtcInfo   *crtc_info;
    gint           n;
    guint          m;

    g_return_if_fail (randr != NULL);
    g_return_if_fail (randr->priv != NULL);
    g_return_if_fail (randr->priv->resources != NULL);

    /* prepare the temporary cache */
    outputs = g_ptr_array_new ();

    /* walk the outputs */
    for (n = 0; n < randr->priv->resources->noutput; ++n)
    {
        /* get the output info */
        output_info = XRRGetOutputInfo (xdisplay, randr->priv->resources,
                                        randr->priv->resources->outputs[n]);

        /* forget about disconnected outputs */
        if (output_info->connection != RR_Connected)
        {
            XRRFreeOutputInfo (output_info);
            continue;
        }

        /* cache it */
        g_ptr_array_add (outputs, output_info);
    }

    /* migrate the temporary cache */
    randr->noutput = outputs->len;
    randr->priv->output_info = (XRROutputInfo **) g_ptr_array_free (outputs, FALSE);

    /* allocate final space for the settings */
    randr->mode = g_new0 (RRMode, randr->noutput);
    randr->priv->modes = g_new0 (XfceRRMode *, randr->noutput);
    randr->priv->position = g_new0 (XfceOutputPosition, randr->noutput);
    randr->rotation = g_new0 (Rotation, randr->noutput);
    randr->rotations = g_new0 (Rotation, randr->noutput);
    randr->relation = g_new0 (XfceOutputRelation, randr->noutput);
    randr->related_to = g_new0 (guint, randr->noutput);
    randr->status = g_new0 (XfceOutputStatus, randr->noutput);
    randr->friendly_name = g_new0 (gchar *, randr->noutput);

    /* walk the connected outputs */
    for (m = 0; m < randr->noutput; ++m)
    {
        /* fill in supported modes */
        randr->priv->modes[m] = xfce_randr_list_supported_modes (randr->priv->resources, randr->priv->output_info[m]);

#ifdef HAS_RANDR_ONE_POINT_THREE
        /* find the primary screen if supported */
        if (randr->priv->has_1_3 && XRRGetOutputPrimary (xdisplay, GDK_WINDOW_XID (root_window)) == randr->priv->resources->outputs[m])
            randr->status[m] = XFCE_OUTPUT_STATUS_PRIMARY;
        else
#endif
            randr->status[m] = XFCE_OUTPUT_STATUS_SECONDARY;

        if (randr->priv->output_info[m]->crtc != None)
        {
            crtc_info = XRRGetCrtcInfo (xdisplay, randr->priv->resources,
                                        randr->priv->output_info[m]->crtc);
            randr->mode[m] = crtc_info->mode;
            randr->rotation[m] = crtc_info->rotation;
            randr->rotations[m] = crtc_info->rotations;
            randr->priv->position[m].x = crtc_info->x;
            randr->priv->position[m].y = crtc_info->y;
            XRRFreeCrtcInfo (crtc_info);
        }
        else
        {
            /* output disabled */
            randr->mode[m] = None;
            randr->rotation[m] = RR_Rotate_0;
            randr->rotations[m] = xfce_randr_get_safe_rotations (randr, xdisplay, m);
        }

        /* fill in the name used by the UI */
        randr->friendly_name[m] = xfce_randr_friendly_name (randr, m);
    }

    /* calculate relations from positions */
    xfce_randr_guess_relations (randr);
}
Exemple #8
0
static gboolean
init_randr13 (GdkScreen *screen)
{
#ifdef HAVE_RANDR
  GdkDisplay *display = gdk_screen_get_display (screen);
  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
  GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
  Display *dpy = GDK_SCREEN_XDISPLAY (screen);
  XRRScreenResources *resources;
  RROutput primary_output;
  RROutput first_output = None;
  int i;
  GArray *monitors;
  gboolean randr12_compat = FALSE;

  if (!display_x11->have_randr13)
      return FALSE;

  resources = XRRGetScreenResourcesCurrent (x11_screen->xdisplay,
				            x11_screen->xroot_window);
  if (!resources)
    return FALSE;

  monitors = g_array_sized_new (FALSE, TRUE, sizeof (GdkX11Monitor),
                                resources->noutput);

  for (i = 0; i < resources->noutput; ++i)
    {
      XRROutputInfo *output =
	XRRGetOutputInfo (dpy, resources, resources->outputs[i]);

      /* Non RandR1.2 X driver have output name "default" */
      randr12_compat |= !g_strcmp0 (output->name, "default");

      if (output->connection == RR_Disconnected)
        {
          XRRFreeOutputInfo (output);
          continue;
        }

      if (output->crtc)
	{
	  GdkX11Monitor monitor;
	  XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, output->crtc);

	  monitor.geometry.x = crtc->x;
	  monitor.geometry.y = crtc->y;
	  monitor.geometry.width = crtc->width;
	  monitor.geometry.height = crtc->height;

	  monitor.output = resources->outputs[i];
	  monitor.width_mm = output->mm_width;
	  monitor.height_mm = output->mm_height;
	  monitor.output_name = g_strdup (output->name);
	  /* FIXME: need EDID parser */
	  monitor.manufacturer = NULL;

	  g_array_append_val (monitors, monitor);

          XRRFreeCrtcInfo (crtc);
	}

      XRRFreeOutputInfo (output);
    }

  if (resources->noutput > 0)
    first_output = resources->outputs[0];

  XRRFreeScreenResources (resources);

  /* non RandR 1.2 X driver doesn't return any usable multihead data */
  if (randr12_compat)
    {
      guint n_monitors = monitors->len;

      free_monitors ((GdkX11Monitor *)g_array_free (monitors, FALSE),
		     n_monitors);

      return FALSE;
    }

  g_array_sort (monitors,
                (GCompareFunc) monitor_compare_function);
  x11_screen->n_monitors = monitors->len;
  x11_screen->monitors = (GdkX11Monitor *)g_array_free (monitors, FALSE);

  x11_screen->primary_monitor = 0;

  primary_output = XRRGetOutputPrimary (x11_screen->xdisplay,
                                        x11_screen->xroot_window);

  for (i = 0; i < x11_screen->n_monitors; ++i)
    {
      if (x11_screen->monitors[i].output == primary_output)
	{
	  x11_screen->primary_monitor = i;
	  break;
	}

      /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */
      if (primary_output == None &&
          g_ascii_strncasecmp (x11_screen->monitors[i].output_name, "LVDS", 4) == 0)
	{
	  x11_screen->primary_monitor = i;
	  break;
	}

      /* No primary specified and no LVDS found */
      if (x11_screen->monitors[i].output == first_output)
	x11_screen->primary_monitor = i;
    }

  return x11_screen->n_monitors > 0;
#endif

  return FALSE;
}
static gboolean
panel_multiscreen_get_randr_monitors_for_screen (GdkScreen     *screen,
						 int           *monitors_ret,
						 GdkRectangle **geometries_ret)
{
#ifdef HAVE_RANDR
	Display            *xdisplay;
	Window              xroot;
	XRRScreenResources *resources;
	RROutput            primary;
	GArray             *geometries;
	int                 i;
	gboolean            driver_is_pre_randr_1_2;

	if (!have_randr)
		return FALSE;

	/* GTK+ 2.14.x uses the Xinerama API, instead of RANDR, to get the
	 * monitor geometries. It does this to avoid calling
	 * XRRGetScreenResources(), which is slow as it re-detects all the
	 * monitors --- note that XRRGetScreenResourcesCurrent() had not been
	 * introduced yet.  Using Xinerama in GTK+ has the bad side effect that
	 * gdk_screen_get_monitor_plug_name() will return NULL, as Xinerama
	 * does not provide that information, unlike RANDR.
	 *
	 * Here we need to identify the output names, so that we can put the
	 * built-in LCD in a laptop *before* all other outputs.  This is so
	 * that mate-panel will normally prefer to appear on the "native"
	 * display rather than on an external monitor.
	 *
	 * To get the output names and geometries, we will not use
	 * gdk_screen_get_n_monitors() and friends, but rather we will call
	 * XRR*() directly.
	 *
	 * See https://bugzilla.novell.com/show_bug.cgi?id=479684 for this
	 * particular bug, and and
	 * http://bugzilla.gnome.org/show_bug.cgi?id=562944 for a more
	 * long-term solution.
	 */

	xdisplay = GDK_SCREEN_XDISPLAY (screen);
#if GTK_CHECK_VERSION (3, 0, 0)
	xroot = GDK_WINDOW_XID (gdk_screen_get_root_window (screen));
#else
	xroot = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
#endif

#if (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3))
	if (have_randr_1_3) {
		resources = XRRGetScreenResourcesCurrent (xdisplay, xroot);
		if (resources->noutput == 0) {
			/* This might happen if nothing tried to get randr
			 * resources from the server before, so we need an
			 * active probe. See comment #27 in
			 * https://bugzilla.gnome.org/show_bug.cgi?id=597101 */
			XRRFreeScreenResources (resources);
			resources = XRRGetScreenResources (xdisplay, xroot);
		}
	} else
		resources = XRRGetScreenResources (xdisplay, xroot);
#else
	resources = XRRGetScreenResources (xdisplay, xroot);
#endif

	if (!resources)
		return FALSE;

	primary = None;
#if (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3))
	if (have_randr_1_3)
		primary = XRRGetOutputPrimary (xdisplay, xroot);
#endif

	geometries = g_array_sized_new (FALSE, FALSE,
					sizeof (GdkRectangle),
					resources->noutput);

	driver_is_pre_randr_1_2 = FALSE;

	for (i = 0; i < resources->noutput; i++) {
		XRROutputInfo *output;

		output = XRRGetOutputInfo (xdisplay, resources,
					   resources->outputs[i]);

		/* Drivers before RANDR 1.2 return "default" for the output
		 * name */
		if (g_strcmp0 (output->name, "default") == 0)
			driver_is_pre_randr_1_2 = TRUE;

		if (output->connection != RR_Disconnected &&
		    output->crtc != 0) {
			XRRCrtcInfo  *crtc;
			GdkRectangle  rect;

			crtc = XRRGetCrtcInfo (xdisplay, resources,
					       output->crtc);

			rect.x	    = crtc->x;
			rect.y	    = crtc->y;
			rect.width  = crtc->width;
			rect.height = crtc->height;

			XRRFreeCrtcInfo (crtc);

			if (_panel_multiscreen_output_should_be_first (xdisplay,
								       resources->outputs[i],
								       output, primary))
				g_array_prepend_vals (geometries, &rect, 1);
			else
				g_array_append_vals (geometries, &rect, 1);
		}

		XRRFreeOutputInfo (output);
	}

	XRRFreeScreenResources (resources);

	if (driver_is_pre_randr_1_2) {
		/* Drivers before RANDR 1.2 don't provide useful info about
		 * outputs */
		g_array_free (geometries, TRUE);
		return FALSE;
	}

	if (geometries->len == 0) {
		/* This can happen in at least one case:
		 * https://bugzilla.novell.com/show_bug.cgi?id=543876 where all
		 * monitors appear disconnected (possibly because the  screen
		 * is behing a KVM switch) -- see comment #8.
		 * There might be other cases too, so we stay on the safe side.
		 */
		g_array_free (geometries, TRUE);
		return FALSE;
	}

	*monitors_ret = geometries->len;
	*geometries_ret = (GdkRectangle *) g_array_free (geometries, FALSE);

	return TRUE;
#else
	return FALSE;
#endif
}
Exemple #10
0
void get_monitors()
{
	if (XineramaIsActive(server.display)) {
		int num_monitors;
		XineramaScreenInfo *info = XineramaQueryScreens(server.display, &num_monitors);
		XRRScreenResources *res = XRRGetScreenResourcesCurrent(server.display, server.root_win);
		RROutput primary_output = XRRGetOutputPrimary(server.display, server.root_win);

		if (res && res->ncrtc >= num_monitors) {
			// use xrandr to identify monitors (does not work with proprietery nvidia drivers)

			// Workaround for issue https://gitlab.com/o9000/tint2/issues/353
			// on some recent configs, XRRGetScreenResourcesCurrent returns a fantom monitor at last position
			{
				int i = res->ncrtc - 1;
				XRRCrtcInfo *crtc_info = XRRGetCrtcInfo(server.display, res, res->crtcs[i]);
				if (!(crtc_info->x || crtc_info->y || crtc_info->width || crtc_info->height)) {
					res->ncrtc -= 1;
				}
				XRRFreeCrtcInfo(crtc_info);
			}

			printf("xRandr: Found crtc's: %d\n", res->ncrtc);
			server.monitors = calloc(res->ncrtc, sizeof(Monitor));
			for (int i = 0; i < res->ncrtc; ++i) {
				XRRCrtcInfo *crtc_info = XRRGetCrtcInfo(server.display, res, res->crtcs[i]);
				server.monitors[i].x = crtc_info->x;
				server.monitors[i].y = crtc_info->y;
				server.monitors[i].width = crtc_info->width;
				server.monitors[i].height = crtc_info->height;
				server.monitors[i].names = calloc((crtc_info->noutput + 1), sizeof(gchar *));
				for (int j = 0; j < crtc_info->noutput; ++j) {
					XRROutputInfo *output_info = XRRGetOutputInfo(server.display, res, crtc_info->outputs[j]);
					printf("xRandr: Linking output %s with crtc %d\n", output_info->name, i);
					server.monitors[i].names[j] = g_strdup(output_info->name);
					XRRFreeOutputInfo(output_info);
					server.monitors[i].primary = crtc_info->outputs[j] == primary_output;
				}
				server.monitors[i].names[crtc_info->noutput] = NULL;
				XRRFreeCrtcInfo(crtc_info);
			}
			num_monitors = res->ncrtc;
		} else if (info && num_monitors > 0) {
			server.monitors = calloc(num_monitors, sizeof(Monitor));
			for (int i = 0; i < num_monitors; i++) {
				server.monitors[i].x = info[i].x_org;
				server.monitors[i].y = info[i].y_org;
				server.monitors[i].width = info[i].width;
				server.monitors[i].height = info[i].height;
				server.monitors[i].names = 0;
			}
		}

		// Sort monitors by inclusion
		qsort(server.monitors, num_monitors, sizeof(Monitor), monitor_includes_monitor);

		// Remove monitors included in other ones
		int i = 0;
		while (i < num_monitors) {
			for (int j = 0; j < i; j++) {
				if (monitor_includes_monitor(&server.monitors[i], &server.monitors[j]) > 0) {
					goto next;
				}
			}
			i++;
		}
	next:
		for (int j = i; j < num_monitors; ++j)
			if (server.monitors[j].names)
				g_strfreev(server.monitors[j].names);
		server.num_monitors = i;
		server.monitors = realloc(server.monitors, server.num_monitors * sizeof(Monitor));
		qsort(server.monitors, server.num_monitors, sizeof(Monitor), compare_monitor_pos);

		if (res)
			XRRFreeScreenResources(res);
		XFree(info);
	}

	if (!server.num_monitors) {
		server.num_monitors = 1;
		server.monitors = calloc(1, sizeof(Monitor));
		server.monitors[0].x = server.monitors[0].y = 0;
		server.monitors[0].width = DisplayWidth(server.display, server.screen);
		server.monitors[0].height = DisplayHeight(server.display, server.screen);
		server.monitors[0].names = 0;
	}
}
Exemple #11
0
static int _gfx_x11_init_monitors(

		int  major,
		int  minor)
{
	/* Iterate over all screens */
	Screen* def = XDefaultScreenOfDisplay(_gfx_x11.display);
	unsigned int count = XScreenCount(_gfx_x11.display);

	while(count--)
	{
		/* Get screen resources */
		Screen* scr =
			XScreenOfDisplay(_gfx_x11.display, count);
		Window root =
			XRootWindowOfScreen(scr);
		XRRScreenResources* res =
			XRRGetScreenResources(_gfx_x11.display, root);
		RROutput prim =
			res->outputs[0];

		/* Get primary if RandR 1.3 is supported */
		if(major > 1 || (major == 1 && minor > 2))
			prim = XRRGetOutputPrimary(_gfx_x11.display, root);

		/* Insert the screen's display modes */
		size_t first = _gfx_x11_init_modes(scr, res);

		/* Iterate through outputs */
		unsigned int i;
		for(i = 0; i < res->noutput; ++i)
		{
			/* Validate output */
			XRROutputInfo* out =
				XRRGetOutputInfo(_gfx_x11.display, res, res->outputs[i]);

			if(out->connection != RR_Connected)
			{
				XRRFreeOutputInfo(out);
				continue;
			}

			/* Create new monitor */
			XRRCrtcInfo* crtc =
				XRRGetCrtcInfo(_gfx_x11.display, res, out->crtc);
			int rot =
				crtc->rotation & (RR_Rotate_90 | RR_Rotate_270);

			GFX_X11_Monitor mon =
			{
				.screen   = scr,
				.crtc     = out->crtc,
				.mode     = crtc->mode,
				.numModes = 0,
				.modes    = malloc(sizeof(size_t) * out->nmode),
				.x        = crtc->x,
				.y        = crtc->y,
				.width    = rot ? crtc->height : crtc->width,
				.height   = rot ? crtc->width : crtc->height
			};

			/* Retrieve output modes */
			unsigned int j;
			if(mon.modes) for(j = 0; j < out->nmode; ++j)
			{
				GFX_X11_Mode* mode;
				for(
					mode = gfx_vector_at(&_gfx_x11.modes, first);
					mode != _gfx_x11.modes.end;
					mode = gfx_vector_next(&_gfx_x11.modes, mode))
				{
					/* Also check if resolution isn't too big */
					if(
						mode->id == out->modes[j] &&
						mode->mode.width <= crtc->width &&
						mode->mode.height <= crtc->height)
					{
						mon.modes[mon.numModes++] = gfx_vector_get_index(
							&_gfx_x11.modes,
							mode
						);
						break;
					}
				}
			}

			/* Insert at beginning if primary */
			GFXVectorIterator monPos =
				scr == def && res->outputs[i] == prim ?
				_gfx_x11.monitors.begin : _gfx_x11.monitors.end;

			monPos = gfx_vector_insert(&_gfx_x11.monitors, &mon, monPos);
			if(monPos == _gfx_x11.monitors.end) free(mon.modes);

			XRRFreeCrtcInfo(crtc);
			XRRFreeOutputInfo(out);
		}

		XRRFreeScreenResources(res);
	}

	/* Need at least one monitor */
	return _gfx_x11.monitors.begin != _gfx_x11.monitors.end;
}

/******************************************************/
static GFXKey _gfx_x11_get_key(

		KeySym symbol)
{
	/* Unicode numbers */
	if(symbol >= XK_0 && symbol <= XK_9)
		return (GFXKey)(symbol - XK_0 + GFX_KEY_0);

	/* Keypad numbers */
	if(symbol >= XK_KP_0 && symbol <= XK_KP_9)
		return (GFXKey)(symbol - XK_KP_0 + GFX_KEY_KP_0);

	/* Unicode capitals */
	if(symbol >= XK_A && symbol <= XK_Z)
		return (GFXKey)(symbol - XK_A + GFX_KEY_A);

	/* Unicode lowercase */
	if(symbol >= XK_a && symbol <= XK_z)
		return (GFXKey)(symbol - XK_a + GFX_KEY_A);

	/* Function keys */
	if(symbol >= XK_F1 && symbol <= XK_F24)
		return (GFXKey)(symbol - XK_F1 + GFX_KEY_F1);

	/* Non-unicode */
	switch(symbol)
	{
		case XK_VoidSymbol   : return GFX_KEY_UNKNOWN;

		case XK_BackSpace    : return GFX_KEY_BACKSPACE;
		case XK_Tab          : return GFX_KEY_TAB;
		case XK_KP_Tab       : return GFX_KEY_TAB;
		case XK_Clear        : return GFX_KEY_CLEAR;
		case XK_Return       : return GFX_KEY_RETURN;
		case XK_Pause        : return GFX_KEY_PAUSE;
		case XK_Scroll_Lock  : return GFX_KEY_SCROLL_LOCK;
		case XK_Escape       : return GFX_KEY_ESCAPE;
		case XK_Delete       : return GFX_KEY_DELETE;
		case XK_KP_Delete    : return GFX_KEY_DELETE;

		case XK_Home         : return GFX_KEY_HOME;
		case XK_KP_Home      : return GFX_KEY_HOME;
		case XK_Left         : return GFX_KEY_LEFT;
		case XK_KP_Left      : return GFX_KEY_LEFT;
		case XK_Up           : return GFX_KEY_UP;
		case XK_KP_Up        : return GFX_KEY_UP;
		case XK_Right        : return GFX_KEY_RIGHT;
		case XK_KP_Right     : return GFX_KEY_RIGHT;
		case XK_Down         : return GFX_KEY_DOWN;
		case XK_KP_Down      : return GFX_KEY_DOWN;
		case XK_Page_Down    : return GFX_KEY_PAGE_DOWN;
		case XK_KP_Page_Down : return GFX_KEY_PAGE_DOWN;
		case XK_Page_Up      : return GFX_KEY_PAGE_UP;
		case XK_KP_Page_Up   : return GFX_KEY_PAGE_UP;
		case XK_End          : return GFX_KEY_END;
		case XK_KP_End       : return GFX_KEY_END;

		case XK_Select       : return GFX_KEY_SELECT;
		case XK_Print        : return GFX_KEY_PRINT;
		case XK_Execute      : return GFX_KEY_EXECUTE;
		case XK_Insert       : return GFX_KEY_INSERT;
		case XK_KP_Insert    : return GFX_KEY_INSERT;
		case XK_Menu         : return GFX_KEY_MENU;
		case XK_Cancel       : return GFX_KEY_CANCEL;
		case XK_Help         : return GFX_KEY_HELP;
		case XK_Num_Lock     : return GFX_KEY_NUM_LOCK;
		case XK_KP_Space     : return GFX_KEY_SPACE;
		case XK_space        : return GFX_KEY_SPACE;

		case XK_KP_Enter     : return GFX_KEY_KP_RETURN;
		case XK_KP_Multiply  : return GFX_KEY_KP_MULTIPLY;
		case XK_KP_Add       : return GFX_KEY_KP_ADD;
		case XK_KP_Separator : return GFX_KEY_KP_SEPARATOR;
		case XK_KP_Subtract  : return GFX_KEY_KP_SUBTRACT;
		case XK_KP_Decimal   : return GFX_KEY_KP_DECIMAL;
		case XK_KP_Divide    : return GFX_KEY_KP_DIVIDE;

		case XK_Shift_L      : return GFX_KEY_SHIFT_LEFT;
		case XK_Shift_R      : return GFX_KEY_SHIFT_RIGHT;
		case XK_Control_L    : return GFX_KEY_CONTROL_LEFT;
		case XK_Control_R    : return GFX_KEY_CONTROL_RIGHT;
		case XK_Alt_L        : return GFX_KEY_ALT_LEFT;
		case XK_Alt_R        : return GFX_KEY_ALT_RIGHT;
		case XK_Super_L      : return GFX_KEY_SUPER_LEFT;
		case XK_Super_R      : return GFX_KEY_SUPER_RIGHT;
	}

	return GFX_KEY_UNKNOWN;
}

/******************************************************/
static void _gfx_x11_create_key_table(void)
{
	/* Get permitted keycodes and their symbols */
	int minKey, maxKey;
	XDisplayKeycodes(_gfx_x11.display, &minKey, &maxKey);
	maxKey = maxKey > GFX_X11_MAX_KEYCODE ? GFX_X11_MAX_KEYCODE : maxKey;

	int numKeys = maxKey - minKey + 1;

	int symbolsPerKey;
	KeySym* symbols = XGetKeyboardMapping(
		_gfx_x11.display,
		minKey,
		numKeys,
		&symbolsPerKey
	);

	/* Use the first symbol of all keycodes */
	size_t i;
	for(i = minKey; i <= maxKey; ++i) _gfx_x11.keys[i] = _gfx_x11_get_key(
		symbols[(i - minKey) * symbolsPerKey]);

	XFree(symbols);
}
Exemple #12
0
static gboolean
init_randr13 (GdkScreen *screen, gboolean *changed)
{
#ifdef HAVE_RANDR
  GdkDisplay *display = gdk_screen_get_display (screen);
  GdkX11Display *x11_display = GDK_X11_DISPLAY (display);
  GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
  XRRScreenResources *resources;
  RROutput primary_output = None;
  RROutput first_output = None;
  int i;
  gboolean randr12_compat = FALSE;
  int old_primary;

  if (!x11_display->have_randr13)
      return FALSE;

  resources = XRRGetScreenResourcesCurrent (x11_screen->xdisplay,
                                            x11_screen->xroot_window);
  if (!resources)
    return FALSE;

  for (i = 0; i < x11_display->monitors->len; i++)
    {
      GdkX11Monitor *monitor = x11_display->monitors->pdata[i];
      monitor->add = FALSE;
      monitor->remove = TRUE;
    }

  for (i = 0; i < resources->noutput; ++i)
    {
      RROutput output = resources->outputs[i];
      XRROutputInfo *output_info =
        XRRGetOutputInfo (x11_screen->xdisplay, resources, output);

      /* Non RandR1.2+ X driver have output name "default" */
      randr12_compat |= !g_strcmp0 (output_info->name, "default");

      if (output_info->connection == RR_Disconnected)
        {
          XRRFreeOutputInfo (output_info);
          continue;
        }

      if (output_info->crtc)
	{
	  GdkX11Monitor *monitor;
	  XRRCrtcInfo *crtc = XRRGetCrtcInfo (x11_screen->xdisplay, resources, output_info->crtc);
          char *name;
          GdkRectangle geometry;
          GdkRectangle newgeo;
          int j;
          int refresh_rate = 0;

          for (j = 0; j < resources->nmode; j++)
            {
              XRRModeInfo *xmode = &resources->modes[j];
              if (xmode->id == crtc->mode)
                {
                  refresh_rate = (1000 * xmode->dotClock) / (xmode->hTotal *xmode->vTotal);
                  break;
                }
            }

          monitor = find_monitor_by_output (x11_display, output);
          if (monitor)
            monitor->remove = FALSE;
          else
            {
              monitor = g_object_new (gdk_x11_monitor_get_type (),
                                      "display", display,
                                      NULL);
              monitor->output = output;
              monitor->add = TRUE;
              g_ptr_array_add (x11_display->monitors, monitor);
            }

          gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry);
          name = g_strndup (output_info->name, output_info->nameLen);

          newgeo.x = crtc->x / x11_screen->window_scale;
          newgeo.y = crtc->y / x11_screen->window_scale;
          newgeo.width = crtc->width / x11_screen->window_scale;
          newgeo.height = crtc->height / x11_screen->window_scale;
          if (newgeo.x != geometry.x ||
              newgeo.y != geometry.y ||
              newgeo.width != geometry.width ||
              newgeo.height != geometry.height ||
              output_info->mm_width != gdk_monitor_get_width_mm (GDK_MONITOR (monitor)) ||
              output_info->mm_height != gdk_monitor_get_height_mm (GDK_MONITOR (monitor)) ||
              g_strcmp0 (name, gdk_monitor_get_model (GDK_MONITOR (monitor))) != 0)
            *changed = TRUE;

          gdk_monitor_set_position (GDK_MONITOR (monitor), newgeo.x, newgeo.y);
          gdk_monitor_set_size (GDK_MONITOR (monitor), newgeo.width, newgeo.height);
          g_object_notify (G_OBJECT (monitor), "workarea");
          gdk_monitor_set_physical_size (GDK_MONITOR (monitor),
                                         output_info->mm_width,
                                         output_info->mm_height);
          gdk_monitor_set_subpixel_layout (GDK_MONITOR (monitor),
                                           translate_subpixel_order (output_info->subpixel_order));
          gdk_monitor_set_refresh_rate (GDK_MONITOR (monitor), refresh_rate);
          gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), x11_screen->window_scale);
          gdk_monitor_set_model (GDK_MONITOR (monitor), name);

          g_free (name);

          XRRFreeCrtcInfo (crtc);
	}

      XRRFreeOutputInfo (output_info);
    }

  if (resources->noutput > 0)
    first_output = resources->outputs[0];

  XRRFreeScreenResources (resources);

  if (randr12_compat)
    {
      for (i = 0; i < x11_display->monitors->len; i++)
        {
          GdkX11Monitor *monitor = x11_display->monitors->pdata[i];
          if (monitor->remove)
            gdk_display_monitor_removed (display, GDK_MONITOR (monitor));
        }
      g_ptr_array_remove_range (x11_display->monitors, 0, x11_display->monitors->len);
      return FALSE;
    }

  for (i = x11_display->monitors->len - 1; i >= 0; i--)
    {
      GdkX11Monitor *monitor = x11_display->monitors->pdata[i];
      if (monitor->add)
        {
          gdk_display_monitor_added (display, GDK_MONITOR (monitor));
          *changed = TRUE;
        }
      else if (monitor->remove)
        {
          g_object_ref (monitor);
          g_ptr_array_remove (x11_display->monitors, monitor);
          gdk_display_monitor_removed (display, GDK_MONITOR (monitor));
          g_object_unref (monitor);
          *changed = TRUE;
        }
    }

  old_primary = x11_display->primary_monitor;
  x11_display->primary_monitor = 0;
  primary_output = XRRGetOutputPrimary (x11_screen->xdisplay,
                                        x11_screen->xroot_window);

  for (i = 0; i < x11_display->monitors->len; ++i)
    {
      GdkX11Monitor *monitor = x11_display->monitors->pdata[i];
      if (monitor->output == primary_output)
        {
          x11_display->primary_monitor = i;
          break;
        }

      /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */
      if (primary_output == None &&
          g_ascii_strncasecmp (gdk_monitor_get_model (GDK_MONITOR (monitor)), "LVDS", 4) == 0)
        {
          x11_display->primary_monitor = i;
          break;
        }

      /* No primary specified and no LVDS found */
      if (monitor->output == first_output)
        x11_display->primary_monitor = i;
    }

  if (x11_display->primary_monitor != old_primary)
    *changed = TRUE;

  return x11_display->monitors->len > 0;
#endif

  return FALSE;
}
static void
xfce_randr_populate (XfceRandr *randr,
                     Display   *xdisplay,
                     GdkWindow *root_window)
{
    GPtrArray      *outputs;
    XRROutputInfo  *output_info;
    XRRCrtcInfo    *crtc_info;
    gint            n;
    guint           m, connected;
    guint          *output_ids = NULL;

    XfconfChannel *display_channel = xfconf_channel_new ("displays");

    g_return_if_fail (randr != NULL);
    g_return_if_fail (randr->priv != NULL);
    g_return_if_fail (randr->priv->resources != NULL);

    /* prepare the temporary cache */
    outputs = g_ptr_array_new ();
    output_ids = g_malloc0 (randr->priv->resources->noutput * sizeof (guint));

    /* walk the outputs */
    connected = 0;
    for (n = 0; n < randr->priv->resources->noutput; ++n)
    {
        /* get the output info */
        output_info = XRRGetOutputInfo (xdisplay, randr->priv->resources,
                                        randr->priv->resources->outputs[n]);

        /* forget about disconnected outputs */
        if (output_info->connection != RR_Connected)
        {
            XRRFreeOutputInfo (output_info);
            continue;
        }
        else
        {
            output_ids[connected] = n;
            connected++;
        }

        /* cache it */
        g_ptr_array_add (outputs, output_info);
    }

    /* migrate the temporary cache */
    randr->noutput = outputs->len;
    randr->priv->output_info = (XRROutputInfo **) g_ptr_array_free (outputs, FALSE);

    /* allocate final space for the settings */
    randr->mode = g_new0 (RRMode, randr->noutput);
    randr->priv->modes = g_new0 (XfceRRMode *, randr->noutput);
    randr->position = g_new0 (XfceOutputPosition, randr->noutput);
    randr->rotation = g_new0 (Rotation, randr->noutput);
    randr->rotations = g_new0 (Rotation, randr->noutput);
    randr->mirrored = g_new0 (gboolean, randr->noutput);
    randr->status = g_new0 (XfceOutputStatus, randr->noutput);
    randr->friendly_name = g_new0 (gchar *, randr->noutput);

    /* walk the connected outputs */
    for (m = 0; m < randr->noutput; ++m)
    {
        /* fill in supported modes */
        randr->priv->modes[m] = xfce_randr_list_supported_modes (randr->priv->resources, randr->priv->output_info[m]);

#ifdef HAS_RANDR_ONE_POINT_THREE
        /* find the primary screen if supported */
        if (randr->priv->has_1_3 && XRRGetOutputPrimary (xdisplay, GDK_WINDOW_XID (root_window)) == randr->priv->resources->outputs[output_ids[m]])
            randr->status[m] = XFCE_OUTPUT_STATUS_PRIMARY;
        else
#endif
            randr->status[m] = XFCE_OUTPUT_STATUS_SECONDARY;

        if (randr->priv->output_info[m]->crtc != None)
        {
            crtc_info = XRRGetCrtcInfo (xdisplay, randr->priv->resources,
                                        randr->priv->output_info[m]->crtc);
            randr->mode[m] = crtc_info->mode;
            randr->rotation[m] = crtc_info->rotation;
            randr->rotations[m] = crtc_info->rotations;
            randr->position[m].x = crtc_info->x;
            randr->position[m].y = crtc_info->y;
            XRRFreeCrtcInfo (crtc_info);
        }
        else
        {
            /* output disabled */
            randr->mode[m] = None;
            randr->rotation[m] = RR_Rotate_0;
            randr->rotations[m] = xfce_randr_get_safe_rotations (randr, xdisplay, m);
        }

        /* fill in the name used by the UI */
        randr->friendly_name[m] = xfce_randr_friendly_name (randr, m, output_ids[m]);

        /* Update display info, primary display may have changed. */
        xfce_randr_save_output (randr, "Default", display_channel, m);
        
        /* Replace spaces with underscore in name for xfconf compatibility */
        g_strcanon(randr->priv->output_info[m]->name, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_<>", '_');
    }
    /* populate mirrored details */
    xfce_randr_guess_relations (randr);

    g_free (output_ids);
}
Exemple #14
0
/*
 * Class:     jogamp_newt_driver_x11_RandR13
 * Method:    getMonitorDevice0
 * Signature: (JJJJ)[I
 */
JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorDevice0
  (JNIEnv *env, jclass clazz, jlong display, jlong screenResources, jlong monitorInfo, jint crt_id)
{
    Display * dpy = (Display *) (intptr_t) display;
    XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
    RRCrtc crtc = findRRCrtc( resources, (RRCrtc)(intptr_t)crt_id );
    if( 0 == crtc ) {
        // n/a
        return NULL;
    }
    XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
    if( NULL == xrrCrtcInfo ) {
        // n/a
        return NULL;
    }
    if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
        // disabled
        return NULL;
    }

    Window root = RootWindow(dpy, 0); // FIXME screen_idx);
    RROutput pxid = XRRGetOutputPrimary (dpy, root);
    int isPrimary = 0;

    RROutput output = xrrCrtcInfo->outputs[0];
    if ( None != pxid && pxid == output ) {
        isPrimary = 1;
    }
    XRROutputInfo * xrrOutputInfo = XRRGetOutputInfo (dpy, resources, output);
    int numModes = xrrOutputInfo->nmode;

    jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 + numModes;
    jint prop[ propCount ];
    int propIndex = 0;

    prop[propIndex++] = propCount;
    prop[propIndex++] = crt_id;
    prop[propIndex++] = 0; // isClone, does not work: 0 < xrrOutputInfo->nclone ? 1 : 0;
    prop[propIndex++] = isPrimary;
    prop[propIndex++] = xrrOutputInfo->mm_width;
    prop[propIndex++] = xrrOutputInfo->mm_height;
    prop[propIndex++] = xrrCrtcInfo->x;      // rotated viewport pixel units
    prop[propIndex++] = xrrCrtcInfo->y;      // rotated viewport pixel units
    prop[propIndex++] = xrrCrtcInfo->width;  // rotated viewport pixel units
    prop[propIndex++] = xrrCrtcInfo->height; // rotated viewport pixel units
    prop[propIndex++] = xrrCrtcInfo->x;      // rotated viewport window units (same)
    prop[propIndex++] = xrrCrtcInfo->y;      // rotated viewport window units (same)
    prop[propIndex++] = xrrCrtcInfo->width;  // rotated viewport window units (same)
    prop[propIndex++] = xrrCrtcInfo->height; // rotated viewport window units (same)
    prop[propIndex++] = xrrCrtcInfo->mode;   // current mode id
    prop[propIndex++] = NewtScreen_XRotation2Degree(env, xrrCrtcInfo->rotation);
    int i;
    for(i=0; i<numModes; i++) {
        // avail modes ..
        prop[propIndex++] = xrrOutputInfo->modes[i];
    }
    XRRFreeOutputInfo (xrrOutputInfo);

    jintArray properties = (*env)->NewIntArray(env, propCount);
    if (properties == NULL) {
        NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
    }
    (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
    
    return properties;
}
Exemple #15
0
bool iRandR::reload( bool _overwriteLatest, bool _overwriteDefaults ) {
   if ( !vIsRandRSupported_B )
      return false;

   SizeID lTemoID_suI;
   int lTempSizes_I;

   Rotation lTempRotate_XRR; // Exists only for XRRConfigCurrentConfiguration(...); to make it happy

   vConfig_XRR    = XRRGetScreenInfo( vDisplay_X11, vRootWindow_X11 );
   vResources_XRR = XRRGetScreenResources( vDisplay_X11, vRootWindow_X11 );

   lTemoID_suI                   = XRRConfigCurrentConfiguration( vConfig_XRR, &lTempRotate_XRR );
   XRRScreenSize *lTempSizes_XRR = XRRSizes( vDisplay_X11, 0, &lTempSizes_I );

   if ( lTemoID_suI < lTempSizes_I ) {
      vScreenWidth_uI  = static_cast<unsigned>( lTempSizes_XRR[lTemoID_suI].width );
      vScreenHeight_uI = static_cast<unsigned>( lTempSizes_XRR[lTemoID_suI].height );
   }

   if ( _overwriteLatest ) {
      vLatestConfig_RandR.primary = XRRGetOutputPrimary( vDisplay_X11, vRootWindow_X11 );

      for ( auto &elem : vLatestConfig_RandR.gamma )
         XRRFreeGamma( elem );

      vLatestConfig_RandR.gamma.clear();

      for ( int i = 0; i < vResources_XRR->ncrtc; ++i ) {
         vLatestConfig_RandR.gamma.push_back(
               XRRGetCrtcGamma( vDisplay_X11, vResources_XRR->crtcs[i] ) );
      }
   }

   if ( _overwriteDefaults ) {
      vDefaultConfig_RandR.primary = XRRGetOutputPrimary( vDisplay_X11, vRootWindow_X11 );

      for ( auto &elem : vDefaultConfig_RandR.gamma )
         XRRFreeGamma( elem );

      vDefaultConfig_RandR.gamma.clear();

      for ( int i = 0; i < vResources_XRR->ncrtc; ++i ) {
         vDefaultConfig_RandR.gamma.push_back(
               XRRGetCrtcGamma( vDisplay_X11, vResources_XRR->crtcs[i] ) );
      }
   }

   // Clear old data
   vCRTC_V_RandR.clear();
   vOutput_V_RandR.clear();
   vMode_V_RandR.clear();
   vLatestConfig_RandR.CRTCInfo.clear();


   // CRTC
   for ( int i = 0; i < vResources_XRR->ncrtc; ++i ) {
      internal::_crtc lTempCRTC_RandR;

      XRRCrtcInfo *lTempCRTCInfo_XRR =
            XRRGetCrtcInfo( vDisplay_X11, vResources_XRR, vResources_XRR->crtcs[i] );

      lTempCRTC_RandR.id        = vResources_XRR->crtcs[i];
      lTempCRTC_RandR.timestamp = lTempCRTCInfo_XRR->timestamp;
      lTempCRTC_RandR.posX      = lTempCRTCInfo_XRR->x;
      lTempCRTC_RandR.posY      = lTempCRTCInfo_XRR->y;
      lTempCRTC_RandR.width     = lTempCRTCInfo_XRR->width;
      lTempCRTC_RandR.height    = lTempCRTCInfo_XRR->height;
      lTempCRTC_RandR.mode      = lTempCRTCInfo_XRR->mode;
      lTempCRTC_RandR.rotation  = lTempCRTCInfo_XRR->rotation;
      lTempCRTC_RandR.rotations = lTempCRTCInfo_XRR->rotations;

      for ( int j = 0; j < lTempCRTCInfo_XRR->noutput; ++j ) {
         lTempCRTC_RandR.outputs.push_back( lTempCRTCInfo_XRR->outputs[j] );
      }

      for ( int j = 0; j < lTempCRTCInfo_XRR->npossible; ++j ) {
         lTempCRTC_RandR.possibleOutputs.push_back( lTempCRTCInfo_XRR->possible[j] );
      }

      vCRTC_V_RandR.push_back( lTempCRTC_RandR );
      XRRFreeCrtcInfo( lTempCRTCInfo_XRR );
   }


   // Output
   for ( int i = 0; i < vResources_XRR->noutput; ++i ) {
      internal::_output lTempOutput_RandR;

      XRROutputInfo *lTempOutputInfo_XRR =
            XRRGetOutputInfo( vDisplay_X11, vResources_XRR, vResources_XRR->outputs[i] );

      lTempOutput_RandR.id             = vResources_XRR->outputs[i];
      lTempOutput_RandR.timestamp      = lTempOutputInfo_XRR->timestamp;
      lTempOutput_RandR.crtc           = lTempOutputInfo_XRR->crtc;
      lTempOutput_RandR.name           = lTempOutputInfo_XRR->name;
      lTempOutput_RandR.mm_width       = lTempOutputInfo_XRR->mm_width;
      lTempOutput_RandR.mm_height      = lTempOutputInfo_XRR->mm_height;
      lTempOutput_RandR.connection     = lTempOutputInfo_XRR->connection;
      lTempOutput_RandR.subpixel_order = lTempOutputInfo_XRR->subpixel_order;
      lTempOutput_RandR.npreferred     = lTempOutputInfo_XRR->npreferred;

      for ( int j = 0; j < lTempOutputInfo_XRR->ncrtc; ++j ) {
         lTempOutput_RandR.crtcs.push_back( lTempOutputInfo_XRR->crtcs[j] );
      }

      for ( int j = 0; j < lTempOutputInfo_XRR->nclone; ++j ) {
         lTempOutput_RandR.clones.push_back( lTempOutputInfo_XRR->clones[j] );
      }

      for ( int j = 0; j < lTempOutputInfo_XRR->nmode; ++j ) {
         lTempOutput_RandR.modes.push_back( lTempOutputInfo_XRR->modes[j] );
      }

      vOutput_V_RandR.push_back( lTempOutput_RandR );
      XRRFreeOutputInfo( lTempOutputInfo_XRR );
   }


   // Modes
   for ( int i = 0; i < vResources_XRR->nmode; ++i ) {
      internal::_mode lTempMode_RandR;

      XRRModeInfo lTempModeInfo_XRR = vResources_XRR->modes[i];

      lTempMode_RandR.id         = lTempModeInfo_XRR.id;
      lTempMode_RandR.width      = lTempModeInfo_XRR.width;
      lTempMode_RandR.height     = lTempModeInfo_XRR.height;
      lTempMode_RandR.dotClock   = lTempModeInfo_XRR.dotClock;
      lTempMode_RandR.hSyncStart = lTempModeInfo_XRR.hSyncStart;
      lTempMode_RandR.hSyncEnd   = lTempModeInfo_XRR.hSyncEnd;
      lTempMode_RandR.hTotal     = lTempModeInfo_XRR.hTotal;
      lTempMode_RandR.hSkew      = lTempModeInfo_XRR.hSkew;
      lTempMode_RandR.vSyncStart = lTempModeInfo_XRR.vSyncStart;
      lTempMode_RandR.vSyncEnd   = lTempModeInfo_XRR.vSyncEnd;
      lTempMode_RandR.vTotal     = lTempModeInfo_XRR.vTotal;
      lTempMode_RandR.name       = lTempModeInfo_XRR.name;
      lTempMode_RandR.modeFlags  = lTempModeInfo_XRR.modeFlags;


      /* v refresh frequency in Hz */
      unsigned int lVTotalTemp = lTempMode_RandR.vTotal;

      if ( lTempMode_RandR.modeFlags & RR_DoubleScan )
         lVTotalTemp *= 2;

      if ( lTempMode_RandR.modeFlags & RR_Interlace )
         lVTotalTemp /= 2;

      if ( lTempMode_RandR.hTotal && lVTotalTemp )
         lTempMode_RandR.refresh = ( static_cast<double>( lTempMode_RandR.dotClock ) /
                                     ( static_cast<double>( lTempMode_RandR.hTotal ) *
                                       static_cast<double>( lVTotalTemp ) ) );
      else
         lTempMode_RandR.refresh = 0;


      /* h sync frequency in Hz */
      if ( lTempMode_RandR.hTotal )
         lTempMode_RandR.syncFreq = lTempMode_RandR.dotClock / lTempMode_RandR.hTotal;
      else
         lTempMode_RandR.syncFreq = 0;

      vMode_V_RandR.push_back( lTempMode_RandR );
   }


   vLatestConfig_RandR.CRTCInfo = vCRTC_V_RandR;

   if ( _overwriteLatest )
      vDefaultConfig_RandR.CRTCInfo = vCRTC_V_RandR;

   vMode_V_RandR.sort();

   return true;
}
JNIEXPORT jlong JNICALL Java_org_lwjgl_system_linux_Xrandr_nXRRGetOutputPrimary(JNIEnv *__env, jclass clazz, jlong displayAddress, jlong w) {
	Display *display = (Display *)(intptr_t)displayAddress;
	UNUSED_PARAMS(__env, clazz)
	return (jlong)XRRGetOutputPrimary(display, (Window)w);
}
Exemple #17
0
// Poll for changes in the set of connected monitors
//
void _glfwPollMonitorsX11(void)
{
    if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
    {
        int i, j, disconnectedCount, screenCount = 0;
        _GLFWmonitor** disconnected = NULL;
        XineramaScreenInfo* screens = NULL;
        XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display,
                                                              _glfw.x11.root);
        RROutput primary = XRRGetOutputPrimary(_glfw.x11.display,
                                               _glfw.x11.root);

        if (_glfw.x11.xinerama.available)
            screens = XineramaQueryScreens(_glfw.x11.display, &screenCount);

        disconnectedCount = _glfw.monitorCount;
        if (disconnectedCount)
        {
            disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
            memcpy(disconnected,
                   _glfw.monitors,
                   _glfw.monitorCount * sizeof(_GLFWmonitor*));
        }

        for (i = 0;  i < sr->noutput;  i++)
        {
            int type, widthMM, heightMM;
            XRROutputInfo* oi;
            XRRCrtcInfo* ci;
            _GLFWmonitor* monitor;

            oi = XRRGetOutputInfo(_glfw.x11.display, sr, sr->outputs[i]);
            if (oi->connection != RR_Connected || oi->crtc == None)
            {
                XRRFreeOutputInfo(oi);
                continue;
            }

            for (j = 0;  j < disconnectedCount;  j++)
            {
                if (disconnected[j] &&
                    disconnected[j]->x11.output == sr->outputs[i])
                {
                    disconnected[j] = NULL;
                    break;
                }
            }

            if (j < disconnectedCount)
            {
                XRRFreeOutputInfo(oi);
                continue;
            }

            ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc);
            if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
            {
                widthMM  = oi->mm_height;
                heightMM = oi->mm_width;
            }
            else
            {
                widthMM  = oi->mm_width;
                heightMM = oi->mm_height;
            }

            monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM);
            monitor->x11.output = sr->outputs[i];
            monitor->x11.crtc   = oi->crtc;

            for (j = 0;  j < screenCount;  j++)
            {
                if (screens[j].x_org == ci->x &&
                    screens[j].y_org == ci->y &&
                    screens[j].width == ci->width &&
                    screens[j].height == ci->height)
                {
                    monitor->x11.index = j;
                    break;
                }
            }

            if (monitor->x11.output == primary)
                type = _GLFW_INSERT_FIRST;
            else
                type = _GLFW_INSERT_LAST;

            _glfwInputMonitor(monitor, GLFW_CONNECTED, type);

            XRRFreeOutputInfo(oi);
            XRRFreeCrtcInfo(ci);
        }

        XRRFreeScreenResources(sr);

        if (screens)
            XFree(screens);

        for (i = 0;  i < disconnectedCount;  i++)
        {
            if (disconnected[i])
                _glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
        }

        free(disconnected);
    }
    else
    {
        const int widthMM = DisplayWidthMM(_glfw.x11.display, _glfw.x11.screen);
        const int heightMM = DisplayHeightMM(_glfw.x11.display, _glfw.x11.screen);

        _glfwInputMonitor(_glfwAllocMonitor("Display", widthMM, heightMM),
                          GLFW_CONNECTED,
                          _GLFW_INSERT_FIRST);
    }
}