diff --git a/src/window.c b/src/window.c index 819cc71c..f32e552b 100644 --- a/src/window.c +++ b/src/window.c @@ -514,6 +514,12 @@ GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height) if (width == window->width && height == window->height) return; + if (window->monitor) + { + window->videoMode.width = width; + window->videoMode.height = height; + } + _glfwPlatformSetWindowSize(window, width, height); } diff --git a/src/x11_monitor.c b/src/x11_monitor.c index 97de09fc..661f5072 100644 --- a/src/x11_monitor.c +++ b/src/x11_monitor.c @@ -40,140 +40,105 @@ ////////////////////////////////////////////////////////////////////////// //======================================================================== -// Finds the video mode closest in size to the specified desired size +// Set the current video mode for the specified monitor //======================================================================== -int _glfwGetClosestVideoMode(_GLFWmonitor* monitor, int* width, int* height) +void _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* mode) { - int i, match, bestmatch; - if (_glfw.x11.randr.available) { - int sizecount, bestsize; - XRRScreenConfiguration* sc; - XRRScreenSize* sizelist; + int i, j, k; + XRRScreenResources* sr; + XRRCrtcInfo* ci; + RRMode bestMode = 0; + unsigned int leastSizeDiff = UINT_MAX; - sc = XRRGetScreenInfo(_glfw.x11.display, _glfw.x11.root); + sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root); + ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); - sizelist = XRRConfigSizes(sc, &sizecount); - - // Find the best matching mode - bestsize = -1; - bestmatch = INT_MAX; - for (i = 0; i < sizecount; i++) + for (i = 0; i < sr->nmode; i++) { - match = (*width - sizelist[i].width) * - (*width - sizelist[i].width) + - (*height - sizelist[i].height) * - (*height - sizelist[i].height); - if (match < bestmatch) + GLboolean usable = GL_TRUE; + XRRModeInfo* mi = sr->modes + i; + + for (j = 0; j < ci->noutput; j++) { - bestmatch = match; - bestsize = i; + XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, + sr, ci->outputs[j]); + + for (k = 0; k < oi->nmode; k++) + { + if (oi->modes[k] == mi->id) + break; + } + + if (k == oi->nmode) + usable = GL_FALSE; + + XRRFreeOutputInfo(oi); + } + + if (!usable) + continue; + + if (mi->modeFlags & RR_Interlace) + continue; + + unsigned int sizeDiff = (mi->width - mode->width) * + (mi->width - mode->width) + + (mi->height - mode->height) * + (mi->height - mode->height); + + if (sizeDiff < leastSizeDiff) + { + bestMode = mi->id; + leastSizeDiff = sizeDiff; } } - if (bestsize != -1) - { - // Report width & height of best matching mode - *width = sizelist[bestsize].width; - *height = sizelist[bestsize].height; - } + monitor->x11.oldMode = ci->mode; - XRRFreeScreenConfigInfo(sc); + XRRSetCrtcConfig(_glfw.x11.display, + sr, monitor->x11.crtc, + CurrentTime, + ci->x, ci->y, + bestMode, + ci->rotation, + ci->outputs, + ci->noutput); - if (bestsize != -1) - return bestsize; - } - - // Default: Simply use the screen resolution - *width = DisplayWidth(_glfw.x11.display, _glfw.x11.screen); - *height = DisplayHeight(_glfw.x11.display, _glfw.x11.screen); - - return 0; -} - - -//======================================================================== -// Change the current video mode -//======================================================================== - -void _glfwSetVideoModeMODE(_GLFWmonitor* monitor, int mode) -{ - if (_glfw.x11.randr.available) - { - XRRScreenConfiguration* sc; - Window root; - - root = _glfw.x11.root; - sc = XRRGetScreenInfo(_glfw.x11.display, root); - - // Remember old size and flag that we have changed the mode - if (!monitor->x11.modeChanged) - { - monitor->x11.oldSizeID = XRRConfigCurrentConfiguration(sc, &monitor->x11.oldRotation); - monitor->x11.oldWidth = DisplayWidth(_glfw.x11.display, - _glfw.x11.screen); - monitor->x11.oldHeight = DisplayHeight(_glfw.x11.display, - _glfw.x11.screen); - - monitor->x11.modeChanged = GL_TRUE; - } - - XRRSetScreenConfig(_glfw.x11.display, - sc, - root, - mode, - RR_Rotate_0, - CurrentTime); - - XRRFreeScreenConfigInfo(sc); + XRRFreeCrtcInfo(ci); + XRRFreeScreenResources(sr); } } //======================================================================== -// Change the current video mode -//======================================================================== - -void _glfwSetVideoMode(_GLFWmonitor* monitor, int* width, int* height) -{ - int bestmode; - - // Find a best match mode - bestmode = _glfwGetClosestVideoMode(monitor, width, height); - - // Change mode - _glfwSetVideoModeMODE(monitor, bestmode); -} - - -//======================================================================== -// Restore the previously saved (original) video mode +// Restore the saved (original) video mode for the specified monitor //======================================================================== void _glfwRestoreVideoMode(_GLFWmonitor* monitor) { - if (!monitor->x11.modeChanged) - return; - if (_glfw.x11.randr.available) { - XRRScreenConfiguration* sc; + XRRScreenResources* sr; + XRRCrtcInfo* ci; - sc = XRRGetScreenInfo(_glfw.x11.display, _glfw.x11.root); + sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root); + ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); - XRRSetScreenConfig(_glfw.x11.display, - sc, - _glfw.x11.root, - monitor->x11.oldSizeID, - monitor->x11.oldRotation, - CurrentTime); + XRRSetCrtcConfig(_glfw.x11.display, + sr, monitor->x11.crtc, + CurrentTime, + ci->x, ci->y, + monitor->x11.oldMode, + ci->rotation, + ci->outputs, + ci->noutput); - XRRFreeScreenConfigInfo(sc); + XRRFreeCrtcInfo(ci); + XRRFreeScreenResources(sr); } - - monitor->x11.modeChanged = GL_FALSE; } @@ -194,7 +159,6 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* found) XRRScreenResources* sr; sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root); - primary = XRRGetOutputPrimary(_glfw.x11.display, _glfw.x11.root); monitors = (_GLFWmonitor**) calloc(sr->noutput, sizeof(_GLFWmonitor*)); @@ -206,37 +170,48 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* found) return NULL; } - for (i = 0; i < sr->noutput; i++) + for (i = 0; i < sr->ncrtc; i++) { + int j; XRROutputInfo* oi; XRRCrtcInfo* ci; + RROutput output; - oi = XRRGetOutputInfo(_glfw.x11.display, sr, sr->outputs[i]); + ci = XRRGetCrtcInfo(_glfw.x11.display, sr, sr->crtcs[i]); + output = ci->outputs[i]; + + for (j = 0; j < ci->noutput; j++) + { + if (ci->outputs[i] == primary) + { + output = primary; + break; + } + } + + oi = XRRGetOutputInfo(_glfw.x11.display, sr, output); if (oi->connection != RR_Connected) { XRRFreeOutputInfo(oi); + XRRFreeCrtcInfo(ci); continue; } - ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc); - monitors[*found] = _glfwCreateMonitor(oi->name, - sr->outputs[i] == primary, + output == primary, oi->mm_width, oi->mm_height, ci->x, ci->y); + monitors[*found]->x11.output = output; + monitors[*found]->x11.crtc = oi->crtc; + + XRRFreeOutputInfo(oi); XRRFreeCrtcInfo(ci); - if (!monitors[*found]) - { - // TODO: wat - return NULL; - } - - // This is retained until the monitor object is destroyed - monitors[*found]->x11.output = oi; (*found)++; } + + XRRFreeScreenResources(sr); } else { @@ -265,8 +240,6 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* found) void _glfwPlatformDestroyMonitor(_GLFWmonitor* monitor) { - if (_glfw.x11.randr.available) - XRRFreeOutputInfo(monitor->x11.output); } GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) @@ -283,25 +256,27 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) if (_glfw.x11.randr.available) { + int i, j; XRRScreenResources* sr; - int i, j, count = monitor->x11.output->nmode; + XRROutputInfo* oi; sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root); + oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output); - result = (GLFWvidmode*) malloc(sizeof(GLFWvidmode) * count); + result = (GLFWvidmode*) malloc(sizeof(GLFWvidmode) * oi->nmode); if (!result) { _glfwInputError(GLFW_OUT_OF_MEMORY, NULL); return NULL; } - for (i = 0; i < count; i++) + for (i = 0; i < oi->nmode; i++) { GLFWvidmode mode; for (j = 0; j < sr->nmode; j++) { - if (sr->modes[j].id == monitor->x11.output->modes[i]) + if (sr->modes[j].id == oi->modes[i]) break; } @@ -334,6 +309,7 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) (*found)++; } + XRRFreeOutputInfo(oi); XRRFreeScreenResources(sr); } else @@ -365,22 +341,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) XRRCrtcInfo* ci; sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root); - if (!sr) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "X11: Failed to retrieve RandR screen resources"); - return; - } - - ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.output->crtc); - if (!ci) - { - XRRFreeScreenResources(sr); - - _glfwInputError(GLFW_PLATFORM_ERROR, - "X11: Failed to retrieve RandR crtc info"); - return; - } + ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); mode->width = ci->width; mode->height = ci->height; diff --git a/src/x11_platform.h b/src/x11_platform.h index f5fd9fd3..4e7e6a25 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -200,13 +200,9 @@ typedef struct _GLFWlibraryX11 //------------------------------------------------------------------------ typedef struct _GLFWmonitorX11 { - GLboolean modeChanged; - - XRROutputInfo* output; - SizeID oldSizeID; - int oldWidth; - int oldHeight; - Rotation oldRotation; + RROutput output; + RRCrtc crtc; + RRMode oldMode; } _GLFWmonitorX11; @@ -231,9 +227,7 @@ int _glfwCreateContext(_GLFWwindow* window, void _glfwDestroyContext(_GLFWwindow* window); // Fullscreen support -int _glfwGetClosestVideoMode(_GLFWmonitor* monitor, int* width, int* height); -void _glfwSetVideoModeMODE(_GLFWmonitor* monitor, int mode); -void _glfwSetVideoMode(_GLFWmonitor* monitor, int* width, int* height); +void _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* mode); void _glfwRestoreVideoMode(_GLFWmonitor* monitor); // Joystick input diff --git a/src/x11_window.c b/src/x11_window.c index 2b4dcf8d..65127800 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -237,6 +237,9 @@ static GLboolean createWindow(_GLFWwindow* window, _glfwPlatformSetWindowTitle(window, wndconfig->title); + XRRSelectInput(_glfw.x11.display, window->x11.handle, + RRScreenChangeNotifyMask); + return GL_TRUE; } @@ -333,7 +336,7 @@ static void enterFullscreenMode(_GLFWwindow* window) _glfw.x11.saver.changed = GL_TRUE; } - _glfwSetVideoMode(window->monitor, &window->width, &window->height); + _glfwSetVideoMode(window->monitor, &window->videoMode); if (_glfw.x11.hasEWMH && _glfw.x11.NET_WM_STATE != None && @@ -743,7 +746,6 @@ static void processEvent(XEvent *event) case RRScreenChangeNotify: { XRRUpdateConfiguration(event); - _glfwInputMonitorChange(); break; } } @@ -893,13 +895,7 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) { - int mode = 0, sizeChanged = GL_FALSE; - - if (window->monitor) - { - // Get the closest matching video mode for the specified window size - mode = _glfwGetClosestVideoMode(window->monitor, &width, &height); - } + GLboolean sizeChanged = GL_FALSE; if (!window->resizable) { @@ -924,7 +920,7 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) sizeChanged = GL_TRUE; } - _glfwSetVideoModeMODE(window->monitor, mode); + _glfwSetVideoMode(window->monitor, &window->videoMode); } // Set window size (if not already changed)