Merge pull request #1667 from grimmy/xshm-xrandr-support
linux-capture: Add randr support
This commit is contained in:
commit
e7b25a9870
@ -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 \
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -17,6 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/shm.h>
|
||||
#include <xcb/randr.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xinerama.h>
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <xcb/randr.h>
|
||||
#include <xcb/shm.h>
|
||||
#include <xcb/xfixes.h>
|
||||
#include <xcb/xinerama.h>
|
||||
@ -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,8 +301,11 @@ 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) ?
|
||||
int_fast32_t count = (randr) ?
|
||||
randr_screen_count(xcb) :
|
||||
(xinerama) ?
|
||||
xinerama_screen_count(xcb) :
|
||||
xcb_setup_roots_length(xcb_get_setup(xcb));
|
||||
|
||||
@ -296,7 +313,9 @@ static bool xshm_server_changed(obs_properties_t *props,
|
||||
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user