Merge remote-tracking branch 'adrian/multi-display-support' into multi-monitor

Conflicts:
	.gitignore
This commit is contained in:
Camilla Berglund 2012-01-29 19:09:20 +01:00
commit 26c95559d2
19 changed files with 789 additions and 89 deletions

8
.gitignore vendored
View File

@ -1,7 +1,7 @@
*.a
CMakeCache.txt
CMakeFiles
cmake_install.cmake
CMakeCache.txt
Makefile
cmake_uninstall.cmake
.DS_Store
src/config.h
@ -9,6 +9,9 @@ src/libglfw.pc
src/libglfw.so
src/libglfw.a
src/libglfw.dylib
src/libglfw.lib
src/libglfwdll.lib
src/libglfw.dll
examples/boing
examples/gears
examples/heightmap
@ -32,6 +35,7 @@ tests/peter
tests/reopen
tests/sharing
tests/tearing
tests/version
tests/windows
tests/*.app
tests/*.exe

View File

@ -1,8 +1,14 @@
# This line is used to link with static libraries
# Note that the library list should be updated to be obtained from
# the main CMakeLists.txt
# the main CMakeLists.txt
link_libraries(libglfwStatic ${GLFW_LIBRARIES} ${OPENGL_glu_LIBRARY})
if (UNIX AND NOT APPLE AND NOT CYGWIN)
find_library(MATH_LIBRARY m)
find_library(REALTIME_LIBRARY rt)
link_libraries(${MATH_LIBRARY} ${REALTIME_LIBRARY})
endif (UNIX AND NOT APPLE AND NOT CYGWIN)
include_directories(${GLFW_SOURCE_DIR}/include
${GLFW_SOURCE_DIR}/support
${OPENGL_INCLUDE_DIR})

View File

@ -458,10 +458,22 @@ extern "C" {
/* Gamma ramps */
#define GLFW_GAMMA_RAMP_SIZE 256
/* Monitor constants */
#define GLFW_MONITOR_NAME 0x00060000
#define GLFW_MONITOR_PHYSICAL_WIDTH 0x00060001
#define GLFW_MONITOR_PHYSICAL_HEIGHT 0x00060002
#define GLFW_MONITOR_SCREEN_POS_X 0x00060003
#define GLFW_MONITOR_SCREEN_POS_Y 0x00060004
#define GLFW_MONITOR_CONNECTED 0x00061000
#define GLFW_MONITOR_DISCONNECTED 0x00061001
/*************************************************************************
* Typedefs
*************************************************************************/
/* Monitor handle type */
typedef void* GLFWmonitor;
/* Window handle type */
typedef void* GLFWwindow;
@ -479,6 +491,7 @@ typedef void (* GLFWkeyfun)(GLFWwindow,int,int);
typedef void (* GLFWcharfun)(GLFWwindow,int);
typedef void* (* GLFWmallocfun)(size_t);
typedef void (* GLFWfreefun)(void*);
typedef void (* GLFWmonitordevicefun)(GLFWmonitor,int);
/* The video mode structure used by glfwGetVideoModes */
typedef struct
@ -528,8 +541,20 @@ GLFWAPI int glfwGetError(void);
GLFWAPI const char* glfwErrorString(int error);
GLFWAPI void glfwSetErrorCallback(GLFWerrorfun cbfun);
/* Monitor callback registration */
GLFWAPI void glfwSetMonitorDeviceCallback(GLFWmonitordevicefun cbfun);
/* Monitor attributes */
GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor monitor, void* pointer);
GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor monitor);
GLFWAPI int glfwGetMonitorParam(GLFWmonitor monitor, int param);
GLFWAPI const char* glfwGetMonitorString(GLFWmonitor monitor, int param);
/* Monitor discovery */
GLFWAPI GLFWmonitor glfwGetNextMonitor(GLFWmonitor iterator);
/* Video mode functions */
GLFWAPI int glfwGetVideoModes(GLFWvidmode* list, int maxcount);
GLFWAPI int glfwGetVideoModes(GLFWmonitor monitor, GLFWvidmode* list, int maxcount);
GLFWAPI void glfwGetDesktopMode(GLFWvidmode* mode);
/* Gamma ramp functions */

View File

