diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h
index c9750dee..815d5e03 100644
--- a/include/GL/glfw3.h
+++ b/include/GL/glfw3.h
@@ -385,6 +385,7 @@ typedef struct
typedef void (* GLFWwindowsizefun)(GLFWwindow,int,int);
typedef int (* GLFWwindowclosefun)(GLFWwindow);
typedef void (* GLFWwindowrefreshfun)(GLFWwindow);
+typedef void (* GLFWwindowfocusfun)(GLFWwindow,int);
typedef void (* GLFWmousebuttonfun)(GLFWwindow,int,int);
typedef void (* GLFWmouseposfun)(GLFWwindow,int,int);
typedef void (* GLFWmousewheelfun)(GLFWwindow,int);
@@ -429,6 +430,7 @@ GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow window);
GLFWAPI void glfwSetWindowSizeCallback(GLFWwindow window, GLFWwindowsizefun cbfun);
GLFWAPI void glfwSetWindowCloseCallback(GLFWwindow window, GLFWwindowclosefun cbfun);
GLFWAPI void glfwSetWindowRefreshCallback(GLFWwindow window, GLFWwindowrefreshfun cbfun);
+GLFWAPI void glfwSetWindowFocusCallback(GLFWwindow window, GLFWwindowfocusfun cbfun);
/* Event handling */
GLFWAPI void glfwPollEvents(void);
diff --git a/readme.html b/readme.html
index 6bde1f76..2389d891 100644
--- a/readme.html
+++ b/readme.html
@@ -268,6 +268,7 @@ version of GLFW.
Added glfwSetWindowUserPointer
and glfwGetWindowUserPointer
functions for per-window user pointers
Added glfwGetVersionString
function for determining which code paths were enabled at compile time
Added glfwGetWindowPos
function for querying the position of the specified window
+ Added glfwSetWindowFocusCallback
function and GLFWwindowfocusfun type for receiving window focus events
Added windows
simple multi-window test program
Added initial window title parameter to glfwOpenWindow
Changed buffer bit depth parameters of glfwOpenWindow
to window hints
diff --git a/src/internal.h b/src/internal.h
index 736c361e..d7bb5d05 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -148,6 +148,7 @@ typedef struct _GLFWwindow
GLFWwindowsizefun windowSizeCallback;
GLFWwindowclosefun windowCloseCallback;
GLFWwindowrefreshfun windowRefreshCallback;
+ GLFWwindowfocusfun windowFocusCallback;
GLFWmousebuttonfun mouseButtonCallback;
GLFWmouseposfun mousePosCallback;
GLFWmousewheelfun mouseWheelCallback;
@@ -295,10 +296,10 @@ void _glfwSetError(int error);
void _glfwClearWindowHints(void);
// Input handling (window.c)
-void _glfwInputDeactivation(_GLFWwindow* window);
void _glfwInputKey(_GLFWwindow* window, int key, int action);
void _glfwInputChar(_GLFWwindow* window, int character);
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action);
+void _glfwInputWindowFocus(_GLFWwindow* window, GLboolean activated);
// OpenGL extensions (glext.c)
void _glfwParseGLVersion(int* major, int* minor, int* rev);
diff --git a/src/win32/win32_window.c b/src/win32/win32_window.c
index bca1b79d..cd61f8af 100755
--- a/src/win32/win32_window.c
+++ b/src/win32/win32_window.c
@@ -642,12 +642,17 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
BOOL active = LOWORD(wParam) != WA_INACTIVE;
BOOL iconified = HIWORD(wParam) ? TRUE : FALSE;
- if ((!active && _glfwLibrary.activeWindow == window) ||
- (iconified && !window->iconified))
+ if (active && iconified)
{
- // The window was either deactivated, iconified or both
+ // This is a workaround for window iconification using the
+ // taskbar leading to windows being told they're active and
+ // iconified and then never told they're deactivated
+ active = FALSE;
+ }
- _glfwInputDeactivation(window);
+ if (!active && _glfwLibrary.activeWindow == window)
+ {
+ // The window was deactivated (or iconified, see above)
if (window == _glfwLibrary.cursorLockWindow)
_glfwPlatformShowMouseCursor(window);
@@ -668,8 +673,10 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
}
}
}
- else if (active && !iconified)
+ else if (active && _glfwLibrary.activeWindow != window)
{
+ // The window was activated
+
if (window == _glfwLibrary.cursorLockWindow)
_glfwPlatformHideMouseCursor(window);
@@ -688,13 +695,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
}
}
- if (active)
- _glfwLibrary.activeWindow = window;
- else
- {
- if (window == _glfwLibrary.activeWindow)
- _glfwLibrary.activeWindow = NULL;
- }
+ _glfwInputWindowFocus(window, active);
window->iconified = iconified;
return 0;
diff --git a/src/window.c b/src/window.c
index b87d5853..104e357b 100644
--- a/src/window.c
+++ b/src/window.c
@@ -117,30 +117,6 @@ void _glfwClearWindowHints(void)
}
-//========================================================================
-// Handle the input tracking part of window deactivation
-//========================================================================
-
-void _glfwInputDeactivation(_GLFWwindow* window)
-{
- int i;
-
- // Release all keyboard keys
- for (i = 0; i <= GLFW_KEY_LAST; i++)
- {
- if (window->key[i] == GLFW_PRESS)
- _glfwInputKey(window, i, GLFW_RELEASE);
- }
-
- // Release all mouse buttons
- for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
- {
- if (window->mouseButton[i] == GLFW_PRESS)
- _glfwInputMouseClick(window, i, GLFW_RELEASE);
- }
-}
-
-
//========================================================================
// Register keyboard activity
//========================================================================
@@ -207,6 +183,51 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action)
}
+//========================================================================
+// Register window focus events
+//========================================================================
+
+void _glfwInputWindowFocus(_GLFWwindow* window, GLboolean activated)
+{
+ if (activated)
+ {
+ if (_glfwLibrary.activeWindow != window)
+ {
+ _glfwLibrary.activeWindow = window;
+
+ if (window->windowFocusCallback)
+ window->windowFocusCallback(window, activated);
+ }
+ }
+ else
+ {
+ if (_glfwLibrary.activeWindow == window)
+ {
+ int i;
+
+ // Release all pressed keyboard keys
+ for (i = 0; i <= GLFW_KEY_LAST; i++)
+ {
+ if (window->key[i] == GLFW_PRESS)
+ _glfwInputKey(window, i, GLFW_RELEASE);
+ }
+
+ // Release all pressed mouse buttons
+ for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
+ {
+ if (window->mouseButton[i] == GLFW_PRESS)
+ _glfwInputMouseClick(window, i, GLFW_RELEASE);
+ }
+
+ _glfwLibrary.activeWindow = NULL;
+
+ if (window->windowFocusCallback)
+ window->windowFocusCallback(window, activated);
+ }
+ }
+}
+
+
//========================================================================
// Return the available framebuffer config closest to the desired values
// This is based on the manual GLX Visual selection from 2.6
@@ -1084,6 +1105,22 @@ GLFWAPI void glfwSetWindowRefreshCallback(GLFWwindow window, GLFWwindowrefreshfu
}
+//========================================================================
+// Set callback function for window focus events
+//========================================================================
+
+GLFWAPI void glfwSetWindowFocusCallback(GLFWwindow window, GLFWwindowfocusfun cbfun)
+{
+ if (!_glfwInitialized)
+ {
+ _glfwSetError(GLFW_NOT_INITIALIZED);
+ return;
+ }
+
+ window->windowFocusCallback = cbfun;
+}
+
+
//========================================================================
// Poll for new window and input events and close any flagged windows
//========================================================================
diff --git a/src/x11/x11_window.c b/src/x11/x11_window.c
index bafdc721..c847bf50 100644
--- a/src/x11/x11_window.c
+++ b/src/x11/x11_window.c
@@ -1299,7 +1299,7 @@ static void processSingleEvent(void)
return;
}
- _glfwLibrary.activeWindow = window;
+ _glfwInputWindowFocus(window, GL_TRUE);
if (_glfwLibrary.cursorLockWindow == window)
_glfwPlatformHideMouseCursor(window);
@@ -1317,10 +1317,7 @@ static void processSingleEvent(void)
return;
}
- if (_glfwLibrary.activeWindow == window)
- _glfwLibrary.activeWindow = NULL;
-
- _glfwInputDeactivation(window);
+ _glfwInputWindowFocus(window, GL_FALSE);
if (_glfwLibrary.cursorLockWindow == window)
_glfwPlatformShowMouseCursor(window);