浏览代码

Merged fullscreen and monitor modules.

Camilla Berglund 13 年之前
父节点
当前提交
55419bda67
共有 9 个文件被更改,包括 1082 次插入1239 次删除
  1. 10 12
      src/CMakeLists.txt
  2. 0 243
      src/cocoa_fullscreen.m
  3. 208 0
      src/cocoa_monitor.m
  4. 0 172
      src/fullscreen.c
  5. 129 0
      src/monitor.c
  6. 0 281
      src/win32_fullscreen.c
  7. 243 0
      src/win32_monitor.c
  8. 0 531
      src/x11_fullscreen.c
  9. 492 0
      src/x11_monitor.c

+ 10 - 12
src/CMakeLists.txt

@@ -3,13 +3,13 @@ include_directories(${GLFW_SOURCE_DIR}/src
                     ${glfw_INCLUDE_DIRS})
 
 set(common_HEADERS ${GLFW_SOURCE_DIR}/include/GL/glfw3.h internal.h)
-set(common_SOURCES clipboard.c fullscreen.c gamma.c init.c input.c
-                   joystick.c monitor.c opengl.c time.c window.c)
+set(common_SOURCES clipboard.c gamma.c init.c input.c joystick.c monitor.c
+                   opengl.c time.c window.c)
 
 if (_GLFW_COCOA_NSGL)
     set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h)
-    set(glfw_SOURCES ${common_SOURCES} cocoa_clipboard.m cocoa_fullscreen.m
-                     cocoa_gamma.c cocoa_init.m cocoa_input.m cocoa_joystick.m
+    set(glfw_SOURCES ${common_SOURCES} cocoa_clipboard.m cocoa_gamma.c
+                     cocoa_init.m cocoa_input.m cocoa_joystick.m cocoa_monitor.m
                      cocoa_opengl.m cocoa_time.c cocoa_window.m)
 
     if (GLFW_NATIVE_API)
@@ -20,20 +20,18 @@ if (_GLFW_COCOA_NSGL)
     set_source_files_properties(${glfw_SOURCES} PROPERTIES LANGUAGE C)
 elseif (_GLFW_WIN32_WGL)
     set(glfw_HEADERS ${common_HEADERS} win32_platform.h)
-    set(glfw_SOURCES ${common_SOURCES} win32_clipboard.c win32_fullscreen.c
-                     win32_gamma.c win32_init.c win32_input.c win32_joystick.c
-                     win32_monitor.c win32_opengl.c win32_time.c win32_window.c
-                     win32_dllmain.c)
+    set(glfw_SOURCES ${common_SOURCES} win32_clipboard.c win32_gamma.c
+                     win32_init.c win32_input.c win32_joystick.c win32_monitor.c
+                     win32_opengl.c win32_time.c win32_window.c win32_dllmain.c)
 
     if (GLFW_NATIVE_API)
         list(APPEND glfw_SOURCES win32_native.c)
     endif()
 elseif (_GLFW_X11_GLX)
     set(glfw_HEADERS ${common_HEADERS} x11_platform.h)
-    set(glfw_SOURCES ${common_SOURCES} x11_clipboard.c x11_fullscreen.c
-                     x11_gamma.c x11_init.c x11_input.c x11_joystick.c
-                     x11_keysym2unicode.c x11_monitor.c x11_opengl.c x11_time.c
-                     x11_window.c)
+    set(glfw_SOURCES ${common_SOURCES} x11_clipboard.c x11_gamma.c x11_init.c
+                     x11_input.c x11_joystick.c x11_keysym2unicode.c
+                     x11_monitor.c x11_opengl.c x11_time.c x11_window.c)
 
     if (GLFW_NATIVE_API)
         list(APPEND glfw_SOURCES x11_native.c)

+ 0 - 243
src/cocoa_fullscreen.m

@@ -1,243 +0,0 @@
-//========================================================================
-// GLFW - An OpenGL library
-// Platform:    Cocoa
-// API Version: 3.0
-// WWW:         http://www.glfw.org/
-//------------------------------------------------------------------------
-// Copyright (c) 2009-2010 Camilla Berglund <[email protected]>
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-//    claim that you wrote the original software. If you use this software
-//    in a product, an acknowledgment in the product documentation would
-//    be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such, and must not
-//    be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source
-//    distribution.
-//
-//========================================================================
-
-#include "internal.h"
-
-#include <stdlib.h>
-#include <limits.h>
-
-
-//========================================================================
-// Check whether the display mode should be included in enumeration
-//========================================================================
-
-static GLboolean modeIsGood(CGDisplayModeRef mode)
-{
-    uint32_t flags = CGDisplayModeGetIOFlags(mode);
-    if (!(flags & kDisplayModeValidFlag) || !(flags & kDisplayModeSafeFlag))
-        return GL_FALSE;
-
-    if (flags & kDisplayModeInterlacedFlag)
-        return GL_FALSE;
-
-    if (flags & kDisplayModeTelevisionFlag)
-        return GL_FALSE;
-
-    if (flags & kDisplayModeStretchedFlag)
-        return GL_FALSE;
-
-    CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
-    if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) &&
-        CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0))
-    {
-        CFRelease(format);
-        return GL_FALSE;
-    }
-
-    CFRelease(format);
-    return GL_TRUE;
-}
-
-
-//========================================================================
-// Convert Core Graphics display mode to GLFW video mode
-//========================================================================
-
-static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode)
-{
-    GLFWvidmode result;
-    result.width = CGDisplayModeGetWidth(mode);
-    result.height = CGDisplayModeGetHeight(mode);
-
-    CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
-
-    if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0)
-    {
-        result.redBits = 5;
-        result.greenBits = 5;
-        result.blueBits = 5;
-    }
-    else
-    {
-        result.redBits = 8;
-        result.greenBits = 8;
-        result.blueBits = 8;
-    }
-
-    CFRelease(format);
-    return result;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-//========================================================================
-// Change the current video mode
-//========================================================================
-
-GLboolean _glfwSetVideoMode(int* width, int* height, int* bpp, int* refreshRate)
-{
-    CGDisplayModeRef bestMode = NULL;
-    CFArrayRef modes;
-    CFIndex count, i;
-    unsigned int leastSizeDiff = UINT_MAX;
-    double leastRateDiff = DBL_MAX;
-
-    modes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL);
-    count = CFArrayGetCount(modes);
-
-    for (i = 0;  i < count;  i++)
-    {
-        CGDisplayModeRef mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
-        if (!modeIsGood(mode))
-            continue;
-
-        int modeBPP;
-
-        // Identify display mode pixel encoding
-        {
-            CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
-
-            if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0)
-                modeBPP = 16;
-            else
-                modeBPP = 32;
-
-            CFRelease(format);
-        }
-
-        int modeWidth = (int) CGDisplayModeGetWidth(mode);
-        int modeHeight = (int) CGDisplayModeGetHeight(mode);
-
-        unsigned int sizeDiff = (abs(modeBPP - *bpp) << 25) |
-                                ((modeWidth - *width) * (modeWidth - *width) +
-                                 (modeHeight - *height) * (modeHeight - *height));
-
-        double rateDiff;
-
-        if (*refreshRate > 0)
-            rateDiff = fabs(CGDisplayModeGetRefreshRate(mode) - *refreshRate);
-        else
-        {
-            // If no refresh rate was specified, then they're all the same
-            rateDiff = 0;
-        }
-
-        if ((sizeDiff < leastSizeDiff) ||
-            (sizeDiff == leastSizeDiff && (rateDiff < leastRateDiff)))
-        {
-            bestMode = mode;
-
-            leastSizeDiff = sizeDiff;
-            leastRateDiff = rateDiff;
-        }
-    }
-
-    if (!bestMode)
-    {
-        CFRelease(modes);
-        return GL_FALSE;
-    }
-
-    _glfwLibrary.NS.previousMode = CGDisplayCopyDisplayMode(CGMainDisplayID());
-
-    CGDisplayCapture(CGMainDisplayID());
-    CGDisplaySetDisplayMode(CGMainDisplayID(), bestMode, NULL);
-
-    CFRelease(modes);
-    return GL_TRUE;
-}
-
-
-//========================================================================
-// Restore the previously saved (original) video mode
-//========================================================================
-
-void _glfwRestoreVideoMode(void)
-{
-    CGDisplaySetDisplayMode(CGMainDisplayID(),
-                            _glfwLibrary.NS.previousMode,
-                            NULL);
-
-    CGDisplayRelease(CGMainDisplayID());
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-//========================================================================
-// Get a list of available video modes
-//========================================================================
-
-GLFWvidmode* _glfwPlatformGetVideoModes(int* found)
-{
-    CFArrayRef modes;
-    CFIndex count, i;
-    GLFWvidmode* result;
-
-    modes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL);
-    count = CFArrayGetCount(modes);
-
-    result = (GLFWvidmode*) malloc(sizeof(GLFWvidmode) * count);
-    *found = 0;
-
-    for (i = 0;  i < count;  i++)
-    {
-        CGDisplayModeRef mode;
-
-        mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
-        if (modeIsGood(mode))
-        {
-            result[*found] = vidmodeFromCGDisplayMode(mode);
-            (*found)++;
-        }
-    }
-
-    CFRelease(modes);
-    return result;
-}
-
-
-//========================================================================
-// Get the current video mode for the specified monitor
-//========================================================================
-
-void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
-{
-    CGDisplayModeRef displayMode;
-
-    displayMode = CGDisplayCopyDisplayMode(CGMainDisplayID());
-    *mode = vidmodeFromCGDisplayMode(displayMode);
-    CGDisplayModeRelease(displayMode);
-}
-

