mirror of
https://github.com/glfw/glfw.git
synced 2024-11-22 13:04:35 +00:00
Cleanup.
This commit is contained in:
parent
83f5b920b9
commit
830f2b439c
@ -529,15 +529,14 @@ GLFWAPI const char* glfwErrorString(int error);
|
|||||||
GLFWAPI void glfwSetErrorCallback(GLFWerrorfun cbfun);
|
GLFWAPI void glfwSetErrorCallback(GLFWerrorfun cbfun);
|
||||||
|
|
||||||
/* Monitor functions */
|
/* Monitor functions */
|
||||||
|
GLFWAPI GLFWmonitor* glfwGetMonitors(int* count);
|
||||||
|
GLFWAPI GLFWmonitor glfwGetPrimaryMonitor(void);
|
||||||
GLFWAPI int glfwGetMonitorParam(GLFWmonitor monitor, int param);
|
GLFWAPI int glfwGetMonitorParam(GLFWmonitor monitor, int param);
|
||||||
GLFWAPI const char* glfwGetMonitorString(GLFWmonitor monitor, int param);
|
GLFWAPI const char* glfwGetMonitorString(GLFWmonitor monitor, int param);
|
||||||
GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor monitor, void* pointer);
|
GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor monitor, void* pointer);
|
||||||
GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor monitor);
|
GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor monitor);
|
||||||
GLFWAPI void glfwSetMonitorCallback(GLFWmonitorfun cbfun);
|
GLFWAPI void glfwSetMonitorCallback(GLFWmonitorfun cbfun);
|
||||||
|
|
||||||
/* Monitor discovery */
|
|
||||||
GLFWAPI GLFWmonitor glfwGetNextMonitor(GLFWmonitor iterator);
|
|
||||||
|
|
||||||
/* Video mode functions */
|
/* Video mode functions */
|
||||||
GLFWAPI GLFWvidmode* glfwGetVideoModes(GLFWmonitor monitor, int* count);
|
GLFWAPI GLFWvidmode* glfwGetVideoModes(GLFWmonitor monitor, int* count);
|
||||||
GLFWAPI void glfwGetVideoMode(GLFWmonitor monitor, GLFWvidmode* mode);
|
GLFWAPI void glfwGetVideoMode(GLFWmonitor monitor, GLFWvidmode* mode);
|
||||||
|
@ -130,6 +130,13 @@ GLFWAPI int glfwInit(void)
|
|||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_glfwLibrary.monitors = _glfwPlatformGetMonitors(&_glfwLibrary.monitorCount);
|
||||||
|
if (!_glfwLibrary.monitors)
|
||||||
|
{
|
||||||
|
_glfwPlatformTerminate();
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
atexit(glfwTerminate);
|
atexit(glfwTerminate);
|
||||||
|
|
||||||
_glfwInitialized = GL_TRUE;
|
_glfwInitialized = GL_TRUE;
|
||||||
@ -151,6 +158,8 @@ GLFWAPI void glfwTerminate(void)
|
|||||||
while (_glfwLibrary.windowListHead)
|
while (_glfwLibrary.windowListHead)
|
||||||
glfwDestroyWindow(_glfwLibrary.windowListHead);
|
glfwDestroyWindow(_glfwLibrary.windowListHead);
|
||||||
|
|
||||||
|
_glfwDestroyMonitors();
|
||||||
|
|
||||||
if (!_glfwPlatformTerminate())
|
if (!_glfwPlatformTerminate())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -206,8 +206,6 @@ struct _GLFWwindow
|
|||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
struct _GLFWmonitor
|
struct _GLFWmonitor
|
||||||
{
|
{
|
||||||
struct _GLFWmonitor* next;
|
|
||||||
|
|
||||||
void* userPointer;
|
void* userPointer;
|
||||||
|
|
||||||
char* name;
|
char* name;
|
||||||
@ -234,7 +232,9 @@ struct _GLFWlibrary
|
|||||||
_GLFWwindow* windowListHead;
|
_GLFWwindow* windowListHead;
|
||||||
_GLFWwindow* activeWindow;
|
_GLFWwindow* activeWindow;
|
||||||
_GLFWwindow* cursorLockWindow;
|
_GLFWwindow* cursorLockWindow;
|
||||||
_GLFWmonitor* monitorListHead;
|
|
||||||
|
_GLFWmonitor** monitors;
|
||||||
|
int monitorCount;
|
||||||
|
|
||||||
GLFWwindowsizefun windowSizeCallback;
|
GLFWwindowsizefun windowSizeCallback;
|
||||||
GLFWwindowclosefun windowCloseCallback;
|
GLFWwindowclosefun windowCloseCallback;
|
||||||
@ -286,6 +286,10 @@ void _glfwPlatformDisableSystemKeys(_GLFWwindow* window);
|
|||||||
void _glfwPlatformSetCursorPos(_GLFWwindow* window, int x, int y);
|
void _glfwPlatformSetCursorPos(_GLFWwindow* window, int x, int y);
|
||||||
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
|
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
|
||||||
|
|
||||||
|
// Monitor support
|
||||||
|
_GLFWmonitor** _glfwPlatformGetMonitors(int* count);
|
||||||
|
void _glfwPlatformDestroyMonitor(_GLFWmonitor* monitor);
|
||||||
|
|
||||||
// Video mode support
|
// Video mode support
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
|
||||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
|
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
|
||||||
@ -357,6 +361,9 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action);
|
|||||||
void _glfwInputCursorMotion(_GLFWwindow* window, int x, int y);
|
void _glfwInputCursorMotion(_GLFWwindow* window, int x, int y);
|
||||||
void _glfwInputCursorEnter(_GLFWwindow* window, int entered);
|
void _glfwInputCursorEnter(_GLFWwindow* window, int entered);
|
||||||
|
|
||||||
|
// Monitor event notification (monitor.c)
|
||||||
|
void _glfwInputMonitorChange(void);
|
||||||
|
|
||||||
|
|
||||||
//========================================================================
|
//========================================================================
|
||||||
// Prototypes for internal utility functions
|
// Prototypes for internal utility functions
|
||||||
@ -385,8 +392,10 @@ GLboolean _glfwIsValidContextConfig(_GLFWwndconfig* wndconfig);
|
|||||||
GLboolean _glfwIsValidContext(_GLFWwndconfig* wndconfig);
|
GLboolean _glfwIsValidContext(_GLFWwndconfig* wndconfig);
|
||||||
|
|
||||||
// Monitor management (monitor.c)
|
// Monitor management (monitor.c)
|
||||||
void _glfwInitMonitors(void);
|
_GLFWmonitor* _glfwCreateMonitor(const char* name,
|
||||||
void _glfwRefreshMonitors(void);
|
int physicalWidth, int physicalHeight,
|
||||||
void _glfwTerminateMonitors(void);
|
int screenX, int screenY);
|
||||||
|
void _glfwDestroyMonitor(_GLFWmonitor* monitor);
|
||||||
|
void _glfwDestroyMonitors(void);
|
||||||
|
|
||||||
#endif // _internal_h_
|
#endif // _internal_h_
|
||||||
|
187
src/monitor.c
187
src/monitor.c
@ -31,6 +31,7 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@ -38,108 +39,115 @@
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//========================================================================
|
//========================================================================
|
||||||
// Initialize the monitor list
|
// Create a monitor struct from the specified information
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
void _glfwInitMonitors(void)
|
_GLFWmonitor* _glfwCreateMonitor(const char* name,
|
||||||
|
int physicalWidth, int physicalHeight,
|
||||||
|
int screenX, int screenY)
|
||||||
{
|
{
|
||||||
_glfwLibrary.monitorListHead = _glfwCreateMonitors();
|
_GLFWmonitor* monitor = (_GLFWmonitor*) calloc(1, sizeof(_GLFWmonitor));
|
||||||
|
if (!monitor)
|
||||||
|
{
|
||||||
|
_glfwSetError(GLFW_OUT_OF_MEMORY, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor->name = strdup(name);
|
||||||
|
monitor->physicalWidth = physicalWidth;
|
||||||
|
monitor->physicalHeight = physicalHeight;
|
||||||
|
monitor->screenX = screenX;
|
||||||
|
monitor->screenY = screenY;
|
||||||
|
|
||||||
|
return monitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//========================================================================
|
//========================================================================
|
||||||
// Refresh monitor list and notify callback
|
// Destroy the specified monitor
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
void _glfwRefreshMonitors(void)
|
void _glfwDestroyMonitor(_GLFWmonitor* monitor)
|
||||||
{
|
{
|
||||||
_GLFWmonitor* newMonitorList;
|
if (monitor == NULL)
|
||||||
_GLFWmonitor* curNewMonitor;
|
return;
|
||||||
_GLFWmonitor* curOldMonitor;
|
|
||||||
|
|
||||||
newMonitorList = _glfwCreateMonitors();
|
_glfwPlatformDestroyMonitor(monitor);
|
||||||
curNewMonitor = newMonitorList;
|
|
||||||
curOldMonitor = _glfwLibrary.monitorListHead;
|
|
||||||
|
|
||||||
while (_glfwLibrary.monitorCallback && (curNewMonitor || curOldMonitor))
|
free(monitor->modes);
|
||||||
|
free(monitor->name);
|
||||||
|
free(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//========================================================================
|
||||||
|
// Enumerate monitors and notify user of changes
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
void _glfwInputMonitorChange(void)
|
||||||
{
|
{
|
||||||
_GLFWmonitor* lookAheadOldMonitor;
|
int i, j, monitorCount;
|
||||||
_GLFWmonitor* lookAheadNewMonitor;
|
_GLFWmonitor** monitors;
|
||||||
|
|
||||||
if (curOldMonitor && curNewMonitor && !strcmp(curOldMonitor->name, curOldMonitor->name))
|
monitors = _glfwPlatformGetMonitors(&monitorCount);
|
||||||
|
|
||||||
|
for (i = 0; i < monitorCount; i++)
|
||||||
{
|
{
|
||||||
curNewMonitor = curNewMonitor->next;
|
for (j = 0; j < _glfwLibrary.monitorCount; j++)
|
||||||
curOldMonitor = curOldMonitor->next;
|
{
|
||||||
|
if (_glfwLibrary.monitors[j] == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (strcmp(monitors[i]->name, _glfwLibrary.monitors[j]->name) == 0)
|
||||||
|
{
|
||||||
|
// This monitor was connected before, so re-use the existing
|
||||||
|
// monitor object to preserve its address and user pointer
|
||||||
|
|
||||||
|
_glfwDestroyMonitor(monitors[i]);
|
||||||
|
monitors[i] = _glfwLibrary.monitors[j];
|
||||||
|
_glfwLibrary.monitors[j] = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curNewMonitor && !curOldMonitor)
|
if (j == _glfwLibrary.monitorCount)
|
||||||
{
|
{
|
||||||
_glfwLibrary.monitorCallback(curNewMonitor, GLFW_MONITOR_CONNECTED);
|
// This monitor was not connected before
|
||||||
curNewMonitor = curNewMonitor->next;
|
_glfwLibrary.monitorCallback(monitors[i], GLFW_MONITOR_CONNECTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < _glfwLibrary.monitorCount; i++)
|
||||||
|
{
|
||||||
|
if (_glfwLibrary.monitors[i] == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// This monitor is no longer connected
|
||||||
|
_glfwLibrary.monitorCallback(_glfwLibrary.monitors[i],
|
||||||
|
GLFW_MONITOR_DISCONNECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!curNewMonitor && curOldMonitor)
|
_glfwDestroyMonitors();
|
||||||
{
|
|
||||||
_glfwLibrary.monitorCallback(curOldMonitor, GLFW_MONITOR_DISCONNECTED);
|
|
||||||
curOldMonitor = curOldMonitor->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
lookAheadOldMonitor = curOldMonitor->next;
|
_glfwLibrary.monitors = monitors;
|
||||||
lookAheadNewMonitor = curNewMonitor->next;
|
_glfwLibrary.monitorCount = monitorCount;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//========================================================================
|
//========================================================================
|
||||||
// Delete the monitor list
|
// Destroy all monitors
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
void _glfwTerminateMonitors(void)
|
void _glfwDestroyMonitors(void)
|
||||||
{
|
{
|
||||||
while (_glfwLibrary.monitorListHead)
|
int i;
|
||||||
_glfwLibrary.monitorListHead = _glfwDestroyMonitor(_glfwLibrary.monitorListHead);
|
|
||||||
|
for (i = 0; i < _glfwLibrary.monitorCount; i++)
|
||||||
|
_glfwDestroyMonitor(_glfwLibrary.monitors[i]);
|
||||||
|
|
||||||
|
free(_glfwLibrary.monitors);
|
||||||
|
_glfwLibrary.monitors = NULL;
|
||||||
|
_glfwLibrary.monitorCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -148,26 +156,41 @@ void _glfwTerminateMonitors(void)
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//========================================================================
|
//========================================================================
|
||||||
// Iterate through connected monitors
|
// Return the currently connected monitors
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
GLFWAPI GLFWmonitor glfwGetNextMonitor(GLFWmonitor handle)
|
GLFWAPI GLFWmonitor* glfwGetMonitors(int* count)
|
||||||
{
|
{
|
||||||
_GLFWmonitor* iterator = (_GLFWmonitor*) handle;
|
|
||||||
_GLFWmonitor* result;
|
|
||||||
|
|
||||||
if (!_glfwInitialized)
|
if (!_glfwInitialized)
|
||||||
{
|
{
|
||||||
_glfwSetError(GLFW_NOT_INITIALIZED, NULL);
|
_glfwSetError(GLFW_NOT_INITIALIZED, NULL);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iterator == NULL)
|
if (count == NULL)
|
||||||
result = _glfwLibrary.monitorListHead;
|
{
|
||||||
else
|
_glfwSetError(GLFW_INVALID_VALUE, NULL);
|
||||||
result = iterator->next;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
*count = _glfwLibrary.monitorCount;
|
||||||
|
return (GLFWmonitor*) _glfwLibrary.monitors;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//========================================================================
|
||||||
|
// Get the primary monitor
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
GLFWAPI GLFWmonitor glfwGetPrimaryMonitor(void)
|
||||||
|
{
|
||||||
|
if (!_glfwInitialized)
|
||||||
|
{
|
||||||
|
_glfwSetError(GLFW_NOT_INITIALIZED, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _glfwLibrary.monitors[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -185,16 +185,8 @@ void _glfwRestoreVideoMode(void)
|
|||||||
|
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||||
{
|
{
|
||||||
int deviceModeIndex = 0, count = 0;
|
int modeIndex = 0, count = 0;
|
||||||
GLFWvidmode* result = NULL;
|
GLFWvidmode* result = NULL;
|
||||||
WCHAR* deviceName;
|
|
||||||
|
|
||||||
deviceName = _glfwCreateWideStringFromUTF8(monitor->Win32.name);
|
|
||||||
if (!deviceName)
|
|
||||||
{
|
|
||||||
_glfwSetError(GLFW_PLATFORM_ERROR, "Win32: Failed to convert device name");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
*found = 0;
|
*found = 0;
|
||||||
|
|
||||||
@ -207,10 +199,10 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
|||||||
ZeroMemory(&dm, sizeof(DEVMODE));
|
ZeroMemory(&dm, sizeof(DEVMODE));
|
||||||
dm.dmSize = sizeof(DEVMODE);
|
dm.dmSize = sizeof(DEVMODE);
|
||||||
|
|
||||||
if (!EnumDisplaySettings(deviceName, deviceModeIndex, &dm))
|
if (!EnumDisplaySettings(monitor->Win32.name, modeIndex, &dm))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
deviceModeIndex++;
|
modeIndex++;
|
||||||
|
|
||||||
if (dm.dmBitsPerPel < 15)
|
if (dm.dmBitsPerPel < 15)
|
||||||
{
|
{
|
||||||
@ -262,7 +254,6 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
|||||||
(*found)++;
|
(*found)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(deviceName);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,19 +265,11 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
|||||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||||
{
|
{
|
||||||
DEVMODE dm;
|
DEVMODE dm;
|
||||||
WCHAR* deviceName;
|
|
||||||
|
|
||||||
deviceName = _glfwCreateWideStringFromUTF8(monitor->Win32.name);
|
|
||||||
if (!deviceName)
|
|
||||||
{
|
|
||||||
_glfwSetError(GLFW_PLATFORM_ERROR, "Win32: Failed to convert device name");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZeroMemory(&dm, sizeof(DEVMODE));
|
ZeroMemory(&dm, sizeof(DEVMODE));
|
||||||
dm.dmSize = sizeof(DEVMODE);
|
dm.dmSize = sizeof(DEVMODE);
|
||||||
|
|
||||||
EnumDisplaySettings(deviceName, ENUM_REGISTRY_SETTINGS, &dm);
|
EnumDisplaySettings(monitor->Win32.name, ENUM_REGISTRY_SETTINGS, &dm);
|
||||||
|
|
||||||
mode->width = dm.dmPelsWidth;
|
mode->width = dm.dmPelsWidth;
|
||||||
mode->height = dm.dmPelsHeight;
|
mode->height = dm.dmPelsHeight;
|
||||||
|
@ -178,8 +178,6 @@ int _glfwPlatformInit(void)
|
|||||||
_glfwPlatformGetGammaRamp(&_glfwLibrary.originalRamp);
|
_glfwPlatformGetGammaRamp(&_glfwLibrary.originalRamp);
|
||||||
_glfwLibrary.currentRamp = _glfwLibrary.originalRamp;
|
_glfwLibrary.currentRamp = _glfwLibrary.originalRamp;
|
||||||
|
|
||||||
_glfwInitMonitors();
|
|
||||||
|
|
||||||
_glfwInitTimer();
|
_glfwInitTimer();
|
||||||
|
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
@ -196,8 +194,6 @@ int _glfwPlatformTerminate(void)
|
|||||||
if (_glfwLibrary.rampChanged)
|
if (_glfwLibrary.rampChanged)
|
||||||
_glfwPlatformSetGammaRamp(&_glfwLibrary.originalRamp);
|
_glfwPlatformSetGammaRamp(&_glfwLibrary.originalRamp);
|
||||||
|
|
||||||
_glfwTerminateMonitors();
|
|
||||||
|
|
||||||
if (_glfwLibrary.Win32.classAtom)
|
if (_glfwLibrary.Win32.classAtom)
|
||||||
{
|
{
|
||||||
UnregisterClass(_GLFW_WNDCLASSNAME, _glfwLibrary.Win32.instance);
|
UnregisterClass(_GLFW_WNDCLASSNAME, _glfwLibrary.Win32.instance);
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
// The MinGW package for Debian lacks this
|
// The MinGW package for Debian lacks this
|
||||||
#ifndef EDS_ROTATEDMODE
|
#ifndef EDS_ROTATEDMODE
|
||||||
@ -49,34 +50,102 @@
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//========================================================================
|
//========================================================================
|
||||||
// Create a monitor struct from the specified information
|
// Return a list of available monitors
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
_GLFWmonitor** _glfwCreateMonitor(_GLFWmonitor** current,
|
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
||||||
DISPLAY_DEVICE* adapter,
|
|
||||||
DISPLAY_DEVICE* monitor,
|
|
||||||
DEVMODE* setting)
|
|
||||||
{
|
{
|
||||||
HDC dc = NULL;
|
int size = 0, found = 0;
|
||||||
|
_GLFWmonitor** monitors = NULL;
|
||||||
|
DWORD adapterIndex = 0;
|
||||||
|
|
||||||
*current = malloc(sizeof(_GLFWmonitor));
|
for (;;)
|
||||||
memset(*current, 0, sizeof(_GLFWmonitor));
|
{
|
||||||
|
DISPLAY_DEVICE adapter;
|
||||||
|
DWORD monitorIndex = 0;
|
||||||
|
|
||||||
dc = CreateDC(L"DISPLAY", monitor->DeviceString, NULL, NULL);
|
ZeroMemory(&adapter, sizeof(DISPLAY_DEVICE));
|
||||||
|
adapter.cb = sizeof(DISPLAY_DEVICE);
|
||||||
|
|
||||||
(*current)->physicalWidth = GetDeviceCaps(dc, HORZSIZE);
|
if (!EnumDisplayDevices(NULL, adapterIndex, &adapter, 0))
|
||||||
(*current)->physicalHeight = GetDeviceCaps(dc, VERTSIZE);
|
break;
|
||||||
|
|
||||||
|
adapterIndex++;
|
||||||
|
|
||||||
|
if ((adapter.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) ||
|
||||||
|
!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
DISPLAY_DEVICE monitor;
|
||||||
|
DEVMODE settings;
|
||||||
|
const char* name;
|
||||||
|
HDC dc;
|
||||||
|
|
||||||
|
ZeroMemory(&monitor, sizeof(DISPLAY_DEVICE));
|
||||||
|
monitor.cb = sizeof(DISPLAY_DEVICE);
|
||||||
|
|
||||||
|
if (!EnumDisplayDevices(adapter.DeviceName, monitorIndex, &monitor, 0))
|
||||||
|
break;
|
||||||
|
|
||||||
|
ZeroMemory(&settings, sizeof(DEVMODE));
|
||||||
|
settings.dmSize = sizeof(DEVMODE);
|
||||||
|
|
||||||
|
EnumDisplaySettingsEx(adapter.DeviceName,
|
||||||
|
ENUM_CURRENT_SETTINGS,
|
||||||
|
&settings,
|
||||||
|
EDS_ROTATEDMODE);
|
||||||
|
|
||||||
|
name = _glfwCreateUTF8FromWideString(monitor.DeviceName);
|
||||||
|
if (!name)
|
||||||
|
{
|
||||||
|
// TODO: wat
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dc = CreateDC(L"DISPLAY", monitor.DeviceString, NULL, NULL);
|
||||||
|
if (!dc)
|
||||||
|
{
|
||||||
|
// TODO: wat
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found == size)
|
||||||
|
{
|
||||||
|
if (size)
|
||||||
|
size *= 2;
|
||||||
|
else
|
||||||
|
size = 4;
|
||||||
|
|
||||||
|
monitors = (_GLFWmonitor**) realloc(monitors, sizeof(_GLFWmonitor*) * size);
|
||||||
|
}
|
||||||
|
|
||||||
|
monitors[found] = _glfwCreateMonitor(name,
|
||||||
|
GetDeviceCaps(dc, HORZSIZE),
|
||||||
|
GetDeviceCaps(dc, VERTSIZE),
|
||||||
|
settings.dmPosition.x,
|
||||||
|
settings.dmPosition.y);
|
||||||
|
|
||||||
DeleteDC(dc);
|
DeleteDC(dc);
|
||||||
|
|
||||||
(*current)->name = _glfwCreateUTF8FromWideString(monitor->DeviceName);
|
if (!monitors[found])
|
||||||
|
{
|
||||||
|
// TODO: wat
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
(*current)->screenX = setting->dmPosition.x;
|
monitors[found]->Win32.name = wcsdup(monitor.DeviceName);
|
||||||
(*current)->screenY = setting->dmPosition.y;
|
|
||||||
|
|
||||||
(*current)->Win32.name = _glfwCreateUTF8FromWideString(adapter->DeviceName);
|
found++;
|
||||||
|
monitorIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &((*current)->next);
|
*count = found;
|
||||||
|
return monitors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -84,55 +153,8 @@ _GLFWmonitor** _glfwCreateMonitor(_GLFWmonitor** current,
|
|||||||
// Destroy a monitor struct
|
// Destroy a monitor struct
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
_GLFWmonitor* _glfwDestroyMonitor(_GLFWmonitor* monitor)
|
void _glfwPlatformDestroyMonitor(_GLFWmonitor* monitor)
|
||||||
{
|
{
|
||||||
_GLFWmonitor* result;
|
|
||||||
|
|
||||||
result = monitor->next;
|
|
||||||
|
|
||||||
free(monitor->Win32.name);
|
free(monitor->Win32.name);
|
||||||
free(monitor->name);
|
|
||||||
free(monitor);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//========================================================================
|
|
||||||
// Return a list of available monitors
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
_GLFWmonitor* _glfwCreateMonitors(void)
|
|
||||||
{
|
|
||||||
DISPLAY_DEVICE adapter;
|
|
||||||
DWORD adapterNum;
|
|
||||||
DISPLAY_DEVICE monitor;
|
|
||||||
DEVMODE setting;
|
|
||||||
_GLFWmonitor* monitorList;
|
|
||||||
_GLFWmonitor** curMonitor;
|
|
||||||
|
|
||||||
adapter.cb = sizeof(DISPLAY_DEVICE);
|
|
||||||
adapterNum = 0;
|
|
||||||
monitor.cb = sizeof(DISPLAY_DEVICE);
|
|
||||||
setting.dmSize = sizeof(DEVMODE);
|
|
||||||
monitorList = NULL;
|
|
||||||
curMonitor = &monitorList;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return monitorList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ typedef struct _GLFWlibraryWin32
|
|||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
typedef struct _GLFWmonitorWin32
|
typedef struct _GLFWmonitorWin32
|
||||||
{
|
{
|
||||||
char* name;
|
WCHAR* name;
|
||||||
|
|
||||||
} _GLFWmonitorWin32;
|
} _GLFWmonitorWin32;
|
||||||
|
|
||||||
@ -244,10 +244,6 @@ char* _glfwCreateUTF8FromWideString(const WCHAR* source);
|
|||||||
// Time
|
// Time
|
||||||
void _glfwInitTimer(void);
|
void _glfwInitTimer(void);
|
||||||
|
|
||||||
// Monitor support
|
|
||||||
_GLFWmonitor* _glfwCreateMonitors(void);
|
|
||||||
_GLFWmonitor* _glfwDestroyMonitor(_GLFWmonitor* monitor);
|
|
||||||
|
|
||||||
// OpenGL support
|
// OpenGL support
|
||||||
int _glfwCreateContext(_GLFWwindow* window,
|
int _glfwCreateContext(_GLFWwindow* window,
|
||||||
const _GLFWwndconfig* wndconfig,
|
const _GLFWwndconfig* wndconfig,
|
||||||
|
@ -670,7 +670,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
{
|
{
|
||||||
if (DBT_DEVNODES_CHANGED == wParam)
|
if (DBT_DEVNODES_CHANGED == wParam)
|
||||||
{
|
{
|
||||||
_glfwRefreshMonitors();
|
_glfwInputMonitorChange();
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -651,8 +651,6 @@ int _glfwPlatformInit(void)
|
|||||||
if (!_glfwInitJoysticks())
|
if (!_glfwInitJoysticks())
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
|
|
||||||
_glfwInitMonitors();
|
|
||||||
|
|
||||||
// Start the timer
|
// Start the timer
|
||||||
_glfwInitTimer();
|
_glfwInitTimer();
|
||||||
|
|
||||||
@ -676,8 +674,6 @@ int _glfwPlatformTerminate(void)
|
|||||||
|
|
||||||
terminateDisplay();
|
terminateDisplay();
|
||||||
|
|
||||||
_glfwTerminateMonitors();
|
|
||||||
|
|
||||||
_glfwTerminateJoysticks();
|
_glfwTerminateJoysticks();
|
||||||
|
|
||||||
_glfwTerminateOpenGL();
|
_glfwTerminateOpenGL();
|
||||||
|
@ -34,111 +34,83 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
//========================================================================
|
|
||||||
// Create a monitor struct from the specified information
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#if defined (_GLFW_HAS_XRANDR)
|
|
||||||
static _GLFWmonitor** createMonitor(_GLFWmonitor** current,
|
|
||||||
XRROutputInfo* outputInfo,
|
|
||||||
XRRCrtcInfo* crtcInfo)
|
|
||||||
{
|
|
||||||
*current = malloc(sizeof(_GLFWmonitor));
|
|
||||||
memset(*current, 0, sizeof(_GLFWmonitor));
|
|
||||||
|
|
||||||
(*current)->physicalWidth = outputInfo->mm_width;
|
|
||||||
(*current)->physicalHeight = outputInfo->mm_height;
|
|
||||||
|
|
||||||
(*current)->name = strdup(outputInfo->name);
|
|
||||||
|
|
||||||
(*current)->screenX = crtcInfo->x;
|
|
||||||
(*current)->screenY = crtcInfo->y;
|
|
||||||
|
|
||||||
(*current)->X11.output = outputInfo;
|
|
||||||
return &((*current)->next);
|
|
||||||
}
|
|
||||||
#endif /*_GLFW_HAS_XRANDR*/
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//========================================================================
|
|
||||||
// Destroy a monitor struct
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
_GLFWmonitor* _glfwDestroyMonitor(_GLFWmonitor* monitor)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* result;
|
|
||||||
|
|
||||||
result = monitor->next;
|
|
||||||
|
|
||||||
#if defined (_GLFW_HAS_XRANDR)
|
|
||||||
XRRFreeOutputInfo(monitor->X11.output);
|
|
||||||
#endif /*_GLFW_HAS_XRANDR*/
|
|
||||||
|
|
||||||
free(monitor->modes);
|
|
||||||
free(monitor->name);
|
|
||||||
free(monitor);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//========================================================================
|
//========================================================================
|
||||||
// Return a list of available monitors
|
// Return a list of available monitors
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
_GLFWmonitor* _glfwCreateMonitors(void)
|
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
||||||
{
|
{
|
||||||
_GLFWmonitor* monitorList = NULL;
|
int found = 0;
|
||||||
|
_GLFWmonitor** monitors = NULL;
|
||||||
|
|
||||||
if (_glfwLibrary.X11.RandR.available)
|
if (_glfwLibrary.X11.RandR.available)
|
||||||
{
|
{
|
||||||
#if defined (_GLFW_HAS_XRANDR)
|
#if defined (_GLFW_HAS_XRANDR)
|
||||||
int oi;
|
int i;
|
||||||
XRRScreenResources* resources;
|
XRRScreenResources* sr;
|
||||||
_GLFWmonitor** monitor = &monitorList;
|
|
||||||
|
|
||||||
resources = XRRGetScreenResources(_glfwLibrary.X11.display,
|
sr = XRRGetScreenResources(_glfwLibrary.X11.display,
|
||||||
_glfwLibrary.X11.root);
|
_glfwLibrary.X11.root);
|
||||||
|
|
||||||
for (oi = 0; oi < resources->noutput; oi++)
|
monitors = (_GLFWmonitor**) calloc(sr->noutput, sizeof(_GLFWmonitor*));
|
||||||
|
if (!monitors)
|
||||||
{
|
{
|
||||||
// physical device
|
_glfwSetError(GLFW_OUT_OF_MEMORY, NULL);
|
||||||
XRROutputInfo* outputInfo = NULL;
|
return NULL;
|
||||||
// logical surface
|
|
||||||
XRRCrtcInfo* crtcInfo = NULL;
|
|
||||||
|
|
||||||
outputInfo = XRRGetOutputInfo(_glfwLibrary.X11.display,
|
|
||||||
resources,
|
|
||||||
resources->outputs[oi]);
|
|
||||||
|
|
||||||
if (outputInfo->connection == RR_Connected)
|
|
||||||
{
|
|
||||||
int ci;
|
|
||||||
|
|
||||||
for (ci = 0; ci < outputInfo->ncrtc; ci++)
|
|
||||||
{
|
|
||||||
if (outputInfo->crtc == outputInfo->crtcs[ci])
|
|
||||||
{
|
|
||||||
crtcInfo = XRRGetCrtcInfo(_glfwLibrary.X11.display,
|
|
||||||
resources,
|
|
||||||
outputInfo->crtcs[ci]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
monitor = createMonitor(monitor, outputInfo, crtcInfo);
|
for (i = 0; i < sr->noutput; i++)
|
||||||
|
{
|
||||||
|
XRROutputInfo* oi;
|
||||||
|
XRRCrtcInfo* ci;
|
||||||
|
|
||||||
// Freeing of the outputInfo is done in _glfwDestroyMonitor
|
oi = XRRGetOutputInfo(_glfwLibrary.X11.display, sr, sr->outputs[i]);
|
||||||
XRRFreeCrtcInfo(crtcInfo);
|
if (oi->connection != RR_Connected)
|
||||||
|
{
|
||||||
|
XRRFreeOutputInfo(oi);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ci = XRRGetCrtcInfo(_glfwLibrary.X11.display, sr, oi->crtc);
|
||||||
|
|
||||||
|
monitors[found] = _glfwCreateMonitor(oi->name,
|
||||||
|
oi->mm_width, oi->mm_height,
|
||||||
|
ci->x, ci->y);
|
||||||
|
|
||||||
|
XRRFreeCrtcInfo(ci);
|
||||||
|
|
||||||
|
if (!monitors[found])
|
||||||
|
{
|
||||||
|
// TODO: wat
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is retained until the monitor object is destroyed
|
||||||
|
monitors[found]->X11.output = oi;
|
||||||
|
|
||||||
|
found++;
|
||||||
}
|
}
|
||||||
#endif /*_GLFW_HAS_XRANDR*/
|
#endif /*_GLFW_HAS_XRANDR*/
|
||||||
}
|
}
|
||||||
|
|
||||||
return monitorList;
|
*count = found;
|
||||||
|
return monitors;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//========================================================================
|
||||||
|
// Destroy a monitor struct
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
void _glfwPlatformDestroyMonitor(_GLFWmonitor* monitor)
|
||||||
|
{
|
||||||
|
#if defined (_GLFW_HAS_XRANDR)
|
||||||
|
XRRFreeOutputInfo(monitor->X11.output);
|
||||||
|
#endif /*_GLFW_HAS_XRANDR*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,10 +325,6 @@ void _glfwRestoreVideoMode(void);
|
|||||||
int _glfwInitJoysticks(void);
|
int _glfwInitJoysticks(void);
|
||||||
void _glfwTerminateJoysticks(void);
|
void _glfwTerminateJoysticks(void);
|
||||||
|
|
||||||
// Monitors
|
|
||||||
_GLFWmonitor* _glfwCreateMonitors(void);
|
|
||||||
_GLFWmonitor* _glfwDestroyMonitor(_GLFWmonitor* monitor);
|
|
||||||
|
|
||||||
// Unicode support
|
// Unicode support
|
||||||
long _glfwKeySym2Unicode(KeySym keysym);
|
long _glfwKeySym2Unicode(KeySym keysym);
|
||||||
|
|
||||||
|
@ -810,7 +810,7 @@ static void processEvent(XEvent *event)
|
|||||||
case RRScreenChangeNotify:
|
case RRScreenChangeNotify:
|
||||||
{
|
{
|
||||||
XRRUpdateConfiguration(event);
|
XRRUpdateConfiguration(event);
|
||||||
_glfwRefreshMonitors();
|
_glfwInputMonitorChange();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ int main(int argc, char** argv)
|
|||||||
if (mode == GLFW_FULLSCREEN)
|
if (mode == GLFW_FULLSCREEN)
|
||||||
{
|
{
|
||||||
GLFWvidmode mode;
|
GLFWvidmode mode;
|
||||||
glfwGetVideoMode(glfwGetNextMonitor(NULL), &mode);
|
glfwGetVideoMode(glfwGetPrimaryMonitor(), &mode);
|
||||||
width = mode.width;
|
width = mode.width;
|
||||||
height = mode.height;
|
height = mode.height;
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ int main(int argc, char** argv)
|
|||||||
if (mode == GLFW_FULLSCREEN)
|
if (mode == GLFW_FULLSCREEN)
|
||||||
{
|
{
|
||||||
GLFWvidmode current_mode;
|
GLFWvidmode current_mode;
|
||||||
glfwGetVideoMode(glfwGetNextMonitor(NULL), ¤t_mode);
|
glfwGetVideoMode(glfwGetPrimaryMonitor(), ¤t_mode);
|
||||||
width = current_mode.width;
|
width = current_mode.width;
|
||||||
height = current_mode.height;
|
height = current_mode.height;
|
||||||
}
|
}
|
||||||
|
@ -199,8 +199,8 @@ static void test_modes(GLFWmonitor monitor)
|
|||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
int ch, mode = LIST_MODE;
|
int ch, i, count, mode = LIST_MODE;
|
||||||
GLFWmonitor monitor = NULL;
|
GLFWmonitor* monitors;
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "th")) != -1)
|
while ((ch = getopt(argc, argv, "th")) != -1)
|
||||||
{
|
{
|
||||||
@ -226,12 +226,14 @@ int main(int argc, char** argv)
|
|||||||
if (!glfwInit())
|
if (!glfwInit())
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
while ((monitor = glfwGetNextMonitor(monitor)))
|
monitors = glfwGetMonitors(&count);
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
if (mode == LIST_MODE)
|
if (mode == LIST_MODE)
|
||||||
list_modes(monitor);
|
list_modes(monitors[i]);
|
||||||
else if (mode == TEST_MODE)
|
else if (mode == TEST_MODE)
|
||||||
test_modes(monitor);
|
test_modes(monitors[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
|
Loading…
Reference in New Issue
Block a user