@ -1,4 +1,8 @@
if(WIN32)
add_definitions(-DWINVER=0x0501)
endif(WIN32)
if(UNIX)
if(_GLFW_HAS_XRANDR)
set(GLFW_PKGLIBS "${GLFW_PKGLIBS} xrandr")
@ -15,7 +19,7 @@ include_directories(${GLFW_SOURCE_DIR}/src
${GLFW_BINARY_DIR}/src
${GLFW_INCLUDE_DIR})
set(common_SOURCES enable.c error.c fullscreen.c gamma.c init.c input.c
set(common_SOURCES monitor.c enable.c error.c fullscreen.c gamma.c init.c input.c
joystick.c opengl.c time.c window.c)
if(_GLFW_COCOA_NSGL)
@ -29,10 +33,10 @@ elseif(_GLFW_WIN32_WGL)
set(libglfw_SOURCES ${common_SOURCES} win32_enable.c win32_fullscreen.c
win32_gamma.c win32_init.c win32_joystick.c
win32_opengl.c win32_time.c win32_window.c
win32_dllmain.c)
win32_dllmain.c win32_monitor.c)
elseif(_GLFW_X11_GLX)
set(libglfw_SOURCES ${common_SOURCES} x11_enable.c x11_fullscreen.c
x11_gamma.c x11_init.c x11_joystick.c
set(libglfw_SOURCES ${common_SOURCES} x11_monitor.c x11_enable.c
x11_fullscreen.c x11_gamma.c x11_init.c x11_joystick.c
x11_keysym2unicode.c x11_opengl.c x11_time.c
x11_window.c)
else()

View File

@ -37,7 +37,7 @@
// Lexical comparison function for GLFW video modes, used by qsort
//========================================================================
static int compareVideoModes(const void* firstPtr, const void* secondPtr)
int _glfwCompareVideoModes(const void* firstPtr, const void* secondPtr)
{
int firstBPP, secondBPP, firstSize, secondSize;
GLFWvidmode* first = (GLFWvidmode*) firstPtr;
@ -100,9 +100,10 @@ void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
// Get a list of available video modes
//========================================================================
GLFWAPI int glfwGetVideoModes(GLFWvidmode* list, int maxcount)
GLFWAPI int glfwGetVideoModes(GLFWmonitor handle, GLFWvidmode* list, int maxcount)
{
int count;
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
if (!_glfwInitialized)
{
@ -110,6 +111,13 @@ GLFWAPI int glfwGetVideoModes(GLFWvidmode* list, int maxcount)
return 0;
}
if (monitor == NULL)
{
_glfwSetError(GLFW_INVALID_VALUE,
"glfwGetVideoModes: Invalid monitor handle");
return 0;
}
if (maxcount <= 0)
{
_glfwSetError(GLFW_INVALID_VALUE,
@ -125,9 +133,9 @@ GLFWAPI int glfwGetVideoModes(GLFWvidmode* list, int maxcount)
return 0;
}
count = _glfwPlatformGetVideoModes(list, maxcount);
count = _glfwPlatformGetVideoModes(monitor, list, maxcount);
if (count > 0)
qsort(list, count, sizeof(GLFWvidmode), compareVideoModes);
qsort(list, count, sizeof(GLFWvidmode), _glfwCompareVideoModes);
return count;
}

View File

@ -80,6 +80,7 @@ typedef struct _GLFWwndconfig _GLFWwndconfig;
typedef struct _GLFWfbconfig _GLFWfbconfig;
typedef struct _GLFWwindow _GLFWwindow;
typedef struct _GLFWlibrary _GLFWlibrary;
typedef struct _GLFWmonitor _GLFWmonitor;
//------------------------------------------------------------------------
@ -219,6 +220,27 @@ struct _GLFWwindow
};
//------------------------------------------------------------------------
// Display structure
//------------------------------------------------------------------------
struct _GLFWmonitor
{
struct _GLFWmonitor* next;
void* userPointer;
char* name;
// physical dimensions in millimeters.
int physicalWidth;
int physicalHeight;
// logical orientation of the screen on the desktop
int screenX;
int screenY;
// These are defined in the current port's platform.h
_GLFW_PLATFORM_MONITOR_STATE;
};
//------------------------------------------------------------------------
// Library global data
//------------------------------------------------------------------------
@ -229,6 +251,8 @@ struct _GLFWlibrary
_GLFWwindow* windowListHead;
_GLFWwindow* currentWindow;
_GLFWwindow* activeWindow;
_GLFWwindow* cursorLockWindow;
_GLFWmonitor* monitorListHead;
GLFWwindowsizefun windowSizeCallback;
GLFWwindowclosefun windowCloseCallback;
@ -240,6 +264,7 @@ struct _GLFWlibrary
GLFWscrollfun scrollCallback;
GLFWkeyfun keyCallback;
GLFWcharfun charCallback;
GLFWmonitordevicefun monitorCallback;
GLFWthreadmodel threading;
GLFWallocator allocator;
@ -281,7 +306,7 @@ void _glfwPlatformEnableSystemKeys(_GLFWwindow* window);
void _glfwPlatformDisableSystemKeys(_GLFWwindow* window);
// Fullscreen
int _glfwPlatformGetVideoModes(GLFWvidmode* list, int maxcount);
int _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, GLFWvidmode* list, int maxcount);
void _glfwPlatformGetDesktopMode(GLFWvidmode* mode);
// Gamma ramp
@ -332,6 +357,7 @@ void _glfwFree(void* ptr);
// Fullscren management (fullscreen.c)
void _glfwSplitBPP(int bpp, int* red, int* green, int* blue);
int _glfwCompareVideoModes(const void* firstPtr, const void* secondPtr);
// Error handling (error.c)
void _glfwSetError(int error, const char* description);

147
src/monitor.c Normal file
View File

@ -0,0 +1,147 @@
//========================================================================
// GLFW - An OpenGL framework
// Platform: Any
// API version: 3.0
// WWW: http://www.glfw.org/
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
//
// 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"
//////////////////////////////////////////////////////////////////////////
////// GLFW public API //////
//////////////////////////////////////////////////////////////////////////
//========================================================================
// Iterate through connected monitors
//========================================================================
GLFWAPI GLFWmonitor glfwGetNextMonitor(GLFWmonitor handle)
{
_GLFWmonitor* iterator = (_GLFWmonitor*) handle;
_GLFWmonitor* result = NULL;
if (!_glfwInitialized)
{
_glfwSetError(GLFW_NOT_INITIALIZED, NULL);
return result;
}
if (iterator == NULL)
result = _glfwLibrary.monitorListHead;
else
result = iterator->next;
return result;
}
//========================================================================
// Get monitor parameter
//========================================================================
GLFWAPI int glfwGetMonitorParam(GLFWmonitor handle, int param)
{
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
if (!_glfwInitialized)
{
_glfwSetError(GLFW_NOT_INITIALIZED, NULL);
return 0;
}
if (monitor == NULL)
{
_glfwSetError(GLFW_INVALID_VALUE,
"glfwGetMonitorParam: Invalid monitor handle");
return 0;
}
switch (param)
{
case GLFW_MONITOR_PHYSICAL_WIDTH:
return monitor->physicalWidth;
case GLFW_MONITOR_PHYSICAL_HEIGHT:
return monitor->physicalHeight;
case GLFW_MONITOR_SCREEN_POS_X:
return monitor->screenX;
case GLFW_MONITOR_SCREEN_POS_Y:
return monitor->screenY;
}
_glfwSetError(GLFW_INVALID_ENUM,
"glfwGetMonitorParam: Invalid enum value for 'param' parameter");
return 0;
}
//========================================================================
// Get monitor string
//========================================================================
GLFWAPI const char* glfwGetMonitorString(GLFWmonitor handle, int param)
{
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
if (!_glfwInitialized)
{
_glfwSetError(GLFW_NOT_INITIALIZED, NULL);
return NULL;
}
if (monitor == NULL)
{
_glfwSetError(GLFW_INVALID_VALUE,
"glfwGetMonitorString: Invalid monitor handle");
return NULL;
}
switch (param)
{
case GLFW_MONITOR_NAME:
return monitor->name;
}
_glfwSetError(GLFW_INVALID_ENUM,
"glfwGetMonitorString: Invalid enum value for 'param' parameter");
return NULL;
}
//========================================================================
// Set a callback function for monitor events
//========================================================================
GLFWAPI void glfwSetMonitorDeviceCallback(GLFWmonitordevicefun cbfun)
{
if (!_glfwInitialized)
{
_glfwSetError(GLFW_NOT_INITIALIZED, NULL);
return;
}
_glfwLibrary.monitorCallback= cbfun;
}

View File

@ -182,71 +182,58 @@ void _glfwRestoreVideoMode(void)
// Get a list of available video modes
//========================================================================
int _glfwPlatformGetVideoModes(GLFWvidmode* list, int maxcount)
int _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, GLFWvidmode* list, int maxcount)
{
int count, success, mode, i, j;
int m1, m2, bpp, r, g, b;
DEVMODE dm;
DEVMODE deviceMode;
DWORD deviceModeNum;
// Loop through all video modes and extract all the UNIQUE modes
count = 0;
mode = 0;
GLFWvidmode* vidModes;
int vidModesCount;
GLFWvidmode vidMode;
do
deviceMode.dmSize = sizeof(DEVMODE);
deviceModeNum = 0;
vidModes = NULL;
vidModesCount = 0;
for (;;)
{
// Get video mode properties
dm.dmSize = sizeof(DEVMODE);
success = EnumDisplaySettings(NULL, mode, &dm);
if (!EnumDisplaySettings(monitor->Win32.name, deviceModeNum, &deviceMode))
break;
// Is it a valid mode? (only list depths >= 15 bpp)
if (success && dm.dmBitsPerPel >= 15)
{
// Convert to RGB, and back to bpp ("mask out" alpha bits etc)
_glfwSplitBPP(dm.dmBitsPerPel, &r, &g, &b);
bpp = r + g + b;
if (vidModesCount >= maxcount)
break;
// Mode "code" for this mode
m1 = (bpp << 25) | (dm.dmPelsWidth * dm.dmPelsHeight);
deviceModeNum++;
// Insert mode in list (sorted), and avoid duplicates
for (i = 0; i < count; i++)
{
// Mode "code" for already listed mode
bpp = list[i].redBits + list[i].greenBits + list[i].blueBits;
m2 = (bpp << 25) | (list[i].width * list[i].height);
if (m1 <= m2)
break;
}
if (deviceMode.dmBitsPerPel < 15)
continue;
// New entry at the end of the list?
if (i >= count)
{
list[count].width = dm.dmPelsWidth;
list[count].height = dm.dmPelsHeight;
list[count].redBits = r;
list[count].greenBits = g;
list[count].blueBits = b;
count ++;
}
// Insert new entry in the list?
else if (m1 < m2)
{
for (j = count; j > i; j--)
list[j] = list[j - 1];
vidMode.height = deviceMode.dmPelsHeight;
vidMode.width = deviceMode.dmPelsWidth;
// Convert to RGB, and back to bpp ("mask out" alpha bits etc)
_glfwSplitBPP(deviceMode.dmBitsPerPel,
&vidMode.redBits,
&vidMode.greenBits,
&vidMode.blueBits);
list[i].width = dm.dmPelsWidth;
list[i].height = dm.dmPelsHeight;
list[i].redBits = r;
list[i].greenBits = g;
list[i].blueBits = b;
count++;
}
}
mode++;
// skip duplicates.
if (vidModes && bsearch(&vidMode, vidModes, vidModesCount, sizeof(GLFWvidmode), _glfwCompareVideoModes))
continue;
vidModes = realloc(vidModes, sizeof(GLFWvidmode) * ++vidModesCount);
memcpy(vidModes + (vidModesCount - 1), &vidMode, sizeof(GLFWvidmode));
qsort(vidModes, vidModesCount, sizeof(GLFWvidmode), _glfwCompareVideoModes);
}
while (success && (count < maxcount));
return count;
if (list && maxcount)
memcpy(list, vidModes, sizeof(GLFWvidmode) * min(vidModesCount, maxcount));
free(vidModes);
return vidModesCount;
}