+ 208 - 0
src/cocoa_monitor.m

@@ -30,6 +30,167 @@
 
 #include "internal.h"
 
+#include <stdlib.h>
+#include <limits.h>
+
+
+//========================================================================
+// Check whether the display mode should be included in enumeration
+//========================================================================
+
+static GLboolean modeIsGood(CGDisplayModeRef mode)
+{
+    uint32_t flags = CGDisplayModeGetIOFlags(mode);
+    if (!(flags & kDisplayModeValidFlag) || !(flags & kDisplayModeSafeFlag))
+        return GL_FALSE;
+
+    if (flags & kDisplayModeInterlacedFlag)
+        return GL_FALSE;
+
+    if (flags & kDisplayModeTelevisionFlag)
+        return GL_FALSE;
+
+    if (flags & kDisplayModeStretchedFlag)
+        return GL_FALSE;
+
+    CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
+    if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) &&
+        CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0))
+    {
+        CFRelease(format);
+        return GL_FALSE;
+    }
+
+    CFRelease(format);
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// Convert Core Graphics display mode to GLFW video mode
+//========================================================================
+
+static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode)
+{
+    GLFWvidmode result;
+    result.width = CGDisplayModeGetWidth(mode);
+    result.height = CGDisplayModeGetHeight(mode);
+
+    CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
+
+    if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0)
+    {
+        result.redBits = 5;
+        result.greenBits = 5;
+        result.blueBits = 5;
+    }
+    else
+    {
+        result.redBits = 8;
+        result.greenBits = 8;
+        result.blueBits = 8;
+    }
+
+    CFRelease(format);
+    return result;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+//========================================================================
+// Change the current video mode
+//========================================================================
+
+GLboolean _glfwSetVideoMode(int* width, int* height, int* bpp, int* refreshRate)
+{
+    CGDisplayModeRef bestMode = NULL;
+    CFArrayRef modes;
+    CFIndex count, i;
+    unsigned int leastSizeDiff = UINT_MAX;
+    double leastRateDiff = DBL_MAX;
+
+    modes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL);
+    count = CFArrayGetCount(modes);
+
+    for (i = 0;  i < count;  i++)
+    {
+        CGDisplayModeRef mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
+        if (!modeIsGood(mode))
+            continue;
+
+        int modeBPP;
+
+        // Identify display mode pixel encoding
+        {
+            CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
+
+            if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0)
+                modeBPP = 16;
+            else
+                modeBPP = 32;
+
+            CFRelease(format);
+        }
+
+        int modeWidth = (int) CGDisplayModeGetWidth(mode);
+        int modeHeight = (int) CGDisplayModeGetHeight(mode);
+
+        unsigned int sizeDiff = (abs(modeBPP - *bpp) << 25) |
+                                ((modeWidth - *width) * (modeWidth - *width) +
+                                 (modeHeight - *height) * (modeHeight - *height));
+
+        double rateDiff;
+
+        if (*refreshRate > 0)
+            rateDiff = fabs(CGDisplayModeGetRefreshRate(mode) - *refreshRate);
+        else
+        {
+            // If no refresh rate was specified, then they're all the same
+            rateDiff = 0;
+        }
+
+        if ((sizeDiff < leastSizeDiff) ||
+            (sizeDiff == leastSizeDiff && (rateDiff < leastRateDiff)))
+        {
+            bestMode = mode;
+
+            leastSizeDiff = sizeDiff;
+            leastRateDiff = rateDiff;
+        }
+    }
+
+    if (!bestMode)
+    {
+        CFRelease(modes);
+        return GL_FALSE;
+    }
+
+    _glfwLibrary.NS.previousMode = CGDisplayCopyDisplayMode(CGMainDisplayID());
+
+    CGDisplayCapture(CGMainDisplayID());
+    CGDisplaySetDisplayMode(CGMainDisplayID(), bestMode, NULL);
+
+    CFRelease(modes);
+    return GL_TRUE;
+}
+
+
+//========================================================================
+// Restore the previously saved (original) video mode
+//========================================================================
+
+void _glfwRestoreVideoMode(void)
+{
+    CGDisplaySetDisplayMode(CGMainDisplayID(),
+                            _glfwLibrary.NS.previousMode,
+                            NULL);
+
+    CGDisplayRelease(CGMainDisplayID());
+}
+
 
 //////////////////////////////////////////////////////////////////////////
 //////                       GLFW platform API                      //////
@@ -54,3 +215,50 @@ void _glfwPlatformDestroyMonitor(_GLFWmonitor* monitor)
 {
 }
 
+
+//========================================================================
+// Get a list of available video modes
+//========================================================================
+
+GLFWvidmode* _glfwPlatformGetVideoModes(int* found)
+{
+    CFArrayRef modes;
+    CFIndex count, i;
+    GLFWvidmode* result;
+
+    modes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL);
+    count = CFArrayGetCount(modes);
+
+    result = (GLFWvidmode*) malloc(sizeof(GLFWvidmode) * count);
+    *found = 0;
+
+    for (i = 0;  i < count;  i++)
+    {
+        CGDisplayModeRef mode;
+
+        mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
+        if (modeIsGood(mode))
+        {
+            result[*found] = vidmodeFromCGDisplayMode(mode);
+            (*found)++;
+        }
+    }
+
+    CFRelease(modes);
+    return result;
+}
+
+
+//========================================================================
+// Get the current video mode for the specified monitor
+//========================================================================
+
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
+{
+    CGDisplayModeRef displayMode;
+
+    displayMode = CGDisplayCopyDisplayMode(CGMainDisplayID());
+    *mode = vidmodeFromCGDisplayMode(displayMode);
+    CGDisplayModeRelease(displayMode);
+}
+

+ 0 - 172
src/fullscreen.c

