Browse Source

Merge pull request #2497 from keith-packard/linux-capture-randr-monitors

linux-capture: Use RandR monitors for screen information
Jim 5 years ago
parent
commit
8e7481fb75

+ 77 - 1
plugins/linux-capture/xhelpers.c

@@ -104,6 +104,22 @@ bool randr_is_active(xcb_connection_t *xcb)
 	return true;
 }
 
+static bool randr_has_monitors(xcb_connection_t *xcb)
+{
+	xcb_randr_query_version_cookie_t ver_c;
+	xcb_randr_query_version_reply_t *ver_r;
+
+	ver_c = xcb_randr_query_version(xcb, XCB_RANDR_MAJOR_VERSION,
+					XCB_RANDR_MINOR_VERSION);
+	ver_r = xcb_randr_query_version_reply(xcb, ver_c, 0);
+	if (!ver_r)
+		return 0;
+
+	bool ret = ver_r->major_version > 1 || ver_r->minor_version >= 5;
+	free(ver_r);
+	return ret;
+}
+
 int randr_screen_count(xcb_connection_t *xcb)
 {
 	if (!xcb)
@@ -111,6 +127,19 @@ int randr_screen_count(xcb_connection_t *xcb)
 	xcb_screen_t *screen;
 	screen = xcb_setup_roots_iterator(xcb_get_setup(xcb)).data;
 
+	if (randr_has_monitors(xcb)) {
+		xcb_randr_get_monitors_cookie_t mon_c;
+		xcb_randr_get_monitors_reply_t *mon_r;
+
+		mon_c = xcb_randr_get_monitors(xcb, screen->root, true);
+		mon_r = xcb_randr_get_monitors_reply(xcb, mon_c, 0);
+		if (!mon_r)
+			return 0;
+
+		int count = xcb_randr_get_monitors_monitors_length(mon_r);
+		free(mon_r);
+		return count;
+	}
 	xcb_randr_get_screen_resources_cookie_t res_c;
 	xcb_randr_get_screen_resources_reply_t *res_r;
 
@@ -124,11 +153,58 @@ int randr_screen_count(xcb_connection_t *xcb)
 
 int randr_screen_geo(xcb_connection_t *xcb, int_fast32_t screen,
 		     int_fast32_t *x, int_fast32_t *y, int_fast32_t *w,
-		     int_fast32_t *h, xcb_screen_t **rscreen)
+		     int_fast32_t *h, xcb_screen_t **rscreen, char **name)
 {
 	xcb_screen_t *xscreen;
 	xscreen = xcb_setup_roots_iterator(xcb_get_setup(xcb)).data;
 
+	if (randr_has_monitors(xcb)) {
+		xcb_randr_get_monitors_cookie_t mon_c;
+		xcb_randr_get_monitors_reply_t *mon_r;
+
+		mon_c = xcb_randr_get_monitors(xcb, xscreen->root, true);
+		mon_r = xcb_randr_get_monitors_reply(xcb, mon_c, 0);
+		if (!mon_r)
+			return 0;
+
+		int monitors = xcb_randr_get_monitors_monitors_length(mon_r);
+		if (screen < 0 || screen >= monitors) {
+			free(mon_r);
+			goto fail;
+		}
+
+		xcb_randr_monitor_info_iterator_t mon_i;
+		mon_i = xcb_randr_get_monitors_monitors_iterator(mon_r);
+
+		int s;
+		for (s = 0; s < screen; s++)
+			xcb_randr_monitor_info_next(&mon_i);
+
+		xcb_randr_monitor_info_t *mon = mon_i.data;
+
+		*x = mon->x;
+		*y = mon->y;
+		*w = mon->width;
+		*h = mon->height;
+		if (rscreen)
+			*rscreen = xscreen;
+
+		if (mon->name && name) {
+			xcb_get_atom_name_cookie_t atom_c;
+			xcb_get_atom_name_reply_t *atom_r;
+
+			atom_c = xcb_get_atom_name(xcb, mon->name);
+			atom_r = xcb_get_atom_name_reply(xcb, atom_c, 0);
+			if (atom_r) {
+				*name = strndup(
+					xcb_get_atom_name_name(atom_r),
+					xcb_get_atom_name_name_length(atom_r));
+				free(atom_r);
+			}
+		}
+		free(mon_r);
+		return 0;
+	}
 	xcb_randr_get_screen_resources_cookie_t res_c;
 	xcb_randr_get_screen_resources_reply_t *res_r;
 

+ 1 - 1
plugins/linux-capture/xhelpers.h

@@ -94,7 +94,7 @@ int randr_screen_count(xcb_connection_t *xcb);
  */
 int randr_screen_geo(xcb_connection_t *xcb, int_fast32_t screen,
 		     int_fast32_t *x, int_fast32_t *y, int_fast32_t *w,
-		     int_fast32_t *h, xcb_screen_t **rscreen);
+		     int_fast32_t *h, xcb_screen_t **rscreen, char **name);
 
 /**
  * Get screen geometry for a X11 screen

+ 16 - 6
plugins/linux-capture/xshm-input.c

@@ -104,7 +104,7 @@ static int_fast32_t xshm_update_geometry(struct xshm_data *data)
 	if (data->use_randr) {
 		if (randr_screen_geo(data->xcb, data->screen_id, &data->x_org,
 				     &data->y_org, &data->width, &data->height,
-				     &data->xcb_screen) < 0) {
+				     &data->xcb_screen, NULL) < 0) {
 			return -1;
 		}
 	} else if (data->use_xinerama) {
@@ -308,21 +308,31 @@ static bool xshm_server_changed(obs_properties_t *props, obs_property_t *p,
 				  : xcb_setup_roots_length(xcb_get_setup(xcb));
 
 	for (int_fast32_t i = 0; i < count; ++i) {
+		char *name;
+		char name_tmp[12];
 		int_fast32_t x, y, w, h;
 		x = y = w = h = 0;
 
+		name = NULL;
 		if (randr)
-			randr_screen_geo(xcb, i, &x, &y, &w, &h, NULL);
+			randr_screen_geo(xcb, i, &x, &y, &w, &h, NULL, &name);
 		else if (xinerama)
 			xinerama_screen_geo(xcb, i, &x, &y, &w, &h);
 		else
 			x11_screen_geo(xcb, i, &w, &h);
 
+		if (name == NULL) {
+			sprintf(name_tmp, "%" PRIuFAST32, i);
+			name = name_tmp;
+		}
+
 		dstr_printf(&screen_info,
-			    "Screen %" PRIuFAST32 " (%" PRIuFAST32
-			    "x%" PRIuFAST32 " @ %" PRIuFAST32 ",%" PRIuFAST32
-			    ")",
-			    i, w, h, x, y);
+			    "Screen %s (%" PRIuFAST32 "x%" PRIuFAST32
+			    " @ %" PRIuFAST32 ",%" PRIuFAST32 ")",
+			    name, w, h, x, y);
+
+		if (name != name_tmp)
+			free(name);
 
 		if (h > 0 && w > 0)
 			obs_property_list_add_int(screens, screen_info.array,