// Restore the saved (original) video mode for the specified monitor // void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor) { if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) { XRRScreenResources* sr; XRRCrtcInfo* ci; if (monitor->x11.oldMode == None) return; sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); XRRSetCrtcConfig(_glfw.x11.display, sr, monitor->x11.crtc, CurrentTime, ci->x, ci->y, monitor->x11.oldMode, ci->rotation, ci->outputs, ci->noutput); XRRFreeCrtcInfo(ci); XRRFreeScreenResources(sr); monitor->x11.oldMode = None; } }
int get_screen_geom(Window last_focused, int *x, int *y, int *w, int *h) { int i; XWindowAttributes wa; XRRScreenResources *resources; XRRCrtcInfo *monitor_info; XGetWindowAttributes(dpy, last_focused, &wa); /* TODO externalize resources */ resources = XRRGetScreenResourcesCurrent(dpy, last_focused); for (i = 0; i < resources->ncrtc; i++) { monitor_info = XRRGetCrtcInfo(dpy, resources, resources->crtcs[i]); if (wa.x >= monitor_info->x && wa.x <= monitor_info->x + monitor_info->width - 1 && wa.y >= monitor_info->y && wa.y <= monitor_info->y + monitor_info->height - 1) { *x = monitor_info->x; *y = monitor_info->y; *w = monitor_info->width; *h = monitor_info->height; return 1; } } return 0; }
XRRConfiguration::XRRConfiguration(Display *_dpy, Window _win) : dpy(_dpy) , win(_win) , screenResources(nullptr), outputInfo(nullptr), crtcInfo(nullptr) , fullMode(0) , fs_fb_width(0), fs_fb_height(0), fs_fb_width_mm(0), fs_fb_height_mm(0) , bValid(true), bIsFullscreen(false) { int XRRMajorVersion, XRRMinorVersion; if (!XRRQueryVersion(dpy, &XRRMajorVersion, &XRRMinorVersion) || (XRRMajorVersion < 1 || (XRRMajorVersion == 1 && XRRMinorVersion < 3))) { WARN_LOG(VIDEO, "XRRExtension not supported."); bValid = false; return; } screenResources = XRRGetScreenResourcesCurrent(dpy, win); screen = DefaultScreen(dpy); fb_width = DisplayWidth(dpy, screen); fb_height = DisplayHeight(dpy, screen); fb_width_mm = DisplayWidthMM(dpy, screen); fb_height_mm = DisplayHeightMM(dpy, screen); INFO_LOG(VIDEO, "XRRExtension-Version %d.%d", XRRMajorVersion, XRRMinorVersion); Update(); }
void xfce_randr_reload (XfceRandr *randr) { Display *xdisplay; GdkWindow *root_window; xfce_randr_cleanup (randr); /* get the x display */ xdisplay = gdk_x11_display_get_xdisplay (randr->priv->display); /* get the root window */ root_window = gdk_get_default_root_window (); /* get the screen resource */ #ifdef HAS_RANDR_ONE_POINT_THREE /* xfce_randr_reload() is only called after a xrandr notification, which means that X is aware of the new hardware already. So, if possible, do not reprobe the hardware again. */ if (randr->priv->has_1_3) randr->priv->resources = XRRGetScreenResourcesCurrent (xdisplay, GDK_WINDOW_XID (root_window)); else #endif randr->priv->resources = XRRGetScreenResources (xdisplay, GDK_WINDOW_XID (root_window)); /* repopulate */ xfce_randr_populate (randr, xdisplay, root_window); }
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) { if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) { XRRScreenResources* sr; XRRCrtcInfo* ci; sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); *mode = vidmodeFromModeInfo(getModeInfo(sr, ci->mode), ci); XRRFreeCrtcInfo(ci); XRRFreeScreenResources(sr); } else { mode->width = DisplayWidth(_glfw.x11.display, _glfw.x11.screen); mode->height = DisplayHeight(_glfw.x11.display, _glfw.x11.screen); mode->refreshRate = 0; _glfwSplitBPP(DefaultDepth(_glfw.x11.display, _glfw.x11.screen), &mode->redBits, &mode->greenBits, &mode->blueBits); } }
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) { GLFWvidmode* result; *found = 0; // Build array of available resolutions if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) { int i, j; XRRScreenResources* sr; XRRCrtcInfo* ci; XRROutputInfo* oi; sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output); result = calloc(oi->nmode, sizeof(GLFWvidmode)); for (i = 0; i < oi->nmode; i++) { const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]); if (!modeIsGood(mi)) continue; const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci); for (j = 0; j < *found; j++) { if (_glfwCompareVideoModes(result + j, &mode) == 0) break; } if (j < *found) { // This is a duplicate, so skip it continue; } result[*found] = mode; (*found)++; } XRRFreeOutputInfo(oi); XRRFreeCrtcInfo(ci); XRRFreeScreenResources(sr); } else { *found = 1; result = calloc(1, sizeof(GLFWvidmode)); _glfwPlatformGetVideoMode(monitor, result); } return result; }
static inline XRRScreenResources *_XRRGetScreenResourcesCurrent(Display *dpy, Window window) { XRRScreenResources *res; res = XRRGetScreenResourcesCurrent(dpy, window); if (res == NULL) res = XRRGetScreenResources(dpy, window); return res; }
// Set the current video mode for the specified monitor // void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired) { if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) { XRRScreenResources* sr; XRRCrtcInfo* ci; XRROutputInfo* oi; GLFWvidmode current; const GLFWvidmode* best; RRMode native = None; int i; best = _glfwChooseVideoMode(monitor, desired); _glfwPlatformGetVideoMode(monitor, ¤t); if (_glfwCompareVideoModes(¤t, best) == 0) return; sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output); for (i = 0; i < oi->nmode; i++) { const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]); if (!modeIsGood(mi)) continue; const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci); if (_glfwCompareVideoModes(best, &mode) == 0) { native = mi->id; break; } } if (native) { if (monitor->x11.oldMode == None) monitor->x11.oldMode = ci->mode; XRRSetCrtcConfig(_glfw.x11.display, sr, monitor->x11.crtc, CurrentTime, ci->x, ci->y, native, ci->rotation, ci->outputs, ci->noutput); } XRRFreeOutputInfo(oi); XRRFreeCrtcInfo(ci); XRRFreeScreenResources(sr); } }
/* * Class: jogamp_newt_driver_x11_RandR13 * Method: getScreenResources0 * Signature: (JI)J */ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR13_getScreenResources0 (JNIEnv *env, jclass clazz, jlong display, jint screen_idx) { Display *dpy = (Display *) (intptr_t) display; Window root = RootWindow(dpy, (int)screen_idx); XRRScreenResources *res = XRRGetScreenResourcesCurrent( dpy, root); // 1.3 // XRRScreenResources *res = XRRGetScreenResources( dpy, root); // 1.2 return (jlong) (intptr_t) res; }
static int SwitchRes(char inout, int x __UNUSED__, int y __UNUSED__, int w, int h, int *dw, int *dh) { XRRScreenResources *xsr; XRRCrtcInfo *xci; RRCrtc crtc; RRMode ss_mode_new; int ok = 0; Dprintf("%s: inout=%d\n", __func__, inout); xsr = XRRGetScreenResourcesCurrent(disp, WinGetXwin(VROOT)); if (!xsr) goto done; crtc = xsr->crtcs[0]; /* FIXME - Which crtc? */ if (inout) { /* Save current setup */ xci = XRRGetCrtcInfo(disp, xsr, crtc); if (!xci) goto done; ss_mode = xci->mode; ss_rot = xci->rotation; XRRFreeCrtcInfo(xci); /* Select zoomed setup */ ss_mode_new = FindMode(xsr, w, h, dw, dh); /* Set zoomed setup */ SetPanning(xsr, crtc, 1); ok = SetMode(xsr, crtc, ss_mode_new, ss_rot); } else { /* Revert to original setup */ ok = SetMode(xsr, crtc, ss_mode, ss_rot); SetPanning(xsr, crtc, 0); } done: if (xsr) XRRFreeScreenResources(xsr); Dprintf("%s: ok=%d\n", __func__, ok); return ok; }
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) { if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) { XRRScreenResources* sr; XRRCrtcInfo* ci; sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); if (xpos) *xpos = ci->x; if (ypos) *ypos = ci->y; XRRFreeCrtcInfo(ci); XRRFreeScreenResources(sr); } }
/* * Class: jogamp_newt_driver_x11_RandR13 * Method: getScreenResources0 * Signature: (JI)J */ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR13_getScreenResources0 (JNIEnv *env, jclass clazz, jlong display, jint screen_idx) { Display *dpy = (Display *) (intptr_t) display; Window root = RootWindow(dpy, (int)screen_idx); /* Bug 1183 * XRRGetScreenResourcesCurrent (or XRRGetScreenResources) * _occasionally_ reports empty data * unless XRRGetScreenSizeRange has been called once. */ int minWidth, minHeight, maxWidth, maxHeight; XRRGetScreenSizeRange ( dpy, root, &minWidth, &minHeight, &maxWidth, &maxHeight); XRRScreenResources *res = XRRGetScreenResourcesCurrent( dpy, root); // 1.3 // XRRScreenResources *res = XRRGetScreenResources( dpy, root); // 1.2 return (jlong) (intptr_t) res; }
int main(int argc, char **argv) { Display *dpy = XOpenDisplay(NULL); int screen = DefaultScreen(dpy); Window root = RootWindow(dpy, screen); XRRScreenResources *res = XRRGetScreenResourcesCurrent(dpy, root); int temp = 6500; if (argc > 1) temp = atoi(argv[1]); if (temp < 1000 || temp > 10000) temp = 6500; temp -= 1000; double ratio = temp % 500 / 500.0; #define AVG(c) whitepoints[temp / 500].c * (1 - ratio) + whitepoints[temp / 500 + 1].c * ratio double gammar = AVG(r); double gammag = AVG(g); double gammab = AVG(b); int num_crtcs = res->ncrtc; for (int c = 0; c < res->ncrtc; c++) { int crtcxid = res->crtcs[c]; XRRCrtcInfo *crtc_info = XRRGetCrtcInfo(dpy, res, crtcxid); int size = XRRGetCrtcGammaSize(dpy, crtcxid); XRRCrtcGamma *crtc_gamma = XRRAllocGamma(size); for (int i = 0; i < size; i++) { double g = 65535.0 * i / size; crtc_gamma->red[i] = g * gammar; crtc_gamma->green[i] = g * gammag; crtc_gamma->blue[i] = g * gammab; } XRRSetCrtcGamma(dpy, crtcxid, crtc_gamma); XFree(crtc_gamma); } }
void handleDisplayChange(XRRScreenChangeNotifyEvent *evt) { int screenWidth, screenHeight; if(evt==NULL) { screenWidth = lastScreenWidth; screenHeight = lastScreenHeight; } else { screenWidth = evt->width; lastScreenWidth = screenWidth; screenHeight = evt->height; lastScreenHeight = screenHeight; } if(debugMode) { printf("Screen size: %ix%i\n", screenWidth, screenHeight); } XRRScreenResources *res = XRRGetScreenResourcesCurrent(display, root); int d; for(d = 0; d < profiles.nDeviceSettings; d++) { if(profiles.deviceSettings[d].attachedOutput == NULL && !(profiles.deviceSettings[d].autoOutput)) { /* Set calibration of whole screen */ int id = 0; for(id = 0; id<profiles.deviceSettings[d].inputDeviceCount; id++) { if(debugMode) { printf("Calibrate Device with ID %i\n", profiles.deviceSettings[d].inputDeviceIDs[id]); } setCalibration(profiles.deviceSettings[d].inputDeviceIDs[id], profiles.deviceSettings[d].outputMinX, profiles.deviceSettings[d].outputMaxX, profiles.deviceSettings[d].outputMinY, profiles.deviceSettings[d].outputMaxY, profiles.deviceSettings[d].swapAxes, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight, 0); } } else if(profiles.deviceSettings[d].inputDeviceCount > 0) { int o; for(o = 0; o < res->noutput; o++) { XRROutputInfo *outpInf = XRRGetOutputInfo(display, res, res->outputs[o]); if((profiles.deviceSettings[d].autoOutput && (strstr(outpInf->name, "LVDS") || strstr(outpInf->name, "lvds")) ) || (profiles.deviceSettings[d].attachedOutput && !strcmp(outpInf->name, profiles.deviceSettings[d].attachedOutput))) { /* This is the attached output */ if(outpInf->crtc != 0) { /* The output is active (has a CRTC) */ XRRCrtcInfo* crtcInf = XRRGetCrtcInfo(display, res, outpInf->crtc); if(debugMode) { printf("Output %s -- x: %i; y: %i; w: %i; h: %i\n", outpInf->name, crtcInf->x, crtcInf->y, crtcInf->width, crtcInf->height); } /* Set calibration */ int id = 0; for(id = 0; id<profiles.deviceSettings[d].inputDeviceCount; id++) { if(debugMode) { printf("Calibrate Device with ID %i\n", profiles.deviceSettings[d].inputDeviceIDs[id]); } setCalibration(profiles.deviceSettings[d].inputDeviceIDs[id], profiles.deviceSettings[d].outputMinX, profiles.deviceSettings[d].outputMaxX, profiles.deviceSettings[d].outputMinY, profiles.deviceSettings[d].outputMaxY, profiles.deviceSettings[d].swapAxes, screenWidth, screenHeight, crtcInf->x, crtcInf->y, crtcInf->width, crtcInf->height, crtcInf->rotation); } XRRFreeCrtcInfo(crtcInf); } /* Output found, so break */ break; } XRRFreeOutputInfo(outpInf); } } } XRRFreeScreenResources(res); }
void subScreenInit(void) { SubScreen *s = NULL; #ifdef HAVE_X11_EXTENSIONS_XRANDR_H /* Check both but prefer xrandr */ if(subtle->flags & SUB_SUBTLE_XRANDR) { XRRScreenResources *res = NULL; if((res = XRRGetScreenResourcesCurrent(subtle->dpy, ROOT))) { int i; XRRCrtcInfo *crtc = NULL; /* Query screens */ for(i = 0; i < res->ncrtc; i++) { if((crtc = XRRGetCrtcInfo(subtle->dpy, res, res->crtcs[i]))) { /* Create new screen if crtc is enabled */ if(None != crtc->mode && (s = subScreenNew(crtc->x, crtc->y, crtc->width, crtc->height))) subArrayPush(subtle->screens, (void *)s); XRRFreeCrtcInfo(crtc); } } XRRFreeScreenResources(res); } } #endif /* HAVE_X11_EXTENSIONS_XRANDR_H */ #ifdef HAVE_X11_EXTENSIONS_XINERAMA_H if(subtle->flags & SUB_SUBTLE_XINERAMA && 0 == subtle->screens->ndata && XineramaIsActive(subtle->dpy)) { int i, n = 0; XineramaScreenInfo *info = NULL; /* Query screens */ if((info = XineramaQueryScreens(subtle->dpy, &n))) { for(i = 0; i < n; i++) { /* Create new screen */ if((s = subScreenNew(info[i].x_org, info[i].y_org, info[i].width, info[i].height))) subArrayPush(subtle->screens, (void *)s); } XFree(info); } } #endif /* HAVE_X11_EXTENSIONS_XINERAMA_H */ /* Create default screen */ if(0 == subtle->screens->ndata) { /* Create new screen */ if((s = subScreenNew(0, 0, subtle->width, subtle->height))) subArrayPush(subtle->screens, (void *)s); } printf("Running on %d screen(s)\n", subtle->screens->ndata); ScreenPublish(); subScreenPublish(); subSharedLogDebugSubtle("init=screen\n"); } /* }}} */
// Look for and initialize supported X11 extensions // static GLFWbool initExtensions(void) { _glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1"); if (_glfw.x11.vidmode.handle) { _glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension) _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension"); _glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp) _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp"); _glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp) _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp"); _glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize) _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize"); _glfw.x11.vidmode.available = XF86VidModeQueryExtension(_glfw.x11.display, &_glfw.x11.vidmode.eventBase, &_glfw.x11.vidmode.errorBase); } #if defined(__CYGWIN__) _glfw.x11.xi.handle = _glfw_dlopen("libXi-6.so"); #else _glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6"); #endif if (_glfw.x11.xi.handle) { _glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion) _glfw_dlsym(_glfw.x11.xi.handle, "XIQueryVersion"); _glfw.x11.xi.SelectEvents = (PFN_XISelectEvents) _glfw_dlsym(_glfw.x11.xi.handle, "XISelectEvents"); if (XQueryExtension(_glfw.x11.display, "XInputExtension", &_glfw.x11.xi.majorOpcode, &_glfw.x11.xi.eventBase, &_glfw.x11.xi.errorBase)) { _glfw.x11.xi.major = 2; _glfw.x11.xi.minor = 0; if (XIQueryVersion(_glfw.x11.display, &_glfw.x11.xi.major, &_glfw.x11.xi.minor) == Success) { _glfw.x11.xi.available = GLFW_TRUE; } } } #if defined(__CYGWIN__) _glfw.x11.randr.handle = _glfw_dlopen("libXrandr-2.so"); #else _glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2"); #endif if (_glfw.x11.randr.handle) { _glfw.x11.randr.AllocGamma = (PFN_XRRAllocGamma) _glfw_dlsym(_glfw.x11.randr.handle, "XRRAllocGamma"); _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma) _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma"); _glfw.x11.randr.FreeCrtcInfo = (PFN_XRRFreeCrtcInfo) _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeCrtcInfo"); _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma) _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma"); _glfw.x11.randr.FreeOutputInfo = (PFN_XRRFreeOutputInfo) _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeOutputInfo"); _glfw.x11.randr.FreeScreenResources = (PFN_XRRFreeScreenResources) _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeScreenResources"); _glfw.x11.randr.GetCrtcGamma = (PFN_XRRGetCrtcGamma) _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGamma"); _glfw.x11.randr.GetCrtcGammaSize = (PFN_XRRGetCrtcGammaSize) _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize"); _glfw.x11.randr.GetCrtcInfo = (PFN_XRRGetCrtcInfo) _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcInfo"); _glfw.x11.randr.GetOutputInfo = (PFN_XRRGetOutputInfo) _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputInfo"); _glfw.x11.randr.GetOutputPrimary = (PFN_XRRGetOutputPrimary) _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputPrimary"); _glfw.x11.randr.GetScreenResourcesCurrent = (PFN_XRRGetScreenResourcesCurrent) _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent"); _glfw.x11.randr.QueryExtension = (PFN_XRRQueryExtension) _glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryExtension"); _glfw.x11.randr.QueryVersion = (PFN_XRRQueryVersion) _glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryVersion"); _glfw.x11.randr.SelectInput = (PFN_XRRSelectInput) _glfw_dlsym(_glfw.x11.randr.handle, "XRRSelectInput"); _glfw.x11.randr.SetCrtcConfig = (PFN_XRRSetCrtcConfig) _glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcConfig"); _glfw.x11.randr.SetCrtcGamma = (PFN_XRRSetCrtcGamma) _glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcGamma"); _glfw.x11.randr.UpdateConfiguration = (PFN_XRRUpdateConfiguration) _glfw_dlsym(_glfw.x11.randr.handle, "XRRUpdateConfiguration"); if (XRRQueryExtension(_glfw.x11.display, &_glfw.x11.randr.eventBase, &_glfw.x11.randr.errorBase)) { if (XRRQueryVersion(_glfw.x11.display, &_glfw.x11.randr.major, &_glfw.x11.randr.minor)) { // The GLFW RandR path requires at least version 1.3 if (_glfw.x11.randr.major > 1 || _glfw.x11.randr.minor >= 3) _glfw.x11.randr.available = GLFW_TRUE; } else { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to query RandR version"); } } } if (_glfw.x11.randr.available) { XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0])) { // This is likely an older Nvidia driver with broken gamma support // Flag it as useless and fall back to xf86vm gamma, if available _glfw.x11.randr.gammaBroken = GLFW_TRUE; } if (!sr->ncrtc) { // A system without CRTCs is likely a system with broken RandR // Disable the RandR monitor path and fall back to core functions _glfw.x11.randr.monitorBroken = GLFW_TRUE; } XRRFreeScreenResources(sr); } if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) { XRRSelectInput(_glfw.x11.display, _glfw.x11.root, RROutputChangeNotifyMask); } #if defined(__CYGWIN__) _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor-1.so"); #else _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1"); #endif if (_glfw.x11.xcursor.handle) { _glfw.x11.xcursor.ImageCreate = (PFN_XcursorImageCreate) _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageCreate"); _glfw.x11.xcursor.ImageDestroy = (PFN_XcursorImageDestroy) _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageDestroy"); _glfw.x11.xcursor.ImageLoadCursor = (PFN_XcursorImageLoadCursor) _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor"); } #if defined(__CYGWIN__) _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama-1.so"); #else _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1"); #endif if (_glfw.x11.xinerama.handle) { _glfw.x11.xinerama.IsActive = (PFN_XineramaIsActive) _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaIsActive"); _glfw.x11.xinerama.QueryExtension = (PFN_XineramaQueryExtension) _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryExtension"); _glfw.x11.xinerama.QueryScreens = (PFN_XineramaQueryScreens) _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryScreens"); if (XineramaQueryExtension(_glfw.x11.display, &_glfw.x11.xinerama.major, &_glfw.x11.xinerama.minor)) { if (XineramaIsActive(_glfw.x11.display)) _glfw.x11.xinerama.available = GLFW_TRUE; } } _glfw.x11.xkb.major = 1; _glfw.x11.xkb.minor = 0; _glfw.x11.xkb.available = XkbQueryExtension(_glfw.x11.display, &_glfw.x11.xkb.majorOpcode, &_glfw.x11.xkb.eventBase, &_glfw.x11.xkb.errorBase, &_glfw.x11.xkb.major, &_glfw.x11.xkb.minor); if (_glfw.x11.xkb.available) { Bool supported; if (XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported)) { if (supported) _glfw.x11.xkb.detectable = GLFW_TRUE; } } #if defined(__CYGWIN__) _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb-1.so"); #else _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1"); #endif if (_glfw.x11.x11xcb.handle) { _glfw.x11.x11xcb.GetXCBConnection = (PFN_XGetXCBConnection) _glfw_dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection"); } #if defined(__CYGWIN__) _glfw.x11.xrender.handle = _glfw_dlopen("libXrender-1.so"); #else _glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1"); #endif if (_glfw.x11.xrender.handle) { _glfw.x11.xrender.QueryExtension = (PFN_XRenderQueryExtension) _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryExtension"); _glfw.x11.xrender.QueryVersion = (PFN_XRenderQueryVersion) _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryVersion"); _glfw.x11.xrender.FindVisualFormat = (PFN_XRenderFindVisualFormat) _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderFindVisualFormat"); if (XRenderQueryExtension(_glfw.x11.display, &_glfw.x11.xrender.errorBase, &_glfw.x11.xrender.eventBase)) { if (XRenderQueryVersion(_glfw.x11.display, &_glfw.x11.xrender.major, &_glfw.x11.xrender.minor)) { _glfw.x11.xrender.available = GLFW_TRUE; } } } // Update the key code LUT // FIXME: We should listen to XkbMapNotify events to track changes to // the keyboard mapping. createKeyTables(); // Detect whether an EWMH-conformant window manager is running detectEWMH(); // String format atoms _glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False); _glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False); _glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False); // Custom selection property atom _glfw.x11.GLFW_SELECTION = XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False); // ICCCM standard clipboard atoms _glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False); _glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False); _glfw.x11.PRIMARY = XInternAtom(_glfw.x11.display, "PRIMARY", False); _glfw.x11.INCR = XInternAtom(_glfw.x11.display, "INCR", False); _glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False); // Clipboard manager atoms _glfw.x11.CLIPBOARD_MANAGER = XInternAtom(_glfw.x11.display, "CLIPBOARD_MANAGER", False); _glfw.x11.SAVE_TARGETS = XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False); // Xdnd (drag and drop) atoms _glfw.x11.XdndAware = XInternAtom(_glfw.x11.display, "XdndAware", False); _glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", False); _glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", False); _glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", False); _glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", False); _glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", False); _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False); _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False); _glfw.x11.XdndTypeList = XInternAtom(_glfw.x11.display, "XdndTypeList", False); _glfw.x11.text_uri_list = XInternAtom(_glfw.x11.display, "text/uri-list", False); // ICCCM, EWMH and Motif window property atoms // These can be set safely even without WM support // The EWMH atoms that require WM support are handled in detectEWMH _glfw.x11.WM_PROTOCOLS = XInternAtom(_glfw.x11.display, "WM_PROTOCOLS", False); _glfw.x11.WM_STATE = XInternAtom(_glfw.x11.display, "WM_STATE", False); _glfw.x11.WM_DELETE_WINDOW = XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False); _glfw.x11.NET_WM_ICON = XInternAtom(_glfw.x11.display, "_NET_WM_ICON", False); _glfw.x11.NET_WM_PING = XInternAtom(_glfw.x11.display, "_NET_WM_PING", False); _glfw.x11.NET_WM_PID = XInternAtom(_glfw.x11.display, "_NET_WM_PID", False); _glfw.x11.NET_WM_NAME = XInternAtom(_glfw.x11.display, "_NET_WM_NAME", False); _glfw.x11.NET_WM_ICON_NAME = XInternAtom(_glfw.x11.display, "_NET_WM_ICON_NAME", False); _glfw.x11.NET_WM_BYPASS_COMPOSITOR = XInternAtom(_glfw.x11.display, "_NET_WM_BYPASS_COMPOSITOR", False); _glfw.x11.NET_WM_WINDOW_OPACITY = XInternAtom(_glfw.x11.display, "_NET_WM_WINDOW_OPACITY", False); _glfw.x11.MOTIF_WM_HINTS = XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False); // The compositing manager selection name contains the screen number { char name[32]; snprintf(name, sizeof(name), "_NET_WM_CM_S%u", _glfw.x11.screen); _glfw.x11.NET_WM_CM_Sx = XInternAtom(_glfw.x11.display, name, False); } return GLFW_TRUE; }
static gboolean init_randr13 (GdkScreen *screen) { #ifdef HAVE_RANDR GdkDisplay *display = gdk_screen_get_display (screen); GdkX11Display *display_x11 = GDK_X11_DISPLAY (display); GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); Display *dpy = GDK_SCREEN_XDISPLAY (screen); XRRScreenResources *resources; RROutput primary_output; RROutput first_output = None; int i; GArray *monitors; gboolean randr12_compat = FALSE; if (!display_x11->have_randr13) return FALSE; resources = XRRGetScreenResourcesCurrent (x11_screen->xdisplay, x11_screen->xroot_window); if (!resources) return FALSE; monitors = g_array_sized_new (FALSE, TRUE, sizeof (GdkX11Monitor), resources->noutput); for (i = 0; i < resources->noutput; ++i) { XRROutputInfo *output = XRRGetOutputInfo (dpy, resources, resources->outputs[i]); /* Non RandR1.2 X driver have output name "default" */ randr12_compat |= !g_strcmp0 (output->name, "default"); if (output->connection == RR_Disconnected) { XRRFreeOutputInfo (output); continue; } if (output->crtc) { GdkX11Monitor monitor; XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, output->crtc); monitor.geometry.x = crtc->x; monitor.geometry.y = crtc->y; monitor.geometry.width = crtc->width; monitor.geometry.height = crtc->height; monitor.output = resources->outputs[i]; monitor.width_mm = output->mm_width; monitor.height_mm = output->mm_height; monitor.output_name = g_strdup (output->name); /* FIXME: need EDID parser */ monitor.manufacturer = NULL; g_array_append_val (monitors, monitor); XRRFreeCrtcInfo (crtc); } XRRFreeOutputInfo (output); } if (resources->noutput > 0) first_output = resources->outputs[0]; XRRFreeScreenResources (resources); /* non RandR 1.2 X driver doesn't return any usable multihead data */ if (randr12_compat) { guint n_monitors = monitors->len; free_monitors ((GdkX11Monitor *)g_array_free (monitors, FALSE), n_monitors); return FALSE; } g_array_sort (monitors, (GCompareFunc) monitor_compare_function); x11_screen->n_monitors = monitors->len; x11_screen->monitors = (GdkX11Monitor *)g_array_free (monitors, FALSE); x11_screen->primary_monitor = 0; primary_output = XRRGetOutputPrimary (x11_screen->xdisplay, x11_screen->xroot_window); for (i = 0; i < x11_screen->n_monitors; ++i) { if (x11_screen->monitors[i].output == primary_output) { x11_screen->primary_monitor = i; break; } /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */ if (primary_output == None && g_ascii_strncasecmp (x11_screen->monitors[i].output_name, "LVDS", 4) == 0) { x11_screen->primary_monitor = i; break; } /* No primary specified and no LVDS found */ if (x11_screen->monitors[i].output == first_output) x11_screen->primary_monitor = i; } return x11_screen->n_monitors > 0; #endif return FALSE; }
static gboolean panel_multiscreen_get_randr_monitors_for_screen (GdkScreen *screen, int *monitors_ret, GdkRectangle **geometries_ret) { #ifdef HAVE_RANDR Display *xdisplay; Window xroot; XRRScreenResources *resources; RROutput primary; GArray *geometries; int i; gboolean driver_is_pre_randr_1_2; if (!have_randr) return FALSE; /* GTK+ 2.14.x uses the Xinerama API, instead of RANDR, to get the * monitor geometries. It does this to avoid calling * XRRGetScreenResources(), which is slow as it re-detects all the * monitors --- note that XRRGetScreenResourcesCurrent() had not been * introduced yet. Using Xinerama in GTK+ has the bad side effect that * gdk_screen_get_monitor_plug_name() will return NULL, as Xinerama * does not provide that information, unlike RANDR. * * Here we need to identify the output names, so that we can put the * built-in LCD in a laptop *before* all other outputs. This is so * that mate-panel will normally prefer to appear on the "native" * display rather than on an external monitor. * * To get the output names and geometries, we will not use * gdk_screen_get_n_monitors() and friends, but rather we will call * XRR*() directly. * * See https://bugzilla.novell.com/show_bug.cgi?id=479684 for this * particular bug, and and * http://bugzilla.gnome.org/show_bug.cgi?id=562944 for a more * long-term solution. */ xdisplay = GDK_SCREEN_XDISPLAY (screen); #if GTK_CHECK_VERSION (3, 0, 0) xroot = GDK_WINDOW_XID (gdk_screen_get_root_window (screen)); #else xroot = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen)); #endif #if (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3)) if (have_randr_1_3) { resources = XRRGetScreenResourcesCurrent (xdisplay, xroot); if (resources->noutput == 0) { /* This might happen if nothing tried to get randr * resources from the server before, so we need an * active probe. See comment #27 in * https://bugzilla.gnome.org/show_bug.cgi?id=597101 */ XRRFreeScreenResources (resources); resources = XRRGetScreenResources (xdisplay, xroot); } } else resources = XRRGetScreenResources (xdisplay, xroot); #else resources = XRRGetScreenResources (xdisplay, xroot); #endif if (!resources) return FALSE; primary = None; #if (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3)) if (have_randr_1_3) primary = XRRGetOutputPrimary (xdisplay, xroot); #endif geometries = g_array_sized_new (FALSE, FALSE, sizeof (GdkRectangle), resources->noutput); driver_is_pre_randr_1_2 = FALSE; for (i = 0; i < resources->noutput; i++) { XRROutputInfo *output; output = XRRGetOutputInfo (xdisplay, resources, resources->outputs[i]); /* Drivers before RANDR 1.2 return "default" for the output * name */ if (g_strcmp0 (output->name, "default") == 0) driver_is_pre_randr_1_2 = TRUE; if (output->connection != RR_Disconnected && output->crtc != 0) { XRRCrtcInfo *crtc; GdkRectangle rect; crtc = XRRGetCrtcInfo (xdisplay, resources, output->crtc); rect.x = crtc->x; rect.y = crtc->y; rect.width = crtc->width; rect.height = crtc->height; XRRFreeCrtcInfo (crtc); if (_panel_multiscreen_output_should_be_first (xdisplay, resources->outputs[i], output, primary)) g_array_prepend_vals (geometries, &rect, 1); else g_array_append_vals (geometries, &rect, 1); } XRRFreeOutputInfo (output); } XRRFreeScreenResources (resources); if (driver_is_pre_randr_1_2) { /* Drivers before RANDR 1.2 don't provide useful info about * outputs */ g_array_free (geometries, TRUE); return FALSE; } if (geometries->len == 0) { /* This can happen in at least one case: * https://bugzilla.novell.com/show_bug.cgi?id=543876 where all * monitors appear disconnected (possibly because the screen * is behing a KVM switch) -- see comment #8. * There might be other cases too, so we stay on the safe side. */ g_array_free (geometries, TRUE); return FALSE; } *monitors_ret = geometries->len; *geometries_ret = (GdkRectangle *) g_array_free (geometries, FALSE); return TRUE; #else return FALSE; #endif }
static void reload_monitor_infos (CsScreen *screen) { GdkDisplay *gdk_display; Display *xdisplay; Window xroot; gdk_display = gdk_screen_get_display (screen->gdk_screen); xdisplay = gdk_x11_display_get_xdisplay (gdk_display); xroot = gdk_x11_window_get_xid (gdk_screen_get_root_window (screen->gdk_screen)); /* Any previous screen->monitor_infos is freed by the caller */ screen->monitor_infos = NULL; screen->n_monitor_infos = 0; /* Xinerama doesn't have a concept of primary monitor, however XRandR * does. However, the XRandR xinerama compat code always sorts the * primary output first, so we rely on that here. We could use the * native XRandR calls instead of xinerama, but that would be * slightly problematic for _NET_WM_FULLSCREEN_MONITORS support, as * that is defined in terms of xinerama monitor indexes. * So, since we don't need anything in xrandr except the primary * we can keep using xinerama and use the first monitor as the * primary. */ screen->primary_monitor_index = PRIMARY_MONITOR; #ifdef HAVE_XFREE_XINERAMA if (screen->n_monitor_infos == 0 && XineramaIsActive (xdisplay)) { XineramaScreenInfo *infos; int n_infos; int i; n_infos = 0; infos = XineramaQueryScreens (xdisplay, &n_infos); DEBUG ("Found %d Xinerama screens on display %s\n", n_infos, gdk_display_get_name (gdk_display)); if (n_infos > 0) { screen->monitor_infos = g_new0 (CsMonitorInfo, n_infos); screen->n_monitor_infos = n_infos; i = 0; while (i < n_infos) { screen->monitor_infos[i].number = infos[i].screen_number; screen->monitor_infos[i].rect.x = infos[i].x_org; screen->monitor_infos[i].rect.y = infos[i].y_org; screen->monitor_infos[i].rect.width = infos[i].width; screen->monitor_infos[i].rect.height = infos[i].height; DEBUG ("Monitor %d is %d,%d %d x %d\n", screen->monitor_infos[i].number, screen->monitor_infos[i].rect.x, screen->monitor_infos[i].rect.y, screen->monitor_infos[i].rect.width, screen->monitor_infos[i].rect.height); ++i; } } cs_XFree (infos); #ifdef HAVE_RANDR { XRRScreenResources *resources; resources = XRRGetScreenResourcesCurrent (xdisplay, xroot); if (resources) { for (i = 0; i < resources->ncrtc; i++) { XRRCrtcInfo *crtc; CsMonitorInfo *info; crtc = XRRGetCrtcInfo (xdisplay, resources, resources->crtcs[i]); info = find_monitor_with_rect (screen, crtc->x, crtc->y, (int)crtc->width, (int)crtc->height); if (info) { info->output = find_main_output_for_crtc (resources, crtc, xdisplay, xroot); } XRRFreeCrtcInfo (crtc); } XRRFreeScreenResources (resources); } } #endif } else if (screen->n_monitor_infos > 0) { DEBUG ("No XFree86 Xinerama extension or XFree86 Xinerama inactive on display %s\n", gdk_display_get_name (gdk_display)); } #else DEBUG ("Muffin compiled without XFree86 Xinerama support\n"); #endif /* HAVE_XFREE_XINERAMA */ #ifdef HAVE_SOLARIS_XINERAMA /* This code from GDK, Copyright (C) 2002 Sun Microsystems */ if (screen->n_monitor_infos == 0 && XineramaGetState (xdisplay, gdk_screen_get_number (screen->gdk_screen))) { XRectangle monitors[MAXFRAMEBUFFERS]; unsigned char hints[16]; int result; int n_monitors; int i; n_monitors = 0; result = XineramaGetInfo (xdisplay, gdk_screen_get_number (screen->gdk_screen), monitors, hints, &n_monitors); /* Yes I know it should be Success but the current implementation * returns the num of monitor */ if (result > 0) { g_assert (n_monitors > 0); screen->monitor_infos = g_new0 (CsMonitorInfo, n_monitors); screen->n_monitor_infos = n_monitors; i = 0; while (i < n_monitors) { screen->monitor_infos[i].number = i; screen->monitor_infos[i].rect.x = monitors[i].x; screen->monitor_infos[i].rect.y = monitors[i].y; screen->monitor_infos[i].rect.width = monitors[i].width; screen->monitor_infos[i].rect.height = monitors[i].height; DEBUG ("Monitor %d is %d,%d %d x %d\n", screen->monitor_infos[i].number, screen->monitor_infos[i].rect.x, screen->monitor_infos[i].rect.y, screen->monitor_infos[i].rect.width, screen->monitor_infos[i].rect.height); ++i; } } } else if (screen->n_monitor_infos == 0) { DEBUG ("No Solaris Xinerama extension or Solaris Xinerama inactive on display %s\n", gdk_display_get_name (gdk_display)); } #else DEBUG ("Cinnamon Screensaver compiled without Solaris Xinerama support\n"); #endif /* HAVE_SOLARIS_XINERAMA */ /* If no Xinerama, fill in the single screen info so * we can use the field unconditionally */ if (screen->n_monitor_infos == 0) { DEBUG ("No Xinerama screens, using default screen info\n"); screen->monitor_infos = g_new0 (CsMonitorInfo, 1); screen->n_monitor_infos = 1; screen->monitor_infos[0].number = 0; screen->monitor_infos[0].rect = screen->rect; } filter_mirrored_monitors (screen); screen->monitor_infos[screen->primary_monitor_index].is_primary = TRUE; apply_scale_factor (screen->monitor_infos, screen->n_monitor_infos, gdk_screen_get_monitor_scale_factor (screen->gdk_screen, PRIMARY_MONITOR)); g_assert (screen->n_monitor_infos > 0); g_assert (screen->monitor_infos != NULL); }
// Initialize X11 display and look for supported X11 extensions // static GLFWbool initExtensions(void) { _glfw.x11.vidmode.handle = dlopen("libXxf86vm.so.1", RTLD_LAZY | RTLD_GLOBAL); if (_glfw.x11.vidmode.handle) { _glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension) dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension"); _glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp) dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp"); _glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp) dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp"); _glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize) dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize"); _glfw.x11.vidmode.available = XF86VidModeQueryExtension(_glfw.x11.display, &_glfw.x11.vidmode.eventBase, &_glfw.x11.vidmode.errorBase); } _glfw.x11.xi.handle = dlopen("libXi.so", RTLD_LAZY | RTLD_GLOBAL); if (_glfw.x11.xi.handle) { _glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion) dlsym(_glfw.x11.xi.handle, "XIQueryVersion"); _glfw.x11.xi.SelectEvents = (PFN_XISelectEvents) dlsym(_glfw.x11.xi.handle, "XISelectEvents"); if (XQueryExtension(_glfw.x11.display, "XInputExtension", &_glfw.x11.xi.majorOpcode, &_glfw.x11.xi.eventBase, &_glfw.x11.xi.errorBase)) { _glfw.x11.xi.major = 2; _glfw.x11.xi.minor = 0; if (XIQueryVersion(_glfw.x11.display, &_glfw.x11.xi.major, &_glfw.x11.xi.minor) == Success) { _glfw.x11.xi.available = GLFW_TRUE; } } } // Check for RandR extension if (XRRQueryExtension(_glfw.x11.display, &_glfw.x11.randr.eventBase, &_glfw.x11.randr.errorBase)) { if (XRRQueryVersion(_glfw.x11.display, &_glfw.x11.randr.major, &_glfw.x11.randr.minor)) { // The GLFW RandR path requires at least version 1.3 if (_glfw.x11.randr.major > 1 || _glfw.x11.randr.minor >= 3) _glfw.x11.randr.available = GLFW_TRUE; } else { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to query RandR version"); } } if (_glfw.x11.randr.available) { XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0])) { // This is either a headless system or an older Nvidia binary driver // with broken gamma support // Flag it as useless and fall back to Xf86VidMode gamma, if // available _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Detected broken RandR gamma ramp support"); _glfw.x11.randr.gammaBroken = GLFW_TRUE; } if (!sr->ncrtc || !sr->noutput || !sr->nmode) { // This is either a headless system or broken Cygwin/X RandR // Flag it as useless and fall back to Xlib display functions _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Detected broken RandR monitor support"); _glfw.x11.randr.monitorBroken = GLFW_TRUE; } XRRFreeScreenResources(sr); XRRSelectInput(_glfw.x11.display, _glfw.x11.root, RROutputChangeNotifyMask); } if (XineramaQueryExtension(_glfw.x11.display, &_glfw.x11.xinerama.major, &_glfw.x11.xinerama.minor)) { if (XineramaIsActive(_glfw.x11.display)) _glfw.x11.xinerama.available = GLFW_TRUE; } // Check if Xkb is supported on this display _glfw.x11.xkb.major = 1; _glfw.x11.xkb.minor = 0; _glfw.x11.xkb.available = XkbQueryExtension(_glfw.x11.display, &_glfw.x11.xkb.majorOpcode, &_glfw.x11.xkb.eventBase, &_glfw.x11.xkb.errorBase, &_glfw.x11.xkb.major, &_glfw.x11.xkb.minor); if (_glfw.x11.xkb.available) { Bool supported; if (XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported)) { if (supported) _glfw.x11.xkb.detectable = GLFW_TRUE; } } _glfw.x11.x11xcb.handle = dlopen("libX11-xcb.so.1", RTLD_LAZY | RTLD_GLOBAL); if (_glfw.x11.x11xcb.handle) { _glfw.x11.x11xcb.XGetXCBConnection = (PFN_XGetXCBConnection) dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection"); } // Update the key code LUT // FIXME: We should listen to XkbMapNotify events to track changes to // the keyboard mapping. createKeyTables(); // Detect whether an EWMH-conformant window manager is running detectEWMH(); // String format atoms _glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False); _glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False); _glfw.x11.COMPOUND_STRING = XInternAtom(_glfw.x11.display, "COMPOUND_STRING", False); _glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False); // Custom selection property atom _glfw.x11.GLFW_SELECTION = XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False); // ICCCM standard clipboard atoms _glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False); _glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False); _glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False); // Clipboard manager atoms _glfw.x11.CLIPBOARD_MANAGER = XInternAtom(_glfw.x11.display, "CLIPBOARD_MANAGER", False); _glfw.x11.SAVE_TARGETS = XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False); // Xdnd (drag and drop) atoms _glfw.x11.XdndAware = XInternAtom(_glfw.x11.display, "XdndAware", False); _glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", False); _glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", False); _glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", False); _glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", False); _glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", False); _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False); _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False); _glfw.x11.XdndTypeList = XInternAtom(_glfw.x11.display, "XdndTypeList", False); _glfw.x11.text_uri_list = XInternAtom(_glfw.x11.display, "text/uri-list", False); // ICCCM, EWMH and Motif window property atoms // These can be set safely even without WM support // The EWMH atoms that require WM support are handled in detectEWMH _glfw.x11.WM_PROTOCOLS = XInternAtom(_glfw.x11.display, "WM_PROTOCOLS", False); _glfw.x11.WM_STATE = XInternAtom(_glfw.x11.display, "WM_STATE", False); _glfw.x11.WM_DELETE_WINDOW = XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False); _glfw.x11.NET_WM_ICON = XInternAtom(_glfw.x11.display, "_NET_WM_ICON", False); _glfw.x11.NET_WM_PING = XInternAtom(_glfw.x11.display, "_NET_WM_PING", False); _glfw.x11.NET_WM_PID = XInternAtom(_glfw.x11.display, "_NET_WM_PID", False); _glfw.x11.NET_WM_NAME = XInternAtom(_glfw.x11.display, "_NET_WM_NAME", False); _glfw.x11.NET_WM_ICON_NAME = XInternAtom(_glfw.x11.display, "_NET_WM_ICON_NAME", False); _glfw.x11.NET_WM_BYPASS_COMPOSITOR = XInternAtom(_glfw.x11.display, "_NET_WM_BYPASS_COMPOSITOR", False); _glfw.x11.MOTIF_WM_HINTS = XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False); return GLFW_TRUE; }
void get_monitors() { int i, j, nbmonitor; if (XineramaIsActive(server.dsp)) { XineramaScreenInfo *info = XineramaQueryScreens(server.dsp, &nbmonitor); XRRScreenResources *res = XRRGetScreenResourcesCurrent(server.dsp, server.root_win); if (res && res->ncrtc >= nbmonitor) { // use xrandr to identify monitors (does not work with proprietery nvidia drivers) // Workaround for issue https://code.google.com/p/tint2/issues/detail?id=353 // on some recent configs, XRRGetScreenResourcesCurrent returns a fantom monitor at last position { int i = res->ncrtc - 1; XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(server.dsp, res, res->crtcs[i]); if (!(crtc_info->x || crtc_info->y || crtc_info->width || crtc_info->height)) { res->ncrtc -= 1; } XRRFreeCrtcInfo(crtc_info); } printf("xRandr: Found crtc's: %d\n", res->ncrtc ); server.monitor = malloc(res->ncrtc * sizeof(Monitor)); for (i=0; i<res->ncrtc; ++i) { XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(server.dsp, res, res->crtcs[i]); server.monitor[i].x = crtc_info->x; server.monitor[i].y = crtc_info->y; server.monitor[i].width = crtc_info->width; server.monitor[i].height = crtc_info->height; server.monitor[i].names = malloc((crtc_info->noutput+1) * sizeof(char*)); for (j=0; j<crtc_info->noutput; ++j) { XRROutputInfo* output_info = XRRGetOutputInfo(server.dsp, res, crtc_info->outputs[j]); printf("xRandr: Linking output %s with crtc %d\n", output_info->name, i); server.monitor[i].names[j] = g_strdup(output_info->name); XRRFreeOutputInfo(output_info); } server.monitor[i].names[j] = 0; XRRFreeCrtcInfo(crtc_info); } nbmonitor = res->ncrtc; } else if (info && nbmonitor > 0) { server.monitor = malloc(nbmonitor * sizeof(Monitor)); for (i=0 ; i < nbmonitor ; i++) { server.monitor[i].x = info[i].x_org; server.monitor[i].y = info[i].y_org; server.monitor[i].width = info[i].width; server.monitor[i].height = info[i].height; server.monitor[i].names = 0; } } // ordered monitor qsort(server.monitor, nbmonitor, sizeof(Monitor), compareMonitorIncluded); // remove monitor included into another one i = 0; while (i < nbmonitor) { for (j=0; j < i ; j++) { if (compareMonitorIncluded(&server.monitor[i], &server.monitor[j]) > 0) { goto next; } } i++; } next: for (j=i; j<nbmonitor; ++j) if (server.monitor[j].names) g_strfreev(server.monitor[j].names); server.nb_monitor = i; server.monitor = realloc(server.monitor, server.nb_monitor * sizeof(Monitor)); qsort(server.monitor, server.nb_monitor, sizeof(Monitor), compareMonitorPos); if (res) XRRFreeScreenResources(res); XFree(info); } if (!server.nb_monitor) { server.nb_monitor = 1; server.monitor = malloc(sizeof(Monitor)); server.monitor[0].x = server.monitor[0].y = 0; server.monitor[0].width = DisplayWidth (server.dsp, server.screen); server.monitor[0].height = DisplayHeight (server.dsp, server.screen); server.monitor[0].names = 0; } }
int main (int argc, char **argv) { Display *xdpy; XRRScreenResources *screen_res = NULL; XRROutputInfo *output = NULL; XRRCrtcInfo *ci = NULL; RRMode mode; GList *modes = NULL; GList *modes_w = NULL; GList *modes_n = NULL; int i, j; int retval = 1; xdpy = XOpenDisplay (g_getenv("DISPLAY")); g_assert (xdpy); screen_res = XRRGetScreenResourcesCurrent (xdpy, DefaultRootWindow (xdpy)); output = pick_output (xdpy, screen_res); for (i = 0; i < screen_res->nmode; i++) { int ratio; gboolean widescreen = FALSE; gboolean valid = FALSE; XRRModeInfo *mi = &screen_res->modes[i]; /* Skip modes with a height less than 720 straight away */ if (mi->width < 720) continue; /* * Check whether this mode is available on our selected output */ for (j = 0; j < output->nmode; ++j) { if (output->modes[j] == mi->id) { valid = TRUE; break; } } if (!valid) continue; /* * Build a list of all modes that are widescreen. * * Multiply by ten and truncate into an integer to avoid annoying float * comparisons. */ ratio = ((double)mi->width / mi->height) * 10; switch (ratio) { default: g_debug ("Unknown ratio for %d x %d", mi->width, mi->height); case 13: /* 1.33, or 4:3 */ widescreen = FALSE; break; case 16: /* 1.6, or 16:10 */ case 17: /* 1.777, or 16;9 */ case 23: /* 2.333, or 21:9 */ g_debug ("Found widescreen ratio %d", ratio); widescreen = TRUE; break; } if (widescreen) modes_w = g_list_prepend (modes_w, mi); else modes_n = g_list_prepend (modes_n, mi); } if (modes_w) modes = modes_w; else modes = modes_n; if (!modes) { g_warning ("No usable modes detected!\n"); goto done; } /* Now sort it so they are sorted in order of distance from 720 */ modes = g_list_sort (modes, size_sorter); mode = ((XRRModeInfo*)(modes->data))->id; g_debug ("Chose %d x %d", ((XRRModeInfo*)(modes->data))->width, ((XRRModeInfo*)(modes->data))->height); ci = XRRGetCrtcInfo (xdpy, screen_res, output->crtc); if (ci->mode != mode) { if (Success != XRRSetCrtcConfig (xdpy, screen_res, output->crtc, CurrentTime, 0, 0, ((XRRModeInfo*)(modes->data))->id, RR_Rotate_0, ci->outputs, ci->noutput)) { g_warning ("Failed to apply chosen mode"); } else retval = 0; } else { retval = 0; g_debug ("Already in best mode"); } done: if (output) XRRFreeOutputInfo (output); if (ci) XRRFreeCrtcInfo (ci); if (screen_res) XRRFreeScreenResources (screen_res); g_list_free (modes_w); g_list_free (modes_n); XCloseDisplay (xdpy); return retval; }
static gboolean init_randr15 (GdkX11Screen *x11_screen, gboolean *changed) { #ifdef HAVE_RANDR15 GdkDisplay *display = GDK_SCREEN_DISPLAY (x11_screen); GdkX11Display *x11_display = GDK_X11_DISPLAY (display); XRRScreenResources *resources; RROutput primary_output = None; RROutput first_output = None; int i; XRRMonitorInfo *rr_monitors; int num_rr_monitors; int old_primary; if (!x11_display->have_randr15) return FALSE; resources = XRRGetScreenResourcesCurrent (x11_screen->xdisplay, x11_screen->xroot_window); if (!resources) return FALSE; rr_monitors = XRRGetMonitors (x11_screen->xdisplay, x11_screen->xroot_window, True, &num_rr_monitors); if (!rr_monitors) return FALSE; for (i = 0; i < x11_display->monitors->len; i++) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; monitor->add = FALSE; monitor->remove = TRUE; } for (i = 0; i < num_rr_monitors; i++) { RROutput output = rr_monitors[i].outputs[0]; XRROutputInfo *output_info; GdkX11Monitor *monitor; GdkRectangle geometry; GdkRectangle newgeo; char *name; int refresh_rate = 0; gdk_x11_display_error_trap_push (display); output_info = XRRGetOutputInfo (x11_screen->xdisplay, resources, output); if (gdk_x11_display_error_trap_pop (display)) continue; if (output_info == NULL) continue; if (output_info->connection == RR_Disconnected) { XRRFreeOutputInfo (output_info); continue; } if (first_output == None) first_output = output; if (output_info->crtc) { XRRCrtcInfo *crtc = XRRGetCrtcInfo (x11_screen->xdisplay, resources, output_info->crtc); int j; for (j = 0; j < resources->nmode; j++) { XRRModeInfo *xmode = &resources->modes[j]; if (xmode->id == crtc->mode) { if (xmode->hTotal != 0 && xmode->vTotal != 0) refresh_rate = (1000 * xmode->dotClock) / (xmode->hTotal * xmode->vTotal); break; } } XRRFreeCrtcInfo (crtc); } monitor = find_monitor_by_output (x11_display, output); if (monitor) monitor->remove = FALSE; else { monitor = g_object_new (GDK_TYPE_X11_MONITOR, "display", display, NULL); monitor->output = output; monitor->add = TRUE; g_ptr_array_add (x11_display->monitors, monitor); } gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry); name = g_strndup (output_info->name, output_info->nameLen); newgeo.x = rr_monitors[i].x / x11_screen->surface_scale; newgeo.y = rr_monitors[i].y / x11_screen->surface_scale; newgeo.width = rr_monitors[i].width / x11_screen->surface_scale; newgeo.height = rr_monitors[i].height / x11_screen->surface_scale; if (newgeo.x != geometry.x || newgeo.y != geometry.y || newgeo.width != geometry.width || newgeo.height != geometry.height || rr_monitors[i].mwidth != gdk_monitor_get_width_mm (GDK_MONITOR (monitor)) || rr_monitors[i].mheight != gdk_monitor_get_height_mm (GDK_MONITOR (monitor)) || g_strcmp0 (name, gdk_monitor_get_model (GDK_MONITOR (monitor)))) *changed = TRUE; gdk_monitor_set_position (GDK_MONITOR (monitor), newgeo.x, newgeo.y); gdk_monitor_set_size (GDK_MONITOR (monitor), newgeo.width, newgeo.height); g_object_notify (G_OBJECT (monitor), "workarea"); gdk_monitor_set_physical_size (GDK_MONITOR (monitor), rr_monitors[i].mwidth, rr_monitors[i].mheight); gdk_monitor_set_subpixel_layout (GDK_MONITOR (monitor), translate_subpixel_order (output_info->subpixel_order)); gdk_monitor_set_refresh_rate (GDK_MONITOR (monitor), refresh_rate); gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), x11_screen->surface_scale); gdk_monitor_set_model (GDK_MONITOR (monitor), name); g_free (name); if (rr_monitors[i].primary) primary_output = monitor->output; XRRFreeOutputInfo (output_info); } XRRFreeMonitors (rr_monitors); XRRFreeScreenResources (resources); for (i = x11_display->monitors->len - 1; i >= 0; i--) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; if (monitor->add) { gdk_display_monitor_added (display, GDK_MONITOR (monitor)); *changed = TRUE; } else if (monitor->remove) { g_object_ref (monitor); g_ptr_array_remove (x11_display->monitors, monitor); gdk_display_monitor_removed (display, GDK_MONITOR (monitor)); g_object_unref (monitor); *changed = TRUE; } } old_primary = x11_display->primary_monitor; x11_display->primary_monitor = 0; for (i = 0; i < x11_display->monitors->len; ++i) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; if (monitor->output == primary_output) { x11_display->primary_monitor = i; break; } /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */ if (primary_output == None && g_ascii_strncasecmp (gdk_monitor_get_model (GDK_MONITOR (monitor)), "LVDS", 4) == 0) { x11_display->primary_monitor = i; break; } /* No primary specified and no LVDS found */ if (monitor->output == first_output) x11_display->primary_monitor = i; } if (x11_display->primary_monitor != old_primary) *changed = TRUE; return x11_display->monitors->len > 0; #endif return FALSE; }
static gboolean fill_out_screen_info (Display *xdisplay, Window xroot, ScreenInfo *info, gboolean needs_reprobe, GError **error) { #ifdef HAVE_RANDR XRRScreenResources *resources; g_assert (xdisplay != NULL); g_assert (info != NULL); /* First update the screen resources */ if (needs_reprobe) resources = XRRGetScreenResources (xdisplay, xroot); else { /* XRRGetScreenResourcesCurrent is less expensive than * XRRGetScreenResources, however it is available only * in RandR 1.3 or higher */ #if (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3)) /* Runtime check for RandR 1.3 or higher */ if (info->screen->rr_major_version == 1 && info->screen->rr_minor_version >= 3) resources = XRRGetScreenResourcesCurrent (xdisplay, xroot); else resources = XRRGetScreenResources (xdisplay, xroot); #else resources = XRRGetScreenResources (xdisplay, xroot); #endif } if (resources) { if (!fill_screen_info_from_resources (info, resources, error)) return FALSE; } else { g_set_error (error, MATE_RR_ERROR, MATE_RR_ERROR_RANDR_ERROR, /* Translators: a CRTC is a CRT Controller (this is X terminology). */ _("could not get the screen resources (CRTCs, outputs, modes)")); return FALSE; } /* Then update the screen size range. We do this after XRRGetScreenResources() so that * the X server will already have an updated view of the outputs. */ if (needs_reprobe) { gboolean success; gdk_error_trap_push (); success = XRRGetScreenSizeRange (xdisplay, xroot, &(info->min_width), &(info->min_height), &(info->max_width), &(info->max_height)); gdk_flush (); if (gdk_error_trap_pop ()) { g_set_error (error, MATE_RR_ERROR, MATE_RR_ERROR_UNKNOWN, _("unhandled X error while getting the range of screen sizes")); return FALSE; } if (!success) { g_set_error (error, MATE_RR_ERROR, MATE_RR_ERROR_RANDR_ERROR, _("could not get the range of screen sizes")); return FALSE; } } else { mate_rr_screen_get_ranges (info->screen, &(info->min_width), &(info->max_width), &(info->min_height), &(info->max_height)); } info->primary = None; #if (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3)) /* Runtime check for RandR 1.3 or higher */ if (info->screen->rr_major_version == 1 && info->screen->rr_minor_version >= 3) { gdk_error_trap_push (); info->primary = XRRGetOutputPrimary (xdisplay, xroot); #if GTK_CHECK_VERSION (3, 0, 0) gdk_error_trap_pop_ignored (); #else gdk_flush (); gdk_error_trap_pop (); /* ignore error */ #endif } #endif return TRUE; #else return FALSE; #endif /* HAVE_RANDR */ }
static gboolean init_randr13 (GdkScreen *screen, gboolean *changed) { #ifdef HAVE_RANDR GdkDisplay *display = gdk_screen_get_display (screen); GdkX11Display *x11_display = GDK_X11_DISPLAY (display); GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); XRRScreenResources *resources; RROutput primary_output = None; RROutput first_output = None; int i; gboolean randr12_compat = FALSE; int old_primary; if (!x11_display->have_randr13) return FALSE; resources = XRRGetScreenResourcesCurrent (x11_screen->xdisplay, x11_screen->xroot_window); if (!resources) return FALSE; for (i = 0; i < x11_display->monitors->len; i++) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; monitor->add = FALSE; monitor->remove = TRUE; } for (i = 0; i < resources->noutput; ++i) { RROutput output = resources->outputs[i]; XRROutputInfo *output_info = XRRGetOutputInfo (x11_screen->xdisplay, resources, output); /* Non RandR1.2+ X driver have output name "default" */ randr12_compat |= !g_strcmp0 (output_info->name, "default"); if (output_info->connection == RR_Disconnected) { XRRFreeOutputInfo (output_info); continue; } if (output_info->crtc) { GdkX11Monitor *monitor; XRRCrtcInfo *crtc = XRRGetCrtcInfo (x11_screen->xdisplay, resources, output_info->crtc); char *name; GdkRectangle geometry; GdkRectangle newgeo; int j; int refresh_rate = 0; for (j = 0; j < resources->nmode; j++) { XRRModeInfo *xmode = &resources->modes[j]; if (xmode->id == crtc->mode) { refresh_rate = (1000 * xmode->dotClock) / (xmode->hTotal *xmode->vTotal); break; } } monitor = find_monitor_by_output (x11_display, output); if (monitor) monitor->remove = FALSE; else { monitor = g_object_new (gdk_x11_monitor_get_type (), "display", display, NULL); monitor->output = output; monitor->add = TRUE; g_ptr_array_add (x11_display->monitors, monitor); } gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry); name = g_strndup (output_info->name, output_info->nameLen); newgeo.x = crtc->x / x11_screen->window_scale; newgeo.y = crtc->y / x11_screen->window_scale; newgeo.width = crtc->width / x11_screen->window_scale; newgeo.height = crtc->height / x11_screen->window_scale; if (newgeo.x != geometry.x || newgeo.y != geometry.y || newgeo.width != geometry.width || newgeo.height != geometry.height || output_info->mm_width != gdk_monitor_get_width_mm (GDK_MONITOR (monitor)) || output_info->mm_height != gdk_monitor_get_height_mm (GDK_MONITOR (monitor)) || g_strcmp0 (name, gdk_monitor_get_model (GDK_MONITOR (monitor))) != 0) *changed = TRUE; gdk_monitor_set_position (GDK_MONITOR (monitor), newgeo.x, newgeo.y); gdk_monitor_set_size (GDK_MONITOR (monitor), newgeo.width, newgeo.height); g_object_notify (G_OBJECT (monitor), "workarea"); gdk_monitor_set_physical_size (GDK_MONITOR (monitor), output_info->mm_width, output_info->mm_height); gdk_monitor_set_subpixel_layout (GDK_MONITOR (monitor), translate_subpixel_order (output_info->subpixel_order)); gdk_monitor_set_refresh_rate (GDK_MONITOR (monitor), refresh_rate); gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), x11_screen->window_scale); gdk_monitor_set_model (GDK_MONITOR (monitor), name); g_free (name); XRRFreeCrtcInfo (crtc); } XRRFreeOutputInfo (output_info); } if (resources->noutput > 0) first_output = resources->outputs[0]; XRRFreeScreenResources (resources); if (randr12_compat) { for (i = 0; i < x11_display->monitors->len; i++) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; if (monitor->remove) gdk_display_monitor_removed (display, GDK_MONITOR (monitor)); } g_ptr_array_remove_range (x11_display->monitors, 0, x11_display->monitors->len); return FALSE; } for (i = x11_display->monitors->len - 1; i >= 0; i--) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; if (monitor->add) { gdk_display_monitor_added (display, GDK_MONITOR (monitor)); *changed = TRUE; } else if (monitor->remove) { g_object_ref (monitor); g_ptr_array_remove (x11_display->monitors, monitor); gdk_display_monitor_removed (display, GDK_MONITOR (monitor)); g_object_unref (monitor); *changed = TRUE; } } old_primary = x11_display->primary_monitor; x11_display->primary_monitor = 0; primary_output = XRRGetOutputPrimary (x11_screen->xdisplay, x11_screen->xroot_window); for (i = 0; i < x11_display->monitors->len; ++i) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; if (monitor->output == primary_output) { x11_display->primary_monitor = i; break; } /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */ if (primary_output == None && g_ascii_strncasecmp (gdk_monitor_get_model (GDK_MONITOR (monitor)), "LVDS", 4) == 0) { x11_display->primary_monitor = i; break; } /* No primary specified and no LVDS found */ if (monitor->output == first_output) x11_display->primary_monitor = i; } if (x11_display->primary_monitor != old_primary) *changed = TRUE; return x11_display->monitors->len > 0; #endif return FALSE; }
void get_monitors() { if (XineramaIsActive(server.display)) { int num_monitors; XineramaScreenInfo *info = XineramaQueryScreens(server.display, &num_monitors); XRRScreenResources *res = XRRGetScreenResourcesCurrent(server.display, server.root_win); RROutput primary_output = XRRGetOutputPrimary(server.display, server.root_win); if (res && res->ncrtc >= num_monitors) { // use xrandr to identify monitors (does not work with proprietery nvidia drivers) // Workaround for issue https://gitlab.com/o9000/tint2/issues/353 // on some recent configs, XRRGetScreenResourcesCurrent returns a fantom monitor at last position { int i = res->ncrtc - 1; XRRCrtcInfo *crtc_info = XRRGetCrtcInfo(server.display, res, res->crtcs[i]); if (!(crtc_info->x || crtc_info->y || crtc_info->width || crtc_info->height)) { res->ncrtc -= 1; } XRRFreeCrtcInfo(crtc_info); } printf("xRandr: Found crtc's: %d\n", res->ncrtc); server.monitors = calloc(res->ncrtc, sizeof(Monitor)); for (int i = 0; i < res->ncrtc; ++i) { XRRCrtcInfo *crtc_info = XRRGetCrtcInfo(server.display, res, res->crtcs[i]); server.monitors[i].x = crtc_info->x; server.monitors[i].y = crtc_info->y; server.monitors[i].width = crtc_info->width; server.monitors[i].height = crtc_info->height; server.monitors[i].names = calloc((crtc_info->noutput + 1), sizeof(gchar *)); for (int j = 0; j < crtc_info->noutput; ++j) { XRROutputInfo *output_info = XRRGetOutputInfo(server.display, res, crtc_info->outputs[j]); printf("xRandr: Linking output %s with crtc %d\n", output_info->name, i); server.monitors[i].names[j] = g_strdup(output_info->name); XRRFreeOutputInfo(output_info); server.monitors[i].primary = crtc_info->outputs[j] == primary_output; } server.monitors[i].names[crtc_info->noutput] = NULL; XRRFreeCrtcInfo(crtc_info); } num_monitors = res->ncrtc; } else if (info && num_monitors > 0) { server.monitors = calloc(num_monitors, sizeof(Monitor)); for (int i = 0; i < num_monitors; i++) { server.monitors[i].x = info[i].x_org; server.monitors[i].y = info[i].y_org; server.monitors[i].width = info[i].width; server.monitors[i].height = info[i].height; server.monitors[i].names = 0; } } // Sort monitors by inclusion qsort(server.monitors, num_monitors, sizeof(Monitor), monitor_includes_monitor); // Remove monitors included in other ones int i = 0; while (i < num_monitors) { for (int j = 0; j < i; j++) { if (monitor_includes_monitor(&server.monitors[i], &server.monitors[j]) > 0) { goto next; } } i++; } next: for (int j = i; j < num_monitors; ++j) if (server.monitors[j].names) g_strfreev(server.monitors[j].names); server.num_monitors = i; server.monitors = realloc(server.monitors, server.num_monitors * sizeof(Monitor)); qsort(server.monitors, server.num_monitors, sizeof(Monitor), compare_monitor_pos); if (res) XRRFreeScreenResources(res); XFree(info); } if (!server.num_monitors) { server.num_monitors = 1; server.monitors = calloc(1, sizeof(Monitor)); server.monitors[0].x = server.monitors[0].y = 0; server.monitors[0].width = DisplayWidth(server.display, server.screen); server.monitors[0].height = DisplayHeight(server.display, server.screen); server.monitors[0].names = 0; } }
int apply_transform (Display *display, Window root, RRCrtc crtcnum, const char *input_name) { int ret; ret = EXIT_SUCCESS; if (ret != EXIT_FAILURE) { XRRScreenConfiguration *sconf; XRRScreenResources *res; XRRCrtcInfo *crtc; XRRCrtcTransformAttributes *transform; Status status; double amx[3][3]; double sina, cosa; double hscale, vscale, hoffs, voffs; XRRScreenSize *ssize; int nsizes; Rotation srot; res = XRRGetScreenResourcesCurrent (display, root); sconf = XRRGetScreenInfo (display, root); ssize = XRRConfigSizes(sconf, &nsizes) + XRRConfigCurrentConfiguration (sconf, &srot); crtc = XRRGetCrtcInfo (display, res, crtcnum); if (verbose) { fprintf (stderr, "Screen: (%u, %u) 0x%02x\n", ssize->width, ssize->height, srot); fprintf (stderr, "CRTC: (%i, %i) (%u, %u) 0x%02x\n", crtc->x, crtc->y, crtc->width, crtc->height, crtc->rotation); } switch (srot) { case RR_Rotate_0: case RR_Rotate_180: hscale = (double)crtc->width/(double)ssize->width; vscale = (double)crtc->height/(double)ssize->height; break; case RR_Rotate_90: case RR_Rotate_270: hscale = (double)crtc->width/(double)ssize->height; vscale = (double)crtc->height/(double)ssize->width; break; default: ret = EXIT_FAILURE; fprintf (stderr, "The screen rotation/reflection 0x%02x is not supported yet. Sorry.\n", srot); } switch (crtc->rotation) { case RR_Rotate_0: sina = 0; cosa = 1; hoffs = 0; voffs = 0; break; case RR_Rotate_90: sina = 1; cosa = 0; hoffs = 1; voffs = 0; break; case RR_Rotate_180: sina = 0; cosa = -1; hoffs = 1; voffs = 1; break; case RR_Rotate_270: sina = -1; cosa = 0; hoffs = 0; voffs = 1; break; default: ret = EXIT_FAILURE; fprintf (stderr, "The rotation/reflection 0x%02x is not supported yet. Sorry.\n", crtc->rotation); } if (ret != EXIT_FAILURE) { amx[0][0] = cosa*hscale; amx[0][1] = -sina*hscale; amx[0][2] = hoffs*hscale + crtc->x/ssize->width; amx[1][0] = sina*vscale; amx[1][1] = cosa*vscale; amx[1][2] = voffs*vscale + crtc->y/ssize->height; amx[2][0] = 0; amx[2][1] = 0; amx[2][2] = 1; status = XRRGetCrtcTransform (display, crtcnum, &transform); if (!status) { fprintf (stderr, "Unable to get the current transformation\n"); ret = EXIT_FAILURE; } } if (ret != EXIT_FAILURE) { static char strmx[3][3][8]; static const char *args[11]; double mx[3][3]; int i, j; for (j = 0; j < 3; j++) { for (i = 0; i < 3; i++) { XFixed fv = transform->currentTransform.matrix[j][i]; mx[j][i] = XFixedToDouble (fv); } } args[0] = input_name; args[1] = "Coordinate Transformation Matrix"; for (j = 0; j < 3; j++) { for (i = 0; i < 3; i++) { double v = mx[0][i]*amx[j][0] + mx[1][i]*amx[j][1] + mx[2][i]*amx[j][2]; snprintf (strmx[j][i], 8, "%8.6f", v); args[2 + i + j*3] = strmx[j][i]; } } if (verbose) { fprintf (stderr, "Debug: set-float-prop"); for (i = 0; i < 11; i++) { fprintf (stderr, " %s", args[i]); } fprintf (stderr, "\n"); } ret = set_float_prop(display, 11, args, "set-float-prop", ": error calling function, please report a bug."); XFree (transform); } XRRFreeCrtcInfo (crtc); XRRFreeScreenResources (res); XRRFreeScreenConfigInfo (sconf); } return ret; }
// Poll for changes in the set of connected monitors // void _glfwPollMonitorsX11(void) { if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) { int i, j, disconnectedCount, screenCount = 0; _GLFWmonitor** disconnected = NULL; XineramaScreenInfo* screens = NULL; XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); RROutput primary = XRRGetOutputPrimary(_glfw.x11.display, _glfw.x11.root); if (_glfw.x11.xinerama.available) screens = XineramaQueryScreens(_glfw.x11.display, &screenCount); disconnectedCount = _glfw.monitorCount; if (disconnectedCount) { disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*)); memcpy(disconnected, _glfw.monitors, _glfw.monitorCount * sizeof(_GLFWmonitor*)); } for (i = 0; i < sr->noutput; i++) { int type, widthMM, heightMM; XRROutputInfo* oi; XRRCrtcInfo* ci; _GLFWmonitor* monitor; oi = XRRGetOutputInfo(_glfw.x11.display, sr, sr->outputs[i]); if (oi->connection != RR_Connected || oi->crtc == None) { XRRFreeOutputInfo(oi); continue; } for (j = 0; j < disconnectedCount; j++) { if (disconnected[j] && disconnected[j]->x11.output == sr->outputs[i]) { disconnected[j] = NULL; break; } } if (j < disconnectedCount) { XRRFreeOutputInfo(oi); continue; } ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc); if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270) { widthMM = oi->mm_height; heightMM = oi->mm_width; } else { widthMM = oi->mm_width; heightMM = oi->mm_height; } monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM); monitor->x11.output = sr->outputs[i]; monitor->x11.crtc = oi->crtc; for (j = 0; j < screenCount; j++) { if (screens[j].x_org == ci->x && screens[j].y_org == ci->y && screens[j].width == ci->width && screens[j].height == ci->height) { monitor->x11.index = j; break; } } if (monitor->x11.output == primary) type = _GLFW_INSERT_FIRST; else type = _GLFW_INSERT_LAST; _glfwInputMonitor(monitor, GLFW_CONNECTED, type); XRRFreeOutputInfo(oi); XRRFreeCrtcInfo(ci); } XRRFreeScreenResources(sr); if (screens) XFree(screens); for (i = 0; i < disconnectedCount; i++) { if (disconnected[i]) _glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0); } free(disconnected); } else { const int widthMM = DisplayWidthMM(_glfw.x11.display, _glfw.x11.screen); const int heightMM = DisplayHeightMM(_glfw.x11.display, _glfw.x11.screen); _glfwInputMonitor(_glfwAllocMonitor("Display", widthMM, heightMM), GLFW_CONNECTED, _GLFW_INSERT_FIRST); } }
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height) { int areaX = 0, areaY = 0, areaWidth = 0, areaHeight = 0; if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) { XRRScreenResources* sr; XRRCrtcInfo* ci; sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); areaX = ci->x; areaY = ci->y; const XRRModeInfo* mi = getModeInfo(sr, ci->mode); if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270) { areaWidth = mi->height; areaHeight = mi->width; } else { areaWidth = mi->width; areaHeight = mi->height; } XRRFreeCrtcInfo(ci); XRRFreeScreenResources(sr); } else { areaWidth = DisplayWidth(_glfw.x11.display, _glfw.x11.screen); areaHeight = DisplayHeight(_glfw.x11.display, _glfw.x11.screen); } if (_glfw.x11.NET_WORKAREA && _glfw.x11.NET_CURRENT_DESKTOP) { Atom* extents = NULL; Atom* desktop = NULL; const unsigned long extentCount = _glfwGetWindowPropertyX11(_glfw.x11.root, _glfw.x11.NET_WORKAREA, XA_CARDINAL, (unsigned char**) &extents); if (_glfwGetWindowPropertyX11(_glfw.x11.root, _glfw.x11.NET_CURRENT_DESKTOP, XA_CARDINAL, (unsigned char**) &desktop) > 0) { if (extentCount >= 4 && *desktop < extentCount / 4) { const int globalX = extents[*desktop * 4 + 0]; const int globalY = extents[*desktop * 4 + 1]; const int globalWidth = extents[*desktop * 4 + 2]; const int globalHeight = extents[*desktop * 4 + 3]; if (areaX < globalX) { areaWidth -= globalX - areaX; areaX = globalX; } if (areaY < globalY) { areaHeight -= globalY - areaY; areaY = globalY; } if (areaX + areaWidth > globalX + globalWidth) areaWidth = globalX - areaX + globalWidth; if (areaY + areaHeight > globalY + globalHeight) areaHeight = globalY - areaY + globalHeight; } } if (extents) XFree(extents); if (desktop) XFree(desktop); } if (xpos) *xpos = areaX; if (ypos) *ypos = areaY; if (width) *width = areaWidth; if (height) *height = areaHeight; }