@@ -1,172 +0,0 @@
-//========================================================================
-// GLFW - An OpenGL library
-// Platform:    Any
-// API version: 3.0
-// WWW:         http://www.glfw.org/
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
-// Copyright (c) 2012 Torsten Walluhn <[email protected]>
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-//    claim that you wrote the original software. If you use this software
-//    in a product, an acknowledgment in the product documentation would
-//    be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such, and must not
-//    be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source
-//    distribution.
-//
-//========================================================================
-
-#include "internal.h"
-
-#include <stdlib.h>
-#if _WIN32
- #include <malloc.h>
-#endif
-
-
-//========================================================================
-// Lexical comparison function for GLFW video modes, used by qsort
-//========================================================================
-
-int compareVideoModes(const void* firstPtr, const void* secondPtr)
-{
-    int firstBPP, secondBPP, firstSize, secondSize;
-    GLFWvidmode* first = (GLFWvidmode*) firstPtr;
-    GLFWvidmode* second = (GLFWvidmode*) secondPtr;
-
-    // First sort on color bits per pixel
-
-    firstBPP = first->redBits +
-               first->greenBits +
-               first->blueBits;
-    secondBPP = second->redBits +
-                second->greenBits +
-                second->blueBits;
-
-    if (firstBPP != secondBPP)
-        return firstBPP - secondBPP;
-
-    // Then sort on screen area, in pixels
-
-    firstSize = first->width * first->height;
-    secondSize = second->width * second->height;
-
-    return firstSize - secondSize;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-//========================================================================
-// Lexical comparison of GLFW video modes
-//========================================================================
-
-int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second)
-{
-    return compareVideoModes(first, second);
-}
-
-
-//========================================================================
-// Convert BPP to RGB bits based on "best guess"
-//========================================================================
-
-void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
-{
-    int delta;
-
-    // We assume that by 32 the user really meant 24
-    if (bpp == 32)
-        bpp = 24;
-
-    // Convert "bits per pixel" to red, green & blue sizes
-
-    *red = *green = *blue = bpp / 3;
-    delta = bpp - (*red * 3);
-    if (delta >= 1)
-        *green = *green + 1;
-
-    if (delta == 2)
-        *red = *red + 1;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                        GLFW public API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-//========================================================================
-// Get a list of available video modes
-//========================================================================
-
-GLFWAPI GLFWvidmode* glfwGetVideoModes(GLFWmonitor handle, int* count)
-{
-    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
-
-    if (!_glfwInitialized)
-    {
-        _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
-        return NULL;
-    }
-
-    if (monitor == NULL)
-    {
-        _glfwSetError(GLFW_INVALID_VALUE,
-                      "glfwGetVideoModes: Invalid monitor handle");
-        return 0;
-    }
-
-    if (count == NULL)
-    {
-        _glfwSetError(GLFW_INVALID_VALUE, NULL);
-        return NULL;
-    }
-
-    free(monitor->modes);
-
-    monitor->modes = _glfwPlatformGetVideoModes(monitor, count);
-    if (monitor->modes)
-        qsort(monitor->modes, *count, sizeof(GLFWvidmode), compareVideoModes);
-
-    return monitor->modes;
-}
-
-
-//========================================================================
-// Get the current video mode for the specified monitor
-//========================================================================
-
-GLFWAPI void glfwGetVideoMode(GLFWmonitor handle, GLFWvidmode* mode)
-{
-    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
-
-    if (!_glfwInitialized)
-    {
-        _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
-        return;
-    }
-
-    if (mode == NULL)
-    {
-        _glfwSetError(GLFW_INVALID_VALUE, NULL);
-        return;
-    }
-
-    _glfwPlatformGetVideoMode(monitor, mode);
-}
-

+ 129 - 0
src/monitor.c

@@ -32,6 +32,40 @@
 
 #include <string.h>
 #include <stdlib.h>
+#if _WIN32
+ #include <malloc.h>
+#endif
+
+
+//========================================================================
+// Lexical comparison function for GLFW video modes, used by qsort
+//========================================================================
+
+int compareVideoModes(const void* firstPtr, const void* secondPtr)
+{
+    int firstBPP, secondBPP, firstSize, secondSize;
+    GLFWvidmode* first = (GLFWvidmode*) firstPtr;
+    GLFWvidmode* second = (GLFWvidmode*) secondPtr;
+
+    // First sort on color bits per pixel
+
+    firstBPP = first->redBits +
+               first->greenBits +
+               first->blueBits;
+    secondBPP = second->redBits +
+                second->greenBits +
+                second->blueBits;
+
+    if (firstBPP != secondBPP)
+        return firstBPP - secondBPP;
+
+    // Then sort on screen area, in pixels
+
+    firstSize = first->width * first->height;
+    secondSize = second->width * second->height;
+
+    return firstSize - secondSize;
+}
 
 
 //////////////////////////////////////////////////////////////////////////
@@ -151,6 +185,40 @@ void _glfwDestroyMonitors(void)
 }
 
 
+//========================================================================
+// Lexical comparison of GLFW video modes
+//========================================================================
+
+int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second)
+{
+    return compareVideoModes(first, second);
+}
+
+
+//========================================================================
+// Convert BPP to RGB bits based on "best guess"
+//========================================================================
+
+void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
+{
+    int delta;
+
+    // We assume that by 32 the user really meant 24
+    if (bpp == 32)
+        bpp = 24;
+
+    // Convert "bits per pixel" to red, green & blue sizes
+
+    *red = *green = *blue = bpp / 3;
+    delta = bpp - (*red * 3);
+    if (delta >= 1)
+        *green = *green + 1;
+
+    if (delta == 2)
+        *red = *red + 1;
+}
+
+
 //////////////////////////////////////////////////////////////////////////
 //////                        GLFW public API                       //////
 //////////////////////////////////////////////////////////////////////////
@@ -281,3 +349,64 @@ GLFWAPI void glfwSetMonitorCallback(GLFWmonitorfun cbfun)
     _glfwLibrary.monitorCallback= cbfun;
 }
 
+
+//========================================================================
+// Get a list of available video modes
+//========================================================================
+
+GLFWAPI GLFWvidmode* glfwGetVideoModes(GLFWmonitor handle, int* count)
+{
+    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+
+    if (!_glfwInitialized)
+    {
+        _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
+        return NULL;
+    }
+
+    if (monitor == NULL)
+    {
+        _glfwSetError(GLFW_INVALID_VALUE,
+                      "glfwGetVideoModes: Invalid monitor handle");
+        return 0;
+    }
+
+    if (count == NULL)
+    {
+        _glfwSetError(GLFW_INVALID_VALUE, NULL);
+        return NULL;
+    }
+
+    free(monitor->modes);
+
+    monitor->modes = _glfwPlatformGetVideoModes(monitor, count);
+    if (monitor->modes)
+        qsort(monitor->modes, *count, sizeof(GLFWvidmode), compareVideoModes);
+
+    return monitor->modes;
+}
+
+
+//========================================================================
+// Get the current video mode for the specified monitor
+//========================================================================
+
+GLFWAPI void glfwGetVideoMode(GLFWmonitor handle, GLFWvidmode* mode)
+{
+    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+
+    if (!_glfwInitialized)
+    {
+        _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
+        return;
+    }
+
+    if (mode == NULL)
+    {
+        _glfwSetError(GLFW_INVALID_VALUE, NULL);
+        return;
+    }
+
+    _glfwPlatformGetVideoMode(monitor, mode);
+}
+

+ 0 - 281
src/win32_fullscreen.c

