diff --git a/CI/install-dependencies-linux-ubuntu16.sh b/CI/install-dependencies-linux-ubuntu16.sh
index e6652e5d6..52e8d2268 100755
--- a/CI/install-dependencies-linux-ubuntu16.sh
+++ b/CI/install-dependencies-linux-ubuntu16.sh
@@ -30,6 +30,7 @@ sudo apt-get install -y \
libvlc-dev \
libx11-dev \
libx264-dev \
+ libxcb-randr0-dev \
libxcb-shm0-dev \
libxcb-xinerama0-dev \
libxcomposite-dev \
diff --git a/CI/install-dependencies-linux.sh b/CI/install-dependencies-linux.sh
index f7749201c..4ab021959 100755
--- a/CI/install-dependencies-linux.sh
+++ b/CI/install-dependencies-linux.sh
@@ -33,6 +33,7 @@ sudo apt-get install -y \
libvlc-dev \
libx11-dev \
libx264-dev \
+ libxcb-randr0-dev \
libxcb-shm0-dev \
libxcb-xinerama0-dev \
libxcomposite-dev \
diff --git a/plugins/linux-capture/CMakeLists.txt b/plugins/linux-capture/CMakeLists.txt
index d4f1649f3..70803461f 100644
--- a/plugins/linux-capture/CMakeLists.txt
+++ b/plugins/linux-capture/CMakeLists.txt
@@ -6,7 +6,7 @@ if(NOT X11_Xcomposite_FOUND)
return()
endif()
-find_package(XCB COMPONENTS XCB SHM XFIXES XINERAMA REQUIRED)
+find_package(XCB COMPONENTS XCB RANDR SHM XFIXES XINERAMA REQUIRED)
find_package(X11_XCB REQUIRED)
include_directories(SYSTEM
diff --git a/plugins/linux-capture/xhelpers.c b/plugins/linux-capture/xhelpers.c
index 1eeda7c22..724f4f3ed 100644
--- a/plugins/linux-capture/xhelpers.c
+++ b/plugins/linux-capture/xhelpers.c
@@ -17,6 +17,7 @@ along with this program. If not, see .
#include
#include
+#include
#include
#include
@@ -95,6 +96,78 @@ fail:
return -1;
}
+bool randr_is_active(xcb_connection_t *xcb)
+{
+ if (!xcb || !xcb_get_extension_data(xcb, &xcb_randr_id)->present)
+ return false;
+
+ return true;
+}
+
+int randr_screen_count(xcb_connection_t *xcb)
+{
+ if (!xcb)
+ return 0;
+
+ xcb_screen_t *screen;
+ screen = xcb_setup_roots_iterator(xcb_get_setup(xcb)).data;
+
+ xcb_randr_get_screen_resources_cookie_t res_c;
+ xcb_randr_get_screen_resources_reply_t* res_r;
+
+ res_c = xcb_randr_get_screen_resources(xcb, screen->root);
+ res_r = xcb_randr_get_screen_resources_reply(xcb, res_c, 0);
+ if (!res_r)
+ return 0;
+
+ return xcb_randr_get_screen_resources_crtcs_length(res_r);
+}
+
+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)
+{
+ xcb_screen_t *xscreen;
+ xscreen = xcb_setup_roots_iterator(xcb_get_setup(xcb)).data;
+
+ xcb_randr_get_screen_resources_cookie_t res_c;
+ xcb_randr_get_screen_resources_reply_t* res_r;
+
+ res_c = xcb_randr_get_screen_resources(xcb, xscreen->root);
+ res_r = xcb_randr_get_screen_resources_reply(xcb, res_c, 0);
+ if (!res_r)
+ goto fail;
+
+ int screens = xcb_randr_get_screen_resources_crtcs_length(res_r);
+ if (screen < 0 || screen >= screens)
+ goto fail;
+
+ xcb_randr_crtc_t *crtc = xcb_randr_get_screen_resources_crtcs(res_r);
+
+ xcb_randr_get_crtc_info_cookie_t crtc_c;
+ xcb_randr_get_crtc_info_reply_t *crtc_r;
+
+ crtc_c = xcb_randr_get_crtc_info(xcb, *(crtc + screen), 0);
+ crtc_r = xcb_randr_get_crtc_info_reply(xcb, crtc_c, 0);
+ if (!crtc_r)
+ goto fail;
+
+ *x = crtc_r->x;
+ *y = crtc_r->y;
+ *w = crtc_r->width;
+ *h = crtc_r->height;
+
+ if (rscreen)
+ *rscreen = xscreen;
+
+ return 0;
+
+fail:
+ *x = *y = *w = *h = 0;
+ return -1;
+}
+
int x11_screen_geo(xcb_connection_t *xcb, int_fast32_t screen,
int_fast32_t *w, int_fast32_t *h)
{
diff --git a/plugins/linux-capture/xhelpers.h b/plugins/linux-capture/xhelpers.h
index 066684fea..95aff5c59 100644
--- a/plugins/linux-capture/xhelpers.h
+++ b/plugins/linux-capture/xhelpers.h
@@ -64,6 +64,39 @@ int xinerama_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);
+/**
+ * Check for Randr extension
+ *
+ * @return true if randr is available which means it's active.
+ */
+bool randr_is_active(xcb_connection_t *xcb);
+
+/**
+ * Get the number of Randr screens
+ *
+ * @return number of screens
+ */
+int randr_screen_count(xcb_connection_t *xcb);
+
+/**
+ * Get screen geometry for a Rand crtc (screen)
+ *
+ * @note On error the passed coordinates/sizes will be set to 0.
+ *
+ * @param xcb xcb connection
+ * @param screen screen number to get geometry for
+ * @param x x-coordinate of the screen
+ * @param y y-coordinate of the screen
+ * @param w width of the screen
+ * @param h height of the screen
+ *
+ * @return < 0 on error
+ */
+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);
+
/**
* Get screen geometry for a X11 screen
*
diff --git a/plugins/linux-capture/xshm-input.c b/plugins/linux-capture/xshm-input.c
index b5fa3a307..f00c0eb8c 100644
--- a/plugins/linux-capture/xshm-input.c
+++ b/plugins/linux-capture/xshm-input.c
@@ -18,6 +18,7 @@ along with this program. If not, see .
#include
#include
#include
+#include
#include
#include
#include
@@ -50,6 +51,7 @@ struct xshm_data {
bool show_cursor;
bool use_xinerama;
+ bool use_randr;
bool advanced;
};
@@ -83,6 +85,9 @@ static bool xshm_check_extensions(xcb_connection_t *xcb)
if (!xcb_get_extension_data(xcb, &xcb_xinerama_id)->present)
blog(LOG_INFO, "Missing Xinerama extension !");
+ if (!xcb_get_extension_data(xcb, &xcb_randr_id)->present)
+ blog(LOG_INFO, "Missing Randr extension !");
+
return ok;
}
@@ -96,7 +101,15 @@ static int_fast32_t xshm_update_geometry(struct xshm_data *data)
int_fast32_t old_width = data->width;
int_fast32_t old_height = data->height;
- if (data->use_xinerama) {
+ 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) {
+ return -1;
+ }
+ }
+ else if (data->use_xinerama) {
if (xinerama_screen_geo(data->xcb, data->screen_id,
&data->x_org, &data->y_org,
&data->width, &data->height) < 0) {
@@ -189,6 +202,7 @@ static void xshm_capture_start(struct xshm_data *data)
if (!xshm_check_extensions(data->xcb))
goto fail;
+ data->use_randr = randr_is_active(data->xcb) ? true : false;
data->use_xinerama = xinerama_is_active(data->xcb) ? true : false;
if (xshm_update_geometry(data) < 0) {
@@ -287,16 +301,21 @@ static bool xshm_server_changed(obs_properties_t *props,
struct dstr screen_info;
dstr_init(&screen_info);
+ bool randr = randr_is_active(xcb);
bool xinerama = xinerama_is_active(xcb);
- int_fast32_t count = (xinerama) ?
- xinerama_screen_count(xcb) :
- xcb_setup_roots_length(xcb_get_setup(xcb));
+ int_fast32_t count = (randr) ?
+ randr_screen_count(xcb) :
+ (xinerama) ?
+ xinerama_screen_count(xcb) :
+ xcb_setup_roots_length(xcb_get_setup(xcb));
for (int_fast32_t i = 0; i < count; ++i) {
int_fast32_t x, y, w, h;
x = y = w = h = 0;
- if (xinerama)
+ if (randr)
+ randr_screen_geo(xcb, i, &x, &y, &w, &h, NULL);
+ else if (xinerama)
xinerama_screen_geo(xcb, i, &x, &y, &w, &h);
else
x11_screen_geo(xcb, i, &w, &h);