Changed state attribs to direct access.

Changed the window states (focused, iconified and visible) to query the
system directly.

THIS IS A BREAKING CHANGE, although a fairly obscure one.  It affects
applications that both care about telling actual key events from
synthetic ones, and are implemented in a non-self-synchronizing way, and
that poll the GLFW_FOCUSED window attribute instead of using the window
focus callback.

If you maintain one of these, please feel free to drop me an email and
I'll help any way I can to transition your application to 3.1.

Fixes #189.
Fixes #204.
This commit is contained in:
Camilla Berglund 2014-12-26 12:25:48 +01:00
parent f9c1f85f02
commit 641761ddb0
8 changed files with 159 additions and 139 deletions

View File

@ -86,6 +86,8 @@ GLFW bundles a number of dependencies in the `deps/` directory.
- Added `GLFW_FOCUSED` window hint for controlling initial input focus - Added `GLFW_FOCUSED` window hint for controlling initial input focus
- Added *partial and experimental* support for Wayland - Added *partial and experimental* support for Wayland
- Added *partial and experimental* support for Mir - Added *partial and experimental* support for Mir
- Changed the window states (focused, iconified and visible) to query the
system directly
- Changed the default of `GLFW_REFRESH_RATE` to `GLFW_DONT_CARE` to maintain - Changed the default of `GLFW_REFRESH_RATE` to `GLFW_DONT_CARE` to maintain
the default behavior the default behavior
- Changed static library to build as position independent code for easier use - Changed static library to build as position independent code for easier use

View File