@@ -1,281 +0,0 @@
-//========================================================================
-// GLFW - An OpenGL library
-// Platform:    Win32
-// API version: 3.0
-// WWW:         http://www.glfw.org/
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-//    claim that you wrote the original software. If you use this software
-//    in a product, an acknowledgment in the product documentation would
-//    be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such, and must not
-//    be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source
-//    distribution.
-//
-//========================================================================
-
-#include "internal.h"
-
-#include <stdlib.h>
-#include <limits.h>
-#include <malloc.h>
-
-
-//========================================================================
-// Return closest video mode by dimensions, refresh rate and bits per pixel
-//========================================================================
-
-static GLboolean getClosestVideoMode(int* width, int* height,
-                                     int* bpp, int* refreshRate,
-                                     GLboolean exactBPP)
-{
-    int mode, bestWidth, bestHeight, bestBPP, bestRate;
-    unsigned int sizeDiff, rateDiff, leastSizeDiff, leastRateDiff;
-    GLboolean foundMode = GL_FALSE;
-    DEVMODE dm;
-
-    leastSizeDiff = leastRateDiff = UINT_MAX;
-
-    for (mode = 0;  ;  mode++)
-    {
-        dm.dmSize = sizeof(DEVMODE);
-        if (!EnumDisplaySettings(NULL, mode, &dm))
-            break;
-
-        if (exactBPP && dm.dmBitsPerPel != *bpp)
-            continue;
-
-        sizeDiff = (abs(dm.dmBitsPerPel - *bpp) << 25) |
-                   ((dm.dmPelsWidth - *width) *
-                    (dm.dmPelsWidth - *width) +
-                    (dm.dmPelsHeight - *height) *
-                    (dm.dmPelsHeight - *height));
-
-        if (*refreshRate > 0)
-        {
-            rateDiff = (dm.dmDisplayFrequency - *refreshRate) *
-                       (dm.dmDisplayFrequency - *refreshRate);
-        }
-        else
-        {
-            // If no refresh rate was specified, then they're all the same
-            rateDiff = 0;
-        }
-
-        // We match first BPP, then screen area and last refresh rate
-
-        if ((sizeDiff < leastSizeDiff) ||
-            (sizeDiff == leastSizeDiff && (rateDiff < leastRateDiff)))
-        {
-            bestWidth  = dm.dmPelsWidth;
-            bestHeight = dm.dmPelsHeight;
-            bestBPP    = dm.dmBitsPerPel;
-            bestRate   = dm.dmDisplayFrequency;
-
-            leastSizeDiff = sizeDiff;
-            leastRateDiff = rateDiff;
-
-            foundMode = GL_TRUE;
-        }
-    }
-
-    if (!foundMode)
-        return GL_FALSE;
-
-    *width  = bestWidth;
-    *height = bestHeight;
-    *bpp    = bestBPP;
-
-    // Only save the found refresh rate if the client requested a specific
-    // rate; otherwise keep it at zero to let Windows select the best rate
-    if (*refreshRate > 0)
-        *refreshRate = bestRate;
-
-    return GL_TRUE;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-//========================================================================
-// Change the current video mode
-//========================================================================
-
-void _glfwSetVideoMode(int* width, int* height,
-                       int* bpp, int* refreshRate,
-                       GLboolean exactBPP)
-{
-    DEVMODE dm;
-    int closestWidth, closestHeight, closestBPP, closestRate;
-
-    closestWidth  = *width;
-    closestHeight = *height;
-    closestBPP    = *bpp;
-    closestRate   = *refreshRate;
-
-    if (getClosestVideoMode(&closestWidth, &closestHeight,
-                            &closestBPP, &closestRate, GL_FALSE))
-    {
-        dm.dmSize = sizeof(DEVMODE);
-        dm.dmFields     = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
-        dm.dmPelsWidth  = closestWidth;
-        dm.dmPelsHeight = closestHeight;
-        dm.dmBitsPerPel = closestBPP;
-
-        if (*refreshRate > 0)
-        {
-            dm.dmFields |= DM_DISPLAYFREQUENCY;
-            dm.dmDisplayFrequency = closestRate;
-        }
-
-        if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL)
-        {
-            *width       = closestWidth;
-            *height      = closestHeight;
-            *bpp         = closestBPP;
-            *refreshRate = closestRate;
-        }
-    }
-    else
-    {
-        dm.dmSize = sizeof(DEVMODE);
-        EnumDisplaySettings(NULL, ENUM_REGISTRY_SETTINGS, &dm);
-
-        *width       = dm.dmPelsWidth;
-        *height      = dm.dmPelsHeight;
-        *bpp         = dm.dmBitsPerPel;
-        *refreshRate = dm.dmDisplayFrequency;
-    }
-}
-
-
-//========================================================================
-// Restore the previously saved (original) video mode
-//========================================================================
-
-void _glfwRestoreVideoMode(void)
-{
-    ChangeDisplaySettings(NULL, CDS_FULLSCREEN);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-//========================================================================
-// Get a list of available video modes
-//========================================================================
-
-GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
-{
-    int modeIndex = 0, count = 0;
-    GLFWvidmode* result = NULL;
-
-    *found = 0;
-
-    for (;;)
-    {
-        int i;
-        GLFWvidmode mode;
-        DEVMODE dm;
-
-        ZeroMemory(&dm, sizeof(DEVMODE));
-        dm.dmSize = sizeof(DEVMODE);
-
-        if (!EnumDisplaySettings(monitor->Win32.name, modeIndex, &dm))
-            break;
-
-        modeIndex++;
-
-        if (dm.dmBitsPerPel < 15)
-        {
-            // Skip modes with less than 15 BPP
-            continue;
-        }
-
-        mode.width = dm.dmPelsWidth;
-        mode.height = dm.dmPelsHeight;
-        _glfwSplitBPP(dm.dmBitsPerPel,
-                        &mode.redBits,
-                        &mode.greenBits,
-                        &mode.blueBits);
-
-        for (i = 0;  i < *found;  i++)
-        {
-            if (_glfwCompareVideoModes(result + i, &mode) == 0)
-                break;
-        }
-
-        if (i < *found)
-        {
-            // This is a duplicate, so skip it
-            continue;
-        }
-
-        if (*found == count)
-        {
-            void* larger;
-
-            if (count)
-                count *= 2;
-            else
-                count = 128;
-
-            larger = realloc(result, count * sizeof(GLFWvidmode));
-            if (!larger)
-            {
-                free(result);
-
-                _glfwSetError(GLFW_OUT_OF_MEMORY, NULL);
-                return NULL;
-            }
-
-            result = (GLFWvidmode*) larger;
-        }
-
-        result[*found] = mode;
-        (*found)++;
-    }
-
-    return result;
-}
-
-
-//========================================================================
-// Get the current video mode for the specified monitor
-//========================================================================
-
-void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
-{
-    DEVMODE dm;
-
-    ZeroMemory(&dm, sizeof(DEVMODE));
-    dm.dmSize = sizeof(DEVMODE);
-
-    EnumDisplaySettings(monitor->Win32.name, ENUM_REGISTRY_SETTINGS, &dm);
-
-    mode->width  = dm.dmPelsWidth;
-    mode->height = dm.dmPelsHeight;
-    _glfwSplitBPP(dm.dmBitsPerPel,
-                  &mode->redBits,
-                  &mode->greenBits,
-                  &mode->blueBits);
-}
-

+ 243 - 0
src/win32_monitor.c

@@ -32,6 +32,8 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
+#include <malloc.h>
 
 // These constants are missing on MinGW
 #ifndef EDS_ROTATEDMODE
@@ -42,6 +44,146 @@
 #endif
 
 
+//========================================================================
+// Return closest video mode by dimensions, refresh rate and bits per pixel
+//========================================================================
+
+static GLboolean getClosestVideoMode(int* width, int* height,
+                                     int* bpp, int* refreshRate,
+                                     GLboolean exactBPP)
+{
+    int mode, bestWidth, bestHeight, bestBPP, bestRate;
+    unsigned int sizeDiff, rateDiff, leastSizeDiff, leastRateDiff;
+    GLboolean foundMode = GL_FALSE;
+    DEVMODE dm;
+
+    leastSizeDiff = leastRateDiff = UINT_MAX;
+
+    for (mode = 0;  ;  mode++)
+    {
+        dm.dmSize = sizeof(DEVMODE);
+        if (!EnumDisplaySettings(NULL, mode, &dm))
+            break;
+
+        if (exactBPP && dm.dmBitsPerPel != *bpp)
+            continue;
+
+        sizeDiff = (abs(dm.dmBitsPerPel - *bpp) << 25) |
+                   ((dm.dmPelsWidth - *width) *
+                    (dm.dmPelsWidth - *width) +
+                    (dm.dmPelsHeight - *height) *
+                    (dm.dmPelsHeight - *height));
+
+        if (*refreshRate > 0)
+        {
+            rateDiff = (dm.dmDisplayFrequency - *refreshRate) *
+                       (dm.dmDisplayFrequency - *refreshRate);
+        }
+        else
+        {
+            // If no refresh rate was specified, then they're all the same
+            rateDiff = 0;
+        }
+
+        // We match first BPP, then screen area and last refresh rate
+
+        if ((sizeDiff < leastSizeDiff) ||
+            (sizeDiff == leastSizeDiff && (rateDiff < leastRateDiff)))
+        {
+            bestWidth  = dm.dmPelsWidth;
+            bestHeight = dm.dmPelsHeight;
+            bestBPP    = dm.dmBitsPerPel;
+            bestRate   = dm.dmDisplayFrequency;
+
+            leastSizeDiff = sizeDiff;
+            leastRateDiff = rateDiff;
+
+            foundMode = GL_TRUE;
+        }
+    }
+
+    if (!foundMode)
+        return GL_FALSE;
+
+    *width  = bestWidth;
+    *height = bestHeight;
+    *bpp    = bestBPP;
+
+    // Only save the found refresh rate if the client requested a specific
+    // rate; otherwise keep it at zero to let Windows select the best rate
+    if (*refreshRate > 0)
+        *refreshRate = bestRate;
+
+    return GL_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+//========================================================================
+// Change the current video mode
+//========================================================================
+
+void _glfwSetVideoMode(int* width, int* height,
+                       int* bpp, int* refreshRate,
+                       GLboolean exactBPP)
+{
+    DEVMODE dm;
+    int closestWidth, closestHeight, closestBPP, closestRate;
+
+    closestWidth  = *width;
+    closestHeight = *height;
+    closestBPP    = *bpp;
+    closestRate   = *refreshRate;
+
+    if (getClosestVideoMode(&closestWidth, &closestHeight,
+                            &closestBPP, &closestRate, GL_FALSE))
+    {
+        dm.dmSize = sizeof(DEVMODE);
+        dm.dmFields     = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
+        dm.dmPelsWidth  = closestWidth;
+        dm.dmPelsHeight = closestHeight;
+        dm.dmBitsPerPel = closestBPP;
+
+        if (*refreshRate > 0)
+        {
+            dm.dmFields |= DM_DISPLAYFREQUENCY;
+            dm.dmDisplayFrequency = closestRate;
+        }
+
+        if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL)
+        {
+            *width       = closestWidth;
+            *height      = closestHeight;
+            *bpp         = closestBPP;
+            *refreshRate = closestRate;
+        }
+    }
+    else
+    {
+        dm.dmSize = sizeof(DEVMODE);
+        EnumDisplaySettings(NULL, ENUM_REGISTRY_SETTINGS, &dm);
+
+        *width       = dm.dmPelsWidth;
+        *height      = dm.dmPelsHeight;
+        *bpp         = dm.dmBitsPerPel;
+        *refreshRate = dm.dmDisplayFrequency;
+    }
+}
+
+
+//========================================================================
+// Restore the previously saved (original) video mode
+//========================================================================
+
+void _glfwRestoreVideoMode(void)
+{
+    ChangeDisplaySettings(NULL, CDS_FULLSCREEN);
+}
+
+
 //////////////////////////////////////////////////////////////////////////
 //////                       GLFW platform API                      //////
 //////////////////////////////////////////////////////////////////////////
@@ -164,3 +306,104 @@ void _glfwPlatformDestroyMonitor(_GLFWmonitor* monitor)
     free(monitor->Win32.name);
 }
 
