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

View File

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

View File

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

View File

@ -1026,15 +1026,31 @@ static void leaveFullscreenMode(_GLFWwindow* 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)
// Returns GL_TRUE if a window close request was received
//========================================================================
static GLboolean processSingleEvent(void)
static void processSingleEvent(void)
{
// Yuck
_GLFWwindow* window = _glfwLibrary.window;
_GLFWwindow* window;
XEvent event;
XNextEvent(_glfwLibrary.X11.display, &event);
@ -1044,6 +1060,12 @@ static GLboolean processSingleEvent(void)
case KeyPress:
{
// 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
_glfwInputKey(window, translateKey(event.xkey.keycode), GLFW_PRESS);
@ -1057,6 +1079,12 @@ static GLboolean processSingleEvent(void)
case KeyRelease:
{
// 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
// will get KeyRelease/KeyPress pairs with similar or identical
@ -1093,6 +1121,12 @@ static GLboolean processSingleEvent(void)
case ButtonPress:
{
// 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)
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS);
@ -1121,6 +1155,12 @@ static GLboolean processSingleEvent(void)
case ButtonRelease:
{
// 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)
{
@ -1146,6 +1186,12 @@ static GLboolean processSingleEvent(void)
case MotionNotify:
{
// 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 ||
event.xmotion.y != window->X11.cursorPosY)
@ -1184,6 +1230,14 @@ static GLboolean processSingleEvent(void)
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 ||
event.xconfigure.height != window->height)
{
@ -1203,12 +1257,20 @@ static GLboolean processSingleEvent(void)
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)
{
// The window manager was asked to close the window, for example by
// the user pressing a 'close' window decoration button
return GL_TRUE;
window->closed = GL_TRUE;
}
else if (window->X11.wmPing != None &&
(Atom) event.xclient.data.l[ 0 ] == window->X11.wmPing)
@ -1230,6 +1292,12 @@ static GLboolean processSingleEvent(void)
case MapNotify:
{
// 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;
break;
@ -1238,6 +1306,12 @@ static GLboolean processSingleEvent(void)
case UnmapNotify:
{
// 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;
break;
@ -1246,6 +1320,12 @@ static GLboolean processSingleEvent(void)
case FocusIn:
{
// 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;
@ -1258,6 +1338,12 @@ static GLboolean processSingleEvent(void)
case FocusOut:
{
// 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;
_glfwInputDeactivation(window);
@ -1271,6 +1357,12 @@ static GLboolean processSingleEvent(void)
case Expose:
{
// 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)
window->windowRefreshCallback(window);
@ -1280,7 +1372,7 @@ static GLboolean processSingleEvent(void)
// Was the window destroyed?
case DestroyNotify:
return GL_FALSE;
return;
default:
{
@ -1298,9 +1390,6 @@ static GLboolean processSingleEvent(void)
break;
}
}
// The window was not destroyed
return GL_FALSE;
}
@ -1690,33 +1779,39 @@ void _glfwPlatformRefreshWindowParams(void)
void _glfwPlatformPollEvents(void)
{
GLboolean closeRequested = GL_FALSE;
_GLFWwindow* window = _glfwLibrary.window;
_GLFWwindow* window;
// Flag that the cursor has not moved
if (window = _glfwLibrary.cursorLockWindow)
window->X11.mouseMoved = GL_FALSE;
// Process all pending events
while (XPending(_glfwLibrary.X11.display))
{
if (processSingleEvent())
closeRequested = GL_TRUE;
}
processSingleEvent();
// Did we get mouse movement in fully enabled hidden cursor mode?
if (window = _glfwLibrary.cursorLockWindow)
{
if (window->X11.mouseMoved && window->X11.pointerHidden)
{
_glfwPlatformSetMouseCursorPos(window,
window->width / 2,
window->height / 2);
}
}
if (closeRequested && window->windowCloseCallback)
closeRequested = window->windowCloseCallback(window);
for (window = _glfwLibrary.windowListHead; window; window = window->next)
{
if (window->closed && window->windowCloseCallback)
window->closed = window->windowCloseCallback(window);
if (closeRequested)
if (window->closed)
{
_GLFWwindow* next = window->next;
glfwCloseWindow(window);
window = next;
}
}
}