mirror of
https://github.com/glfw/glfw.git
synced 2024-11-22 13:04:35 +00:00
Initial multi-window support pass.
This commit is contained in:
parent
93046aecd0
commit
326d997c1c
@ -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;
|
||||||
|
|
||||||
|
29
src/window.c
29
src/window.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
window->X11.mouseMoved = GL_FALSE;
|
if (window = _glfwLibrary.cursorLockWindow)
|
||||||
|
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->X11.mouseMoved && window->X11.pointerHidden)
|
if (window = _glfwLibrary.cursorLockWindow)
|
||||||
{
|
{
|
||||||
_glfwPlatformSetMouseCursorPos(window,
|
if (window->X11.mouseMoved && window->X11.pointerHidden)
|
||||||
window->width / 2,
|
{
|
||||||
window->height / 2);
|
_glfwPlatformSetMouseCursorPos(window,
|
||||||
|
window->width / 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)
|
||||||
glfwCloseWindow(window);
|
{
|
||||||
|
_GLFWwindow* next = window->next;
|
||||||
|
glfwCloseWindow(window);
|
||||||
|
window = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user