+
+//========================================================================
+// Get a list of available video modes
+//========================================================================
+
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
+{
+    int modeIndex = 0, count = 0;
+    GLFWvidmode* result = NULL;
+
+    *found = 0;
+
+    for (;;)
+    {
+        int i;
+        GLFWvidmode mode;
+        DEVMODE dm;
+
+        ZeroMemory(&dm, sizeof(DEVMODE));
+        dm.dmSize = sizeof(DEVMODE);
+
+        if (!EnumDisplaySettings(monitor->Win32.name, modeIndex, &dm))
+            break;
+
+        modeIndex++;
+
+        if (dm.dmBitsPerPel < 15)
+        {
+            // Skip modes with less than 15 BPP
+            continue;
+        }
+
+        mode.width = dm.dmPelsWidth;
+        mode.height = dm.dmPelsHeight;
+        _glfwSplitBPP(dm.dmBitsPerPel,
+                        &mode.redBits,
+                        &mode.greenBits,
+                        &mode.blueBits);
+
+        for (i = 0;  i < *found;  i++)
+        {
+            if (_glfwCompareVideoModes(result + i, &mode) == 0)
+                break;
+        }
+
+        if (i < *found)
+        {
+            // This is a duplicate, so skip it
+            continue;
+        }
+
+        if (*found == count)
+        {
+            void* larger;
+
+            if (count)
+                count *= 2;
+            else
+                count = 128;
+
+            larger = realloc(result, count * sizeof(GLFWvidmode));
+            if (!larger)
+            {
+                free(result);
+
+                _glfwSetError(GLFW_OUT_OF_MEMORY, NULL);
+                return NULL;
+            }
+
+            result = (GLFWvidmode*) larger;
+        }
+
+        result[*found] = mode;
+        (*found)++;
+    }
+
+    return result;
+}
+
+
+//========================================================================
+// Get the current video mode for the specified monitor
+//========================================================================
+
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
+{
+    DEVMODE dm;
+
+    ZeroMemory(&dm, sizeof(DEVMODE));
+    dm.dmSize = sizeof(DEVMODE);
+
+    EnumDisplaySettings(monitor->Win32.name, ENUM_REGISTRY_SETTINGS, &dm);
+
+    mode->width  = dm.dmPelsWidth;
+    mode->height = dm.dmPelsHeight;
+    _glfwSplitBPP(dm.dmBitsPerPel,
+                  &mode->redBits,
+                  &mode->greenBits,
+                  &mode->blueBits);
+}
+

+ 0 - 531
src/x11_fullscreen.c

