提交 96924553 编写于 作者: K Keith Packard

linux-capture: Use RandR monitors for screen information

RandR has two sets of screen geometry information:

 1. CRTC. These are the physical scanout engines in the hardware

 2. Monitors. These are the logical partitions of the screen.

By default, each CRTC gets mapped to a Monitor. However, some monitors
actually require two CRTCs to drive them due to limitations in the
scanout hardware. Users can also create 'virtual' monitors to support
VNC or other systems.

This patch makes the RandR code prefer the Monitor mechanism to the
older CRTC mechanism. If the server doesn't support a new enough RandR
version, the existing CRTC code is used instead.

The name of the monitor is also provided in place of the arbitrary
number to help users select the desired source.
Signed-off-by: NKeith Packard <keithp@keithp.com>
上级 81a20171
...@@ -104,6 +104,22 @@ bool randr_is_active(xcb_connection_t *xcb) ...@@ -104,6 +104,22 @@ bool randr_is_active(xcb_connection_t *xcb)
return true; 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) int randr_screen_count(xcb_connection_t *xcb)
{ {
if (!xcb) if (!xcb)
...@@ -111,6 +127,19 @@ int randr_screen_count(xcb_connection_t *xcb) ...@@ -111,6 +127,19 @@ int randr_screen_count(xcb_connection_t *xcb)
xcb_screen_t *screen; xcb_screen_t *screen;
screen = xcb_setup_roots_iterator(xcb_get_setup(xcb)).data; 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_cookie_t res_c;
xcb_randr_get_screen_resources_reply_t *res_r; xcb_randr_get_screen_resources_reply_t *res_r;
...@@ -124,11 +153,58 @@ int randr_screen_count(xcb_connection_t *xcb) ...@@ -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 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 *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; xcb_screen_t *xscreen;
xscreen = xcb_setup_roots_iterator(xcb_get_setup(xcb)).data; 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_cookie_t res_c;
xcb_randr_get_screen_resources_reply_t *res_r; xcb_randr_get_screen_resources_reply_t *res_r;
......
...@@ -94,7 +94,7 @@ int randr_screen_count(xcb_connection_t *xcb); ...@@ -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 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 *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 * Get screen geometry for a X11 screen
......
...@@ -104,7 +104,7 @@ static int_fast32_t xshm_update_geometry(struct xshm_data *data) ...@@ -104,7 +104,7 @@ static int_fast32_t xshm_update_geometry(struct xshm_data *data)
if (data->use_randr) { if (data->use_randr) {
if (randr_screen_geo(data->xcb, data->screen_id, &data->x_org, if (randr_screen_geo(data->xcb, data->screen_id, &data->x_org,
&data->y_org, &data->width, &data->height, &data->y_org, &data->width, &data->height,
&data->xcb_screen) < 0) { &data->xcb_screen, NULL) < 0) {
return -1; return -1;
} }
} else if (data->use_xinerama) { } else if (data->use_xinerama) {
...@@ -308,21 +308,31 @@ static bool xshm_server_changed(obs_properties_t *props, obs_property_t *p, ...@@ -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)); : xcb_setup_roots_length(xcb_get_setup(xcb));
for (int_fast32_t i = 0; i < count; ++i) { for (int_fast32_t i = 0; i < count; ++i) {
char *name;
char name_tmp[12];
int_fast32_t x, y, w, h; int_fast32_t x, y, w, h;
x = y = w = h = 0; x = y = w = h = 0;
name = NULL;
if (randr) 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) else if (xinerama)
xinerama_screen_geo(xcb, i, &x, &y, &w, &h); xinerama_screen_geo(xcb, i, &x, &y, &w, &h);
else else
x11_screen_geo(xcb, i, &w, &h); x11_screen_geo(xcb, i, &w, &h);
if (name == NULL) {
sprintf(name_tmp, "%" PRIuFAST32, i);
name = name_tmp;
}
dstr_printf(&screen_info, dstr_printf(&screen_info,
"Screen %" PRIuFAST32 " (%" PRIuFAST32 "Screen %s (%" PRIuFAST32 "x%" PRIuFAST32
"x%" PRIuFAST32 " @ %" PRIuFAST32 ",%" PRIuFAST32 " @ %" PRIuFAST32 ",%" PRIuFAST32 ")",
")", name, w, h, x, y);
i, w, h, x, y);
if (name != name_tmp)
free(name);
if (h > 0 && w > 0) if (h > 0 && w > 0)
obs_property_list_add_int(screens, screen_info.array, obs_property_list_add_int(screens, screen_info.array,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册