View File

@ -165,6 +165,8 @@ int _glfwPlatformInit(void)
_glfwPlatformGetGammaRamp(&_glfwLibrary.originalRamp);
_glfwLibrary.currentRamp = _glfwLibrary.originalRamp;
_glfwInitMonitors();
_glfwInitTimer();
return GL_TRUE;
@ -180,6 +182,8 @@ int _glfwPlatformTerminate(void)
// Restore the original gamma ramp
_glfwPlatformSetGammaRamp(&_glfwLibrary.originalRamp);
_glfwTerminateMonitors();
if (_glfwLibrary.Win32.classAtom)
{
UnregisterClass(_GLFW_WNDCLASSNAME, _glfwLibrary.Win32.instance);

231
src/win32_monitor.c Normal file
View File

@ -0,0 +1,231 @@
//========================================================================
// GLFW - An OpenGL library
// Platform: X11 (Unix)
// API version: 3.0
// WWW: http://www.glfw.org/
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
//
// 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 <string.h>
// The MinGW package for Debian lacks this
#ifndef EDS_ROTATEDMODE
#define EDS_ROTATEDMODE 0x00000004
#endif
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
_GLFWmonitor** _glfwCreateMonitor(_GLFWmonitor** current,
DISPLAY_DEVICE* adapter,
DISPLAY_DEVICE* monitor,
DEVMODE* setting)
{
HDC dc = NULL;
*current = _glfwMalloc(sizeof(_GLFWmonitor));
memset(*current, 0, sizeof(_GLFWmonitor));
dc = CreateDC("DISPLAY", monitor->DeviceString, NULL, NULL);
(*current)->physicalWidth = GetDeviceCaps(dc, HORZSIZE);
(*current)->physicalHeight = GetDeviceCaps(dc, VERTSIZE);
DeleteDC(dc);
(*current)->name = _glfwMalloc(strlen(monitor->DeviceName) + 1);
memcpy((*current)->name, monitor->DeviceName, strlen(monitor->DeviceName) + 1);
(*current)->name[strlen(monitor->DeviceName)] = '\0';
(*current)->screenX = setting->dmPosition.x;
(*current)->screenY = setting->dmPosition.y;
memcpy((*current)->Win32.name, adapter->DeviceName, 32);
return &((*current)->next);
}
_GLFWmonitor* _glfwDestroyMonitor(_GLFWmonitor* monitor)
{
_GLFWmonitor* result;
result = monitor->next;
_glfwFree(monitor->name);
_glfwFree(monitor);
return result;
}
// todo: This is ugly. The platform should only allocate a list of the current devices.
// The platform independent code should be in charge of the handling for the initial
// setup, refreshing and freeing the list.
void _glfwInitMonitors(void)
{
_GLFWmonitor** curMonitor;
DISPLAY_DEVICE adapter;
DWORD adapterNum;
DISPLAY_DEVICE monitor;
DEVMODE setting;
DWORD settingNum;
curMonitor = &_glfwLibrary.monitorListHead;
adapter.cb = sizeof(DISPLAY_DEVICE);
adapterNum = 0;
monitor.cb = sizeof(DISPLAY_DEVICE);
setting.dmSize = sizeof(DEVMODE);
settingNum = 0;
while (EnumDisplayDevices(NULL, adapterNum++, &adapter, 0))
{
if (adapter.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER || !(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
continue;
EnumDisplaySettingsEx(adapter.DeviceName,
ENUM_CURRENT_SETTINGS,
&setting,
EDS_ROTATEDMODE);
EnumDisplayDevices(adapter.DeviceName, 0, &monitor, 0);
curMonitor = _glfwCreateMonitor(curMonitor, &adapter, &monitor, &setting);
}
}
void _glfwRefreshMonitors(void)
{
DISPLAY_DEVICE adapter;
DWORD adapterNum = 0;
DISPLAY_DEVICE monitor;
DEVMODE setting;
_GLFWmonitor* newMonitorList = NULL;
_GLFWmonitor** curMonitor = &newMonitorList;
_GLFWmonitor* curNewMonitor;
_GLFWmonitor* curOldMonitor;
while (EnumDisplayDevices(NULL, adapterNum++, &adapter, 0))
{
if (adapter.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER || !(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
continue;
EnumDisplaySettingsEx(adapter.DeviceName, ENUM_CURRENT_SETTINGS, &setting, EDS_ROTATEDMODE);
EnumDisplayDevices(adapter.DeviceName, 0, &monitor, 0);
curMonitor = _glfwCreateMonitor(curMonitor, &adapter, &monitor, &setting);
}
curNewMonitor = newMonitorList;
curOldMonitor = _glfwLibrary.monitorListHead;
while (_glfwLibrary.monitorCallback && (curNewMonitor || curOldMonitor))
{
_GLFWmonitor* lookAheadOldMonitor;
_GLFWmonitor* lookAheadNewMonitor;
if (curOldMonitor && curNewMonitor && !strcmp(curOldMonitor->name, curOldMonitor->name))
{
curNewMonitor = curNewMonitor->next;
curOldMonitor = curOldMonitor->next;
continue;
}
if (curNewMonitor && !curOldMonitor)
{
_glfwLibrary.monitorCallback(curNewMonitor, GLFW_MONITOR_CONNECTED);
curNewMonitor = curNewMonitor->next;
continue;
}
if (!curNewMonitor && curOldMonitor)
{
_glfwLibrary.monitorCallback(curOldMonitor, GLFW_MONITOR_DISCONNECTED);
curOldMonitor = curOldMonitor->next;
continue;
}
lookAheadOldMonitor = curOldMonitor->next;
lookAheadNewMonitor = curNewMonitor->next;
while (lookAheadOldMonitor && !strcmp(curNewMonitor->name, lookAheadOldMonitor->name))
lookAheadOldMonitor = lookAheadOldMonitor->next;
while (lookAheadNewMonitor && !strcmp(curOldMonitor->name, lookAheadNewMonitor->name))
lookAheadNewMonitor = lookAheadNewMonitor->next;
if (!lookAheadOldMonitor)
{
// nothing found in the old monitor list, that matches the current new monitor.
_glfwLibrary.monitorCallback(curNewMonitor, GLFW_MONITOR_CONNECTED);
curNewMonitor = curNewMonitor->next;
}
else
{
while (strcmp(curOldMonitor->name, lookAheadOldMonitor->name))
{
_glfwLibrary.monitorCallback(curOldMonitor, GLFW_MONITOR_DISCONNECTED);
curOldMonitor = curOldMonitor->next;
}
}
if (!lookAheadNewMonitor)
{
// nothing found in the new monitor list, that matches the current old monitor.
_glfwLibrary.monitorCallback(curOldMonitor, GLFW_MONITOR_DISCONNECTED);
curOldMonitor = curOldMonitor->next;
}
else
{
while (strcmp(curNewMonitor->name, lookAheadNewMonitor->name))
{
_glfwLibrary.monitorCallback(curNewMonitor, GLFW_MONITOR_CONNECTED);
curNewMonitor = curNewMonitor->next;
}
}
}
_glfwTerminateMonitors();
_glfwLibrary.monitorListHead = newMonitorList;
}
void _glfwTerminateMonitors(void)
{
while (_glfwLibrary.monitorListHead)
_glfwLibrary.monitorListHead = _glfwDestroyMonitor(_glfwLibrary.monitorListHead);
}

View File

@ -47,6 +47,7 @@
#include <windows.h>
#include <mmsystem.h>
#include <Dbt.h>
// This path may need to be changed if you build GLFW using your own setup
// We ship and use our own copy of wglext.h since GLFW uses fairly new
@ -210,6 +211,7 @@ typedef DWORD (WINAPI * TIMEGETTIME_T) (void);
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 Win32
#define _GLFW_PLATFORM_LIBRARY_STATE _GLFWlibraryWin32 Win32
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextWGL WGL
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 Win32
//========================================================================
@ -318,6 +320,14 @@ typedef struct _GLFWlibraryWin32
} _GLFWlibraryWin32;
//------------------------------------------------------------------------
// Platform-specific monitor structure
//------------------------------------------------------------------------
typedef struct _GLFWmonitorWin32
{
char name[32];
} _GLFWmonitorWin32;
//========================================================================
// Prototypes for platform specific internal functions
@ -326,6 +336,11 @@ typedef struct _GLFWlibraryWin32
// Time
void _glfwInitTimer(void);
// Monitor support
void _glfwInitMonitors(void);
void _glfwRefreshMonitors(void);
void _glfwTerminateMonitors(void);
// Fullscreen support
void _glfwSetVideoMode(int* width, int* height,
int* bpp, int* refreshRate,

View File

@ -30,7 +30,6 @@
#include "internal.h"
#include <stdio.h>
#include <stdlib.h>
@ -1079,6 +1078,16 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
break;
}
case WM_DEVICECHANGE:
{
if (DBT_DEVNODES_CHANGED == wParam)
{
_glfwRefreshMonitors();
return TRUE;
}
break;
}
}
// Pass all unhandled messages to DefWindowProc
@ -1780,7 +1789,7 @@ void _glfwPlatformPollEvents(void)
window = _glfwLibrary.activeWindow;
if (window)
{
window->Win32.cursorCentered = GL_FALSE;
window->Win32.cursorCentered = GL_TRUE;
window->Win32.oldMouseX = window->width / 2;
window->Win32.oldMouseY = window->height / 2;
}
@ -1902,3 +1911,4 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
}
}

View File

@ -316,11 +316,26 @@ struct _glfwResolution
int height;
};
int _glfwCompareResolution(const void* left, const void* right)
{
int result = 0;
const struct _glfwResolution* leftResolution = left;
const struct _glfwResolution* rightResolution = right;
result = leftResolution->height - rightResolution->height;
if (result == 0)
{
result = leftResolution->width - rightResolution->width;
}
return result;
}
//========================================================================
// List available video modes
//========================================================================
int _glfwPlatformGetVideoModes(GLFWvidmode* list, int maxcount)
int _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, GLFWvidmode* list, int maxcount)
{
int count, k, l, r, g, b, rgba, gl;
int depth, screen;
@ -380,23 +395,37 @@ int _glfwPlatformGetVideoModes(GLFWvidmode* list, int maxcount)
if (_glfwLibrary.X11.RandR.available)
{
#if defined(_GLFW_HAS_XRANDR)
XRRScreenConfiguration* sc;
XRRScreenSize* sizelist;
int sizecount;
XRRScreenResources* resource;
unsigned int a;
resource = XRRGetScreenResources(_glfwLibrary.X11.display, _glfwLibrary.X11.root);
sc = XRRGetScreenInfo(_glfwLibrary.X11.display, _glfwLibrary.X11.root);
sizelist = XRRConfigSizes(sc, &sizecount);
resarray = (struct _glfwResolution*) _glfwMalloc(sizeof(struct _glfwResolution) * monitor->X11.output->nmode);
resarray = (struct _glfwResolution*) _glfwMalloc(sizeof(struct _glfwResolution) * sizecount);
for (k = 0; k < sizecount; k++)
for (k = 0; k < monitor->X11.output->nmode; k++)
{
resarray[rescount].width = sizelist[k].width;
resarray[rescount].height = sizelist[k].height;
rescount++;
for (a = 0; a < resource->nmode; a++)
{
if (resource->modes[a].id != monitor->X11.output->modes[k])
{
continue;
}
struct _glfwResolution res = {
resource->modes[a].width,
resource->modes[a].height
};
if (!bsearch(&res, resarray, rescount, sizeof(struct _glfwResolution), _glfwCompareResolution))
{
resarray[rescount].width = resource->modes[a].width;
resarray[rescount].height = resource->modes[a].height;
rescount++;
qsort(resarray, rescount, sizeof(struct _glfwResolution), _glfwCompareResolution);
}
}
}
XRRFreeScreenConfigInfo(sc);
XRRFreeScreenResources(resource);
#endif /*_GLFW_HAS_XRANDR*/
}
else if (_glfwLibrary.X11.VidMode.available)

View File

@ -578,6 +578,8 @@ int _glfwPlatformInit(void)
_glfwInitJoysticks();
_glfwInitMonitors();
// Start the timer
_glfwInitTimer();
@ -599,6 +601,8 @@ int _glfwPlatformTerminate(void)
terminateDisplay();
_glfwTerminateMonitors();
_glfwTerminateJoysticks();
// Unload libGL.so if necessary

136
src/x11_monitor.c Normal file
View File

@ -0,0 +1,136 @@
//========================================================================
// GLFW - An OpenGL library
// Platform: X11 (Unix)
// API version: 3.0
// WWW: http://www.glfw.org/
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
//
// 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 <string.h>
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
#if defined (_GLFW_HAS_XRANDR)
_GLFWmonitor** _glfwCreateMonitor(_GLFWmonitor** current,
XRROutputInfo* outputInfo,
XRRCrtcInfo* crtcInfo)
{
*current = _glfwMalloc(sizeof(_GLFWmonitor));
memset(*current, 0, sizeof(_GLFWmonitor));
(*current)->physicalWidth = outputInfo->mm_width;
(*current)->physicalHeight = outputInfo->mm_height;
(*current)->name = _glfwMalloc(strlen(outputInfo->name) + 1);
memcpy((*current)->name, outputInfo->name, strlen(outputInfo->name) + 1);
(*current)->name[strlen(outputInfo->name)] = '\0';
(*current)->screenX = crtcInfo->x;
(*current)->screenY = crtcInfo->y;
(*current)->X11.output = outputInfo;
return &((*current)->next);
}
#endif /*_GLFW_HAS_XRANDR*/
_GLFWmonitor* _glfwDestroyMonitor(_GLFWmonitor* monitor)
{
_GLFWmonitor* result;
result = monitor->next;
#if defined (_GLFW_HAS_XRANDR)
XRRFreeOutputInfo(monitor->X11.output);
#endif /*_GLFW_HAS_XRANDR*/
_glfwFree(monitor->name);
_glfwFree(monitor);
return result;
}
void _glfwInitMonitors(void)
{
_glfwLibrary.monitorListHead = NULL;
if (_glfwLibrary.X11.RandR.available)
{
#if defined (_GLFW_HAS_XRANDR)
XRRScreenResources* resources;
int outputIDX;
_GLFWmonitor** curMonitor;
curMonitor = &_glfwLibrary.monitorListHead;
resources = XRRGetScreenResources(_glfwLibrary.X11.display,
_glfwLibrary.X11.root);
for (outputIDX = 0; outputIDX < resources->noutput; outputIDX++)
{
// physical device
XRROutputInfo* outputInfo = NULL;
// logical surface
XRRCrtcInfo* crtcInfo = NULL;
int crtcIDX;
outputInfo = XRRGetOutputInfo(_glfwLibrary.X11.display,
resources,
resources->outputs[outputIDX]);
if (outputInfo->connection == RR_Connected)
{
for (crtcIDX = 0; crtcIDX < outputInfo->ncrtc; crtcIDX++)
{
if (outputInfo->crtc == outputInfo->crtcs[crtcIDX])
{
crtcInfo = XRRGetCrtcInfo(_glfwLibrary.X11.display,
resources,
outputInfo->crtcs[crtcIDX]);
break;
}
}
curMonitor = _glfwCreateMonitor(curMonitor, outputInfo, crtcInfo);
// Freeing of the outputInfo is done in _glfwDestroyMonitor
XRRFreeCrtcInfo(crtcInfo);
}
}
#endif /*_GLFW_HAS_XRANDR*/
}
}
void _glfwTerminateMonitors(void)
{
while (_glfwLibrary.monitorListHead)
_glfwLibrary.monitorListHead = _glfwDestroyMonitor(_glfwLibrary.monitorListHead);
}

View File

@ -91,6 +91,7 @@
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 X11
#define _GLFW_PLATFORM_LIBRARY_STATE _GLFWlibraryX11 X11
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX GLX
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 X11
//========================================================================
@ -247,6 +248,20 @@ GLFWGLOBAL struct {
} _glfwJoy[GLFW_JOYSTICK_LAST + 1];
//------------------------------------------------------------------------
// Platform-specific window structure
//------------------------------------------------------------------------
typedef struct _GLFWmonitorX11
{
#if defined(_GLFW_HAS_XRANDR)
XRROutputInfo* output;
#else
int dummy;
#endif /*_GLFW_HAS_XRANDR*/
} _GLFWmonitorX11;
//========================================================================
// Prototypes for platform specific internal functions
//========================================================================
@ -264,6 +279,10 @@ void _glfwRestoreVideoMode(int screen);
void _glfwInitJoysticks(void);
void _glfwTerminateJoysticks(void);
// Monitors
void _glfwInitMonitors(void);
void _glfwTerminateMonitors(void);
// Unicode support
long _glfwKeySym2Unicode(KeySym keysym);

View File

@ -2,6 +2,12 @@
set(STATIC_DEPS libglfwStatic ${GLFW_LIBRARIES} ${OPENGL_glu_LIBRARY})
set(SHARED_DEPS libglfwShared ${GLFW_LIBRARIES} ${OPENGL_glu_LIBRARY})
if (UNIX AND NOT APPLE AND NOT CYGWIN)
find_library(MATH_LIBRARY m)
find_library(REALTIME_LIBRARY rt)
link_libraries(${MATH_LIBRARY} ${REALTIME_LIBRARY})
endif (UNIX AND NOT APPLE AND NOT CYGWIN)
include_directories(${GLFW_SOURCE_DIR}/include
${GLFW_SOURCE_DIR}/support
${OPENGL_INCLUDE_DIR})

View File

@ -216,6 +216,19 @@ static const char* get_character_string(int character)
return result;
}
static const char* get_monitor_event_name(int event)
{
switch (event)
{
case GLFW_MONITOR_CONNECTED:
return "connected";
case GLFW_MONITOR_DISCONNECTED:
return "disconnected";
}
return NULL;
}
static void window_size_callback(GLFWwindow window, int width, int height)
{
printf("%08x at %0.3f: Window size: %i %i\n",
@ -330,6 +343,16 @@ static void char_callback(GLFWwindow window, int character)
get_character_string(character));
}
void monitor_callback(GLFWmonitor monitor, int event)
{
printf("%08x at %0.3f: Monitor %s %s",
counter++,
glfwGetTime(),
glfwGetMonitorString(monitor, GLFW_MONITOR_NAME),
get_monitor_event_name(event));
}
int main(void)
{
GLFWwindow window;
@ -354,6 +377,7 @@ int main(void)
glfwSetScrollCallback(scroll_callback);
glfwSetKeyCallback(key_callback);
glfwSetCharCallback(char_callback);
glfwSetMonitorDeviceCallback(monitor_callback);
window = glfwOpenWindow(0, 0, GLFW_WINDOWED, "Event Linter", NULL);
if (!window)

View File

@ -18,6 +18,7 @@ static void print_mode(GLFWvidmode* mode)
int main(void)
{
GLFWmonitor monitor;
GLFWvidmode dtmode, modes[400];
int modecount, i;
@ -32,16 +33,30 @@ int main(void)
printf("Desktop mode: ");
print_mode(&dtmode);
// List available video modes
modecount = glfwGetVideoModes(modes, sizeof(modes) / sizeof(GLFWvidmode));
printf("Available modes:\n");
for (i = 0; i < modecount; i++)
monitor = NULL;
while ((monitor = glfwGetNextMonitor(monitor)))
{
printf("%3i: ", i);
print_mode(modes + i);
printf("Monitor name: %s\n"
"Physical dimensions: %dmm x %dmm\n"
"Logical position: (%d,%d)\n",
glfwGetMonitorString(monitor, GLFW_MONITOR_NAME),
glfwGetMonitorParam(monitor, GLFW_MONITOR_PHYSICAL_WIDTH),
glfwGetMonitorParam(monitor, GLFW_MONITOR_PHYSICAL_HEIGHT),
glfwGetMonitorParam(monitor, GLFW_MONITOR_SCREEN_POS_X),
glfwGetMonitorParam(monitor, GLFW_MONITOR_SCREEN_POS_Y));
// List available video modes
modecount = glfwGetVideoModes(monitor, modes, sizeof(modes) / sizeof(GLFWvidmode));
printf("Available modes:\n");
for (i = 0; i < modecount; i++)
{
printf("%3i: ", i);
print_mode(modes + i);
}
}
glfwTerminate();
exit(EXIT_SUCCESS);
}