@@ -1,531 +0,0 @@
-//========================================================================
-// GLFW - An OpenGL library
-// Platform:    X11
-// API version: 3.0
-// WWW:         http://www.glfw.org/
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2010 Camilla Berglund <[email protected]>
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-//    claim that you wrote the original software. If you use this software
-//    in a product, an acknowledgment in the product documentation would
-//    be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such, and must not
-//    be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source
-//    distribution.
-//
-//========================================================================
-
-#include "internal.h"
-
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-//------------------------------------------------------------------------
-// Display resolution
-//------------------------------------------------------------------------
-
-typedef struct
-{
-    int width;
-    int height;
-} _GLFWvidsize;
-
-
-//========================================================================
-// List available resolutions
-//========================================================================
-
-static _GLFWvidsize* getResolutions(_GLFWmonitor* monitor, int* found)
-{
-    int i, j;
-    _GLFWvidsize* result = NULL;
-
-    *found = 0;
-
-    // Build array of available resolutions
-
-    if (_glfwLibrary.X11.RandR.available)
-    {
-#if defined(_GLFW_HAS_XRANDR)
-        XRRScreenConfiguration* sc;
-        XRRScreenSize* sizes;
-
-        sc = XRRGetScreenInfo(_glfwLibrary.X11.display, _glfwLibrary.X11.root);
-        sizes = XRRConfigSizes(sc, found);
-
-        result = (_GLFWvidsize*) malloc(sizeof(_GLFWvidsize) * *found);
-
-        for (i = 0;  i < *found;  i++)
-        {
-            result[i].width  = sizes[i].width;
-            result[i].height = sizes[i].height;
-        }
-
-        XRRFreeScreenConfigInfo(sc);
-#endif /*_GLFW_HAS_XRANDR*/
-    }
-    else if (_glfwLibrary.X11.VidMode.available)
-    {
-#if defined(_GLFW_HAS_XF86VIDMODE)
-        XF86VidModeModeInfo** modes;
-        int modeCount;
-
-        XF86VidModeGetAllModeLines(_glfwLibrary.X11.display,
-                                   _glfwLibrary.X11.screen,
-                                   &modeCount, &modes);
-
-        result = (_GLFWvidsize*) malloc(sizeof(_GLFWvidsize) * modeCount);
-
-        for (i = 0;  i < modeCount;  i++)
-        {
-            _GLFWvidsize size;
-            size.width  = modes[i]->hdisplay;
-            size.height = modes[i]->vdisplay;
-
-            for (j = 0;  j < *found;  j++)
-            {
-                if (memcmp(result + j, &size, sizeof(_GLFWvidsize)) == 0)
-                    break;
-            }
-
-            if (j < *found)
-            {
-                // This size is a duplicate, so skip it
-                continue;
-            }
-
-            result[*found] = size;
-            (*found)++;
-        }
-
-        XFree(modes);
-#endif /*_GLFW_HAS_XF86VIDMODE*/
-    }
-
-    if (result == NULL)
-    {
-        *found = 1;
-        result = (_GLFWvidsize*) malloc(sizeof(_GLFWvidsize));
-
-        result[0].width = DisplayWidth(_glfwLibrary.X11.display,
-                                       _glfwLibrary.X11.screen);
-        result[0].height = DisplayHeight(_glfwLibrary.X11.display,
-                                         _glfwLibrary.X11.screen);
-    }
-
-    return result;
-}
-
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-//========================================================================
-// Finds the video mode closest in size to the specified desired size
-//========================================================================
-
-int _glfwGetClosestVideoMode(int* width, int* height, int* rate)
-{
-    int i, match, bestmatch;
-
-    if (_glfwLibrary.X11.RandR.available)
-    {
-#if defined(_GLFW_HAS_XRANDR)
-        int sizecount, bestsize;
-        int ratecount, bestrate;
-        short* ratelist;
-        XRRScreenConfiguration* sc;
-        XRRScreenSize* sizelist;
-
-        sc = XRRGetScreenInfo(_glfwLibrary.X11.display, _glfwLibrary.X11.root);
-
-        sizelist = XRRConfigSizes(sc, &sizecount);
-
-        // Find the best matching mode
-        bestsize  = -1;
-        bestmatch = INT_MAX;
-        for (i = 0;  i < sizecount;  i++)
-        {
-            match = (*width - sizelist[i].width) *
-                    (*width - sizelist[i].width) +
-                    (*height - sizelist[i].height) *
-                    (*height - sizelist[i].height);
-            if (match < bestmatch)
-            {
-                bestmatch = match;
-                bestsize  = i;
-            }
-        }
-
-        if (bestsize != -1)
-        {
-            // Report width & height of best matching mode
-            *width = sizelist[bestsize].width;
-            *height = sizelist[bestsize].height;
-
-            if (*rate > 0)
-            {
-                ratelist = XRRConfigRates(sc, bestsize, &ratecount);
-
-                bestrate = -1;
-                bestmatch = INT_MAX;
-                for (i = 0;  i < ratecount;  i++)
-                {
-                    match = abs(ratelist[i] - *rate);
-                    if (match < bestmatch)
-                    {
-                        bestmatch = match;
-                        bestrate = ratelist[i];
-                    }
-                }
-
-                if (bestrate != -1)
-                    *rate = bestrate;
-            }
-        }
-
-        XRRFreeScreenConfigInfo(sc);
-
-        if (bestsize != -1)
-            return bestsize;
-#endif /*_GLFW_HAS_XRANDR*/
-    }
-    else if (_glfwLibrary.X11.VidMode.available)
-    {
-#if defined(_GLFW_HAS_XF86VIDMODE)
-        XF86VidModeModeInfo** modelist;
-        int bestmode, modecount;
-
-        // Get a list of all available display modes
-        XF86VidModeGetAllModeLines(_glfwLibrary.X11.display,
-                                   _glfwLibrary.X11.screen,
-                                   &modecount, &modelist);
-
-        // Find the best matching mode
-        bestmode  = -1;
-        bestmatch = INT_MAX;
-        for (i = 0;  i < modecount;  i++)
-        {
-            match = (*width - modelist[i]->hdisplay) *
-                    (*width - modelist[i]->hdisplay) +
-                    (*height - modelist[i]->vdisplay) *
-                    (*height - modelist[i]->vdisplay);
-            if (match < bestmatch)
-            {
-                bestmatch = match;
-                bestmode  = i;
-            }
-        }
-
-        if (bestmode != -1)
-        {
-            // Report width & height of best matching mode
-            *width = modelist[bestmode]->hdisplay;
-            *height = modelist[bestmode]->vdisplay;
-        }
-
-        XFree(modelist);
-
-        if (bestmode != -1)
-            return bestmode;
-#endif /*_GLFW_HAS_XF86VIDMODE*/
-    }
-
-    // Default: Simply use the screen resolution
-    *width = DisplayWidth(_glfwLibrary.X11.display, _glfwLibrary.X11.screen);
-    *height = DisplayHeight(_glfwLibrary.X11.display, _glfwLibrary.X11.screen);
-
-    return 0;
-}
-
-
-//========================================================================
-// Change the current video mode
-//========================================================================
-
-void _glfwSetVideoModeMODE(int mode, int rate)
-{
-    if (_glfwLibrary.X11.RandR.available)
-    {
-#if defined(_GLFW_HAS_XRANDR)
-        XRRScreenConfiguration* sc;
-        Window root;
-
-        root = _glfwLibrary.X11.root;
-        sc   = XRRGetScreenInfo(_glfwLibrary.X11.display, root);
-
-        // Remember old size and flag that we have changed the mode
-        if (!_glfwLibrary.X11.FS.modeChanged)
-        {
-            _glfwLibrary.X11.FS.oldSizeID = XRRConfigCurrentConfiguration(sc, &_glfwLibrary.X11.FS.oldRotation);
-            _glfwLibrary.X11.FS.oldWidth  = DisplayWidth(_glfwLibrary.X11.display,
-                                                         _glfwLibrary.X11.screen);
-            _glfwLibrary.X11.FS.oldHeight = DisplayHeight(_glfwLibrary.X11.display,
-                                                          _glfwLibrary.X11.screen);
-
-            _glfwLibrary.X11.FS.modeChanged = GL_TRUE;
-        }
-
-        if (rate > 0)
-        {
-            // Set desired configuration
-            XRRSetScreenConfigAndRate(_glfwLibrary.X11.display,
-                                      sc,
-                                      root,
-                                      mode,
-                                      RR_Rotate_0,
-                                      (short) rate,
-                                      CurrentTime);
-        }
-        else
-        {
-            // Set desired configuration
-            XRRSetScreenConfig(_glfwLibrary.X11.display,
-                               sc,
-                               root,
-                               mode,
-                               RR_Rotate_0,
-                               CurrentTime);
-        }
-
-        XRRFreeScreenConfigInfo(sc);
-#endif /*_GLFW_HAS_XRANDR*/
-    }
-    else if (_glfwLibrary.X11.VidMode.available)
-    {
-#if defined(_GLFW_HAS_XF86VIDMODE)
-        XF86VidModeModeInfo **modelist;
-        int modecount;
-
-        // Get a list of all available display modes
-        XF86VidModeGetAllModeLines(_glfwLibrary.X11.display,
-                                   _glfwLibrary.X11.screen,
-                                   &modecount, &modelist);
-
-        // Unlock mode switch if necessary
-        if (_glfwLibrary.X11.FS.modeChanged)
-        {
-            XF86VidModeLockModeSwitch(_glfwLibrary.X11.display,
-                                      _glfwLibrary.X11.screen,
-                                      0);
-        }
-
-        // Change the video mode to the desired mode
-        XF86VidModeSwitchToMode(_glfwLibrary.X11.display,
-                                _glfwLibrary.X11.screen,
-                                modelist[mode]);
-
-        // Set viewport to upper left corner (where our window will be)
-        XF86VidModeSetViewPort(_glfwLibrary.X11.display,
-                               _glfwLibrary.X11.screen,
-                               0, 0);
-
-        // Lock mode switch
-        XF86VidModeLockModeSwitch(_glfwLibrary.X11.display,
-                                  _glfwLibrary.X11.screen,
-                                  1);
-
-        // Remember old mode and flag that we have changed the mode
-        if (!_glfwLibrary.X11.FS.modeChanged)
-        {
-            _glfwLibrary.X11.FS.oldMode = *modelist[0];
-            _glfwLibrary.X11.FS.modeChanged = GL_TRUE;
-        }
-
-        XFree(modelist);
-#endif /*_GLFW_HAS_XF86VIDMODE*/
-    }
-}
-
-
-//========================================================================
-// Change the current video mode
-//========================================================================
-
-void _glfwSetVideoMode(int* width, int* height, int* rate)
-{
-    int bestmode;
-
-    // Find a best match mode
-    bestmode = _glfwGetClosestVideoMode(width, height, rate);
-
-    // Change mode
-    _glfwSetVideoModeMODE(bestmode, *rate);
-}
-
-
-//========================================================================
-// Restore the previously saved (original) video mode
-//========================================================================
-
-void _glfwRestoreVideoMode(void)
-{
-    if (_glfwLibrary.X11.FS.modeChanged)
-    {
-        if (_glfwLibrary.X11.RandR.available)
-        {
-#if defined(_GLFW_HAS_XRANDR)
-            XRRScreenConfiguration* sc;
-
-            if (_glfwLibrary.X11.RandR.available)
-            {
-                sc = XRRGetScreenInfo(_glfwLibrary.X11.display,
-                                      _glfwLibrary.X11.root);
-
-                XRRSetScreenConfig(_glfwLibrary.X11.display,
-                                   sc,
-                                   _glfwLibrary.X11.root,
-                                   _glfwLibrary.X11.FS.oldSizeID,
-                                   _glfwLibrary.X11.FS.oldRotation,
-                                   CurrentTime);
-
-                XRRFreeScreenConfigInfo(sc);
-            }
-#endif /*_GLFW_HAS_XRANDR*/
-        }
-        else if (_glfwLibrary.X11.VidMode.available)
-        {
-#if defined(_GLFW_HAS_XF86VIDMODE)
-            // Unlock mode switch
-            XF86VidModeLockModeSwitch(_glfwLibrary.X11.display,
-                                      _glfwLibrary.X11.screen,
-                                      0);
-
-            // Change the video mode back to the old mode
-            XF86VidModeSwitchToMode(_glfwLibrary.X11.display,
-                                    _glfwLibrary.X11.screen,
-                                    &_glfwLibrary.X11.FS.oldMode);
-#endif /*_GLFW_HAS_XF86VIDMODE*/
-        }
-
-        _glfwLibrary.X11.FS.modeChanged = GL_FALSE;
-    }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-//========================================================================
-// List available video modes
-//========================================================================
-
-GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
-{
-    XVisualInfo* visuals;
-    XVisualInfo dummy;
-    int i, j, visualCount, sizeCount, rgbCount;
-    int* rgbs;
-    _GLFWvidsize* sizes;
-    GLFWvidmode* result;
-
-    visuals = XGetVisualInfo(_glfwLibrary.X11.display, 0, &dummy, &visualCount);
-    if (visuals == NULL)
-    {
-        _glfwSetError(GLFW_PLATFORM_ERROR,
-                      "X11: Failed to retrieve the available visuals");
-        return 0;
-    }
-
-    // Build array of available RGB channel depths
-
-    rgbs = (int*) malloc(sizeof(int) * visualCount);
-    rgbCount = 0;
-
-    for (i = 0;  i < visualCount;  i++)
-    {
-        int gl, rgba, rgb, r, g, b;
-
-        glXGetConfig(_glfwLibrary.X11.display, &visuals[i], GLX_USE_GL, &gl);
-        glXGetConfig(_glfwLibrary.X11.display, &visuals[i], GLX_RGBA, &rgba);
-
-        if (!gl || !rgba)
-        {
-            // The visual lacks OpenGL or true color, so skip it
-            continue;
-        }
-
-        // Convert to RGB channel depths and encode
-        _glfwSplitBPP(visuals[i].depth, &r, &g, &b);
-        rgb = (r << 16) | (g << 8) | b;
-
-        for (j = 0;  j < rgbCount;  j++)
-        {
-            if (rgbs[j] == rgb)
-                break;
-        }
-
-        if (j < rgbCount)
-        {
-            // This channel depth is a duplicate, so skip it
-            continue;
-        }
-
-        rgbs[rgbCount] = rgb;
-        rgbCount++;
-    }
-
-    XFree(visuals);
-
-    // Build all permutations of channel depths and resolutions
-
-    sizes = getResolutions(monitor, &sizeCount);
-
-    result = (GLFWvidmode*) malloc(sizeof(GLFWvidmode) * rgbCount * sizeCount);
-    *found = 0;
-
-    for (i = 0;  i < rgbCount;  i++)
-    {
-        for (j = 0;  j < sizeCount;  j++)
-        {
-            result[*found].width     = sizes[j].width;
-            result[*found].height    = sizes[j].height;
-            result[*found].redBits   = (rgbs[i] >> 16) & 255;
-            result[*found].greenBits = (rgbs[i] >> 8) & 255;
-            result[*found].blueBits  = rgbs[i] & 255;
-
-            (*found)++;
-        }
-    }
-
-    free(sizes);
-    free(rgbs);
-
-    return result;
-}
-
-
-//========================================================================
-// Get the current video mode for the specified monitor
-//========================================================================
-
-void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
-{
-    _glfwSplitBPP(DefaultDepth(_glfwLibrary.X11.display,
-                               _glfwLibrary.X11.screen),
-                  &mode->redBits, &mode->greenBits, &mode->blueBits);
-
-    mode->width = DisplayWidth(_glfwLibrary.X11.display,
-                               _glfwLibrary.X11.screen);
-    mode->height = DisplayHeight(_glfwLibrary.X11.display,
-                                 _glfwLibrary.X11.screen);
-}
-

+ 492 - 0
src/x11_monitor.c

@@ -30,10 +30,396 @@
 
 #include "internal.h"
 
+#include <limits.h>
 #include <stdlib.h>
 #include <string.h>
 
 
+//------------------------------------------------------------------------
+// Display resolution
+//------------------------------------------------------------------------
+
+typedef struct
+{
+    int width;
+    int height;
+} _GLFWvidsize;
+
+
+//========================================================================
+// List available resolutions
+//========================================================================
+
+static _GLFWvidsize* getResolutions(_GLFWmonitor* monitor, int* found)
+{
+    int i, j;
+    _GLFWvidsize* result = NULL;
+
+    *found = 0;
+
+    // Build array of available resolutions
+
+    if (_glfwLibrary.X11.RandR.available)
+    {
+#if defined(_GLFW_HAS_XRANDR)
+        XRRScreenConfiguration* sc;
+        XRRScreenSize* sizes;
+
+        sc = XRRGetScreenInfo(_glfwLibrary.X11.display, _glfwLibrary.X11.root);
+        sizes = XRRConfigSizes(sc, found);
+
+        result = (_GLFWvidsize*) malloc(sizeof(_GLFWvidsize) * *found);
+
+        for (i = 0;  i < *found;  i++)
+        {
+            result[i].width  = sizes[i].width;
+            result[i].height = sizes[i].height;
+        }
+
+        XRRFreeScreenConfigInfo(sc);
+#endif /*_GLFW_HAS_XRANDR*/
+    }
+    else if (_glfwLibrary.X11.VidMode.available)
+    {
+#if defined(_GLFW_HAS_XF86VIDMODE)
+        XF86VidModeModeInfo** modes;
+        int modeCount;
+
+        XF86VidModeGetAllModeLines(_glfwLibrary.X11.display,
+                                   _glfwLibrary.X11.screen,
+                                   &modeCount, &modes);
+
+        result = (_GLFWvidsize*) malloc(sizeof(_GLFWvidsize) * modeCount);
+
+        for (i = 0;  i < modeCount;  i++)
+        {
+            _GLFWvidsize size;
+            size.width  = modes[i]->hdisplay;
+            size.height = modes[i]->vdisplay;
+
+            for (j = 0;  j < *found;  j++)
+            {
+                if (memcmp(result + j, &size, sizeof(_GLFWvidsize)) == 0)
+                    break;
+            }
+
+            if (j < *found)
+            {
+                // This size is a duplicate, so skip it
+                continue;
+            }
+
+            result[*found] = size;
+            (*found)++;
+        }
+
+        XFree(modes);
+#endif /*_GLFW_HAS_XF86VIDMODE*/
+    }
+
+    if (result == NULL)
+    {
+        *found = 1;
+        result = (_GLFWvidsize*) malloc(sizeof(_GLFWvidsize));
+
+        result[0].width = DisplayWidth(_glfwLibrary.X11.display,
+                                       _glfwLibrary.X11.screen);
+        result[0].height = DisplayHeight(_glfwLibrary.X11.display,
+                                         _glfwLibrary.X11.screen);
+    }
+
+    return result;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+//========================================================================
+// Finds the video mode closest in size to the specified desired size
+//========================================================================
+
+int _glfwGetClosestVideoMode(int* width, int* height, int* rate)
+{
+    int i, match, bestmatch;
+
+    if (_glfwLibrary.X11.RandR.available)
+    {
+#if defined(_GLFW_HAS_XRANDR)
+        int sizecount, bestsize;
+        int ratecount, bestrate;
+        short* ratelist;
+        XRRScreenConfiguration* sc;
+        XRRScreenSize* sizelist;
+
+        sc = XRRGetScreenInfo(_glfwLibrary.X11.display, _glfwLibrary.X11.root);
+
+        sizelist = XRRConfigSizes(sc, &sizecount);
+
+        // Find the best matching mode
+        bestsize  = -1;
+        bestmatch = INT_MAX;
+        for (i = 0;  i < sizecount;  i++)
+        {
+            match = (*width - sizelist[i].width) *
+                    (*width - sizelist[i].width) +
+                    (*height - sizelist[i].height) *
+                    (*height - sizelist[i].height);
+            if (match < bestmatch)
+            {
+                bestmatch = match;
+                bestsize  = i;
+            }
+        }
+
+        if (bestsize != -1)
+        {
+            // Report width & height of best matching mode
+            *width = sizelist[bestsize].width;
+            *height = sizelist[bestsize].height;
+
+            if (*rate > 0)
+            {
+                ratelist = XRRConfigRates(sc, bestsize, &ratecount);
+
+                bestrate = -1;
+                bestmatch = INT_MAX;
+                for (i = 0;  i < ratecount;  i++)
+                {
+                    match = abs(ratelist[i] - *rate);
+                    if (match < bestmatch)
+                    {
+                        bestmatch = match;
+                        bestrate = ratelist[i];
+                    }
+                }
+
+                if (bestrate != -1)
+                    *rate = bestrate;
+            }
+        }
+
+        XRRFreeScreenConfigInfo(sc);
+
+        if (bestsize != -1)
+            return bestsize;
+#endif /*_GLFW_HAS_XRANDR*/
+    }
+    else if (_glfwLibrary.X11.VidMode.available)
+    {
+#if defined(_GLFW_HAS_XF86VIDMODE)
+        XF86VidModeModeInfo** modelist;
+        int bestmode, modecount;
+
+        // Get a list of all available display modes
+        XF86VidModeGetAllModeLines(_glfwLibrary.X11.display,
+                                   _glfwLibrary.X11.screen,
+                                   &modecount, &modelist);
+
+        // Find the best matching mode
+        bestmode  = -1;
+        bestmatch = INT_MAX;
+        for (i = 0;  i < modecount;  i++)
+        {
+            match = (*width - modelist[i]->hdisplay) *
+                    (*width - modelist[i]->hdisplay) +
+                    (*height - modelist[i]->vdisplay) *
+                    (*height - modelist[i]->vdisplay);
+            if (match < bestmatch)
+            {
+                bestmatch = match;
+                bestmode  = i;
+            }
+        }
+
+        if (bestmode != -1)
+        {
+            // Report width & height of best matching mode
+            *width = modelist[bestmode]->hdisplay;
+            *height = modelist[bestmode]->vdisplay;
+        }
+
+        XFree(modelist);
+
+        if (bestmode != -1)
+            return bestmode;
+#endif /*_GLFW_HAS_XF86VIDMODE*/
+    }
+
+    // Default: Simply use the screen resolution
+    *width = DisplayWidth(_glfwLibrary.X11.display, _glfwLibrary.X11.screen);
+    *height = DisplayHeight(_glfwLibrary.X11.display, _glfwLibrary.X11.screen);
+
+    return 0;
+}
+
+
+//========================================================================
+// Change the current video mode
+//========================================================================
+
+void _glfwSetVideoModeMODE(int mode, int rate)
+{
+    if (_glfwLibrary.X11.RandR.available)
+    {
+#if defined(_GLFW_HAS_XRANDR)
+        XRRScreenConfiguration* sc;
+        Window root;
+
+        root = _glfwLibrary.X11.root;
+        sc   = XRRGetScreenInfo(_glfwLibrary.X11.display, root);
+
+        // Remember old size and flag that we have changed the mode
+        if (!_glfwLibrary.X11.FS.modeChanged)
+        {
+            _glfwLibrary.X11.FS.oldSizeID = XRRConfigCurrentConfiguration(sc, &_glfwLibrary.X11.FS.oldRotation);
+            _glfwLibrary.X11.FS.oldWidth  = DisplayWidth(_glfwLibrary.X11.display,
+                                                         _glfwLibrary.X11.screen);
+            _glfwLibrary.X11.FS.oldHeight = DisplayHeight(_glfwLibrary.X11.display,
+                                                          _glfwLibrary.X11.screen);
+
+            _glfwLibrary.X11.FS.modeChanged = GL_TRUE;
+        }
+
+        if (rate > 0)
+        {
+            // Set desired configuration
+            XRRSetScreenConfigAndRate(_glfwLibrary.X11.display,
+                                      sc,
+                                      root,
+                                      mode,
+                                      RR_Rotate_0,
+                                      (short) rate,
+                                      CurrentTime);
+        }
+        else
+        {
+            // Set desired configuration
+            XRRSetScreenConfig(_glfwLibrary.X11.display,
+                               sc,
+                               root,
+                               mode,
+                               RR_Rotate_0,
+                               CurrentTime);
+        }
+
+        XRRFreeScreenConfigInfo(sc);
+#endif /*_GLFW_HAS_XRANDR*/
+    }
+    else if (_glfwLibrary.X11.VidMode.available)
+    {
+#if defined(_GLFW_HAS_XF86VIDMODE)
+        XF86VidModeModeInfo **modelist;
+        int modecount;
+
+        // Get a list of all available display modes
+        XF86VidModeGetAllModeLines(_glfwLibrary.X11.display,
+                                   _glfwLibrary.X11.screen,
+                                   &modecount, &modelist);
+
+        // Unlock mode switch if necessary
+        if (_glfwLibrary.X11.FS.modeChanged)
+        {
+            XF86VidModeLockModeSwitch(_glfwLibrary.X11.display,
+                                      _glfwLibrary.X11.screen,
+                                      0);
+        }
+
+        // Change the video mode to the desired mode
+        XF86VidModeSwitchToMode(_glfwLibrary.X11.display,
+                                _glfwLibrary.X11.screen,
+                                modelist[mode]);
+
+        // Set viewport to upper left corner (where our window will be)
+        XF86VidModeSetViewPort(_glfwLibrary.X11.display,
+                               _glfwLibrary.X11.screen,
+                               0, 0);
+
+        // Lock mode switch
+        XF86VidModeLockModeSwitch(_glfwLibrary.X11.display,
+                                  _glfwLibrary.X11.screen,
+                                  1);
+
+        // Remember old mode and flag that we have changed the mode
+        if (!_glfwLibrary.X11.FS.modeChanged)
+        {
+            _glfwLibrary.X11.FS.oldMode = *modelist[0];
+            _glfwLibrary.X11.FS.modeChanged = GL_TRUE;
+        }
+
+        XFree(modelist);
+#endif /*_GLFW_HAS_XF86VIDMODE*/
+    }
+}
+
+
+//========================================================================
+// Change the current video mode
+//========================================================================
+
+void _glfwSetVideoMode(int* width, int* height, int* rate)
+{
+    int bestmode;
+
+    // Find a best match mode
+    bestmode = _glfwGetClosestVideoMode(width, height, rate);
+
+    // Change mode
+    _glfwSetVideoModeMODE(bestmode, *rate);
+}
+
+
+//========================================================================
+// Restore the previously saved (original) video mode
+//========================================================================
+
+void _glfwRestoreVideoMode(void)
+{
+    if (_glfwLibrary.X11.FS.modeChanged)
+    {
+        if (_glfwLibrary.X11.RandR.available)
+        {
+#if defined(_GLFW_HAS_XRANDR)
+            XRRScreenConfiguration* sc;
+
+            if (_glfwLibrary.X11.RandR.available)
+            {
+                sc = XRRGetScreenInfo(_glfwLibrary.X11.display,
+                                      _glfwLibrary.X11.root);
+
+                XRRSetScreenConfig(_glfwLibrary.X11.display,
+                                   sc,
+                                   _glfwLibrary.X11.root,
+                                   _glfwLibrary.X11.FS.oldSizeID,
+                                   _glfwLibrary.X11.FS.oldRotation,
+                                   CurrentTime);
+
+                XRRFreeScreenConfigInfo(sc);
+            }
+#endif /*_GLFW_HAS_XRANDR*/
+        }
+        else if (_glfwLibrary.X11.VidMode.available)
+        {
+#if defined(_GLFW_HAS_XF86VIDMODE)
+            // Unlock mode switch
+            XF86VidModeLockModeSwitch(_glfwLibrary.X11.display,
+                                      _glfwLibrary.X11.screen,
+                                      0);
+
+            // Change the video mode back to the old mode
+            XF86VidModeSwitchToMode(_glfwLibrary.X11.display,
+                                    _glfwLibrary.X11.screen,
+                                    &_glfwLibrary.X11.FS.oldMode);
+#endif /*_GLFW_HAS_XF86VIDMODE*/
+        }
+
+        _glfwLibrary.X11.FS.modeChanged = GL_FALSE;
+    }
+}
+
+
 //////////////////////////////////////////////////////////////////////////
 //////                       GLFW platform API                      //////
 //////////////////////////////////////////////////////////////////////////
@@ -113,3 +499,109 @@ void _glfwPlatformDestroyMonitor(_GLFWmonitor* monitor)
 #endif /*_GLFW_HAS_XRANDR*/
 }
 
+
+//========================================================================
+// List available video modes
+//========================================================================
+
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
+{
+    XVisualInfo* visuals;
+    XVisualInfo dummy;
+    int i, j, visualCount, sizeCount, rgbCount;
+    int* rgbs;
+    _GLFWvidsize* sizes;
+    GLFWvidmode* result;
+
+    visuals = XGetVisualInfo(_glfwLibrary.X11.display, 0, &dummy, &visualCount);
+    if (visuals == NULL)
+    {
+        _glfwSetError(GLFW_PLATFORM_ERROR,
+                      "X11: Failed to retrieve the available visuals");
+        return 0;
+    }
+
+    // Build array of available RGB channel depths
+
+    rgbs = (int*) malloc(sizeof(int) * visualCount);
+    rgbCount = 0;
+
+    for (i = 0;  i < visualCount;  i++)
+    {
+        int gl, rgba, rgb, r, g, b;
+
+        glXGetConfig(_glfwLibrary.X11.display, &visuals[i], GLX_USE_GL, &gl);
+        glXGetConfig(_glfwLibrary.X11.display, &visuals[i], GLX_RGBA, &rgba);
+
+        if (!gl || !rgba)
+        {
+            // The visual lacks OpenGL or true color, so skip it
+            continue;
+        }
+
+        // Convert to RGB channel depths and encode
+        _glfwSplitBPP(visuals[i].depth, &r, &g, &b);
+        rgb = (r << 16) | (g << 8) | b;
+
+        for (j = 0;  j < rgbCount;  j++)
+        {
+            if (rgbs[j] == rgb)
+                break;
+        }
+
+        if (j < rgbCount)
+        {
+            // This channel depth is a duplicate, so skip it
+            continue;
+        }
+
+        rgbs[rgbCount] = rgb;
+        rgbCount++;
+    }
+
+    XFree(visuals);
+
+    // Build all permutations of channel depths and resolutions
+
+    sizes = getResolutions(monitor, &sizeCount);
+
+    result = (GLFWvidmode*) malloc(sizeof(GLFWvidmode) * rgbCount * sizeCount);
+    *found = 0;
+
+    for (i = 0;  i < rgbCount;  i++)
+    {
+        for (j = 0;  j < sizeCount;  j++)
+        {
+            result[*found].width     = sizes[j].width;
+            result[*found].height    = sizes[j].height;
+            result[*found].redBits   = (rgbs[i] >> 16) & 255;
+            result[*found].greenBits = (rgbs[i] >> 8) & 255;
+            result[*found].blueBits  = rgbs[i] & 255;
+
+            (*found)++;
+        }
+    }
+
+    free(sizes);
+    free(rgbs);
+
+    return result;
+}
+
+
+//========================================================================
+// Get the current video mode for the specified monitor
+//========================================================================
+
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
+{
+    _glfwSplitBPP(DefaultDepth(_glfwLibrary.X11.display,
+                               _glfwLibrary.X11.screen),
+                  &mode->redBits, &mode->greenBits, &mode->blueBits);
+
+    mode->width = DisplayWidth(_glfwLibrary.X11.display,
+                               _glfwLibrary.X11.screen);
+    mode->height = DisplayHeight(_glfwLibrary.X11.display,
+                                 _glfwLibrary.X11.screen);
+}
+