Initial multi-window support pass.

This commit is contained in:
Camilla Berglund 2010-09-10 00:06:23 +02:00
parent 93046aecd0
commit 326d997c1c
4 changed files with 145 additions and 39 deletions

View File

@ -140,6 +140,8 @@ typedef struct _GLFWfbconfig
//------------------------------------------------------------------------ //------------------------------------------------------------------------
typedef struct _GLFWwindow typedef struct _GLFWwindow
{ {
struct _GLFWwindow* next;
// User callback functions // User callback functions
GLFWwindowsizefun windowSizeCallback; GLFWwindowsizefun windowSizeCallback;
GLFWwindowclosefun windowCloseCallback; GLFWwindowclosefun windowCloseCallback;
@ -153,6 +155,7 @@ typedef struct _GLFWwindow
// Window settings and state // Window settings and state
GLboolean active; // GL_TRUE if this window is active GLboolean active; // GL_TRUE if this window is active
GLboolean iconified; // GL_TRUE if this window is iconified GLboolean iconified; // GL_TRUE if this window is iconified
GLboolean closed; // GL_TRUE if this window should be closed
int width, height; int width, height;
int mode; // GLFW_WINDOW or GLFW_FULLSCREEN int mode; // GLFW_WINDOW or GLFW_FULLSCREEN
GLboolean sysKeysDisabled; // system keys disabled flag GLboolean sysKeysDisabled; // system keys disabled flag
@ -202,7 +205,8 @@ typedef struct _GLFWwindow
typedef struct _GLFWlibrary typedef struct _GLFWlibrary
{ {
_GLFWhints hints; _GLFWhints hints;
_GLFWwindow* window;
_GLFWwindow* windowListHead;
_GLFWwindow* currentWindow; _GLFWwindow* currentWindow;
_GLFWwindow* cursorLockWindow; _GLFWwindow* cursorLockWindow;

View File

@ -381,13 +381,6 @@ GLFWAPI GLFWwindow glfwOpenWindow(int width, int height, int mode)
return NULL; return NULL;
} }
if (_glfwLibrary.window)
{
// TODO: Remove this once multi-window is completed
_glfwSetError(GLFW_INTERNAL_ERROR);
return NULL;
}
window = (_GLFWwindow*) malloc(sizeof(_GLFWwindow)); window = (_GLFWwindow*) malloc(sizeof(_GLFWwindow));
if (!window) if (!window)
{ {
@ -395,7 +388,8 @@ GLFWAPI GLFWwindow glfwOpenWindow(int width, int height, int mode)
return NULL; return NULL;
} }
_glfwLibrary.window = window; window->next = _glfwLibrary.windowListHead;
_glfwLibrary.windowListHead = window;
memset(window, 0, sizeof(_GLFWwindow)); memset(window, 0, sizeof(_GLFWwindow));
@ -579,6 +573,8 @@ GLFWAPI void glfwMakeWindowCurrent(GLFWwindow window)
GLFWAPI int glfwIsWindow(GLFWwindow window) GLFWAPI int glfwIsWindow(GLFWwindow window)
{ {
_GLFWwindow* entry;
if (!_glfwInitialized) if (!_glfwInitialized)
{ {
_glfwSetError(GLFW_NOT_INITIALIZED); _glfwSetError(GLFW_NOT_INITIALIZED);
@ -588,7 +584,13 @@ GLFWAPI int glfwIsWindow(GLFWwindow window)
if (window == NULL) if (window == NULL)
return GL_FALSE; return GL_FALSE;
return (window == _glfwLibrary.window) ? GL_TRUE : GL_FALSE; for (entry = _glfwLibrary.windowListHead; entry; entry = entry->next)
{
if (entry == window)
return GL_TRUE;
}
return GL_FALSE;
} }
@ -678,6 +680,8 @@ GLFWAPI void glfwOpenWindowHint(int target, int hint)
GLFWAPI void glfwCloseWindow(GLFWwindow window) GLFWAPI void glfwCloseWindow(GLFWwindow window)
{ {
_GLFWwindow** prev;
if (!_glfwInitialized) if (!_glfwInitialized)
{ {
_glfwSetError(GLFW_NOT_INITIALIZED); _glfwSetError(GLFW_NOT_INITIALIZED);
@ -695,8 +699,11 @@ GLFWAPI void glfwCloseWindow(GLFWwindow window)
free(window); free(window);
// Yuck prev = &_glfwLibrary.windowListHead;
_glfwLibrary.window = NULL; while (*prev != window)
prev = &((*prev)->next);
*prev = window->next;
} }

View File

@ -188,8 +188,8 @@ int _glfwPlatformInit(void)
int _glfwPlatformTerminate(void) int _glfwPlatformTerminate(void)
{ {
if (_glfwLibrary.window) while (_glfwLibrary.windowListHead)
glfwCloseWindow(_glfwLibrary.window); glfwCloseWindow(_glfwLibrary.windowListHead);
// Terminate display // Terminate display
terminateDisplay(); terminateDisplay();

View File

@ -1026,15 +1026,31 @@ static void leaveFullscreenMode(_GLFWwindow* window)
_glfwPlatformShowMouseCursor(window); _glfwPlatformShowMouseCursor(window);
} }
//========================================================================
// Return the GLFW window corresponding to the specified X11 window
//========================================================================
static _GLFWwindow* findWindow(Window handle)
{
_GLFWwindow* window;
for (window = _glfwLibrary.windowListHead; window; window = window->next)
{
if (window->X11.window == handle)
return window;
}
return NULL;
}
//======================================================================== //========================================================================
// Get and process next X event (called by _glfwPlatformPollEvents) // Get and process next X event (called by _glfwPlatformPollEvents)
// Returns GL_TRUE if a window close request was received
//======================================================================== //========================================================================
static GLboolean processSingleEvent(void) static void processSingleEvent(void)
{ {
// Yuck _GLFWwindow* window;
_GLFWwindow* window = _glfwLibrary.window;
XEvent event; XEvent event;
XNextEvent(_glfwLibrary.X11.display, &event); XNextEvent(_glfwLibrary.X11.display, &event);
@ -1044,6 +1060,12 @@ static GLboolean processSingleEvent(void)
case KeyPress: case KeyPress:
{ {
// A keyboard key was pressed // A keyboard key was pressed
window = findWindow(event.xkey.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for event\n");
return;
}
// Translate and report key press // Translate and report key press
_glfwInputKey(window, translateKey(event.xkey.keycode), GLFW_PRESS); _glfwInputKey(window, translateKey(event.xkey.keycode), GLFW_PRESS);
@ -1057,6 +1079,12 @@ static GLboolean processSingleEvent(void)
case KeyRelease: case KeyRelease:
{ {
// A keyboard key was released // A keyboard key was released
window = findWindow(event.xkey.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for event\n");
return;
}
// Do not report key releases for key repeats. For key repeats we // Do not report key releases for key repeats. For key repeats we
// will get KeyRelease/KeyPress pairs with similar or identical // will get KeyRelease/KeyPress pairs with similar or identical
@ -1093,6 +1121,12 @@ static GLboolean processSingleEvent(void)
case ButtonPress: case ButtonPress:
{ {
// A mouse button was pressed or a scrolling event occurred // A mouse button was pressed or a scrolling event occurred
window = findWindow(event.xbutton.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for event\n");
return;
}
if (event.xbutton.button == Button1) if (event.xbutton.button == Button1)
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS); _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS);
@ -1121,6 +1155,12 @@ static GLboolean processSingleEvent(void)
case ButtonRelease: case ButtonRelease:
{ {
// A mouse button was released // A mouse button was released
window = findWindow(event.xbutton.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for event\n");
return;
}
if (event.xbutton.button == Button1) if (event.xbutton.button == Button1)
{ {
@ -1146,6 +1186,12 @@ static GLboolean processSingleEvent(void)
case MotionNotify: case MotionNotify:
{ {
// The mouse cursor was moved // The mouse cursor was moved
window = findWindow(event.xmotion.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for event\n");
return;
}
if (event.xmotion.x != window->X11.cursorPosX || if (event.xmotion.x != window->X11.cursorPosX ||
event.xmotion.y != window->X11.cursorPosY) event.xmotion.y != window->X11.cursorPosY)
@ -1184,6 +1230,14 @@ static GLboolean processSingleEvent(void)
case ConfigureNotify: case ConfigureNotify:
{ {
// The window configuration changed somehow
window = findWindow(event.xconfigure.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for event\n");
return;
}
if (event.xconfigure.width != window->width || if (event.xconfigure.width != window->width ||
event.xconfigure.height != window->height) event.xconfigure.height != window->height)
{ {
@ -1203,12 +1257,20 @@ static GLboolean processSingleEvent(void)
case ClientMessage: case ClientMessage:
{ {
// Custom client message, probably from the window manager
window = findWindow(event.xclient.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for event\n");
return;
}
if ((Atom) event.xclient.data.l[ 0 ] == window->X11.wmDeleteWindow) if ((Atom) event.xclient.data.l[ 0 ] == window->X11.wmDeleteWindow)
{ {
// The window manager was asked to close the window, for example by // The window manager was asked to close the window, for example by
// the user pressing a 'close' window decoration button // the user pressing a 'close' window decoration button
return GL_TRUE; window->closed = GL_TRUE;
} }
else if (window->X11.wmPing != None && else if (window->X11.wmPing != None &&
(Atom) event.xclient.data.l[ 0 ] == window->X11.wmPing) (Atom) event.xclient.data.l[ 0 ] == window->X11.wmPing)
@ -1230,6 +1292,12 @@ static GLboolean processSingleEvent(void)
case MapNotify: case MapNotify:
{ {
// The window was mapped // The window was mapped
window = findWindow(event.xmap.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for event\n");
return;
}
window->iconified = GL_FALSE; window->iconified = GL_FALSE;
break; break;
@ -1238,6 +1306,12 @@ static GLboolean processSingleEvent(void)
case UnmapNotify: case UnmapNotify:
{ {
// The window was unmapped // The window was unmapped
window = findWindow(event.xmap.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for event\n");
return;
}
window->iconified = GL_TRUE; window->iconified = GL_TRUE;
break; break;
@ -1246,6 +1320,12 @@ static GLboolean processSingleEvent(void)
case FocusIn: case FocusIn:
{ {
// The window gained focus // The window gained focus
window = findWindow(event.xfocus.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for event\n");
return;
}
window->active = GL_TRUE; window->active = GL_TRUE;
@ -1258,6 +1338,12 @@ static GLboolean processSingleEvent(void)
case FocusOut: case FocusOut:
{ {
// The window lost focus // The window lost focus
window = findWindow(event.xfocus.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for event\n");
return;
}
window->active = GL_FALSE; window->active = GL_FALSE;
_glfwInputDeactivation(window); _glfwInputDeactivation(window);
@ -1271,6 +1357,12 @@ static GLboolean processSingleEvent(void)
case Expose: case Expose:
{ {
// The window's contents was damaged // The window's contents was damaged
window = findWindow(event.xexpose.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for event\n");
return;
}
if (window->windowRefreshCallback) if (window->windowRefreshCallback)
window->windowRefreshCallback(window); window->windowRefreshCallback(window);
@ -1280,7 +1372,7 @@ static GLboolean processSingleEvent(void)
// Was the window destroyed? // Was the window destroyed?
case DestroyNotify: case DestroyNotify:
return GL_FALSE; return;
default: default:
{ {
@ -1298,9 +1390,6 @@ static GLboolean processSingleEvent(void)
break; break;
} }
} }
// The window was not destroyed
return GL_FALSE;
} }
@ -1690,33 +1779,39 @@ void _glfwPlatformRefreshWindowParams(void)
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
GLboolean closeRequested = GL_FALSE; _GLFWwindow* window;
_GLFWwindow* window = _glfwLibrary.window;
// Flag that the cursor has not moved // Flag that the cursor has not moved
if (window = _glfwLibrary.cursorLockWindow)
window->X11.mouseMoved = GL_FALSE; window->X11.mouseMoved = GL_FALSE;
// Process all pending events // Process all pending events
while (XPending(_glfwLibrary.X11.display)) while (XPending(_glfwLibrary.X11.display))
{ processSingleEvent();
if (processSingleEvent())
closeRequested = GL_TRUE;
}
// Did we get mouse movement in fully enabled hidden cursor mode? // Did we get mouse movement in fully enabled hidden cursor mode?
if (window = _glfwLibrary.cursorLockWindow)
{
if (window->X11.mouseMoved && window->X11.pointerHidden) if (window->X11.mouseMoved && window->X11.pointerHidden)
{ {
_glfwPlatformSetMouseCursorPos(window, _glfwPlatformSetMouseCursorPos(window,
window->width / 2, window->width / 2,
window->height / 2); window->height / 2);
} }
}
if (closeRequested && window->windowCloseCallback) for (window = _glfwLibrary.windowListHead; window; window = window->next)
closeRequested = window->windowCloseCallback(window); {
if (window->closed && window->windowCloseCallback)
window->closed = window->windowCloseCallback(window);
if (closeRequested) if (window->closed)
{
_GLFWwindow* next = window->next;
glfwCloseWindow(window); glfwCloseWindow(window);
window = next;
}
}
} }