|
|
|
/*
|
|
|
|
* Copyright © 2010 Raptor Engineering
|
|
|
|
* Copyright © 2007 Intel Corporation
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
* THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
#include "lowlevel_randr.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
Status internal_crtc_disable (struct CrtcInfo *crtc);
|
|
|
|
|
|
|
|
char * internal_get_output_name (struct ScreenInfo *screen_info, RROutput id)
|
|
|
|
{
|
|
|
|
char *output_name = NULL;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < screen_info->n_output; i++) {
|
|
|
|
if (id == screen_info->outputs[i]->id) {
|
|
|
|
output_name = screen_info->outputs[i]->info->name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!output_name) {
|
|
|
|
output_name = "Unknown";
|
|
|
|
}
|
|
|
|
|
|
|
|
return output_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
XRRModeInfo * internal_find_mode_by_xid (struct ScreenInfo *screen_info, RRMode mode_id)
|
|
|
|
{
|
|
|
|
XRRModeInfo *mode_info = NULL;
|
|
|
|
XRRScreenResources *res;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
res = screen_info->res;
|
|
|
|
for (i = 0; i < res->nmode; i++) {
|
|
|
|
if (mode_id == res->modes[i].id) {
|
|
|
|
mode_info = &res->modes[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return mode_info;
|
|
|
|
}
|
|
|
|
|
|
|
|
static XRRCrtcInfo * internal_find_crtc_by_xid (struct ScreenInfo *screen_info, RRCrtc crtc_id)
|
|
|
|
{
|
|
|
|
XRRCrtcInfo *crtc_info;
|
|
|
|
Display *dpy;
|
|
|
|
XRRScreenResources *res;
|
|
|
|
|
|
|
|
dpy = screen_info->dpy;
|
|
|
|
res = screen_info->res;
|
|
|
|
|
|
|
|
crtc_info = XRRGetCrtcInfo (dpy, res, crtc_id);
|
|
|
|
|
|
|
|
return crtc_info;
|
|
|
|
}
|
|
|
|
|
|
|
|
int internal_get_width_by_output_id (struct ScreenInfo *screen_info, RROutput output_id)
|
|
|
|
{
|
|
|
|
struct OutputInfo *output_info;
|
|
|
|
struct CrtcInfo *crtc_info;
|
|
|
|
RRMode mode_id;
|
|
|
|
XRRModeInfo *mode_info;
|
|
|
|
int i;
|
|
|
|
int width = -1;
|
|
|
|
|
|
|
|
for (i = 0; i < screen_info->n_output; i++) {
|
|
|
|
if (output_id == screen_info->outputs[i]->id) {
|
|
|
|
crtc_info = screen_info->outputs[i]->cur_crtc;
|
|
|
|
if (!crtc_info) {
|
|
|
|
width = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mode_id = crtc_info->cur_mode_id;
|
|
|
|
mode_info = internal_find_mode_by_xid (screen_info, mode_id);
|
|
|
|
|
|
|
|
width = internal_mode_width (mode_info, crtc_info->cur_rotation);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return width;
|
|
|
|
}
|
|
|
|
|
|
|
|
int internal_get_height_by_output_id (struct ScreenInfo *screen_info, RROutput output_id)
|
|
|
|
{
|
|
|
|
struct OutputInfo *output_info;
|
|
|
|
struct CrtcInfo *crtc_info;
|
|
|
|
RRMode mode_id;
|
|
|
|
XRRModeInfo *mode_info;
|
|
|
|
int i;
|
|
|
|
int height = -1;
|
|
|
|
|
|
|
|
for (i = 0; i < screen_info->n_output; i++) {
|
|
|
|
if (output_id == screen_info->outputs[i]->id) {
|
|
|
|
crtc_info = screen_info->outputs[i]->cur_crtc;
|
|
|
|
if (!crtc_info) {
|
|
|
|
height = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mode_id = crtc_info->cur_mode_id;
|
|
|
|
mode_info = internal_find_mode_by_xid (screen_info, mode_id);
|
|
|
|
|
|
|
|
height = internal_mode_height (mode_info, crtc_info->cur_rotation);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return height;
|
|
|
|
}
|
|
|
|
|
|
|
|
int internal_mode_height (XRRModeInfo *mode_info, Rotation rotation)
|
|
|
|
{
|
|
|
|
switch (rotation & 0xf) {
|
|
|
|
case RR_Rotate_0:
|
|
|
|
case RR_Rotate_180:
|
|
|
|
return mode_info->height;
|
|
|
|
case RR_Rotate_90:
|
|
|
|
case RR_Rotate_270:
|
|
|
|
return mode_info->width;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int internal_mode_width (XRRModeInfo *mode_info, Rotation rotation)
|
|
|
|
{
|
|
|
|
switch (rotation & 0xf) {
|
|
|
|
case RR_Rotate_0:
|
|
|
|
case RR_Rotate_180:
|
|
|
|
return mode_info->width;
|
|
|
|
case RR_Rotate_90:
|
|
|
|
case RR_Rotate_270:
|
|
|
|
return mode_info->height;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static struct CrtcInfo * internal_find_crtc (struct ScreenInfo *screen_info, XRROutputInfo *output)
|
|
|
|
{
|
|
|
|
struct CrtcInfo *crtc_info = NULL;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < screen_info->n_crtc; i++) {
|
|
|
|
if (screen_info->crtcs[i]->id == output->crtc) {
|
|
|
|
crtc_info = screen_info->crtcs[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return crtc_info;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct CrtcInfo * internal_auto_find_crtc (struct ScreenInfo *screen_info, struct OutputInfo *output_info)
|
|
|
|
{
|
|
|
|
struct CrtcInfo *crtc_info = NULL;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < screen_info->n_crtc; i++) {
|
|
|
|
if (0 == screen_info->crtcs[i]->cur_noutput) {
|
|
|
|
crtc_info = screen_info->crtcs[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL == crtc_info) {
|
|
|
|
crtc_info = screen_info->crtcs[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
return crtc_info;
|
|
|
|
}
|
|
|
|
|
|
|
|
int internal_set_screen_size (struct ScreenInfo *screen_info)
|
|
|
|
{
|
|
|
|
Display *dpy;
|
|
|
|
int screen;
|
|
|
|
struct CrtcInfo *crtc;
|
|
|
|
XRRModeInfo *mode_info;
|
|
|
|
int cur_x = 0, cur_y = 0;
|
|
|
|
int w = 0, h = 0;
|
|
|
|
int mmW, mmH;
|
|
|
|
int max_width = 0, max_height = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
dpy = screen_info->dpy;
|
|
|
|
screen = DefaultScreen (dpy);
|
|
|
|
|
|
|
|
for (i = 0; i < screen_info->n_crtc; i++) {
|
|
|
|
crtc = screen_info->crtcs[i];
|
|
|
|
if (!crtc->cur_mode_id) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
mode_info = internal_find_mode_by_xid (screen_info, crtc->cur_mode_id);
|
|
|
|
cur_x = crtc->cur_x;
|
|
|
|
cur_y = crtc->cur_y;
|
|
|
|
|
|
|
|
w = internal_mode_width (mode_info, crtc->cur_rotation);
|
|
|
|
h = internal_mode_height (mode_info, crtc->cur_rotation);
|
|
|
|
|
|
|
|
if (cur_x + w > max_width) {
|
|
|
|
max_width = cur_x + w;
|
|
|
|
}
|
|
|
|
if (cur_y + h > max_height) {
|
|
|
|
max_height = cur_y + h;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (max_width > screen_info->max_width) {
|
|
|
|
#if RANDR_GUI_DEBUG
|
|
|
|
fprintf (stderr, "user set screen width %d, larger than max width %d, set to max width\n",
|
|
|
|
cur_x + w, screen_info->max_width);
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
} else if (max_width < screen_info->min_width) {
|
|
|
|
screen_info->cur_width = screen_info->min_width;
|
|
|
|
} else {
|
|
|
|
screen_info->cur_width = max_width;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (max_height > screen_info->max_height) {
|
|
|
|
#if RANDR_GUI_DEBUG
|
|
|
|
fprintf (stderr, "user set screen height %d, larger than max height %d, set to max height\n",
|
|
|
|
cur_y + h, screen_info->max_height);
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
} else if (max_height < screen_info->min_height) {
|
|
|
|
screen_info->cur_height = screen_info->min_height;
|
|
|
|
} else {
|
|
|
|
screen_info->cur_height = max_height;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* calculate mmWidth, mmHeight */
|
|
|
|
if (screen_info->cur_width != DisplayWidth (dpy, screen) ||
|
|
|
|
screen_info->cur_height != DisplayHeight (dpy, screen) ) {
|
|
|
|
double dpi;
|
|
|
|
|
|
|
|
dpi = (25.4 * DisplayHeight (dpy, screen)) / DisplayHeightMM(dpy, screen);
|
|
|
|
mmW = (25.4 * screen_info->cur_width) / dpi;
|
|
|
|
mmH = (25.4 * screen_info->cur_height) / dpi;
|
|
|
|
} else {
|
|
|
|
mmW = DisplayWidthMM (dpy, screen);
|
|
|
|
mmH = DisplayHeightMM (dpy, screen);
|
|
|
|
}
|
|
|
|
|
|
|
|
screen_info->cur_mmWidth = mmW;
|
|
|
|
screen_info->cur_mmHeight = mmH;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void internal_screen_apply (struct ScreenInfo *screen_info)
|
|
|
|
{
|
|
|
|
int width, height;
|
|
|
|
int mmWidth, mmHeight;
|
|
|
|
Display *dpy, *cur_dpy;
|
|
|
|
Window window;
|
|
|
|
int screen;
|
|
|
|
static int first = 1;
|
|
|
|
|
|
|
|
width = screen_info->cur_width;
|
|
|
|
height = screen_info->cur_height;
|
|
|
|
mmWidth = screen_info->cur_mmWidth;
|
|
|
|
mmHeight = screen_info->cur_mmHeight;
|
|
|
|
dpy = screen_info->dpy;
|
|
|
|
window = screen_info->window;
|
|
|
|
screen = DefaultScreen (dpy);
|
|
|
|
|
|
|
|
cur_dpy = XOpenDisplay (NULL);
|
|
|
|
|
|
|
|
if (width == DisplayWidth (cur_dpy, screen) &&
|
|
|
|
height == DisplayHeight (cur_dpy, screen) &&
|
|
|
|
mmWidth == DisplayWidthMM (cur_dpy, screen) &&
|
|
|
|
mmHeight == DisplayHeightMM (cur_dpy, screen) ) {
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
XRRSetScreenSize (dpy, window, width, height, mmWidth, mmHeight);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Status internal_crtc_apply (struct CrtcInfo *crtc_info)
|
|
|
|
{
|
|
|
|
struct ScreenInfo *screen_info;
|
|
|
|
XRRCrtcInfo *rr_crtc_info;
|
|
|
|
Display *dpy;
|
|
|
|
XRRScreenResources *res;
|
|
|
|
RRCrtc crtc_id;
|
|
|
|
int x, y;
|
|
|
|
RRMode mode_id;
|
|
|
|
Rotation rotation;
|
|
|
|
RROutput *outputs;
|
|
|
|
int noutput;
|
|
|
|
Status s;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/*if (!crtc_info->changed) {
|
|
|
|
return RRSetConfigSuccess;
|
|
|
|
}*/
|
|
|
|
|
|
|
|
screen_info = crtc_info->screen_info;
|
|
|
|
dpy = screen_info->dpy;
|
|
|
|
res = screen_info->res;
|
|
|
|
crtc_id = crtc_info->id;
|
|
|
|
x = crtc_info->cur_x;
|
|
|
|
y = crtc_info->cur_y;
|
|
|
|
|
|
|
|
mode_id = crtc_info->cur_mode_id;
|
|
|
|
rotation = crtc_info->cur_rotation;
|
|
|
|
|
|
|
|
noutput = crtc_info->cur_noutput;
|
|
|
|
|
|
|
|
if (0 == noutput) {
|
|
|
|
return internal_crtc_disable (crtc_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
outputs = malloc (sizeof (RROutput) * noutput);
|
|
|
|
noutput = 0;
|
|
|
|
for (i = 0; i < screen_info->n_output; i++) {
|
|
|
|
struct OutputInfo *output_info = screen_info->outputs[i];
|
|
|
|
|
|
|
|
if (output_info->cur_crtc && crtc_id == output_info->cur_crtc->id) {
|
|
|
|
outputs[noutput++] = output_info->id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
s = XRRSetCrtcConfig (dpy, res, crtc_id, CurrentTime,
|
|
|
|
x, y, mode_id, rotation,
|
|
|
|
outputs, noutput);
|
|
|
|
|
|
|
|
if (RRSetConfigSuccess == s) {
|
|
|
|
crtc_info->changed = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
free (outputs);
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status internal_crtc_disable (struct CrtcInfo *crtc)
|
|
|
|
{
|
|
|
|
struct ScreenInfo *screen_info;
|
|
|
|
|
|
|
|
screen_info = crtc->screen_info;
|
|
|
|
|
|
|
|
return XRRSetCrtcConfig (screen_info->dpy, screen_info->res, crtc->id, CurrentTime,
|
|
|
|
0, 0, None, RR_Rotate_0, NULL, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ScreenInfo* internal_read_screen_info (Display *display)
|
|
|
|
{
|
|
|
|
struct ScreenInfo *screen_info;
|
|
|
|
int screen_num;
|
|
|
|
Window root_window;
|
|
|
|
XRRScreenResources *sr;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
screen_num = DefaultScreen (display);
|
|
|
|
root_window = RootWindow (display, screen_num);
|
|
|
|
|
|
|
|
sr = XRRGetScreenResources (display, root_window);
|
|
|
|
|
|
|
|
if (sr == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
screen_info = malloc (sizeof (struct ScreenInfo));
|
|
|
|
screen_info->dpy = display;
|
|
|
|
screen_info->window = root_window;
|
|
|
|
screen_info->res = sr;
|
|
|
|
screen_info->cur_width = DisplayWidth (display, screen_num);
|
|
|
|
screen_info->cur_height = DisplayHeight (display, screen_num);
|
|
|
|
screen_info->cur_mmWidth = DisplayWidthMM (display, screen_num);
|
|
|
|
screen_info->cur_mmHeight = DisplayHeightMM (display, screen_num);
|
|
|
|
screen_info->n_output = sr->noutput;
|
|
|
|
screen_info->n_crtc = sr->ncrtc;
|
|
|
|
screen_info->outputs = malloc (sizeof (struct OutputInfo *) * sr->noutput);
|
|
|
|
screen_info->crtcs = malloc (sizeof (struct CrtcInfo *) * sr->ncrtc);
|
|
|
|
screen_info->clone = 0;
|
|
|
|
|
|
|
|
XRRGetScreenSizeRange (display, root_window, &screen_info->min_width, &screen_info->min_height, &screen_info->max_width, &screen_info->max_height);
|
|
|
|
|
|
|
|
/* get crtc */
|
|
|
|
for (i = 0; i < sr->ncrtc; i++) {
|
|
|
|
struct CrtcInfo *crtc_info;
|
|
|
|
screen_info->crtcs[i] = malloc (sizeof (struct CrtcInfo));
|
|
|
|
crtc_info = screen_info->crtcs[i];
|
|
|
|
XRRCrtcInfo *xrr_crtc_info = XRRGetCrtcInfo (display, sr, sr->crtcs[i]);
|
|
|
|
|
|
|
|
crtc_info->id = sr->crtcs[i];
|
|
|
|
crtc_info->info = xrr_crtc_info;
|
|
|
|
crtc_info->cur_x = xrr_crtc_info->x;
|
|
|
|
crtc_info->cur_y = xrr_crtc_info->y;
|
|
|
|
crtc_info->cur_mode_id = xrr_crtc_info->mode;
|
|
|
|
crtc_info->cur_rotation = xrr_crtc_info->rotation;
|
|
|
|
crtc_info->rotations = xrr_crtc_info->rotations;
|
|
|
|
crtc_info->cur_noutput = xrr_crtc_info->noutput;
|
|
|
|
|
|
|
|
crtc_info->changed = 0;
|
|
|
|
crtc_info->screen_info = screen_info;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* get output */
|
|
|
|
for (i = 0; i < sr->noutput; i++) {
|
|
|
|
struct OutputInfo *output;
|
|
|
|
screen_info->outputs[i] = malloc (sizeof (struct OutputInfo));
|
|
|
|
output = screen_info->outputs[i];
|
|
|
|
|
|
|
|
output->id = sr->outputs[i];
|
|
|
|
output->info = XRRGetOutputInfo (display, sr, sr->outputs[i]);
|
|
|
|
output->cur_crtc = internal_find_crtc (screen_info, output->info);
|
|
|
|
output->auto_set = 0;
|
|
|
|
if (output->cur_crtc) {
|
|
|
|
output->off_set = 0;
|
|
|
|
} else {
|
|
|
|
output->off_set = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set current crtc */
|
|
|
|
screen_info->cur_crtc = screen_info->outputs[0]->cur_crtc;
|
|
|
|
screen_info->primary_crtc = screen_info->cur_crtc;
|
|
|
|
screen_info->cur_output = screen_info->outputs[0];
|
|
|
|
|
|
|
|
return screen_info;
|
|
|
|
}
|
|
|
|
|
|
|
|
void internal_free_screen_info (struct ScreenInfo *screen_info)
|
|
|
|
{
|
|
|
|
free (screen_info->outputs);
|
|
|
|
free (screen_info->crtcs);
|
|
|
|
free (screen_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*check if other outputs that connected to the same crtc support this mode*/
|
|
|
|
static int internal_check_mode (struct ScreenInfo *screen_info, struct OutputInfo *output, RRMode mode_id)
|
|
|
|
{
|
|
|
|
XRRCrtcInfo *crtc_info;
|
|
|
|
/* XRR */
|
|
|
|
int i, j;
|
|
|
|
int mode_ok = 1;
|
|
|
|
|
|
|
|
if (!output->cur_crtc) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
crtc_info = output->cur_crtc->info;
|
|
|
|
for (i = 0; i < crtc_info->noutput; i++) {
|
|
|
|
XRROutputInfo *output_info;
|
|
|
|
int nmode;
|
|
|
|
|
|
|
|
if (output->id == crtc_info->outputs[i]) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
mode_ok = 0;
|
|
|
|
output_info = XRRGetOutputInfo (screen_info->dpy, screen_info->res, crtc_info->outputs[i]);
|
|
|
|
nmode = output_info->nmode;
|
|
|
|
for (j = 0; j < nmode; j++) {
|
|
|
|
if (mode_id == output_info->modes[j]) {
|
|
|
|
mode_ok = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!mode_ok) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return mode_ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
static RRCrtc internal_get_crtc_id_by_output_id (struct ScreenInfo *screen_info, RROutput output_id)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
RRCrtc crtc_id = -1;
|
|
|
|
|
|
|
|
for (i = 0; i < screen_info->n_output; i++) {
|
|
|
|
if (output_id == screen_info->outputs[i]->id) {
|
|
|
|
if (screen_info->outputs[i]->cur_crtc) {
|
|
|
|
crtc_id = screen_info->outputs[i]->cur_crtc->id;
|
|
|
|
} else {
|
|
|
|
crtc_id = 0; /* this output is off */
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return crtc_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct CrtcInfo *
|
|
|
|
internal_get_crtc_info_by_xid (struct ScreenInfo *screen_info, RRCrtc crtc_id)
|
|
|
|
{
|
|
|
|
struct CrtcInfo *crtc_info = NULL;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < screen_info->n_crtc; i++) {
|
|
|
|
if (crtc_id == screen_info->crtcs[i]->id) {
|
|
|
|
crtc_info = screen_info->crtcs[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return crtc_info;
|
|
|
|
}
|
|
|
|
|
|
|
|
static XRRModeInfo *
|
|
|
|
internal_preferred_mode (struct ScreenInfo *screen_info, struct OutputInfo *output)
|
|
|
|
{
|
|
|
|
XRROutputInfo *output_info = output->info;
|
|
|
|
Display *dpy;
|
|
|
|
int screen;
|
|
|
|
int m;
|
|
|
|
XRRModeInfo *best;
|
|
|
|
int bestDist;
|
|
|
|
|
|
|
|
dpy = screen_info->dpy;
|
|
|
|
screen = DefaultScreen (dpy);
|
|
|
|
best = NULL;
|
|
|
|
bestDist = 0;
|
|
|
|
for (m = 0; m < output_info->nmode; m++) {
|
|
|
|
XRRModeInfo *mode_info = internal_find_mode_by_xid (screen_info, output_info->modes[m]);
|
|
|
|
int dist;
|
|
|
|
|
|
|
|
if (m < output_info->npreferred)
|
|
|
|
dist = 0;
|
|
|
|
else if (output_info->mm_height)
|
|
|
|
dist = (1000 * DisplayHeight(dpy, screen) / DisplayHeightMM(dpy, screen) -
|
|
|
|
1000 * mode_info->height / output_info->mm_height);
|
|
|
|
else
|
|
|
|
dist = DisplayHeight(dpy, screen) - mode_info->height;
|
|
|
|
|
|
|
|
if (dist < 0) dist = -dist;
|
|
|
|
if (!best || dist < bestDist) {
|
|
|
|
best = mode_info;
|
|
|
|
bestDist = dist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return best;
|
|
|
|
}
|
|
|
|
|
|
|
|
int internal_main_low_apply (struct ScreenInfo *screen_info)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct CrtcInfo *crtc_info;
|
|
|
|
|
|
|
|
/* set_positions (screen_info); */
|
|
|
|
|
|
|
|
if (!internal_set_screen_size (screen_info)) {
|
|
|
|
printf("Screen Size FAILURE\n\r");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < screen_info->n_crtc; i++) {
|
|
|
|
int old_x, old_y, old_w, old_h;
|
|
|
|
|
|
|
|
XRRCrtcInfo *crtc_info = XRRGetCrtcInfo (screen_info->dpy, screen_info->res, screen_info->crtcs[i]->id);
|
|
|
|
XRRModeInfo *old_mode = internal_find_mode_by_xid (screen_info, crtc_info->mode);
|
|
|
|
|
|
|
|
if (crtc_info->mode == None) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
old_x = crtc_info->x;
|
|
|
|
old_y = crtc_info->y;
|
|
|
|
old_w = internal_mode_width (old_mode, crtc_info->rotation);
|
|
|
|
old_h = internal_mode_height (old_mode, crtc_info->rotation);
|
|
|
|
|
|
|
|
if (old_x + old_w <= screen_info->cur_width &&
|
|
|
|
old_y + old_h <= screen_info->cur_height ) {
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
internal_crtc_disable (screen_info->crtcs[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal_screen_apply (screen_info);
|
|
|
|
|
|
|
|
for (i = 0; i < screen_info->n_crtc; i++) {
|
|
|
|
Status s;
|
|
|
|
crtc_info = screen_info->crtcs[i];
|
|
|
|
|
|
|
|
s = internal_crtc_apply (crtc_info);
|
|
|
|
if (RRSetConfigSuccess != s) {
|
|
|
|
fprintf (stderr, "crtc apply error\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void internal_output_auto (struct ScreenInfo *screen_info, struct OutputInfo *output_info)
|
|
|
|
{
|
|
|
|
XRRModeInfo *mode_info;
|
|
|
|
RRMode mode_id;
|
|
|
|
struct CrtcInfo *crtc_info;
|
|
|
|
XRROutputInfo *probe_output_info;
|
|
|
|
|
|
|
|
if (RR_Disconnected == output_info->info->connection) {
|
|
|
|
XRRScreenResources *cur_res;
|
|
|
|
|
|
|
|
cur_res = XRRGetScreenResources (screen_info->dpy, screen_info->window);
|
|
|
|
probe_output_info = XRRGetOutputInfo (screen_info->dpy, cur_res, output_info->id);
|
|
|
|
if (RR_Disconnected != probe_output_info->connection) {
|
|
|
|
output_info->info = probe_output_info;
|
|
|
|
output_info->cur_crtc = internal_auto_find_crtc (screen_info, output_info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mode_info = internal_preferred_mode (screen_info, output_info);
|
|
|
|
if (!mode_info) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mode_id = mode_info->id;
|
|
|
|
|
|
|
|
crtc_info = output_info->cur_crtc;
|
|
|
|
if (crtc_info) {
|
|
|
|
crtc_info->cur_mode_id = mode_id;
|
|
|
|
} else {
|
|
|
|
crtc_info = internal_auto_find_crtc (screen_info, output_info);
|
|
|
|
if (!crtc_info) {
|
|
|
|
#if RANDR_GUI_DEBUG
|
|
|
|
fprintf (stderr, "Can not find usable CRTC\n");
|
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
screen_info->cur_output->cur_crtc = crtc_info;
|
|
|
|
screen_info->cur_crtc = crtc_info;
|
|
|
|
screen_info->cur_crtc->cur_noutput++;
|
|
|
|
fprintf (stderr, "n output: %d\n", screen_info->cur_crtc->cur_noutput);
|
|
|
|
screen_info->cur_crtc->cur_mode_id = mode_id;
|
|
|
|
screen_info->cur_crtc->changed = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void internal_output_off (struct ScreenInfo *screen_info, struct OutputInfo *output)
|
|
|
|
{
|
|
|
|
if (output->cur_crtc) {
|
|
|
|
output->cur_crtc->cur_noutput--;
|
|
|
|
}
|
|
|
|
output->cur_crtc = NULL;
|
|
|
|
screen_info->cur_crtc = NULL;
|
|
|
|
output->off_set = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void internal_output_set_primary (struct ScreenInfo *screen_info, RROutput output_id)
|
|
|
|
{
|
|
|
|
XRRSetOutputPrimary(screen_info->dpy, screen_info->window, output_id);
|
|
|
|
}
|