diff --git a/.gitignore b/.gitignore
index f6103c222..859499268 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@ _ReSharper*
*.dir
*.vcxproj*
*.sln
+.vs/
Win32
x64
Debug
diff --git a/README.md b/README.md
index 3235c73cb..4537b360e 100644
--- a/README.md
+++ b/README.md
@@ -75,7 +75,7 @@ more information.
## System requirements
-GLFW supports Windows XP and later and macOS 10.7 and later. Linux and other
+GLFW supports Windows XP and later and macOS 10.8 and later. Linux and other
Unix-like systems running the X Window System are supported even without
a desktop environment or modern extensions, although some features require
a running window or clipboard manager. The OSMesa backend requires Mesa 6.3.
@@ -190,6 +190,8 @@ information on what to include when reporting a bug.
- Removed `GLFW_USE_RETINA` compile-time option
- Removed `GLFW_USE_CHDIR` compile-time option
- Removed `GLFW_USE_MENUBAR` compile-time option
+- Removed requirement of at least one window for `glfwWaitEvents` and
+ `glfwPostEmptyEvent` (#1317)
- Bugfix: Calling `glfwMaximizeWindow` on a full screen window was not ignored
- Bugfix: `GLFW_INCLUDE_VULKAN` could not be combined with the corresponding
OpenGL and OpenGL ES header macros
@@ -198,6 +200,8 @@ information on what to include when reporting a bug.
- Bugfix: Invalid library paths were used in test and example CMake files (#930)
- Bugfix: The scancode for synthetic key release events was always zero
- Bugfix: The generated Doxyfile did not handle paths with spaces (#1081)
+- Bugfix: The gamma ramp generated by `glfwSetGamma` did not use the monitor
+ ramp size (#1387,#1388)
- [Win32] Added system error strings to relevant GLFW error descriptions (#733)
- [Win32] Moved to `WM_INPUT` for disabled cursor mode motion input (#125)
- [Win32] Removed XInput circular deadzone from joystick axis data (#1045)
@@ -226,6 +230,8 @@ information on what to include when reporting a bug.
hint set to false (#1179,#1180)
- [Win32] Bugfix: The keypad equals key was reported as `GLFW_KEY_UNKNOWN`
(#1315,#1316)
+- [Win32] Bugfix: A title bar would be drawn over undecorated windows in some
+ circumstances (#1383)
- [X11] Moved to XI2 `XI_RawMotion` for disable cursor mode motion input (#125)
- [X11] Replaced `_GLFW_HAS_XF86VM` compile-time option with dynamic loading
- [X11] Bugfix: `glfwGetVideoMode` would segfault on Cygwin/X
@@ -242,6 +248,11 @@ information on what to include when reporting a bug.
- [X11] Bugfix: NVidia EGL would segfault if unloaded before closing the display
- [X11] Bugfix: Checking window maximized attrib could crash some WMs (#1356)
- [X11] Bugfix: Update cursor position on enter event (#1366)
+- [X11] Bugfix: `glfwSetWindowMonitor` did not update hints when resizing
+ non-user-resizable windows
+- [X11] Bugfix: `glfwSetWindowMonitor` did not flush output buffer in some cases
+- [X11] Bugfix: `glfwSetWindowMonitor` did not update the EWMH state of hidden
+ windows (#1358)
- [Linux] Added workaround for missing `SYN_DROPPED` in pre-2.6.39 kernel
headers (#1196)
- [Linux] Moved to evdev for joystick input (#906,#1005)
@@ -252,6 +263,7 @@ information on what to include when reporting a bug.
- [Cocoa] Added support for Vulkan window surface creation via
[MoltenVK](https://moltengl.com/moltenvk/) (#870)
- [Cocoa] Added support for loading a `MainMenu.nib` when available
+- [Cocoa] Disabled automatic window tabbing for created windows (#1250)
- [Cocoa] Bugfix: Disabling window aspect ratio would assert (#852)
- [Cocoa] Bugfix: Window creation failed to set first responder (#876,#883)
- [Cocoa] Bugfix: Removed use of deprecated `CGDisplayIOServicePort` function
@@ -276,6 +288,9 @@ information on what to include when reporting a bug.
- [Cocoa] Bugfix: Event polling did not initialize AppKit if necessary (#1218)
- [Cocoa] Bugfix: OpenGL rendering was not initially visible on 10.14
(#1334,#1346)
+- [Cocoa] Bugfix: Caps Lock did not generate any key events (#1368,#1373)
+- [Cocoa] Bugfix: Some buttons for some joysticks were ignored (#1385)
+- [Cocoa] Bugfix: Analog joystick buttons were not translated correctly (#1385)
- [WGL] Added support for `WGL_EXT_colorspace` for OpenGL ES contexts
- [WGL] Added support for `WGL_ARB_create_context_no_error`
- [GLX] Added support for `GLX_ARB_create_context_no_error`
@@ -315,6 +330,7 @@ skills.
- John Bartholomew
- Coşku Baş
- Niklas Behrens
+ - Andrew Belt
- Niklas Bergström
- Denis Bernard
- Doug Binks
@@ -381,6 +397,7 @@ skills.
- Glenn Lewis
- Shane Liesegang
- Eyal Lotem
+ - Aaron Loucks
- Tristam MacDonald
- Hans Mackowiak
- Дмитри Малышев
@@ -397,6 +414,7 @@ skills.
- Bruce Mitchener
- Jack Moffitt
- Jeff Molofee
+ - Alexander Monakov
- Pierre Morel
- Jon Morton
- Pierre Moulon
diff --git a/docs/input.dox b/docs/input.dox
index 84978bd09..159fb454e 100644
--- a/docs/input.dox
+++ b/docs/input.dox
@@ -57,8 +57,7 @@ glfwWaitEvents();
It puts the thread to sleep until at least one event has been received and then
processes all received events. This saves a great deal of CPU cycles and is
-useful for, for example, editing tools. There must be at least one GLFW window
-for this function to sleep.
+useful for, for example, editing tools.
If you want to wait for events but have UI elements or other tasks that need
periodic updates, @ref glfwWaitEventsTimeout lets you specify a timeout.
@@ -249,7 +248,7 @@ glfwSetCursorPosCallback(window, cursor_position_callback);
@endcode
The callback functions receives the cursor position, measured in screen
-coordinates but relative to the top-left corner of the window client area. On
+coordinates but relative to the top-left corner of the window content area. On
platforms that provide it, the full sub-pixel cursor position is passed on.
@code
@@ -378,7 +377,7 @@ glfwSetCursor(window, cursor);
@endcode
Once set, the cursor image will be used as long as the system cursor is over the
-client area of the window and the [cursor mode](@ref cursor_mode) is set
+content area of the window and the [cursor mode](@ref cursor_mode) is set
to `GLFW_CURSOR_NORMAL`.
A single cursor may be set for any number of windows.
@@ -395,7 +394,7 @@ default cursor. This does not affect the cursor mode.
@subsection cursor_enter Cursor enter/leave events
-If you wish to be notified when the cursor enters or leaves the client area of
+If you wish to be notified when the cursor enters or leaves the content area of
a window, set a cursor enter/leave callback.
@code
@@ -409,16 +408,16 @@ void cursor_enter_callback(GLFWwindow* window, int entered)
{
if (entered)
{
- // The cursor entered the client area of the window
+ // The cursor entered the content area of the window
}
else
{
- // The cursor left the client area of the window
+ // The cursor left the content area of the window
}
}
@endcode
-You can query whether the cursor is currently inside the client area of the
+You can query whether the cursor is currently inside the content area of the
window with the [GLFW_HOVERED](@ref GLFW_HOVERED_attrib) window attribute.
@code
diff --git a/docs/intro.dox b/docs/intro.dox
index 58ab8fd5d..36bc73e6f 100644
--- a/docs/intro.dox
+++ b/docs/intro.dox
@@ -208,24 +208,24 @@ future that same call may generate a different error or become valid.
@section coordinate_systems Coordinate systems
GLFW has two primary coordinate systems: the _virtual screen_ and the window
-_client area_ or _content area_. Both use the same unit: _virtual screen
+_content area_ or _content area_. Both use the same unit: _virtual screen
coordinates_, or just _screen coordinates_, which don't necessarily correspond
to pixels.
-Both the virtual screen and the client area coordinate systems have the X-axis
+Both the virtual screen and the content area coordinate systems have the X-axis
pointing to the right and the Y-axis pointing down.
Window and monitor positions are specified as the position of the upper-left
corners of their content areas relative to the virtual screen, while cursor
-positions are specified relative to a window's client area.
+positions are specified relative to a window's content area.
-Because the origin of the window's client area coordinate system is also the
-point from which the window position is specified, you can translate client area
-coordinates to the virtual screen by adding the window position. The window
-frame, when present, extends out from the client area but does not affect the
-window position.
+Because the origin of the window's content area coordinate system is also the
+point from which the window position is specified, you can translate content
+area coordinates to the virtual screen by adding the window position. The
+window frame, when present, extends out from the content area but does not
+affect the window position.
Almost all positions and sizes in GLFW are measured in screen coordinates
relative to one of the two origins above. This includes cursor positions,
diff --git a/docs/news.dox b/docs/news.dox
index 0cdec0055..43f384eab 100644
--- a/docs/news.dox
+++ b/docs/news.dox
@@ -128,7 +128,7 @@ window hint. It is enabled by default.
@subsection news_33_hover Mouse cursor hover window attribute
-GLFW now supports polling whether the cursor is hovering over the window client
+GLFW now supports polling whether the cursor is hovering over the window content
area with the [GLFW_HOVERED](@ref GLFW_HOVERED_attrib) window attribute. This
attribute corresponds to the [cursor enter/leave](@ref cursor_enter) event.
@@ -308,7 +308,7 @@ glfwWaitEvents to return.
@subsection news_31_framesize Window frame size query
GLFW now supports querying the size, on each side, of the frame around the
-client area of a window, with @ref glfwGetWindowFrameSize.
+content area of a window, with @ref glfwGetWindowFrameSize.
@see [Window size](@ref window_size)
@@ -506,7 +506,7 @@ glfwSetWindowFocusCallback.
@subsection news_30_enterleave Cursor enter/leave callback
Each window now has a callback for when the mouse cursor enters or leaves its
-client area, which is set with @ref glfwSetCursorEnterCallback.
+content area, which is set with @ref glfwSetCursorEnterCallback.
@subsection news_30_wndtitle Initial window title
diff --git a/docs/spaces.svg b/docs/spaces.svg
index 562fa8be1..5b3264609 100644
--- a/docs/spaces.svg
+++ b/docs/spaces.svg
@@ -13,7 +13,7 @@
height="327.98221"
id="svg2"
version="1.1"
- inkscape:version="0.48.4 r9939"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="spaces.svg">
@@ -38,11 +38,11 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="2.5611424"
- inkscape:cx="344.24359"
- inkscape:cy="163.9911"
+ inkscape:zoom="1.8110012"
+ inkscape:cx="320.68941"
+ inkscape:cy="159.80509"
inkscape:document-units="px"
- inkscape:current-layer="svg2"
+ inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1021"
@@ -475,18 +475,18 @@
inkscape:export-ydpi="109.89113" />
+ y="340.20465"
+ style="font-size:12px;line-height:1.25;font-family:sans-serif">
@@ -647,74 +647,6 @@
style="font-size:10px"
id="path3239" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -868,5 +800,78 @@
style="font-size:5px"
id="path3161" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/window.dox b/docs/window.dox
index f30127847..5f94f3587 100644
--- a/docs/window.dox
+++ b/docs/window.dox
@@ -599,7 +599,7 @@ void window_close_callback(GLFWwindow* window)
The size of a window can be changed with @ref glfwSetWindowSize. For windowed
mode windows, this sets the size, in
-[screen coordinates](@ref coordinate_systems) of the _client area_ or _content
+[screen coordinates](@ref coordinate_systems) of the _content area_ or _content
area_ of the window. The window system may impose limits on window size.
@code
@@ -619,7 +619,7 @@ glfwSetWindowSizeCallback(window, window_size_callback);
@endcode
The callback function receives the new size, in screen coordinates, of the
-client area of the window when the window is resized.
+content area of the window when the window is resized.
@code
void window_size_callback(GLFWwindow* window, int width, int height)
@@ -640,9 +640,9 @@ calls. The window size is in screen coordinates, not pixels. Use the
[framebuffer size](@ref window_fbsize), which is in pixels, for pixel-based
calls.
-The above functions work with the size of the client area, but decorated windows
-typically have title bars and window frames around this rectangle. You can
-retrieve the extents of these with @ref glfwGetWindowFrameSize.
+The above functions work with the size of the content area, but decorated
+windows typically have title bars and window frames around this rectangle. You
+can retrieve the extents of these with @ref glfwGetWindowFrameSize.
@code
int left, top, right, bottom;
@@ -650,7 +650,7 @@ glfwGetWindowFrameSize(window, &left, &top, &right, &bottom);
@endcode
The returned values are the distances, in screen coordinates, from the edges of
-the client area to the corresponding edges of the full window. As they are
+the content area to the corresponding edges of the full window. As they are
distances and not coordinates, they are always zero or positive.
@@ -737,10 +737,10 @@ GLFW_SCALE_TO_MONITOR window hint.
@subsection window_sizelimits Window size limits
-The minimum and maximum size of the client area of a windowed mode window can be
-enforced with @ref glfwSetWindowSizeLimits. The user may resize the window to
-any size and aspect ratio within the specified limits, unless the aspect ratio
-is also set.
+The minimum and maximum size of the content area of a windowed mode window can
+be enforced with @ref glfwSetWindowSizeLimits. The user may resize the window
+to any size and aspect ratio within the specified limits, unless the aspect
+ratio is also set.
@code
glfwSetWindowSizeLimits(window, 200, 200, 400, 400);
@@ -755,7 +755,7 @@ glfwSetWindowSizeLimits(window, 640, 480, GLFW_DONT_CARE, GLFW_DONT_CARE);
To disable size limits for a window, set them all to `GLFW_DONT_CARE`.
-The aspect ratio of the client area of a windowed mode window can be enforced
+The aspect ratio of the content area of a windowed mode window can be enforced
with @ref glfwSetWindowAspectRatio. The user may resize the window freely
unless size limits are also set, but the size will be constrained to maintain
the aspect ratio.
@@ -785,7 +785,7 @@ are undefined if they conflict.
The position of a windowed-mode window can be changed with @ref
glfwSetWindowPos. This moves the window so that the upper-left corner of its
-client area has the specified [screen coordinates](@ref coordinate_systems).
+content area has the specified [screen coordinates](@ref coordinate_systems).
The window system may put limitations on window placement.
@code
@@ -800,7 +800,7 @@ glfwSetWindowPosCallback(window, window_pos_callback);
@endcode
The callback function receives the new position, in screen coordinates, of the
-upper-left corner of the client area when the window is moved.
+upper-left corner of the content area when the window is moved.
@code
void window_pos_callback(GLFWwindow* window, int xpos, int ypos)
@@ -809,7 +809,7 @@ void window_pos_callback(GLFWwindow* window, int xpos, int ypos)
@endcode
There is also @ref glfwGetWindowPos for directly retrieving the current position
-of the client area of the window.
+of the content area of the window.
@code
int xpos, ypos;
@@ -1249,8 +1249,8 @@ __GLFW_MAXIMIZED__ indicates whether the specified window is maximized. See
@anchor GLFW_HOVERED_attrib
__GLFW_HOVERED__ indicates whether the cursor is currently directly over the
-client area of the window, with no other windows between. See @ref cursor_enter
-for details.
+content area of the window, with no other windows between. See @ref
+cursor_enter for details.
@anchor GLFW_VISIBLE_attrib
__GLFW_VISIBLE__ indicates whether the specified window is visible. See @ref
diff --git a/examples/boing.c b/examples/boing.c
index 45c867fd1..d13c58414 100644
--- a/examples/boing.c
+++ b/examples/boing.c
@@ -165,7 +165,7 @@ void CrossProduct( vertex_t a, vertex_t b, vertex_t c, vertex_t *n )
v2 = c.y - a.y;
v3 = c.z - a.z;
- n->x = u2 * v3 - v2 * v3;
+ n->x = u2 * v3 - v2 * u3;
n->y = u3 * v1 - v3 * u1;
n->z = u1 * v2 - v1 * u2;
}
@@ -302,7 +302,7 @@ void cursor_position_callback( GLFWwindow* window, double x, double y )
* The Boing ball is sphere in which each facet is a rectangle.
* Facet colors alternate between red and white.
* The ball is built by stacking latitudinal circles. Each circle is composed
- * of a widely-separated set of points, so that each facet is noticably large.
+ * of a widely-separated set of points, so that each facet is noticeably large.
*****************************************************************************/
void DrawBoingBall( void )
{
@@ -446,7 +446,7 @@ void DrawBoingBallBand( GLfloat long_lo,
static int colorToggle = 0;
/*
- * Iterate thru the points of a latitude circle.
+ * Iterate through the points of a latitude circle.
* A latitude circle is a 2D set of X,Z points.
*/
for ( lat_deg = 0;
diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h
index 38bf41df5..9556cede6 100644
--- a/include/GLFW/glfw3.h
+++ b/include/GLFW/glfw3.h
@@ -1171,9 +1171,9 @@ typedef void (* GLFWerrorfun)(int,const char*);
*
* @param[in] window The window that was moved.
* @param[in] xpos The new x-coordinate, in screen coordinates, of the
- * upper-left corner of the client area of the window.
+ * upper-left corner of the content area of the window.
* @param[in] ypos The new y-coordinate, in screen coordinates, of the
- * upper-left corner of the client area of the window.
+ * upper-left corner of the content area of the window.
*
* @sa @ref window_pos
* @sa @ref glfwSetWindowPosCallback
@@ -1350,9 +1350,9 @@ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int);
*
* @param[in] window The window that received the event.
* @param[in] xpos The new cursor x-coordinate, relative to the left edge of
- * the client area.
+ * the content area.
* @param[in] ypos The new cursor y-coordinate, relative to the top edge of the
- * client area.
+ * content area.
*
* @sa @ref cursor_pos
* @sa @ref glfwSetCursorPosCallback
@@ -1368,7 +1368,7 @@ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double);
* This is the function signature for cursor enter/leave callback functions.
*
* @param[in] window The window that received the event.
- * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client
+ * @param[in] entered `GLFW_TRUE` if the cursor entered the window's content
* area, or `GLFW_FALSE` if it left it.
*
* @sa @ref cursor_enter
@@ -2157,9 +2157,9 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
/*! @brief Generates a gamma ramp and sets it for the specified monitor.
*
- * This function generates a 256-element gamma ramp from the specified exponent
- * and then calls @ref glfwSetGammaRamp with it. The value must be a finite
- * number greater than zero.
+ * This function generates an appropriately sized gamma ramp from the specified
+ * exponent and then calls @ref glfwSetGammaRamp with it. The value must be
+ * a finite number greater than zero.
*
* The software controlled gamma ramp is applied _in addition_ to the hardware
* gamma correction, which today is usually an approximation of sRGB gamma.
@@ -2238,8 +2238,8 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
- * @remark Gamma ramp sizes other than 256 are not supported by all platforms
- * or graphics hardware.
+ * @remark The size of the specified gamma ramp should match the size of the
+ * current ramp for that monitor.
*
* @remark @win32 The gamma ramp size must be 256.
*
@@ -2645,19 +2645,19 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
*/
GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images);
-/*! @brief Retrieves the position of the client area of the specified window.
+/*! @brief Retrieves the position of the content area of the specified window.
*
* This function retrieves the position, in screen coordinates, of the
- * upper-left corner of the client area of the specified window.
+ * upper-left corner of the content area of the specified window.
*
* Any or all of the position arguments may be `NULL`. If an error occurs, all
* non-`NULL` position arguments will be set to zero.
*
* @param[in] window The window to query.
* @param[out] xpos Where to store the x-coordinate of the upper-left corner of
- * the client area, or `NULL`.
+ * the content area, or `NULL`.
* @param[out] ypos Where to store the y-coordinate of the upper-left corner of
- * the client area, or `NULL`.
+ * the content area, or `NULL`.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
@@ -2677,10 +2677,10 @@ GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* i
*/
GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
-/*! @brief Sets the position of the client area of the specified window.
+/*! @brief Sets the position of the content area of the specified window.
*
* This function sets the position, in screen coordinates, of the upper-left
- * corner of the client area of the specified windowed mode window. If the
+ * corner of the content area of the specified windowed mode window. If the
* window is a full screen window, this function does nothing.
*
* __Do not use this function__ to move an already visible window unless you
@@ -2690,8 +2690,8 @@ GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
* cannot and should not override these limits.
*
* @param[in] window The window to query.
- * @param[in] xpos The x-coordinate of the upper-left corner of the client area.
- * @param[in] ypos The y-coordinate of the upper-left corner of the client area.
+ * @param[in] xpos The x-coordinate of the upper-left corner of the content area.
+ * @param[in] ypos The y-coordinate of the upper-left corner of the content area.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
@@ -2712,9 +2712,9 @@ GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
*/
GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos);
-/*! @brief Retrieves the size of the client area of the specified window.
+/*! @brief Retrieves the size of the content area of the specified window.
*
- * This function retrieves the size, in screen coordinates, of the client area
+ * This function retrieves the size, in screen coordinates, of the content area
* of the specified window. If you wish to retrieve the size of the
* framebuffer of the window in pixels, see @ref glfwGetFramebufferSize.
*
@@ -2723,9 +2723,9 @@ GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos);
*
* @param[in] window The window whose size to retrieve.
* @param[out] width Where to store the width, in screen coordinates, of the
- * client area, or `NULL`.
+ * content area, or `NULL`.
* @param[out] height Where to store the height, in screen coordinates, of the
- * client area, or `NULL`.
+ * content area, or `NULL`.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
@@ -2744,7 +2744,7 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);
/*! @brief Sets the size limits of the specified window.
*
- * This function sets the size limits of the client area of the specified
+ * This function sets the size limits of the content area of the specified
* window. If the window is full screen, the size limits only take effect
* once it is made windowed. If the window is not resizable, this function
* does nothing.
@@ -2756,14 +2756,14 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);
* dimensions and all must be greater than or equal to zero.
*
* @param[in] window The window to set limits for.
- * @param[in] minwidth The minimum width, in screen coordinates, of the client
+ * @param[in] minwidth The minimum width, in screen coordinates, of the content
* area, or `GLFW_DONT_CARE`.
* @param[in] minheight The minimum height, in screen coordinates, of the
- * client area, or `GLFW_DONT_CARE`.
- * @param[in] maxwidth The maximum width, in screen coordinates, of the client
+ * content area, or `GLFW_DONT_CARE`.
+ * @param[in] maxwidth The maximum width, in screen coordinates, of the content
* area, or `GLFW_DONT_CARE`.
* @param[in] maxheight The maximum height, in screen coordinates, of the
- * client area, or `GLFW_DONT_CARE`.
+ * content area, or `GLFW_DONT_CARE`.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
@@ -2787,7 +2787,7 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minhe
/*! @brief Sets the aspect ratio of the specified window.
*
- * This function sets the required aspect ratio of the client area of the
+ * This function sets the required aspect ratio of the content area of the
* specified window. If the window is full screen, the aspect ratio only takes
* effect once it is made windowed. If the window is not resizable, this
* function does nothing.
@@ -2828,9 +2828,9 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minhe
*/
GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);
-/*! @brief Sets the size of the client area of the specified window.
+/*! @brief Sets the size of the content area of the specified window.
*
- * This function sets the size, in screen coordinates, of the client area of
+ * This function sets the size, in screen coordinates, of the content area of
* the specified window.
*
* For full screen windows, this function updates the resolution of its desired
@@ -2846,9 +2846,9 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);
*
* @param[in] window The window to resize.
* @param[in] width The desired width, in screen coordinates, of the window
- * client area.
+ * content area.
* @param[in] height The desired height, in screen coordinates, of the window
- * client area.
+ * content area.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
@@ -3252,7 +3252,7 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
* The window position is ignored when setting a monitor.
*
* When the monitor is `NULL`, the position, width and height are used to
- * place the window client area. The refresh rate is ignored when no monitor
+ * place the window content area. The refresh rate is ignored when no monitor
* is specified.
*
* If you only wish to update the resolution of a full screen window or the
@@ -3265,12 +3265,12 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
* @param[in] window The window whose monitor, size or video mode to set.
* @param[in] monitor The desired monitor, or `NULL` to set windowed mode.
* @param[in] xpos The desired x-coordinate of the upper-left corner of the
- * client area.
+ * content area.
* @param[in] ypos The desired y-coordinate of the upper-left corner of the
- * client area.
- * @param[in] width The desired with, in screen coordinates, of the client area
- * or video mode.
- * @param[in] height The desired height, in screen coordinates, of the client
+ * content area.
+ * @param[in] width The desired with, in screen coordinates, of the content
+ * area or video mode.
+ * @param[in] height The desired height, in screen coordinates, of the content
* area or video mode.
* @param[in] refreshRate The desired refresh rate, in Hz, of the video mode,
* or `GLFW_DONT_CARE`.
@@ -3420,8 +3420,8 @@ GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window);
*
* This function sets the position callback of the specified window, which is
* called when the window is moved. The callback is provided with the
- * position, in screen coordinates, of the upper-left corner of the client area
- * of the window.
+ * position, in screen coordinates, of the upper-left corner of the content
+ * area of the window.
*
* @param[in] window The window whose callback to set.
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
@@ -3448,7 +3448,7 @@ GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindow
*
* This function sets the size callback of the specified window, which is
* called when the window is resized. The callback is provided with the size,
- * in screen coordinates, of the client area of the window.
+ * in screen coordinates, of the content area of the window.
*
* @param[in] window The window whose callback to set.
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
@@ -3505,7 +3505,7 @@ GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwi
/*! @brief Sets the refresh callback for the specified window.
*
* This function sets the refresh callback of the specified window, which is
- * called when the client area of the window needs to be redrawn, for example
+ * called when the content area of the window needs to be redrawn, for example
* if the window has been exposed after having been covered by another window.
*
* On compositing window systems such as Aero, Compiz, Aqua or Wayland, where
@@ -3719,10 +3719,6 @@ GLFWAPI void glfwPollEvents(void);
* GLFW will pass those events on to the application callbacks before
* returning.
*
- * If no windows exist, this function returns immediately. For synchronization
- * of threads in applications that do not create windows, use your threading
- * library of choice.
- *
* Event processing is not required for joystick input to work.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
@@ -3770,14 +3766,13 @@ GLFWAPI void glfwWaitEvents(void);
* GLFW will pass those events on to the application callbacks before
* returning.
*
- * If no windows exist, this function returns immediately. For synchronization
- * of threads in applications that do not create windows, use your threading
- * library of choice.
- *
* Event processing is not required for joystick input to work.
*
* @param[in] timeout The maximum amount of time, in seconds, to wait.
*
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
+ *
* @reentrancy This function must not be called from a callback.
*
* @thread_safety This function must only be called from the main thread.
@@ -3797,10 +3792,6 @@ GLFWAPI void glfwWaitEventsTimeout(double timeout);
* This function posts an empty event from the current thread to the event
* queue, causing @ref glfwWaitEvents or @ref glfwWaitEventsTimeout to return.
*
- * If no windows exist, this function returns immediately. For synchronization
- * of threads in applications that do not create windows, use your threading
- * library of choice.
- *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
@@ -3850,8 +3841,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
* If the mode is `GLFW_CURSOR`, the value must be one of the following cursor
* modes:
* - `GLFW_CURSOR_NORMAL` makes the cursor visible and behaving normally.
- * - `GLFW_CURSOR_HIDDEN` makes the cursor invisible when it is over the client
- * area of the window but does not restrict the cursor from leaving.
+ * - `GLFW_CURSOR_HIDDEN` makes the cursor invisible when it is over the
+ * content area of the window but does not restrict the cursor from leaving.
* - `GLFW_CURSOR_DISABLED` hides and grabs the cursor, providing virtual
* and unlimited cursor movement. This is useful for implementing for
* example 3D camera controls.
@@ -4091,11 +4082,11 @@ GLFWAPI int glfwGetKey(GLFWwindow* window, int key);
*/
GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button);
-/*! @brief Retrieves the position of the cursor relative to the client area of
+/*! @brief Retrieves the position of the cursor relative to the content area of
* the window.
*
* This function returns the position of the cursor, in screen coordinates,
- * relative to the upper-left corner of the client area of the specified
+ * relative to the upper-left corner of the content area of the specified
* window.
*
* If the cursor is disabled (with `GLFW_CURSOR_DISABLED`) then the cursor
@@ -4111,9 +4102,9 @@ GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button);
*
* @param[in] window The desired window.
* @param[out] xpos Where to store the cursor x-coordinate, relative to the
- * left edge of the client area, or `NULL`.
+ * left edge of the content area, or `NULL`.
* @param[out] ypos Where to store the cursor y-coordinate, relative to the to
- * top edge of the client area, or `NULL`.
+ * top edge of the content area, or `NULL`.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
@@ -4129,11 +4120,11 @@ GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button);
*/
GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
-/*! @brief Sets the position of the cursor, relative to the client area of the
+/*! @brief Sets the position of the cursor, relative to the content area of the
* window.
*
* This function sets the position, in screen coordinates, of the cursor
- * relative to the upper-left corner of the client area of the specified
+ * relative to the upper-left corner of the content area of the specified
* window. The window must have input focus. If the window does not have
* input focus when this function is called, it fails silently.
*
@@ -4148,9 +4139,9 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
*
* @param[in] window The desired window.
* @param[in] xpos The desired x-coordinate, relative to the left edge of the
- * client area.
+ * content area.
* @param[in] ypos The desired y-coordinate, relative to the top edge of the
- * client area.
+ * content area.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
@@ -4260,7 +4251,7 @@ GLFWAPI void glfwDestroyCursor(GLFWcursor* cursor);
/*! @brief Sets the cursor for the window.
*
* This function sets the cursor image to be used when the cursor is over the
- * client area of the specified window. The set cursor will only be visible
+ * content area of the specified window. The set cursor will only be visible
* when the [cursor mode](@ref cursor_mode) of the window is
* `GLFW_CURSOR_NORMAL`.
*
@@ -4342,9 +4333,7 @@ GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun cbfun);
* The character callback behaves as system text input normally does and will
* not be called if modifier keys are held down that would prevent normal text
* input on that platform, for example a Super (Command) key on macOS or Alt key
- * on Windows. There is a
- * [character with modifiers callback](@ref glfwSetCharModsCallback) that
- * receives these events.
+ * on Windows.
*
* @param[in] window The window whose callback to set.
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
@@ -4435,7 +4424,7 @@ GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* window, GLFWmo
* This function sets the cursor position callback of the specified window,
* which is called when the cursor is moved. The callback is provided with the
* position, in screen coordinates, relative to the upper-left corner of the
- * client area of the window.
+ * content area of the window.
*
* @param[in] window The window whose callback to set.
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
@@ -4458,7 +4447,7 @@ GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* window, GLFWcursor
/*! @brief Sets the cursor enter/exit callback.
*
* This function sets the cursor boundary crossing callback of the specified
- * window, which is called when the cursor enters or leaves the client area of
+ * window, which is called when the cursor enters or leaves the content area of
* the window.
*
* @param[in] window The window whose callback to set.
diff --git a/src/cocoa_init.m b/src/cocoa_init.m
index 01a746bae..2f08144ab 100644
--- a/src/cocoa_init.m
+++ b/src/cocoa_init.m
@@ -27,6 +27,15 @@
#include "internal.h"
#include // For MAXPATHLEN
+// Needed for _NSGetProgname
+#include
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
+ #define NSEventMaskKeyUp NSKeyUpMask
+ #define NSEventModifierFlagCommand NSCommandKeyMask
+ #define NSEventModifierFlagControl NSControlKeyMask
+ #define NSEventModifierFlagOption NSAlternateKeyMask
+#endif
// Change to our application bundle's resources directory, if present
//
@@ -64,6 +73,111 @@ static void changeToResourcesDirectory(void)
chdir(resourcesPath);
}
+// Set up the menu bar (manually)
+// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
+// could go away at any moment, lots of stuff that really should be
+// localize(d|able), etc. Add a nib to save us this horror.
+//
+static void createMenuBar(void)
+{
+ size_t i;
+ NSString* appName = nil;
+ NSDictionary* bundleInfo = [[NSBundle mainBundle] infoDictionary];
+ NSString* nameKeys[] =
+ {
+ @"CFBundleDisplayName",
+ @"CFBundleName",
+ @"CFBundleExecutable",
+ };
+
+ // Try to figure out what the calling application is called
+
+ for (i = 0; i < sizeof(nameKeys) / sizeof(nameKeys[0]); i++)
+ {
+ id name = bundleInfo[nameKeys[i]];
+ if (name &&
+ [name isKindOfClass:[NSString class]] &&
+ ![name isEqualToString:@""])
+ {
+ appName = name;
+ break;
+ }
+ }
+
+ if (!appName)
+ {
+ char** progname = _NSGetProgname();
+ if (progname && *progname)
+ appName = @(*progname);
+ else
+ appName = @"GLFW Application";
+ }
+
+ NSMenu* bar = [[NSMenu alloc] init];
+ [NSApp setMainMenu:bar];
+
+ NSMenuItem* appMenuItem =
+ [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
+ NSMenu* appMenu = [[NSMenu alloc] init];
+ [appMenuItem setSubmenu:appMenu];
+
+ [appMenu addItemWithTitle:[NSString stringWithFormat:@"About %@", appName]
+ action:@selector(orderFrontStandardAboutPanel:)
+ keyEquivalent:@""];
+ [appMenu addItem:[NSMenuItem separatorItem]];
+ NSMenu* servicesMenu = [[NSMenu alloc] init];
+ [NSApp setServicesMenu:servicesMenu];
+ [[appMenu addItemWithTitle:@"Services"
+ action:NULL
+ keyEquivalent:@""] setSubmenu:servicesMenu];
+ [servicesMenu release];
+ [appMenu addItem:[NSMenuItem separatorItem]];
+ [appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName]
+ action:@selector(hide:)
+ keyEquivalent:@"h"];
+ [[appMenu addItemWithTitle:@"Hide Others"
+ action:@selector(hideOtherApplications:)
+ keyEquivalent:@"h"]
+ setKeyEquivalentModifierMask:NSEventModifierFlagOption | NSEventModifierFlagCommand];
+ [appMenu addItemWithTitle:@"Show All"
+ action:@selector(unhideAllApplications:)
+ keyEquivalent:@""];
+ [appMenu addItem:[NSMenuItem separatorItem]];
+ [appMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %@", appName]
+ action:@selector(terminate:)
+ keyEquivalent:@"q"];
+
+ NSMenuItem* windowMenuItem =
+ [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
+ [bar release];
+ NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
+ [NSApp setWindowsMenu:windowMenu];
+ [windowMenuItem setSubmenu:windowMenu];
+
+ [windowMenu addItemWithTitle:@"Minimize"
+ action:@selector(performMiniaturize:)
+ keyEquivalent:@"m"];
+ [windowMenu addItemWithTitle:@"Zoom"
+ action:@selector(performZoom:)
+ keyEquivalent:@""];
+ [windowMenu addItem:[NSMenuItem separatorItem]];
+ [windowMenu addItemWithTitle:@"Bring All to Front"
+ action:@selector(arrangeInFront:)
+ keyEquivalent:@""];
+
+ // TODO: Make this appear at the bottom of the menu (for consistency)
+ [windowMenu addItem:[NSMenuItem separatorItem]];
+ [[windowMenu addItemWithTitle:@"Enter Full Screen"
+ action:@selector(toggleFullScreen:)
+ keyEquivalent:@"f"]
+ setKeyEquivalentModifierMask:NSEventModifierFlagControl | NSEventModifierFlagCommand];
+
+ // Prior to Snow Leopard, we need to use this oddly-named semi-private API
+ // to get the application menu working properly.
+ SEL setAppleMenuSelector = NSSelectorFromString(@"setAppleMenu:");
+ [NSApp performSelector:setAppleMenuSelector withObject:appMenu];
+}
+
// Create key code translation tables
//
static void createKeyTables(void)
@@ -271,18 +385,93 @@ static GLFWbool initializeTIS(void)
return updateUnicodeDataNS();
}
-@interface GLFWLayoutListener : NSObject
+@interface GLFWHelper : NSObject
@end
-@implementation GLFWLayoutListener
+@implementation GLFWHelper
- (void)selectedKeyboardInputSourceChanged:(NSObject* )object
{
updateUnicodeDataNS();
}
+- (void)doNothing:(id)object
+{
+}
+
+@end // GLFWHelper
+
+@interface GLFWApplicationDelegate : NSObject
@end
+@implementation GLFWApplicationDelegate
+
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
+{
+ _GLFWwindow* window;
+
+ for (window = _glfw.windowListHead; window; window = window->next)
+ _glfwInputWindowCloseRequest(window);
+
+ return NSTerminateCancel;
+}
+
+- (void)applicationDidChangeScreenParameters:(NSNotification *) notification
+{
+ _GLFWwindow* window;
+
+ for (window = _glfw.windowListHead; window; window = window->next)
+ {
+ if (window->context.client != GLFW_NO_API)
+ [window->context.nsgl.object update];
+ }
+
+ _glfwPollMonitorsNS();
+}
+
+- (void)applicationWillFinishLaunching:(NSNotification *)notification
+{
+ if (_glfw.hints.init.ns.menubar)
+ {
+ // In case we are unbundled, make us a proper UI application
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+
+ // Menu bar setup must go between sharedApplication above and
+ // finishLaunching below, in order to properly emulate the behavior
+ // of NSApplicationMain
+
+ if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
+ {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
+ [[NSBundle mainBundle] loadNibNamed:@"MainMenu"
+ owner:NSApp
+ topLevelObjects:&_glfw.ns.nibObjects];
+#else
+ [[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:NSApp];
+#endif
+ }
+ else
+ createMenuBar();
+ }
+}
+
+- (void)applicationDidFinishLaunching:(NSNotification *)notification
+{
+ [NSApp stop:nil];
+
+ _glfwPlatformPostEmptyEvent();
+}
+
+- (void)applicationDidHide:(NSNotification *)notification
+{
+ int i;
+
+ for (i = 0; i < _glfw.monitorCount; i++)
+ _glfwRestoreVideoModeNS(_glfw.monitors[i]);
+}
+
+@end // GLFWApplicationDelegate
+
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
@@ -291,13 +480,45 @@ static GLFWbool initializeTIS(void)
int _glfwPlatformInit(void)
{
_glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
+ _glfw.ns.helper = [[GLFWHelper alloc] init];
+
+ [NSThread detachNewThreadSelector:@selector(doNothing:)
+ toTarget:_glfw.ns.helper
+ withObject:nil];
+
+ [NSApplication sharedApplication];
+
+ _glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init];
+ if (_glfw.ns.delegate == nil)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to create application delegate");
+ return GLFW_FALSE;
+ }
+
+ [NSApp setDelegate:_glfw.ns.delegate];
+
+ NSEvent* (^block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
+ {
+ if ([event modifierFlags] & NSEventModifierFlagCommand)
+ [[NSApp keyWindow] sendEvent:event];
+
+ return event;
+ };
+
+ _glfw.ns.keyUpMonitor =
+ [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyUp
+ handler:block];
if (_glfw.hints.init.ns.chdir)
changeToResourcesDirectory();
- _glfw.ns.listener = [[GLFWLayoutListener alloc] init];
+ // Press and Hold prevents some keys from emitting repeated characters
+ NSDictionary* defaults = @{@"ApplePressAndHoldEnabled":@NO};
+ [[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
+
[[NSNotificationCenter defaultCenter]
- addObserver:_glfw.ns.listener
+ addObserver:_glfw.ns.helper
selector:@selector(selectedKeyboardInputSourceChanged:)
name:NSTextInputContextKeyboardSelectionDidChangeNotification
object:nil];
@@ -342,18 +563,21 @@ void _glfwPlatformTerminate(void)
_glfw.ns.delegate = nil;
}
- if (_glfw.ns.listener)
+ if (_glfw.ns.helper)
{
[[NSNotificationCenter defaultCenter]
- removeObserver:_glfw.ns.listener
+ removeObserver:_glfw.ns.helper
name:NSTextInputContextKeyboardSelectionDidChangeNotification
object:nil];
[[NSNotificationCenter defaultCenter]
- removeObserver:_glfw.ns.listener];
- [_glfw.ns.listener release];
- _glfw.ns.listener = nil;
+ removeObserver:_glfw.ns.helper];
+ [_glfw.ns.helper release];
+ _glfw.ns.helper = nil;
}
+ if (_glfw.ns.keyUpMonitor)
+ [NSEvent removeMonitor:_glfw.ns.keyUpMonitor];
+
free(_glfw.ns.clipboardString);
_glfwTerminateNSGL();
diff --git a/src/cocoa_joystick.m b/src/cocoa_joystick.m
index 0831809f8..1c2818f01 100644
--- a/src/cocoa_joystick.m
+++ b/src/cocoa_joystick.m
@@ -220,9 +220,18 @@ static void matchCallback(void* context,
case kHIDUsage_GD_Hatswitch:
target = hats;
break;
+ case kHIDUsage_GD_DPadUp:
+ case kHIDUsage_GD_DPadRight:
+ case kHIDUsage_GD_DPadDown:
+ case kHIDUsage_GD_DPadLeft:
+ case kHIDUsage_GD_SystemMainMenu:
+ case kHIDUsage_GD_Select:
+ case kHIDUsage_GD_Start:
+ target = buttons;
+ break;
}
}
- else if (page == kHIDPage_Button)
+ else if (page == kHIDPage_Button || page == kHIDPage_Consumer)
target = buttons;
if (target)
@@ -397,12 +406,12 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
if (raw > axis->maximum)
axis->maximum = raw;
- const long delta = axis->maximum - axis->minimum;
- if (delta == 0)
+ const long size = axis->maximum - axis->minimum;
+ if (size == 0)
_glfwInputJoystickAxis(js, (int) i, 0.f);
else
{
- const float value = (2.f * (raw - axis->minimum) / delta) - 1.f;
+ const float value = (2.f * (raw - axis->minimum) / size) - 1.f;
_glfwInputJoystickAxis(js, (int) i, value);
}
}
@@ -417,7 +426,8 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
CFArrayGetValueAtIndex(js->ns.buttons, i);
const char value = getElementValue(js, button) - button->minimum;
- _glfwInputJoystickButton(js, (int) i, value);
+ const int state = (value > 0) ? GLFW_PRESS : GLFW_RELEASE;
+ _glfwInputJoystickButton(js, (int) i, state);
}
for (i = 0; i < CFArrayGetCount(js->ns.hats); i++)
diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m
index 986d799e7..955d52d15 100644
--- a/src/cocoa_monitor.m
+++ b/src/cocoa_monitor.m
@@ -374,14 +374,10 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
{
if (!monitor->ns.screen)
{
- NSUInteger i;
- NSArray* screens = [NSScreen screens];
-
- for (i = 0; i < [screens count]; i++)
+ for (NSScreen* screen in [NSScreen screens])
{
- NSScreen* screen = [screens objectAtIndex:i];
NSNumber* displayID =
- [[screen deviceDescription] objectForKey:@"NSScreenNumber"];
+ [screen deviceDescription][@"NSScreenNumber"];
// HACK: Compare unit numbers instead of display IDs to work around
// display replacement on machines with automatic graphics
@@ -394,7 +390,7 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
}
}
- if (i == [screens count])
+ if (!monitor->ns.screen)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Cocoa: Failed to find a screen for monitor");
@@ -467,7 +463,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
CVDisplayLinkRelease(link);
}
-void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
uint32_t i, size = CGDisplayGammaTableCapacity(monitor->ns.displayID);
CGGammaValue* values = calloc(size * 3, sizeof(CGGammaValue));
@@ -489,6 +485,7 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
}
free(values);
+ return GLFW_TRUE;
}
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h
index 282f7cc8b..cf7ead59e 100644
--- a/src/cocoa_platform.h
+++ b/src/cocoa_platform.h
@@ -105,11 +105,14 @@ typedef struct _GLFWlibraryNS
CGEventSourceRef eventSource;
id delegate;
id autoreleasePool;
+ GLFWbool finishedLaunching;
GLFWbool cursorHidden;
TISInputSourceRef inputSource;
IOHIDManagerRef hidManager;
id unicodeData;
- id listener;
+ id helper;
+ id keyUpMonitor;
+ id nibObjects;
char keyName[64];
short int keycodes[256];
diff --git a/src/cocoa_window.m b/src/cocoa_window.m
index b2119881d..e3e20de79 100644
--- a/src/cocoa_window.m
+++ b/src/cocoa_window.m
@@ -29,9 +29,6 @@
#include
#include
-// Needed for _NSGetProgname
-#include
-
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
#define NSWindowStyleMaskBorderless NSBorderlessWindowMask
#define NSWindowStyleMaskClosable NSClosableWindowMask
@@ -46,7 +43,6 @@
#define NSEventModifierFlagDeviceIndependentFlagsMask NSDeviceIndependentModifierFlagsMask
#define NSEventMaskAny NSAnyEventMask
#define NSEventTypeApplicationDefined NSApplicationDefined
- #define NSEventTypeKeyUp NSKeyUp
#define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
#endif
@@ -71,18 +67,9 @@ static NSUInteger getStyleMask(_GLFWwindow* window)
return styleMask;
}
-// Center the cursor in the view of the window
+// Returns whether the cursor is in the content area of the specified window
//
-static void centerCursor(_GLFWwindow *window)
-{
- int width, height;
- _glfwPlatformGetWindowSize(window, &width, &height);
- _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
-}
-
-// Returns whether the cursor is in the client area of the specified window
-//
-static GLFWbool cursorInClientArea(_GLFWwindow* window)
+static GLFWbool cursorInContentArea(_GLFWwindow* window)
{
const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
return [window->ns.view mouse:pos inRect:[window->ns.view frame]];
@@ -137,7 +124,7 @@ static void updateCursorMode(_GLFWwindow* window)
_glfwPlatformGetCursorPos(window,
&_glfw.ns.restoreCursorPosX,
&_glfw.ns.restoreCursorPosY);
- centerCursor(window);
+ _glfwCenterCursorInContentArea(window);
CGAssociateMouseAndMouseCursorPosition(false);
}
else if (_glfw.ns.disabledCursorWindow == window)
@@ -149,7 +136,7 @@ static void updateCursorMode(_GLFWwindow* window)
_glfw.ns.restoreCursorPosY);
}
- if (cursorInClientArea(window))
+ if (cursorInContentArea(window))
updateCursorImage(window);
}
@@ -236,6 +223,8 @@ static NSUInteger translateKeyToModifierFlag(int key)
case GLFW_KEY_LEFT_SUPER:
case GLFW_KEY_RIGHT_SUPER:
return NSEventModifierFlagCommand;
+ case GLFW_KEY_CAPS_LOCK:
+ return NSEventModifierFlagCapsLock;
}
return 0;
@@ -282,7 +271,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
[window->context.nsgl.object update];
if (_glfw.ns.disabledCursorWindow == window)
- centerCursor(window);
+ _glfwCenterCursorInContentArea(window);
const int maximized = [window->ns.object isZoomed];
if (window->ns.maximized != maximized)
@@ -317,7 +306,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
[window->context.nsgl.object update];
if (_glfw.ns.disabledCursorWindow == window)
- centerCursor(window);
+ _glfwCenterCursorInContentArea(window);
int x, y;
_glfwPlatformGetWindowPos(window, &x, &y);
@@ -343,7 +332,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)windowDidBecomeKey:(NSNotification *)notification
{
if (_glfw.ns.disabledCursorWindow == window)
- centerCursor(window);
+ _glfwCenterCursorInContentArea(window);
_glfwInputWindowFocus(window, GLFW_TRUE);
updateCursorMode(window);
@@ -360,56 +349,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
@end
-//------------------------------------------------------------------------
-// Delegate for application related notifications
-//------------------------------------------------------------------------
-
-@interface GLFWApplicationDelegate : NSObject
-@end
-
-@implementation GLFWApplicationDelegate
-
-- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
-{
- _GLFWwindow* window;
-
- for (window = _glfw.windowListHead; window; window = window->next)
- _glfwInputWindowCloseRequest(window);
-
- return NSTerminateCancel;
-}
-
-- (void)applicationDidChangeScreenParameters:(NSNotification *) notification
-{
- _GLFWwindow* window;
-
- for (window = _glfw.windowListHead; window; window = window->next)
- {
- if (window->context.client != GLFW_NO_API)
- [window->context.nsgl.object update];
- }
-
- _glfwPollMonitorsNS();
-}
-
-- (void)applicationDidFinishLaunching:(NSNotification *)notification
-{
- [NSApp stop:nil];
-
- _glfwPlatformPostEmptyEvent();
-}
-
-- (void)applicationDidHide:(NSNotification *)notification
-{
- int i;
-
- for (i = 0; i < _glfw.monitorCount; i++)
- _glfwRestoreVideoModeNS(_glfw.monitors[i]);
-}
-
-@end
-
-
//------------------------------------------------------------------------
// Content view class for the GLFW window
//------------------------------------------------------------------------
@@ -493,6 +432,11 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
updateCursorImage(window);
}
+- (BOOL)acceptsFirstMouse:(NSEvent *)event
+{
+ return YES;
+}
+
- (void)mouseDown:(NSEvent *)event
{
_glfwInputMouseClick(window,
@@ -658,7 +602,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
_glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
- [self interpretKeyEvents:[NSArray arrayWithObject:event]];
+ [self interpretKeyEvents:@[event]];
}
- (void)flagsChanged:(NSEvent *)event
@@ -731,7 +675,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
char** paths = calloc(count, sizeof(char*));
for (NSUInteger i = 0; i < count; i++)
- paths[i] = _glfw_strdup([[urls objectAtIndex:i] fileSystemRepresentation]);
+ paths[i] = _glfw_strdup([urls[i] fileSystemRepresentation]);
_glfwInputDrop(window, (int) count, (const char**) paths);
@@ -856,210 +800,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
@end
-//------------------------------------------------------------------------
-// GLFW application class
-//------------------------------------------------------------------------
-
-@interface GLFWApplication : NSApplication
-{
- NSArray* nibObjects;
-}
-
-@end
-
-@implementation GLFWApplication
-
-// From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost
-// This works around an AppKit bug, where key up events while holding
-// down the command key don't get sent to the key window.
-- (void)sendEvent:(NSEvent *)event
-{
- if ([event type] == NSEventTypeKeyUp &&
- ([event modifierFlags] & NSEventModifierFlagCommand))
- {
- [[self keyWindow] sendEvent:event];
- }
- else
- [super sendEvent:event];
-}
-
-
-// No-op thread entry point
-//
-- (void)doNothing:(id)object
-{
-}
-
-- (void)loadMainMenu
-{
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
- [[NSBundle mainBundle] loadNibNamed:@"MainMenu"
- owner:NSApp
- topLevelObjects:&nibObjects];
-#else
- [[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:NSApp];
-#endif
-}
-@end
-
-// Set up the menu bar (manually)
-// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
-// could go away at any moment, lots of stuff that really should be
-// localize(d|able), etc. Add a nib to save us this horror.
-//
-static void createMenuBar(void)
-{
- size_t i;
- NSString* appName = nil;
- NSDictionary* bundleInfo = [[NSBundle mainBundle] infoDictionary];
- NSString* nameKeys[] =
- {
- @"CFBundleDisplayName",
- @"CFBundleName",
- @"CFBundleExecutable",
- };
-
- // Try to figure out what the calling application is called
-
- for (i = 0; i < sizeof(nameKeys) / sizeof(nameKeys[0]); i++)
- {
- id name = [bundleInfo objectForKey:nameKeys[i]];
- if (name &&
- [name isKindOfClass:[NSString class]] &&
- ![name isEqualToString:@""])
- {
- appName = name;
- break;
- }
- }
-
- if (!appName)
- {
- char** progname = _NSGetProgname();
- if (progname && *progname)
- appName = [NSString stringWithUTF8String:*progname];
- else
- appName = @"GLFW Application";
- }
-
- NSMenu* bar = [[NSMenu alloc] init];
- [NSApp setMainMenu:bar];
-
- NSMenuItem* appMenuItem =
- [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
- NSMenu* appMenu = [[NSMenu alloc] init];
- [appMenuItem setSubmenu:appMenu];
-
- [appMenu addItemWithTitle:[NSString stringWithFormat:@"About %@", appName]
- action:@selector(orderFrontStandardAboutPanel:)
- keyEquivalent:@""];
- [appMenu addItem:[NSMenuItem separatorItem]];
- NSMenu* servicesMenu = [[NSMenu alloc] init];
- [NSApp setServicesMenu:servicesMenu];
- [[appMenu addItemWithTitle:@"Services"
- action:NULL
- keyEquivalent:@""] setSubmenu:servicesMenu];
- [servicesMenu release];
- [appMenu addItem:[NSMenuItem separatorItem]];
- [appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName]
- action:@selector(hide:)
- keyEquivalent:@"h"];
- [[appMenu addItemWithTitle:@"Hide Others"
- action:@selector(hideOtherApplications:)
- keyEquivalent:@"h"]
- setKeyEquivalentModifierMask:NSEventModifierFlagOption | NSEventModifierFlagCommand];
- [appMenu addItemWithTitle:@"Show All"
- action:@selector(unhideAllApplications:)
- keyEquivalent:@""];
- [appMenu addItem:[NSMenuItem separatorItem]];
- [appMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %@", appName]
- action:@selector(terminate:)
- keyEquivalent:@"q"];
-
- NSMenuItem* windowMenuItem =
- [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
- [bar release];
- NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
- [NSApp setWindowsMenu:windowMenu];
- [windowMenuItem setSubmenu:windowMenu];
-
- [windowMenu addItemWithTitle:@"Minimize"
- action:@selector(performMiniaturize:)
- keyEquivalent:@"m"];
- [windowMenu addItemWithTitle:@"Zoom"
- action:@selector(performZoom:)
- keyEquivalent:@""];
- [windowMenu addItem:[NSMenuItem separatorItem]];
- [windowMenu addItemWithTitle:@"Bring All to Front"
- action:@selector(arrangeInFront:)
- keyEquivalent:@""];
-
- // TODO: Make this appear at the bottom of the menu (for consistency)
- [windowMenu addItem:[NSMenuItem separatorItem]];
- [[windowMenu addItemWithTitle:@"Enter Full Screen"
- action:@selector(toggleFullScreen:)
- keyEquivalent:@"f"]
- setKeyEquivalentModifierMask:NSEventModifierFlagControl | NSEventModifierFlagCommand];
-
- // Prior to Snow Leopard, we need to use this oddly-named semi-private API
- // to get the application menu working properly.
- SEL setAppleMenuSelector = NSSelectorFromString(@"setAppleMenu:");
- [NSApp performSelector:setAppleMenuSelector withObject:appMenu];
-}
-
-// Initialize the Cocoa Application Kit
-//
-static GLFWbool initializeAppKit(void)
-{
- if (NSApp)
- return GLFW_TRUE;
-
- // Implicitly create shared NSApplication instance
- [GLFWApplication sharedApplication];
-
- // Make Cocoa enter multi-threaded mode
- [NSThread detachNewThreadSelector:@selector(doNothing:)
- toTarget:NSApp
- withObject:nil];
-
- if (_glfw.hints.init.ns.menubar)
- {
- // In case we are unbundled, make us a proper UI application
- [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
-
- // Menu bar setup must go between sharedApplication above and
- // finishLaunching below, in order to properly emulate the behavior
- // of NSApplicationMain
-
- if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
- [NSApp loadMainMenu];
- else
- createMenuBar();
- }
-
- // There can only be one application delegate, but we allocate it the
- // first time a window is created to keep all window code in this file
- _glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init];
- if (_glfw.ns.delegate == nil)
- {
- _glfwInputError(GLFW_PLATFORM_ERROR,
- "Cocoa: Failed to create application delegate");
- return GLFW_FALSE;
- }
-
- [NSApp setDelegate:_glfw.ns.delegate];
- [NSApp run];
-
- // Press and Hold prevents some keys from emitting repeated characters
- NSDictionary* defaults =
- [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO],
- @"ApplePressAndHoldEnabled",
- nil];
- [[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
-
- return GLFW_TRUE;
-}
-
// Create the Cocoa window
//
static GLFWbool createNativeWindow(_GLFWwindow* window,
@@ -1126,7 +866,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
}
if (strlen(wndconfig->ns.frameName))
- [window->ns.object setFrameAutosaveName:[NSString stringWithUTF8String:wndconfig->ns.frameName]];
+ [window->ns.object setFrameAutosaveName:@(wndconfig->ns.frameName)];
window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
@@ -1141,10 +881,13 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
[window->ns.object setContentView:window->ns.view];
[window->ns.object makeFirstResponder:window->ns.view];
- [window->ns.object setTitle:[NSString stringWithUTF8String:wndconfig->title]];
+ [window->ns.object setTitle:@(wndconfig->title)];
[window->ns.object setDelegate:window->ns.delegate];
[window->ns.object setAcceptsMouseMovedEvents:YES];
[window->ns.object setRestorable:NO];
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
+ [window->ns.object setTabbingMode:NSWindowTabbingModeDisallowed];
+#endif
_glfwPlatformGetWindowSize(window, &window->ns.width, &window->ns.height);
_glfwPlatformGetFramebufferSize(window, &window->ns.fbWidth, &window->ns.fbHeight);
@@ -1162,8 +905,11 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
- if (!initializeAppKit())
- return GLFW_FALSE;
+ if (!_glfw.ns.finishedLaunching)
+ {
+ [NSApp run];
+ _glfw.ns.finishedLaunching = GLFW_TRUE;
+ }
if (!createNativeWindow(window, wndconfig, fbconfig))
return GLFW_FALSE;
@@ -1232,11 +978,10 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char *title)
{
- NSString* string = [NSString stringWithUTF8String:title];
- [window->ns.object setTitle:string];
+ [window->ns.object setTitle:@(title)];
// HACK: Set the miniwindow title explicitly as setTitle: doesn't update it
// if the window lacks NSWindowStyleMaskTitled
- [window->ns.object setMiniwindowTitle:string];
+ [window->ns.object setMiniwindowTitle:@(title)];
}
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
@@ -1387,9 +1132,9 @@ void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
void _glfwPlatformFocusWindow(_GLFWwindow* window)
{
// Make us the active application
- // HACK: This has been moved here from initializeAppKit to prevent
- // applications using only hidden windows from being activated, but
- // should probably not be done every time any window is shown
+ // HACK: This is here to prevent applications using only hidden windows from
+ // being activated, but should probably not be done every time any
+ // window is shown
[NSApp activateIgnoringOtherApps:YES];
[window->ns.object makeKeyAndOrderFront:nil];
@@ -1564,9 +1309,6 @@ GLFWbool _glfwPlatformRawInputSupported(void)
void _glfwPlatformPollEvents(void)
{
- if (!initializeAppKit())
- return;
-
for (;;)
{
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
@@ -1717,9 +1459,6 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
NSImage* native;
NSBitmapImageRep* rep;
- if (!initializeAppKit())
- return GLFW_FALSE;
-
rep = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:NULL
pixelsWide:image->width
@@ -1755,9 +1494,6 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
{
- if (!initializeAppKit())
- return GLFW_FALSE;
-
if (shape == GLFW_ARROW_CURSOR)
cursor->ns.object = [NSCursor arrowCursor];
else if (shape == GLFW_IBEAM_CURSOR)
@@ -1790,18 +1526,15 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
{
- if (cursorInClientArea(window))
+ if (cursorInContentArea(window))
updateCursorImage(window);
}
void _glfwPlatformSetClipboardString(const char* string)
{
- NSArray* types = [NSArray arrayWithObjects:NSPasteboardTypeString, nil];
-
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
- [pasteboard declareTypes:types owner:nil];
- [pasteboard setString:[NSString stringWithUTF8String:string]
- forType:NSPasteboardTypeString];
+ [pasteboard declareTypes:@[NSPasteboardTypeString] owner:nil];
+ [pasteboard setString:@(string) forType:NSPasteboardTypeString];
}
const char* _glfwPlatformGetClipboardString(void)
diff --git a/src/context.c b/src/context.c
index fd344cf15..385085225 100644
--- a/src/context.c
+++ b/src/context.c
@@ -358,7 +358,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
window->context.source = ctxconfig->source;
window->context.client = GLFW_OPENGL_API;
- previous = _glfwPlatformGetTls(&_glfw.contextSlot);;
+ previous = _glfwPlatformGetTls(&_glfw.contextSlot);
glfwMakeContextCurrent((GLFWwindow*) window);
window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
diff --git a/src/init.c b/src/init.c
index 9e670d423..4f424c4a9 100644
--- a/src/init.c
+++ b/src/init.c
@@ -119,6 +119,30 @@ char* _glfw_strdup(const char* source)
return result;
}
+float _glfw_fminf(float a, float b)
+{
+ if (a != a)
+ return b;
+ else if (b != b)
+ return a;
+ else if (a < b)
+ return a;
+ else
+ return b;
+}
+
+float _glfw_fmaxf(float a, float b)
+{
+ if (a != a)
+ return b;
+ else if (b != b)
+ return a;
+ else if (a > b)
+ return a;
+ else
+ return b;
+}
+
//////////////////////////////////////////////////////////////////////////
////// GLFW event API //////
diff --git a/src/input.c b/src/input.c
index fdc543f6e..ef14fad53 100644
--- a/src/input.c
+++ b/src/input.c
@@ -333,7 +333,7 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
}
// Notifies shared code of a cursor motion event
-// The position is specified in client-area relative screen coordinates
+// The position is specified in content area relative screen coordinates
//
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
{
@@ -453,6 +453,15 @@ void _glfwFreeJoystick(_GLFWjoystick* js)
memset(js, 0, sizeof(_GLFWjoystick));
}
+// Center the cursor in the content area of the specified window
+//
+void _glfwCenterCursorInContentArea(_GLFWwindow* window)
+{
+ int width, height;
+
+ _glfwPlatformGetWindowSize(window, &width, &height);
+ _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
+}
//////////////////////////////////////////////////////////////////////////
////// GLFW public API //////
@@ -1252,7 +1261,7 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
if (e->type == _GLFW_JOYSTICK_AXIS)
{
const float value = js->axes[e->index] * e->axisScale + e->axisOffset;
- state->axes[i] = fminf(fmaxf(value, -1.f), 1.f);
+ state->axes[i] = _glfw_fminf(_glfw_fmaxf(value, -1.f), 1.f);
}
else if (e->type == _GLFW_JOYSTICK_HATBIT)
{
diff --git a/src/internal.h b/src/internal.h
index bee1019c2..65d77cc17 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -614,7 +614,7 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
float* xscale, float* yscale);
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
-void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
+GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
void _glfwPlatformSetClipboardString(const char* string);
@@ -763,10 +763,13 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
int buttonCount,
int hatCount);
void _glfwFreeJoystick(_GLFWjoystick* js);
+void _glfwCenterCursorInContentArea(_GLFWwindow* window);
GLFWbool _glfwInitVulkan(int mode);
void _glfwTerminateVulkan(void);
const char* _glfwGetVulkanResultString(VkResult result);
char* _glfw_strdup(const char* source);
+float _glfw_fminf(float a, float b);
+float _glfw_fmaxf(float a, float b);
diff --git a/src/monitor.c b/src/monitor.c
index f7de5500f..0ab865e3b 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -427,12 +427,12 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle)
GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
{
- int i;
- unsigned short values[256];
+ unsigned int i;
+ unsigned short* values;
GLFWgammaramp ramp;
+ const GLFWgammaramp* original;
assert(handle != NULL);
- assert(gamma == gamma);
- assert(gamma >= 0.f);
+ assert(gamma > 0.f);
assert(gamma <= FLT_MAX);
_GLFW_REQUIRE_INIT();
@@ -443,18 +443,22 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
return;
}
- for (i = 0; i < 256; i++)
+ original = glfwGetGammaRamp(handle);
+ if (!original)
+ return;
+
+ values = calloc(original->size, sizeof(unsigned short));
+
+ for (i = 0; i < original->size; i++)
{
float value;
// Calculate intensity
- value = i / 255.f;
+ value = i / (float) (original->size - 1);
// Apply gamma curve
value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
-
// Clamp to value range
- if (value > 65535.f)
- value = 65535.f;
+ value = _glfw_fminf(value, 65535.f);
values[i] = (unsigned short) value;
}
@@ -462,9 +466,10 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
ramp.red = values;
ramp.green = values;
ramp.blue = values;
- ramp.size = 256;
+ ramp.size = original->size;
glfwSetGammaRamp(handle, &ramp);
+ free(values);
}
GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
@@ -475,7 +480,8 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_glfwFreeGammaArrays(&monitor->currentRamp);
- _glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp);
+ if (!_glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp))
+ return NULL;
return &monitor->currentRamp;
}
@@ -501,7 +507,10 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
_GLFW_REQUIRE_INIT();
if (!monitor->originalRamp.size)
- _glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp);
+ {
+ if (!_glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp))
+ return;
+ }
_glfwPlatformSetGammaRamp(monitor, ramp);
}
diff --git a/src/null_monitor.c b/src/null_monitor.c
index 84b41c7e3..45c4a10f8 100644
--- a/src/null_monitor.c
+++ b/src/null_monitor.c
@@ -58,8 +58,9 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
{
}
-void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
+ return GLFW_FALSE;
}
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
diff --git a/src/osmesa_context.c b/src/osmesa_context.c
index a7de33f26..03651ebf4 100644
--- a/src/osmesa_context.c
+++ b/src/osmesa_context.c
@@ -240,7 +240,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
if (ctxconfig->forward)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
- "OSMesa: Foward-compatible contexts not supported");
+ "OSMesa: Forward-compatible contexts not supported");
return GLFW_FALSE;
}
diff --git a/src/wgl_context.c b/src/wgl_context.c
index 06ba8b55a..0ffe2cfce 100644
--- a/src/wgl_context.c
+++ b/src/wgl_context.c
@@ -31,27 +31,34 @@
#include
#include
-
-// Returns the specified attribute of the specified pixel format
+// Return the value corresponding to the specified attribute
//
-static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib)
+static int findPixelFormatAttribValue(const int* attribs,
+ int attribCount,
+ const int* values,
+ int attrib)
{
- int value = 0;
+ int i;
- assert(_glfw.wgl.ARB_pixel_format);
-
- if (!_glfw.wgl.GetPixelFormatAttribivARB(window->context.wgl.dc,
- pixelFormat,
- 0, 1, &attrib, &value))
+ for (i = 0; i < attribCount; i++)
{
- _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
- "WGL: Failed to retrieve pixel format attribute");
- return 0;
+ if (attribs[i] == attrib)
+ return values[i];
}
- return value;
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "WGL: Unknown pixel format attribute requested");
+ return 0;
}
+#define addAttrib(a) \
+{ \
+ assert((size_t) attribCount < sizeof(attribs) / sizeof(attribs[0])); \
+ attribs[attribCount++] = a; \
+}
+#define findAttribValue(a) \
+ findPixelFormatAttribValue(attribs, attribCount, values, a)
+
// Return a list of available and usable framebuffer configs
//
static int choosePixelFormat(_GLFWwindow* window,
@@ -60,13 +67,58 @@ static int choosePixelFormat(_GLFWwindow* window,
{
_GLFWfbconfig* usableConfigs;
const _GLFWfbconfig* closest;
- int i, pixelFormat, nativeCount, usableCount;
+ int i, pixelFormat, nativeCount, usableCount = 0, attribCount = 0;
+ int attribs[40];
+ int values[sizeof(attribs) / sizeof(attribs[0])];
if (_glfw.wgl.ARB_pixel_format)
{
- nativeCount = getPixelFormatAttrib(window,
- 1,
- WGL_NUMBER_PIXEL_FORMATS_ARB);
+ const int attrib = WGL_NUMBER_PIXEL_FORMATS_ARB;
+
+ if (!_glfw.wgl.GetPixelFormatAttribivARB(window->context.wgl.dc,
+ 1, 0, 1, &attrib, &nativeCount))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to retrieve pixel format attribute");
+ return 0;
+ }
+
+ addAttrib(WGL_SUPPORT_OPENGL_ARB);
+ addAttrib(WGL_DRAW_TO_WINDOW_ARB);
+ addAttrib(WGL_PIXEL_TYPE_ARB);
+ addAttrib(WGL_ACCELERATION_ARB);
+ addAttrib(WGL_RED_BITS_ARB);
+ addAttrib(WGL_RED_SHIFT_ARB);
+ addAttrib(WGL_GREEN_BITS_ARB);
+ addAttrib(WGL_GREEN_SHIFT_ARB);
+ addAttrib(WGL_BLUE_BITS_ARB);
+ addAttrib(WGL_BLUE_SHIFT_ARB);
+ addAttrib(WGL_ALPHA_BITS_ARB);
+ addAttrib(WGL_ALPHA_SHIFT_ARB);
+ addAttrib(WGL_DEPTH_BITS_ARB);
+ addAttrib(WGL_STENCIL_BITS_ARB);
+ addAttrib(WGL_ACCUM_BITS_ARB);
+ addAttrib(WGL_ACCUM_RED_BITS_ARB);
+ addAttrib(WGL_ACCUM_GREEN_BITS_ARB);
+ addAttrib(WGL_ACCUM_BLUE_BITS_ARB);
+ addAttrib(WGL_ACCUM_ALPHA_BITS_ARB);
+ addAttrib(WGL_AUX_BUFFERS_ARB);
+ addAttrib(WGL_STEREO_ARB);
+ addAttrib(WGL_DOUBLE_BUFFER_ARB);
+
+ if (_glfw.wgl.ARB_multisample)
+ addAttrib(WGL_SAMPLES_ARB);
+
+ if (ctxconfig->client == GLFW_OPENGL_API)
+ {
+ if (_glfw.wgl.ARB_framebuffer_sRGB || _glfw.wgl.EXT_framebuffer_sRGB)
+ addAttrib(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
+ }
+ else
+ {
+ if (_glfw.wgl.EXT_colorspace)
+ addAttrib(WGL_COLORSPACE_EXT);
+ }
}
else
{
@@ -77,64 +129,67 @@ static int choosePixelFormat(_GLFWwindow* window,
}
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
- usableCount = 0;
for (i = 0; i < nativeCount; i++)
{
- const int n = i + 1;
_GLFWfbconfig* u = usableConfigs + usableCount;
+ pixelFormat = i + 1;
if (_glfw.wgl.ARB_pixel_format)
{
// Get pixel format attributes through "modern" extension
- if (!getPixelFormatAttrib(window, n, WGL_SUPPORT_OPENGL_ARB) ||
- !getPixelFormatAttrib(window, n, WGL_DRAW_TO_WINDOW_ARB))
+ if (!_glfw.wgl.GetPixelFormatAttribivARB(window->context.wgl.dc,
+ pixelFormat, 0,
+ attribCount,
+ attribs, values))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to retrieve pixel format attributes");
+ return 0;
+ }
+
+ if (!findAttribValue(WGL_SUPPORT_OPENGL_ARB) ||
+ !findAttribValue(WGL_DRAW_TO_WINDOW_ARB))
{
continue;
}
- if (getPixelFormatAttrib(window, n, WGL_PIXEL_TYPE_ARB) !=
- WGL_TYPE_RGBA_ARB)
- {
+ if (findAttribValue(WGL_PIXEL_TYPE_ARB) != WGL_TYPE_RGBA_ARB)
continue;
- }
- if (getPixelFormatAttrib(window, n, WGL_ACCELERATION_ARB) ==
- WGL_NO_ACCELERATION_ARB)
- {
+ if (findAttribValue(WGL_ACCELERATION_ARB) == WGL_NO_ACCELERATION_ARB)
continue;
- }
- u->redBits = getPixelFormatAttrib(window, n, WGL_RED_BITS_ARB);
- u->greenBits = getPixelFormatAttrib(window, n, WGL_GREEN_BITS_ARB);
- u->blueBits = getPixelFormatAttrib(window, n, WGL_BLUE_BITS_ARB);
- u->alphaBits = getPixelFormatAttrib(window, n, WGL_ALPHA_BITS_ARB);
+ u->redBits = findAttribValue(WGL_RED_BITS_ARB);
+ u->greenBits = findAttribValue(WGL_GREEN_BITS_ARB);
+ u->blueBits = findAttribValue(WGL_BLUE_BITS_ARB);
+ u->alphaBits = findAttribValue(WGL_ALPHA_BITS_ARB);
- u->depthBits = getPixelFormatAttrib(window, n, WGL_DEPTH_BITS_ARB);
- u->stencilBits = getPixelFormatAttrib(window, n, WGL_STENCIL_BITS_ARB);
+ u->depthBits = findAttribValue(WGL_DEPTH_BITS_ARB);
+ u->stencilBits = findAttribValue(WGL_STENCIL_BITS_ARB);
- u->accumRedBits = getPixelFormatAttrib(window, n, WGL_ACCUM_RED_BITS_ARB);
- u->accumGreenBits = getPixelFormatAttrib(window, n, WGL_ACCUM_GREEN_BITS_ARB);
- u->accumBlueBits = getPixelFormatAttrib(window, n, WGL_ACCUM_BLUE_BITS_ARB);
- u->accumAlphaBits = getPixelFormatAttrib(window, n, WGL_ACCUM_ALPHA_BITS_ARB);
+ u->accumRedBits = findAttribValue(WGL_ACCUM_RED_BITS_ARB);
+ u->accumGreenBits = findAttribValue(WGL_ACCUM_GREEN_BITS_ARB);
+ u->accumBlueBits = findAttribValue(WGL_ACCUM_BLUE_BITS_ARB);
+ u->accumAlphaBits = findAttribValue(WGL_ACCUM_ALPHA_BITS_ARB);
- u->auxBuffers = getPixelFormatAttrib(window, n, WGL_AUX_BUFFERS_ARB);
+ u->auxBuffers = findAttribValue(WGL_AUX_BUFFERS_ARB);
- if (getPixelFormatAttrib(window, n, WGL_STEREO_ARB))
+ if (findAttribValue(WGL_STEREO_ARB))
u->stereo = GLFW_TRUE;
- if (getPixelFormatAttrib(window, n, WGL_DOUBLE_BUFFER_ARB))
+ if (findAttribValue(WGL_DOUBLE_BUFFER_ARB))
u->doublebuffer = GLFW_TRUE;
if (_glfw.wgl.ARB_multisample)
- u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
+ u->samples = findAttribValue(WGL_SAMPLES_ARB);
if (ctxconfig->client == GLFW_OPENGL_API)
{
if (_glfw.wgl.ARB_framebuffer_sRGB ||
_glfw.wgl.EXT_framebuffer_sRGB)
{
- if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
+ if (findAttribValue(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
u->sRGB = GLFW_TRUE;
}
}
@@ -142,11 +197,8 @@ static int choosePixelFormat(_GLFWwindow* window,
{
if (_glfw.wgl.EXT_colorspace)
{
- if (getPixelFormatAttrib(window, n, WGL_COLORSPACE_EXT) ==
- WGL_COLORSPACE_SRGB_EXT)
- {
+ if (findAttribValue(WGL_COLORSPACE_EXT) == WGL_COLORSPACE_SRGB_EXT)
u->sRGB = GLFW_TRUE;
- }
}
}
}
@@ -157,7 +209,7 @@ static int choosePixelFormat(_GLFWwindow* window,
PIXELFORMATDESCRIPTOR pfd;
if (!DescribePixelFormat(window->context.wgl.dc,
- n,
+ pixelFormat,
sizeof(PIXELFORMATDESCRIPTOR),
&pfd))
{
@@ -200,7 +252,7 @@ static int choosePixelFormat(_GLFWwindow* window,
u->doublebuffer = GLFW_TRUE;
}
- u->handle = n;
+ u->handle = pixelFormat;
usableCount++;
}
@@ -229,6 +281,9 @@ static int choosePixelFormat(_GLFWwindow* window,
return pixelFormat;
}
+#undef addAttrib
+#undef findAttribValue
+
static void makeContextCurrentWGL(_GLFWwindow* window)
{
if (window)
@@ -377,7 +432,7 @@ GLFWbool _glfwInitWGL(void)
// NOTE: This code will accept the Microsoft GDI ICD; accelerated context
// creation failure occurs during manual pixel format enumeration
- dc = GetDC(_glfw.win32.helperWindowHandle);;
+ dc = GetDC(_glfw.win32.helperWindowHandle);
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
diff --git a/src/win32_joystick.c b/src/win32_joystick.c
index d9d341ff5..581239654 100644
--- a/src/win32_joystick.c
+++ b/src/win32_joystick.c
@@ -260,6 +260,8 @@ static void closeJoystick(_GLFWjoystick* js)
IDirectInputDevice8_Release(js->win32.device);
}
+ free(js->win32.objects);
+
_glfwFreeJoystick(js);
_glfwInputJoystick(js, GLFW_DISCONNECTED);
}
diff --git a/src/win32_monitor.c b/src/win32_monitor.c
index b7a24e615..07b3614bb 100644
--- a/src/win32_monitor.c
+++ b/src/win32_monitor.c
@@ -455,7 +455,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
&mode->blueBits);
}
-void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
HDC dc;
WORD values[768];
@@ -469,6 +469,8 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
memcpy(ramp->red, values + 0, 256 * sizeof(unsigned short));
memcpy(ramp->green, values + 256, 256 * sizeof(unsigned short));
memcpy(ramp->blue, values + 512, 256 * sizeof(unsigned short));
+
+ return GLFW_TRUE;
}
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
diff --git a/src/win32_window.c b/src/win32_window.c
index 484715072..ccbb800d6 100644
--- a/src/win32_window.c
+++ b/src/win32_window.c
@@ -186,14 +186,14 @@ static HICON createIcon(const GLFWimage* image,
return handle;
}
-// Translate client window size to full window size according to styles and DPI
+// Translate content area size to full window size according to styles and DPI
//
static void getFullWindowSize(DWORD style, DWORD exStyle,
- int clientWidth, int clientHeight,
+ int contentWidth, int contentHeight,
int* fullWidth, int* fullHeight,
UINT dpi)
{
- RECT rect = { 0, 0, clientWidth, clientHeight };
+ RECT rect = { 0, 0, contentWidth, contentHeight };
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);
@@ -204,7 +204,7 @@ static void getFullWindowSize(DWORD style, DWORD exStyle,
*fullHeight = rect.bottom - rect.top;
}
-// Enforce the client rect aspect ratio based on which edge is being dragged
+// Enforce the content area aspect ratio based on which edge is being dragged
//
static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
{
@@ -236,15 +236,6 @@ static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
}
}
-// Centers the cursor over the window client area
-//
-static void centerCursor(_GLFWwindow* window)
-{
- int width, height;
- _glfwPlatformGetWindowSize(window, &width, &height);
- _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
-}
-
// Updates the cursor image according to its cursor mode
//
static void updateCursorImage(_GLFWwindow* window)
@@ -287,7 +278,7 @@ static void disableCursor(_GLFWwindow* window)
&_glfw.win32.restoreCursorPosX,
&_glfw.win32.restoreCursorPosY);
updateCursorImage(window);
- centerCursor(window);
+ _glfwCenterCursorInContentArea(window);
updateClipRect(window);
if (window->useRawInput && !RegisterRawInputDevices(&rid, 1, sizeof(rid)))
@@ -317,9 +308,9 @@ static void enableCursor(_GLFWwindow* window)
}
}
-// Returns whether the cursor is in the client area of the specified window
+// Returns whether the cursor is in the content area of the specified window
//
-static GLFWbool cursorInClientArea(_GLFWwindow* window)
+static GLFWbool cursorInContentArea(_GLFWwindow* window)
{
RECT area;
POINT pos;
@@ -1069,6 +1060,17 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
return TRUE;
}
+ case WM_NCACTIVATE:
+ case WM_NCPAINT:
+ {
+ // Prevent title bar from being drawn after restoring a minimized
+ // undecorated window
+ if (!window->decorated)
+ return TRUE;
+
+ break;
+ }
+
case WM_DWMCOMPOSITIONCHANGED:
{
if (window->win32.transparent)
@@ -1081,7 +1083,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (window->win32.scaleToMonitor)
break;
- // Adjust the window size to keep the client area size constant
+ // Adjust the window size to keep the content area size constant
if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
{
RECT source = {0}, target = {0};
@@ -1251,7 +1253,7 @@ static int createNativeWindow(_GLFWwindow* window,
window->win32.scaleToMonitor = wndconfig->scaleToMonitor;
// Adjust window size to account for DPI scaling of the window frame and
- // optionally DPI scaling of the client area
+ // optionally DPI scaling of the content area
// This cannot be done until we know what monitor it was placed on
if (!window->monitor)
{
@@ -1786,7 +1788,7 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
int _glfwPlatformWindowHovered(_GLFWwindow* window)
{
- return cursorInClientArea(window);
+ return cursorInContentArea(window);
}
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
@@ -1997,7 +1999,7 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
}
else if (_glfw.win32.disabledCursorWindow == window)
enableCursor(window);
- else if (cursorInClientArea(window))
+ else if (cursorInContentArea(window))
updateCursorImage(window);
}
@@ -2060,7 +2062,7 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
{
- if (cursorInClientArea(window))
+ if (cursorInContentArea(window))
updateCursorImage(window);
}
diff --git a/src/window.c b/src/window.c
index 40991ba3f..f8cb030e3 100644
--- a/src/window.c
+++ b/src/window.c
@@ -67,7 +67,7 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
}
// Notifies shared code that a window has moved
-// The position is specified in client-area relative screen coordinates
+// The position is specified in content area relative screen coordinates
//
void _glfwInputWindowPos(_GLFWwindow* window, int x, int y)
{
@@ -143,7 +143,6 @@ void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor)
window->monitor = monitor;
}
-
//////////////////////////////////////////////////////////////////////////
////// GLFW public API //////
//////////////////////////////////////////////////////////////////////////
@@ -231,11 +230,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
if (window->monitor)
{
if (wndconfig.centerCursor)
- {
- int width, height;
- _glfwPlatformGetWindowSize(window, &width, &height);
- _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
- }
+ _glfwCenterCursorInContentArea(window);
}
else
{
@@ -1079,10 +1074,6 @@ GLFWAPI void glfwPollEvents(void)
GLFWAPI void glfwWaitEvents(void)
{
_GLFW_REQUIRE_INIT();
-
- if (!_glfw.windowListHead)
- return;
-
_glfwPlatformWaitEvents();
}
@@ -1105,9 +1096,5 @@ GLFWAPI void glfwWaitEventsTimeout(double timeout)
GLFWAPI void glfwPostEmptyEvent(void)
{
_GLFW_REQUIRE_INIT();
-
- if (!_glfw.windowListHead)
- return;
-
_glfwPlatformPostEmptyEvent();
}
diff --git a/src/wl_monitor.c b/src/wl_monitor.c
index 7d8e23eb9..588f8b0de 100644
--- a/src/wl_monitor.c
+++ b/src/wl_monitor.c
@@ -180,19 +180,18 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
*mode = monitor->modes[monitor->wl.currentMode];
}
-void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
- // TODO
_glfwInputError(GLFW_PLATFORM_ERROR,
- "Wayland: Gamma ramp getting not supported yet");
+ "Wayland: Gamma ramp access it not available");
+ return GLFW_FALSE;
}
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor,
const GLFWgammaramp* ramp)
{
- // TODO
_glfwInputError(GLFW_PLATFORM_ERROR,
- "Wayland: Gamma ramp setting not supported yet");
+ "Wayland: Gamma ramp access is not available");
}
diff --git a/src/x11_monitor.c b/src/x11_monitor.c
index f557fe472..df53041df 100644
--- a/src/x11_monitor.c
+++ b/src/x11_monitor.c
@@ -422,7 +422,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
}
}
-void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
{
@@ -438,6 +438,7 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
memcpy(ramp->blue, gamma->blue, size * sizeof(unsigned short));
XRRFreeGamma(gamma);
+ return GLFW_TRUE;
}
else if (_glfw.x11.vidmode.available)
{
@@ -449,6 +450,13 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
XF86VidModeGetGammaRamp(_glfw.x11.display,
_glfw.x11.screen,
ramp->size, ramp->red, ramp->green, ramp->blue);
+ return GLFW_TRUE;
+ }
+ else
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Gamma ramp access not supported by server");
+ return GLFW_FALSE;
}
}
@@ -481,6 +489,11 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
(unsigned short*) ramp->green,
(unsigned short*) ramp->blue);
}
+ else
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Gamma ramp access not supported by server");
+ }
}
diff --git a/src/x11_window.c b/src/x11_window.c
index 7d1951d59..59b19240c 100644
--- a/src/x11_window.c
+++ b/src/x11_window.c
@@ -501,15 +501,6 @@ static char* convertLatin1toUTF8(const char* source)
return target;
}
-// Centers the cursor over the window client area
-//
-static void centerCursor(_GLFWwindow* window)
-{
- int width, height;
- _glfwPlatformGetWindowSize(window, &width, &height);
- _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
-}
-
// Updates the cursor image according to its cursor mode
//
static void updateCursorImage(_GLFWwindow* window)
@@ -553,7 +544,7 @@ static void disableCursor(_GLFWwindow* window)
&_glfw.x11.restoreCursorPosX,
&_glfw.x11.restoreCursorPosY);
updateCursorImage(window);
- centerCursor(window);
+ _glfwCenterCursorInContentArea(window);
XGrabPointer(_glfw.x11.display, window->x11.handle, True,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync,
@@ -2404,10 +2395,14 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
}
else
{
+ if (!window->resizable)
+ updateNormalHints(window, width, height);
+
XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
xpos, ypos, width, height);
}
+ XFlush(_glfw.x11.display);
return;
}
@@ -2416,16 +2411,21 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_glfwInputWindowMonitor(window, monitor);
updateNormalHints(window, width, height);
- updateWindowMode(window);
if (window->monitor)
{
- XMapRaised(_glfw.x11.display, window->x11.handle);
- if (waitForVisibilityNotify(window))
- acquireMonitor(window);
+ if (!_glfwPlatformWindowVisible(window))
+ {
+ XMapRaised(_glfw.x11.display, window->x11.handle);
+ waitForVisibilityNotify(window);
+ }
+
+ updateWindowMode(window);
+ acquireMonitor(window);
}
else
{
+ updateWindowMode(window);
XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
xpos, ypos, width, height);
}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 7078b005d..8a15da1db 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -33,7 +33,7 @@ add_executable(icon WIN32 MACOSX_BUNDLE icon.c ${GLAD})
add_executable(inputlag WIN32 MACOSX_BUNDLE inputlag.c ${GETOPT} ${GLAD})
add_executable(joysticks WIN32 MACOSX_BUNDLE joysticks.c ${GLAD})
add_executable(opacity WIN32 MACOSX_BUNDLE opacity.c ${GLAD})
-add_executable(tearing WIN32 MACOSX_BUNDLE tearing.c ${GLAD})
+add_executable(tearing WIN32 MACOSX_BUNDLE tearing.c ${GETOPT} ${GLAD})
add_executable(threads WIN32 MACOSX_BUNDLE threads.c ${TINYCTHREAD} ${GLAD})
add_executable(timeout WIN32 MACOSX_BUNDLE timeout.c ${GLAD})
add_executable(title WIN32 MACOSX_BUNDLE title.c ${GLAD})
diff --git a/tests/events.c b/tests/events.c
index 9a0144d79..5a0fde04a 100644
--- a/tests/events.c
+++ b/tests/events.c
@@ -429,15 +429,6 @@ static void char_callback(GLFWwindow* window, unsigned int codepoint)
get_character_string(codepoint));
}
-static void char_mods_callback(GLFWwindow* window, unsigned int codepoint, int mods)
-{
- Slot* slot = glfwGetWindowUserPointer(window);
- printf("%08x to %i at %0.3f: Character 0x%08x (%s) with modifiers (with%s) input\n",
- counter++, slot->number, glfwGetTime(), codepoint,
- get_character_string(codepoint),
- get_mods_name(mods));
-}
-
static void drop_callback(GLFWwindow* window, int count, const char** paths)
{
int i;
@@ -533,7 +524,7 @@ int main(int argc, char** argv)
break;
case 'n':
- count = (int) strtol(optarg, NULL, 10);
+ count = (int) strtoul(optarg, NULL, 10);
break;
default:
@@ -560,12 +551,6 @@ int main(int argc, char** argv)
height = 480;
}
- if (!count)
- {
- fprintf(stderr, "Invalid user\n");
- exit(EXIT_FAILURE);
- }
-
slots = calloc(count, sizeof(Slot));
for (i = 0; i < count; i++)
@@ -616,7 +601,6 @@ int main(int argc, char** argv)
glfwSetScrollCallback(slots[i].window, scroll_callback);
glfwSetKeyCallback(slots[i].window, key_callback);
glfwSetCharCallback(slots[i].window, char_callback);
- glfwSetCharModsCallback(slots[i].window, char_mods_callback);
glfwSetDropCallback(slots[i].window, drop_callback);
glfwMakeContextCurrent(slots[i].window);
diff --git a/tests/tearing.c b/tests/tearing.c
index fe7ed0761..4acf3b292 100644
--- a/tests/tearing.c
+++ b/tests/tearing.c
@@ -35,6 +35,7 @@
#include
#include
+#include "getopt.h"
#include "linmath.h"
static const struct
@@ -68,6 +69,14 @@ static int swap_tear;
static int swap_interval;
static double frame_rate;
+static void usage(void)
+{
+ printf("Usage: tearing [-f] [-h]\n");
+ printf("Options:\n");
+ printf(" -f use full screen\n");
+ printf(" -h show this help\n");
+}
+
static void update_window_title(GLFWwindow* window)
{
char title[256];
@@ -154,6 +163,8 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
int main(int argc, char** argv)
{
unsigned long frame_count = 0;
+ GLFWmonitor* monitor = NULL;
+ int ch, width, height;
double last_time, current_time;
GLFWwindow* window;
GLuint vertex_buffer, vertex_shader, fragment_shader, program;
@@ -164,10 +175,46 @@ int main(int argc, char** argv)
if (!glfwInit())
exit(EXIT_FAILURE);
+ while ((ch = getopt(argc, argv, "hf")) != -1)
+ {
+ switch (ch)
+ {
+ case 'h':
+ usage();
+ exit(EXIT_SUCCESS);
+
+ case 'f':
+ monitor = glfwGetPrimaryMonitor();
+ break;
+
+ default:
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (monitor)
+ {
+ const GLFWvidmode* mode = glfwGetVideoMode(monitor);
+
+ glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
+ glfwWindowHint(GLFW_RED_BITS, mode->redBits);
+ glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits);
+ glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits);
+
+ width = mode->width;
+ height = mode->height;
+ }
+ else
+ {
+ width = 640;
+ height = 480;
+ }
+
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
- window = glfwCreateWindow(640, 480, "Tearing detector", NULL, NULL);
+ window = glfwCreateWindow(width, height, "Tearing detector", monitor, NULL);
if (!window)
{
glfwTerminate();