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);