screen: store RandR information
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
6a1ce5ce05
commit
8c87b7cb57
85
screen.c
85
screen.c
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
#include <xcb/xinerama.h>
|
#include <xcb/xinerama.h>
|
||||||
|
#include <xcb/randr.h>
|
||||||
|
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "ewmh.h"
|
#include "ewmh.h"
|
||||||
|
@ -33,6 +34,16 @@
|
||||||
#include "luaa.h"
|
#include "luaa.h"
|
||||||
#include "common/xutil.h"
|
#include "common/xutil.h"
|
||||||
|
|
||||||
|
struct screen_output_t
|
||||||
|
{
|
||||||
|
/** The XRandR names of the output */
|
||||||
|
char *name;
|
||||||
|
/** The size in millimeters */
|
||||||
|
uint32_t mm_width, mm_height;
|
||||||
|
};
|
||||||
|
|
||||||
|
ARRAY_FUNCS(screen_output_t, screen_output, DO_NOTHING)
|
||||||
|
|
||||||
static inline area_t
|
static inline area_t
|
||||||
screen_xsitoarea(xcb_xinerama_screen_info_t si)
|
screen_xsitoarea(xcb_xinerama_screen_info_t si)
|
||||||
{
|
{
|
||||||
|
@ -65,6 +76,79 @@ screen_default_visual(xcb_screen_t *s)
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
screen_scan(void)
|
screen_scan(void)
|
||||||
|
{
|
||||||
|
/* Check for extension before checking for XRandR */
|
||||||
|
if(xcb_get_extension_data(globalconf.connection, &xcb_randr_id)->present)
|
||||||
|
{
|
||||||
|
xcb_randr_query_version_reply_t *version_reply =
|
||||||
|
xcb_randr_query_version_reply(globalconf.connection,
|
||||||
|
xcb_randr_query_version(globalconf.connection, 1, 1), 0);
|
||||||
|
if(version_reply)
|
||||||
|
{
|
||||||
|
/* A quick XRandR recall:
|
||||||
|
* You have CRTC that manages a part of a SCREEN.
|
||||||
|
* Each CRTC can draw stuff on one or more OUTPUT. */
|
||||||
|
xcb_screen_t *screen = xutil_screen_get(globalconf.connection, globalconf.default_screen);
|
||||||
|
|
||||||
|
xcb_randr_get_screen_resources_cookie_t screen_res_c = xcb_randr_get_screen_resources(globalconf.connection, screen->root);
|
||||||
|
xcb_randr_get_screen_resources_reply_t *screen_res_r = xcb_randr_get_screen_resources_reply(globalconf.connection, screen_res_c, NULL);
|
||||||
|
|
||||||
|
/* We go through CRTC, and build a screen for each one. */
|
||||||
|
xcb_randr_crtc_t *randr_crtcs = xcb_randr_get_screen_resources_crtcs(screen_res_r);
|
||||||
|
|
||||||
|
for(int i = 0; i < screen_res_r->num_crtcs; i++)
|
||||||
|
{
|
||||||
|
/* Get info on the output crtc */
|
||||||
|
xcb_randr_get_crtc_info_cookie_t crtc_info_c = xcb_randr_get_crtc_info(globalconf.connection, randr_crtcs[i], XCB_CURRENT_TIME);
|
||||||
|
xcb_randr_get_crtc_info_reply_t *crtc_info_r = xcb_randr_get_crtc_info_reply(globalconf.connection, crtc_info_c, NULL);
|
||||||
|
|
||||||
|
/* If CRTC has no OUTPUT, ignore it */
|
||||||
|
if(!xcb_randr_get_crtc_info_outputs_length(crtc_info_r))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Prepare the new screen */
|
||||||
|
screen_t new_screen;
|
||||||
|
p_clear(&new_screen, 1);
|
||||||
|
new_screen.geometry.x = crtc_info_r->x;
|
||||||
|
new_screen.geometry.y = crtc_info_r->y;
|
||||||
|
new_screen.geometry.width= crtc_info_r->width;
|
||||||
|
new_screen.geometry.height= crtc_info_r->height;
|
||||||
|
|
||||||
|
xcb_randr_output_t *randr_outputs = xcb_randr_get_crtc_info_outputs(crtc_info_r);
|
||||||
|
|
||||||
|
for(int j = 0; j < xcb_randr_get_crtc_info_outputs_length(crtc_info_r); j++)
|
||||||
|
{
|
||||||
|
xcb_randr_get_output_info_cookie_t output_info_c = xcb_randr_get_output_info(globalconf.connection, randr_outputs[j], XCB_CURRENT_TIME);
|
||||||
|
xcb_randr_get_output_info_reply_t *output_info_r = xcb_randr_get_output_info_reply(globalconf.connection, output_info_c, NULL);
|
||||||
|
|
||||||
|
int len = xcb_randr_get_output_info_name_length(output_info_r);
|
||||||
|
/* name is not NULL terminated */
|
||||||
|
char *name = memcpy(p_new(char *, len + 1), xcb_randr_get_output_info_name(output_info_r), len);
|
||||||
|
name[len] = '\0';
|
||||||
|
|
||||||
|
screen_output_array_append(&new_screen.outputs,
|
||||||
|
(screen_output_t) { .name = name,
|
||||||
|
.mm_width = output_info_r->mm_width,
|
||||||
|
.mm_height = output_info_r->mm_height });
|
||||||
|
|
||||||
|
p_delete(&output_info_r);
|
||||||
|
}
|
||||||
|
|
||||||
|
screen_array_append(&globalconf.screens, new_screen);
|
||||||
|
|
||||||
|
p_delete(&crtc_info_r);
|
||||||
|
}
|
||||||
|
|
||||||
|
p_delete(&screen_res_r);
|
||||||
|
|
||||||
|
/* If RandR provides more than 2 active CRTC, Xinerama is enabled */
|
||||||
|
if(globalconf.screens.len > 1)
|
||||||
|
globalconf.xinerama_is_active = true;
|
||||||
|
|
||||||
|
globalconf.screens.tab[0].visual = screen_default_visual(xutil_screen_get(globalconf.connection, globalconf.default_screen));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
/* Check for extension before checking for Xinerama */
|
/* Check for extension before checking for Xinerama */
|
||||||
if(xcb_get_extension_data(globalconf.connection, &xcb_xinerama_id)->present)
|
if(xcb_get_extension_data(globalconf.connection, &xcb_xinerama_id)->present)
|
||||||
|
@ -135,6 +219,7 @@ screen_scan(void)
|
||||||
s.visual = screen_default_visual(xcb_screen);
|
s.visual = screen_default_visual(xcb_screen);
|
||||||
screen_array_append(&globalconf.screens, s);
|
screen_array_append(&globalconf.screens, s);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
globalconf.screen_focus = globalconf.screens.tab;
|
globalconf.screen_focus = globalconf.screens.tab;
|
||||||
}
|
}
|
||||||
|
|
5
screen.h
5
screen.h
|
@ -25,6 +25,9 @@
|
||||||
#include "globalconf.h"
|
#include "globalconf.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
|
|
||||||
|
typedef struct screen_output_t screen_output_t;
|
||||||
|
ARRAY_TYPE(screen_output_t, screen_output)
|
||||||
|
|
||||||
struct a_screen
|
struct a_screen
|
||||||
{
|
{
|
||||||
/** Screen geometry */
|
/** Screen geometry */
|
||||||
|
@ -50,6 +53,8 @@ struct a_screen
|
||||||
signal_array_t signals;
|
signal_array_t signals;
|
||||||
/** True if the banning on this screen needs to be updated */
|
/** True if the banning on this screen needs to be updated */
|
||||||
bool need_lazy_banning;
|
bool need_lazy_banning;
|
||||||
|
/** The screen outputs informations */
|
||||||
|
screen_output_array_t outputs;
|
||||||
};
|
};
|
||||||
ARRAY_FUNCS(screen_t, screen, DO_NOTHING)
|
ARRAY_FUNCS(screen_t, screen, DO_NOTHING)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue