diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 855df93e..19f60f2e 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -15,6 +15,7 @@ video tutorials. - Keith Bauer - John Bartholomew - Coşku Baş + - Bayemite - Niklas Behrens - Andrew Belt - Nevyn Bengtsson diff --git a/README.md b/README.md index cf8bf655..476bd87a 100644 --- a/README.md +++ b/README.md @@ -167,6 +167,7 @@ information on what to include when reporting a bug. - Added support for `XDG_SESSION_TYPE` environment variable - Added `GLFW_PKG_CONFIG_REQUIRES_PRIVATE` and `GLFW_PKG_CONFIG_LIBS_PRIVATE` CMake variables exposing pkg-config dependencies (#1307) + - Added `glfwGetWindowTitle` function for GLFWwindow for querying window titles (#1448,#1909) - Made joystick subsystem initialize at first use (#1284,#1646) - Made `GLFW_DOUBLEBUFFER` a read-only window attribute - Updated the minimum required CMake version to 3.1 diff --git a/docs/news.md b/docs/news.md index 7842ddf5..4f8bbbe5 100644 --- a/docs/news.md +++ b/docs/news.md @@ -41,6 +41,12 @@ to whatever window is behind it. This can also be changed after window creation with the matching [window attribute](@ref GLFW_MOUSE_PASSTHROUGH_attrib). +#### Ability to get a window's title {#features_34_get_window_title} + +GLFW now supports retrieving a window's title with the @ref glfwGetWindowTitle +function. + + #### Wayland libdecor decorations {#wayland_libdecor_34} GLFW now supports improved fallback window decorations via @@ -253,6 +259,7 @@ then GLFW will fail to initialize. - @ref glfwGetPlatform - @ref glfwPlatformSupported - @ref glfwInitVulkanLoader + - @ref glfwGetWindowTitle #### New types in version 3.4 {#types_34} diff --git a/docs/window.md b/docs/window.md index f4e153c3..bfd99bc8 100644 --- a/docs/window.md +++ b/docs/window.md @@ -919,6 +919,15 @@ If you are using C++11 or C11, you can use a UTF-8 string literal. glfwSetWindowTitle(window, u8"This is always a UTF-8 string"); ``` +The window title can be retrieved with @ref glfwGetWindowTitle. + +```c +const char* title = glfwGetWindowTitle(window); +``` + +The title returned is an internally managed copy of the title set +by @ref glfwCreateWindow or @ref glfwSetWindowTitle. It does not +include any additional text which may be appended by the platform. ### Window icon {#window_icon} diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 9268e4f3..3563ca62 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -3305,6 +3305,30 @@ GLFWAPI int glfwWindowShouldClose(GLFWwindow* window); */ GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* window, int value); +/*! @brief Retrieves the title of the specified window. + * + * This function gets the window title, encoded as UTF-8, of the specified + * window. + * + * @param[in] window The window to query. + * @return A copy of the UTF-8 encoded window title, as set by glfwCreateWindow + * or glfwSetWindowTitle, or NULL if there is an error. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwSetWindowTitle, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_title + * @sa @ref glfwSetWindowTitle + * + * @ingroup window + */ +GLFWAPI const char* glfwGetWindowTitle(GLFWwindow* window); + /*! @brief Sets the title of the specified window. * * This function sets the window title, encoded as UTF-8, of the specified diff --git a/src/internal.h b/src/internal.h index c6c856f1..24750adc 100644 --- a/src/internal.h +++ b/src/internal.h @@ -532,6 +532,7 @@ struct _GLFWwindow GLFWvidmode videoMode; _GLFWmonitor* monitor; _GLFWcursor* cursor; + char* title; int minwidth, minheight; int maxwidth, maxheight; diff --git a/src/window.c b/src/window.c index 3b8d706e..abd54dc2 100644 --- a/src/window.c +++ b/src/window.c @@ -242,6 +242,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, window->maxheight = GLFW_DONT_CARE; window->numer = GLFW_DONT_CARE; window->denom = GLFW_DONT_CARE; + window->title = _glfw_strdup(title); if (!_glfw.platform.createWindow(window, &wndconfig, &ctxconfig, &fbconfig)) { @@ -493,7 +494,7 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle) *prev = window->next; } - + _glfw_free(window->title); _glfw_free(window); } @@ -515,6 +516,16 @@ GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value) window->shouldClose = value; } +GLFWAPI const char* glfwGetWindowTitle(GLFWwindow* handle) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + + return window->title; +} + GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title) { _GLFWwindow* window = (_GLFWwindow*) handle; @@ -522,7 +533,12 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title) assert(title != NULL); _GLFW_REQUIRE_INIT(); + + char* prev = window->title; + window->title = _glfw_strdup(title); + _glfw.platform.setWindowTitle(window, title); + _glfw_free(prev); } GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle, diff --git a/tests/window.c b/tests/window.c index 94c4f172..00d49b4b 100644 --- a/tests/window.c +++ b/tests/window.c @@ -62,6 +62,7 @@ int main(int argc, char** argv) char min_width_buffer[12] = "", min_height_buffer[12] = ""; char max_width_buffer[12] = "", max_height_buffer[12] = ""; int may_close = true; + char window_title[64] = ""; if (!glfwInit()) exit(EXIT_FAILURE); @@ -71,7 +72,7 @@ int main(int argc, char** argv) glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); - GLFWwindow* window = glfwCreateWindow(600, 630, "Window Features", NULL, NULL); + GLFWwindow* window = glfwCreateWindow(600, 660, "Window Features", NULL, NULL); if (!window) { glfwTerminate(); @@ -109,6 +110,11 @@ int main(int argc, char** argv) nk_glfw3_font_stash_begin(&atlas); nk_glfw3_font_stash_end(); + // test setting title with result from glfwGetWindowTitle + glfwSetWindowTitle(window, glfwGetWindowTitle(window)); + + strncpy( window_title, glfwGetWindowTitle(window), sizeof(window_title)); + while (!(may_close && glfwWindowShouldClose(window))) { int width, height; @@ -188,11 +194,25 @@ int main(int argc, char** argv) nk_label(nk, "Press Enter in a text field to set value", NK_TEXT_CENTERED); + + nk_flags events; const nk_flags flags = NK_EDIT_FIELD | NK_EDIT_SIG_ENTER | NK_EDIT_GOTO_END_ON_ACTIVATE; + nk_layout_row_dynamic(nk, 30, 2); + nk_label(nk, "Window Title:", NK_TEXT_LEFT); + + events = nk_edit_string_zero_terminated( nk, flags, window_title, sizeof(window_title), NULL ); + + if (events & NK_EDIT_COMMITED) + { + glfwSetWindowTitle(window, window_title); + // we do not need to call glfwGetWindowTitle as we already store the title, but using it here for testing purposes + strncpy( window_title, glfwGetWindowTitle(window), sizeof(window_title)); + } + if (position_supported) { int xpos, ypos;