@ -226,25 +226,6 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
return NSTerminateCancel; return NSTerminateCancel;
} }
- (void)applicationDidHide:(NSNotification *)notification
{
_GLFWwindow* window;
for (window = _glfw.windowListHead; window; window = window->next)
_glfwInputWindowVisibility(window, GL_FALSE);
}
- (void)applicationDidUnhide:(NSNotification *)notification
{
_GLFWwindow* window;
for (window = _glfw.windowListHead; window; window = window->next)
{
if ([window->ns.object isVisible])
_glfwInputWindowVisibility(window, GL_TRUE);
}
}
- (void)applicationDidChangeScreenParameters:(NSNotification *) notification - (void)applicationDidChangeScreenParameters:(NSNotification *) notification
{ {
_glfwInputMonitorChange(); _glfwInputMonitorChange();
@ -1047,13 +1028,26 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
void _glfwPlatformUnhideWindow(_GLFWwindow* window) void _glfwPlatformUnhideWindow(_GLFWwindow* window)
{ {
[window->ns.object orderFront:nil]; [window->ns.object orderFront:nil];
_glfwInputWindowVisibility(window, GL_TRUE);
} }
void _glfwPlatformHideWindow(_GLFWwindow* window) void _glfwPlatformHideWindow(_GLFWwindow* window)
{ {
[window->ns.object orderOut:nil]; [window->ns.object orderOut:nil];
_glfwInputWindowVisibility(window, GL_FALSE); }
int _glfwPlatformWindowFocused(_GLFWwindow* window)
{
return [window->ns.object isKeyWindow];
}
int _glfwPlatformWindowIconified(_GLFWwindow* window)
{
return [window->ns.object isMiniaturized];
}
int _glfwPlatformWindowVisible(_GLFWwindow* window)
{
return [window->ns.object isVisible];
} }
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)

View File

@ -219,12 +219,10 @@ struct _GLFWwindow
struct _GLFWwindow* next; struct _GLFWwindow* next;
// Window settings and state // Window settings and state
GLboolean iconified;
GLboolean resizable; GLboolean resizable;
GLboolean decorated; GLboolean decorated;
GLboolean autoIconify; GLboolean autoIconify;
GLboolean floating; GLboolean floating;
GLboolean visible;
GLboolean closed; GLboolean closed;
void* userPointer; void* userPointer;
GLFWvidmode videoMode; GLFWvidmode videoMode;
@ -575,6 +573,21 @@ void _glfwPlatformUnhideWindow(_GLFWwindow* window);
*/ */
void _glfwPlatformHideWindow(_GLFWwindow* window); void _glfwPlatformHideWindow(_GLFWwindow* window);
/*! @brief Returns whether the window is focused.
* @ingroup platform
*/
int _glfwPlatformWindowFocused(_GLFWwindow* window);
/*! @brief Returns whether the window is iconified.
* @ingroup platform
*/
int _glfwPlatformWindowIconified(_GLFWwindow* window);
/*! @brief Returns whether the window is visible.
* @ingroup platform
*/
int _glfwPlatformWindowVisible(_GLFWwindow* window);
/*! @copydoc glfwPollEvents /*! @copydoc glfwPollEvents
* @ingroup platform * @ingroup platform
*/ */
@ -685,14 +698,6 @@ void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
*/ */
void _glfwInputWindowIconify(_GLFWwindow* window, int iconified); void _glfwInputWindowIconify(_GLFWwindow* window, int iconified);
/*! @brief Notifies shared code of a window show/hide event.
* @param[in] window The window that received the event.
* @param[in] visible `GL_TRUE` if the window was shown, or `GL_FALSE` if it
* was hidden.
* @ingroup event
*/
void _glfwInputWindowVisibility(_GLFWwindow* window, int visible);
/*! @brief Notifies shared code of a window damage event. /*! @brief Notifies shared code of a window damage event.
* @param[in] window The window that received the event. * @param[in] window The window that received the event.
*/ */

View File

@ -565,6 +565,27 @@ void _glfwPlatformUnhideWindow(_GLFWwindow* window)
"Mir: Unsupported Function %s!", __PRETTY_FUNCTION__); "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
} }
int _glfwPlatformWindowFocused(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
return GL_FALSE;
}
int _glfwPlatformWindowIconified(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
return GL_FALSE;
}
int _glfwPlatformWindowVisible(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
return GL_FALSE;
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
EventNode* node = NULL; EventNode* node = NULL;

View File

@ -257,86 +257,33 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
break; break;
} }
case WM_ACTIVATE: case WM_SETFOCUS:
{ {
// Window was (de)focused and/or (de)iconified
BOOL focused = LOWORD(wParam) != WA_INACTIVE;
BOOL iconified = HIWORD(wParam) ? TRUE : FALSE;
if (focused && iconified)
{
if (window->iconified && _glfw.focusedWindow != window)
{
// This is a workaround for window restoration using the
// Win+D hot key leading to windows being told they're
// focused and iconified and then never told they're
// restored
iconified = FALSE;
}
else
{
// This is a workaround for window iconification using the
// taskbar leading to windows being told they're focused and
// iconified and then never told they're defocused
focused = FALSE;
}
}
if (!focused && _glfw.focusedWindow == window)
{
// The window was defocused (or iconified, see above)
if (window->cursorMode != GLFW_CURSOR_NORMAL)
restoreCursor(window);
if (window->monitor && window->autoIconify)
{
if (!iconified)
{
// Iconify the (on top, borderless, oddly positioned)
// window or the user will be annoyed
_glfwPlatformIconifyWindow(window);
}
leaveFullscreenMode(window);
}
}
else if (focused && _glfw.focusedWindow != window)
{
// The window was focused
if (window->cursorMode != GLFW_CURSOR_NORMAL) if (window->cursorMode != GLFW_CURSOR_NORMAL)
_glfwPlatformApplyCursorMode(window); _glfwPlatformApplyCursorMode(window);
if (window->monitor && window->autoIconify) if (window->monitor && window->autoIconify)
enterFullscreenMode(window); enterFullscreenMode(window);
}
_glfwInputWindowFocus(window, focused); _glfwInputWindowFocus(window, GL_TRUE);
_glfwInputWindowIconify(window, iconified);
return 0; return 0;
} }
case WM_ACTIVATEAPP: case WM_KILLFOCUS:
{ {
if (!wParam && IsIconic(hWnd)) if (window->cursorMode != GLFW_CURSOR_NORMAL)
restoreCursor(window);
if (window->monitor && window->autoIconify)
{ {
// This is a workaround for full screen windows losing focus _glfwPlatformIconifyWindow(window);
// through Alt+Tab leading to windows being told they're leaveFullscreenMode(window);
// unfocused and restored and then never told they're iconified
_glfwInputWindowIconify(window, GL_TRUE);
} }
_glfwInputWindowFocus(window, GL_FALSE);
return 0; return 0;
} }
case WM_SHOWWINDOW:
{
_glfwInputWindowVisibility(window, wParam ? GL_TRUE : GL_FALSE);
break;
}
case WM_SYSCOMMAND: case WM_SYSCOMMAND:
{ {
switch (wParam & 0xfff0) switch (wParam & 0xfff0)
@ -560,6 +507,11 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_SIZE: case WM_SIZE:
{ {
if (wParam == SIZE_MINIMIZED)
_glfwInputWindowIconify(window, GL_TRUE);
else if (wParam == SIZE_RESTORED)
_glfwInputWindowIconify(window, GL_FALSE);
if (_glfw.focusedWindow == window) if (_glfw.focusedWindow == window)
{ {
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
@ -1041,6 +993,21 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
ShowWindow(window->win32.handle, SW_HIDE); ShowWindow(window->win32.handle, SW_HIDE);
} }
int _glfwPlatformWindowFocused(_GLFWwindow* window)
{
return window->win32.handle == GetActiveWindow();
}
int _glfwPlatformWindowIconified(_GLFWwindow* window)
{
return IsIconic(window->win32.handle);
}
int _glfwPlatformWindowVisible(_GLFWwindow* window)
{
return IsWindowVisible(window->win32.handle);
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
MSG msg; MSG msg;
@ -1238,7 +1205,8 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
// the following condition is not met. That way it should be safe to destroy the // the following condition is not met. That way it should be safe to destroy the
// cursor after calling glfwSetCursor(window, NULL) on all windows using the cursor. // cursor after calling glfwSetCursor(window, NULL) on all windows using the cursor.
if (window->cursorMode == GLFW_CURSOR_NORMAL && _glfw.focusedWindow == window && if (_glfw.focusedWindow == window &&
window->cursorMode == GLFW_CURSOR_NORMAL &&
window->win32.cursorInside) window->win32.cursorInside)
{ {
if (cursor) if (cursor)

View File

@ -84,8 +84,6 @@ void _glfwInputWindowSize(_GLFWwindow* window, int width, int height)
void _glfwInputWindowIconify(_GLFWwindow* window, int iconified) void _glfwInputWindowIconify(_GLFWwindow* window, int iconified)
{ {
window->iconified = iconified;
if (window->callbacks.iconify) if (window->callbacks.iconify)
window->callbacks.iconify((GLFWwindow*) window, iconified); window->callbacks.iconify((GLFWwindow*) window, iconified);
} }
@ -96,11 +94,6 @@ void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
window->callbacks.fbsize((GLFWwindow*) window, width, height); window->callbacks.fbsize((GLFWwindow*) window, width, height);
} }
void _glfwInputWindowVisibility(_GLFWwindow* window, int visible)
{
window->visible = visible;
}
void _glfwInputWindowDamage(_GLFWwindow* window) void _glfwInputWindowDamage(_GLFWwindow* window)
{ {
if (window->callbacks.refresh) if (window->callbacks.refresh)
@ -600,17 +593,17 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
switch (attrib) switch (attrib)
{ {
case GLFW_FOCUSED: case GLFW_FOCUSED:
return window == _glfw.focusedWindow; return _glfwPlatformWindowFocused(window);
case GLFW_ICONIFIED: case GLFW_ICONIFIED:
return window->iconified; return _glfwPlatformWindowIconified(window);
case GLFW_VISIBLE:
return _glfwPlatformWindowVisible(window);
case GLFW_RESIZABLE: case GLFW_RESIZABLE:
return window->resizable; return window->resizable;
case GLFW_DECORATED: case GLFW_DECORATED:
return window->decorated; return window->decorated;
case GLFW_FLOATING: case GLFW_FLOATING:
return window->floating; return window->floating;
case GLFW_VISIBLE:
return window->visible;
case GLFW_CLIENT_API: case GLFW_CLIENT_API:
return window->context.api; return window->context.api;
case GLFW_CONTEXT_VERSION_MAJOR: case GLFW_CONTEXT_VERSION_MAJOR:

View File

@ -307,6 +307,24 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
wl_surface_commit(window->wl.surface); wl_surface_commit(window->wl.surface);
} }
int _glfwPlatformWindowFocused(_GLFWwindow* window)
{
// TODO
return GL_FALSE;
}
int _glfwPlatformWindowIconified(_GLFWwindow* window)
{
// TODO
return GL_FALSE;
}
int _glfwPlatformWindowVisible(_GLFWwindow* window)
{
// TODO
return GL_FALSE;
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
struct wl_display* display = _glfw.wl.display; struct wl_display* display = _glfw.wl.display;

View File

@ -57,6 +57,28 @@ typedef struct
#define MWM_HINTS_DECORATIONS (1L << 1) #define MWM_HINTS_DECORATIONS (1L << 1)
// Returns whether the window is iconified
//
static int getWindowState(_GLFWwindow* window)
{
int result = WithdrawnState;
struct {
CARD32 state;
Window icon;
} *state = NULL;
if (_glfwGetWindowProperty(window->x11.handle,
_glfw.x11.WM_STATE,
_glfw.x11.WM_STATE,
(unsigned char**) &state) >= 2)
{
result = state->state;
}
XFree(state);
return result;
}
// Returns whether the event is a selection event // Returns whether the event is a selection event
// //
static Bool isFrameExtentsEvent(Display* display, XEvent* event, XPointer pointer) static Bool isFrameExtentsEvent(Display* display, XEvent* event, XPointer pointer)
@ -1229,18 +1251,6 @@ static void processEvent(XEvent *event)
break; break;
} }
case MapNotify:
{
_glfwInputWindowVisibility(window, GL_TRUE);
break;
}
case UnmapNotify:
{
_glfwInputWindowVisibility(window, GL_FALSE);
break;
}
case FocusIn: case FocusIn:
{ {
if (event->xfocus.mode == NotifyNormal) if (event->xfocus.mode == NotifyNormal)
@ -1278,25 +1288,13 @@ static void processEvent(XEvent *event)
if (event->xproperty.atom == _glfw.x11.WM_STATE && if (event->xproperty.atom == _glfw.x11.WM_STATE &&
event->xproperty.state == PropertyNewValue) event->xproperty.state == PropertyNewValue)
{ {
struct { const int state = getWindowState(window);
CARD32 state; if (state == IconicState)
Window icon;
} *state = NULL;
if (_glfwGetWindowProperty(window->x11.handle,
_glfw.x11.WM_STATE,
_glfw.x11.WM_STATE,
(unsigned char**) &state) >= 2)
{
if (state->state == IconicState)
_glfwInputWindowIconify(window, GL_TRUE); _glfwInputWindowIconify(window, GL_TRUE);
else if (state->state == NormalState) else if (state == NormalState)
_glfwInputWindowIconify(window, GL_FALSE); _glfwInputWindowIconify(window, GL_FALSE);
} }
XFree(state);
}
break; break;
} }
@ -1671,6 +1669,27 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
XFlush(_glfw.x11.display); XFlush(_glfw.x11.display);
} }
int _glfwPlatformWindowFocused(_GLFWwindow* window)
{
Window focused;
int state;
XGetInputFocus(_glfw.x11.display, &focused, &state);
return window->x11.handle == focused;
}
int _glfwPlatformWindowIconified(_GLFWwindow* window)
{
return getWindowState(window) == IconicState;
}
int _glfwPlatformWindowVisible(_GLFWwindow* window)
{
XWindowAttributes wa;
XGetWindowAttributes(_glfw.x11.display, window->x11.handle, &wa);
return wa.map_state == IsViewable;
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
int count = XPending(_glfw.x11.display); int count = XPending(_glfw.x11.display);