xrandr源码分析
1、XOpenDisplay 打开xrandr句柄,参数是显示后端xorg或者xwayland,也就是localhost:0.0
dpy = XOpenDisplay (display_name); //XOpenDisplay(":0");
if (dpy == NULL) {
fprintf (stderr, "Can't open display %s\n", XDisplayName(display_name));
exit (1);
}
2、RootWindow通过screen下标获取到显示器设备句柄
static int screen = -1;
if (screen < 0)
screen = DefaultScreen (dpy);
if (screen >= ScreenCount (dpy)) {
fprintf (stderr, "Invalid screen number %d (display has %d)\n", screen, ScreenCount (dpy));
exit (1);
}
root = RootWindow (dpy, screen);
3、获取屏幕信息XRRScreenResources(同时获取XRRGetScreenSizeRange最大,最小分辨率,XRRGetScreenResourcesCurrent/XRRGetScreenResources当前分辨率)
static void
get_screen (Bool current)
{
if (!has_1_2)
fatal ("Server RandR version before 1.2\n");
//已经获取到了,直接返回static XRRScreenResources *res;
if (res)
return;
XRRGetScreenSizeRange (dpy, root, &minWidth, &minHeight, &maxWidth, &maxHeight);
if (current)
res = XRRGetScreenResourcesCurrent (dpy, root);
else
res = XRRGetScreenResources (dpy, root);
if (!res)
fatal ("could not get screen resources");
}
4、获取crtcs
typedef struct _XRRPanning {
Time timestamp;
unsigned int left;
unsigned int top;
unsigned int width;
unsigned int height;
unsigned int track_left;
unsigned int track_top;
unsigned int track_width;
unsigned int track_height;
int border_left;
int border_top;
int border_right;
int border_bottom;
} XRRPanning;
typedef struct _XRRModeInfo {
RRMode id;
unsigned int width;
unsigned int height;
unsigned long dotClock;
unsigned int hSyncStart;
unsigned int hSyncEnd;
unsigned int hTotal;
unsigned int hSkew;
unsigned int vSyncStart;
unsigned int vSyncEnd;
unsigned int vTotal;
char *name;
unsigned int nameLength;
XRRModeFlags modeFlags;
} XRRModeInfo;
typedef struct _XRRCrtcInfo {
Time timestamp;
int x, y;
unsigned int width, height;
RRMode mode;
Rotation rotation;
int noutput;
RROutput *outputs;
Rotation rotations;
int npossible;
RROutput *possible;
} XRRCrtcInfo;
struct _crtc {
name_t crtc;
Bool changing;
XRRCrtcInfo *crtc_info;
XRRModeInfo *mode_info;
XRRPanning *panning_info;
int x;
int y;
Rotation rotation;
output_t **outputs;
int noutput;
transform_t current_transform, pending_transform;
};
typedef struct _crtc crtc_t;
static void
get_crtcs (void)
{
num_crtcs = res->ncrtc;
crtcs = calloc (num_crtcs, sizeof (crtc_t)); //保存到crtcs
if (!crtcs)
fatal ("out of memory\n");
for (int c = 0; c < res->ncrtc; c++)
{
XRRCrtcInfo *crtc_info = XRRGetCrtcInfo (dpy, res, res->crtcs[c]);
XRRCrtcTransformAttributes *attr;
XRRPanning *panning_info = NULL;
if (has_1_3) {
XRRPanning zero;
memset(&zero, 0, sizeof(zero));
panning_info = XRRGetPanning (dpy, res, res->crtcs[c]);
zero.timestamp = panning_info->timestamp;
if (!memcmp(panning_info, &zero, sizeof(zero))) {
Xfree(panning_info);
panning_info = NULL;
}
}
set_name_xid (&crtcs[c].crtc, res->crtcs[c]);
set_name_index (&crtcs[c].crtc, c);
if (!crtc_info)
fatal ("could not get crtc 0x%lx information\n", res->crtcs[c]);
crtcs[c].crtc_info = crtc_info;
crtcs[c].panning_info = panning_info;
if (crtc_info->mode == None)
{
crtcs[c].mode_info = NULL;
crtcs[c].x = 0;
crtcs[c].y = 0;
crtcs[c].rotation = RR_Rotate_0;
}
if (XRRGetCrtcTransform (dpy, res->crtcs[c], &attr) && attr) {
set_transform (&crtcs[c].current_transform, &attr->currentTransform, attr->currentFilter, attr->currentParams, attr->currentNparams);
XFree (attr);
}else{
init_transform (&crtcs[c].current_transform);
}
copy_transform (&crtcs[c].pending_transform, &crtcs[c].current_transform);
}
}