diff --git a/README.md b/README.md index e1a638a3..0892b403 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,7 @@ information on what to include when reporting a bug. - Added `glfwSetWindowAttrib` function for changing window attributes (#537) - Added `glfwGetJoystickHats` function for querying joystick hats (#889,#906,#934) -- Added `glfwInitHint` function for setting library initialization hints +- Added `glfwInitHint` and `glfwInitHintString` for setting initialization hints - Added headless [OSMesa](http://mesa3d.org/osmesa.html) backend (#850) - Added definition of `GLAPIENTRY` to public header - Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering @@ -154,6 +154,8 @@ information on what to include when reporting a bug. - Added macOS specific `GLFW_COCOA_GRAPHICS_SWITCHING` window hint (#377,#935) - Added macOS specific `GLFW_COCOA_CHDIR_RESOURCES` init hint - Added macOS specific `GLFW_COCOA_MENUBAR` init hint +- Added X11 specific `GLFW_X11_WM_CLASS_NAME` and `GLFW_X11_WM_CLASS_CLASS` init + hints (#893) - Added `GLFW_INCLUDE_ES32` for including the OpenGL ES 3.2 header - Added `GLFW_OSMESA_CONTEXT_API` for creating OpenGL contexts with [OSMesa](https://www.mesa3d.org/osmesa.html) (#281) diff --git a/docs/intro.dox b/docs/intro.dox index e5de7303..88245d9b 100644 --- a/docs/intro.dox +++ b/docs/intro.dox @@ -33,6 +33,7 @@ successfully initialized, and only from the main thread. - @ref glfwGetError - @ref glfwSetErrorCallback - @ref glfwInitHint + - @ref glfwInitHintString - @ref glfwInit - @ref glfwTerminate @@ -65,23 +66,26 @@ system settings and these might not be restored without termination. @subsection init_hints Initialization hints -There are a number of hints that can be set before initialization, that affect -how the library behaves. +Initialization hints are set before @ref glfwInit and affect how the library +behaves until termination. Integer type hints are set with @ref glfwInitHint +and string type hints with @ref glfwInitHintString. -The values you set are not affected by initialization or termination, but they -are only read during initialization. Once GLFW has been initialized, setting -new hint values will not affect behavior until the next time it is terminated -and initialized. +@code +glfwInitHint(GLFW_JOYSTICK_HAT_BUTTONS, GLFW_FALSE); +@endcode -Some hints are platform specific. These are always valid to set on any -platform but they will only affect their specific platform. Other platforms -will simply ignore them. Setting these hints requires no platform specific -headers or calls. +The values you set hints to are never reset by GLFW, but they only take effect +during initialization. Once GLFW has been initialized, any values you set will +be ignored until the library is terminated and initialized again. + +Some hints are platform specific. These may be set on any platform but they +will only affect their specific platform. Other platforms will simply ignore +them. Setting these hints requires no platform specific headers or functions. @anchor GLFW_JOYSTICK_HAT_BUTTONS __GLFW_JOYSTICK_HAT_BUTTONS__ specifies whether to also expose joystick hats as buttons, for compatibility with earlier versions of GLFW that did not have @ref -glfwGetJoystickHats. +glfwGetJoystickHats. Set this with @ref glfwInitHint. @subsubsection init_hints_osx macOS specific init hints @@ -89,12 +93,21 @@ glfwGetJoystickHats. @anchor GLFW_COCOA_CHDIR_RESOURCES __GLFW_COCOA_CHDIR_RESOURCES__ specifies whether to set the current directory to the application to the `Contents/Resources` subdirectory of the application's -bundle, if present. +bundle, if present. Set this with @ref glfwInitHint. @anchor GLFW_COCOA_MENUBAR __GLFW_COCOA_MENUBAR__ specifies whether to create a basic menu bar, either from a nib or manually, when the first window is created, which is when AppKit is -initialized. +initialized. Set this with @ref glfwInitHint. + + +@subsubsection init_hints_x11 X11 specific init hints + +@anchor GLFW_X11_WM_CLASS_NAME +@anchor GLFW_X11_WM_CLASS_CLASS +__GLFW_X11_WM_CLASS_NAME__ and __GLFW_X11_WM_CLASS_CLASS__ specifies the desired +ASCII encoded name and class parts of the ICCCM `WM_CLASS` hint for all windows. +Set this with @ref glfwInitHintString. @subsubsection init_hints_values Supported and default values @@ -104,6 +117,8 @@ Init hint | Default value | Supported values @ref GLFW_JOYSTICK_HAT_BUTTONS | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` @ref GLFW_COCOA_CHDIR_RESOURCES | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` @ref GLFW_COCOA_MENUBAR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` +@ref GLFW_X11_WM_CLASS_NAME | `""` | An ASCII encoded `WM_CLASS` name +@ref GLFW_X11_WM_CLASS_CLASS | `""` | An ASCII encoded `WM_CLASS` class @subsection intro_init_terminate Terminating GLFW diff --git a/docs/news.dox b/docs/news.dox index 173508ec..2d4b621d 100644 --- a/docs/news.dox +++ b/docs/news.dox @@ -60,8 +60,9 @@ windows with @ref glfwSetWindowAttrib. @subsection news_33_inithint Support for initialization hints -GLFW now supports setting library initialization hints with @ref glfwInitHint. -These must be set before initialization to take effect. +GLFW now supports setting library initialization hints with @ref glfwInitHint +or @ref glfwInitHintString. These must be set before initialization to take +effect. @see @ref init_hints diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 820004e0..83fad737 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1016,6 +1016,9 @@ extern "C" { #define GLFW_COCOA_CHDIR_RESOURCES 0x00051001 #define GLFW_COCOA_MENUBAR 0x00051002 + +#define GLFW_X11_WM_CLASS_NAME 0x00052001 +#define GLFW_X11_WM_CLASS_CLASS 0x00052002 /*! @} */ #define GLFW_DONT_CARE -1 @@ -1609,17 +1612,18 @@ GLFWAPI void glfwTerminate(void); /*! @brief Sets the specified init hint to the desired value. * - * This function sets hints for the next initialization of GLFW. + * This function sets hints for the next initialization of GLFW. Only integer + * type hints can be set with this function. * - * The values you set are not affected by initialization or termination, but - * they are only read during initialization. Once GLFW has been initialized, - * setting new hint values will not affect behavior until the next time the - * library is terminated and initialized. + * The values you set hints to are never reset by GLFW, but they only take + * effect during initialization. Once GLFW has been initialized, any values + * you set will be ignored until the library is terminated and initialized + * again. * - * Some hints are platform specific. These are always valid to set on any - * platform but they will only affect their specific platform. Other platforms - * will simply ignore them. Setting these hints requires no platform specific - * headers or calls. + * Some hints are platform specific. These may be set on any platform but they + * will only affect their specific platform. Other platforms will simply + * ignore them. Setting these hints requires no platform specific headers or + * functions. * * @param[in] hint The [init hint](@ref init_hints) to set. * @param[in] value The new value of the init hint. @@ -1633,6 +1637,7 @@ GLFWAPI void glfwTerminate(void); * * @sa init_hints * @sa glfwInit + * @sa glfwInitHintString * * @since Added in version 3.3. * @@ -1640,6 +1645,41 @@ GLFWAPI void glfwTerminate(void); */ GLFWAPI void glfwInitHint(int hint, int value); +/*! @brief Sets the specified init hint to the desired value. + * + * This function sets hints for the next initialization of GLFW. Only string + * type hints can be set with this function. + * + * The values you set hints to are never reset by GLFW, but they only take + * effect during initialization. Once GLFW has been initialized, any values + * you set will be ignored until the library is terminated and initialized + * again. + * + * Some hints are platform specific. These may be set on any platform but they + * will only affect their specific platform. Other platforms will simply + * ignore them. Setting these hints requires no platform specific headers or + * functions. + * + * @param[in] hint The [init hint](@ref init_hints) to set. + * @param[in] value The new value of the init hint. + * + * @errors Possible errors include @ref GLFW_INVALID_ENUM and @ref + * GLFW_INVALID_VALUE. + * + * @remarks This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa init_hints + * @sa glfwInit + * @sa glfwInitHint + * + * @since Added in version 3.3. + * + * @ingroup init + */ +GLFWAPI void glfwInitHintString(int hint, const char* value); + /*! @brief Retrieves the version of the GLFW library. * * This function retrieves the major, minor and revision numbers of the GLFW @@ -2261,6 +2301,11 @@ GLFWAPI void glfwWindowHint(int hint, int value); * query the final size, position or other attributes directly after window * creation. * + * @remark @x11 The name and class of the `WM_CLASS` window property will by + * default be set to the window title passed to this function. Set the @ref + * GLFW_X11_WM_CLASS_NAME and @ref GLFW_X11_WM_CLASS_CLASS init hints before + * initialization to override this. + * * @remark @wayland The window frame is currently unimplemented, as if * [GLFW_DECORATED](@ref GLFW_DECORATED_hint) was always set to `GLFW_FALSE`. * A compositor can still emit close, resize or maximize events, using for diff --git a/src/init.c b/src/init.c index 7f7d87ea..fd86c5be 100644 --- a/src/init.c +++ b/src/init.c @@ -32,6 +32,7 @@ #include #include #include +#include // The global variables below comprise all global data in GLFW. @@ -48,10 +49,14 @@ static _GLFWerror _glfwMainThreadError; static GLFWerrorfun _glfwErrorCallback; static _GLFWinitconfig _glfwInitHints = { - GLFW_TRUE, // hat buttons + GLFW_TRUE, // hat buttons { - GLFW_TRUE, // menubar - GLFW_TRUE // chdir + GLFW_TRUE, // macOS menu bar + GLFW_TRUE // macOS bundle chdir + }, + { + "", // X11 WM_CLASS name + "" // X11 WM_CLASS class } }; @@ -243,7 +248,28 @@ GLFWAPI void glfwInitHint(int hint, int value) return; } - _glfwInputError(GLFW_INVALID_ENUM, "Invalid init hint 0x%08X", hint); + _glfwInputError(GLFW_INVALID_ENUM, + "Invalid integer type init hint 0x%08X", hint); +} + +GLFWAPI void glfwInitHintString(int hint, const char* value) +{ + assert(value != NULL); + + switch (hint) + { + case GLFW_X11_WM_CLASS_NAME: + strncpy(_glfwInitHints.x11.className, value, + sizeof(_glfwInitHints.x11.className) - 1); + break; + case GLFW_X11_WM_CLASS_CLASS: + strncpy(_glfwInitHints.x11.classClass, value, + sizeof(_glfwInitHints.x11.classClass) - 1); + break; + } + + _glfwInputError(GLFW_INVALID_ENUM, + "Invalid string type init hint 0x%08X", hint); } GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev) diff --git a/src/internal.h b/src/internal.h index e3ea78de..fdff84d0 100644 --- a/src/internal.h +++ b/src/internal.h @@ -277,6 +277,10 @@ struct _GLFWinitconfig GLFWbool menubar; GLFWbool chdir; } ns; + struct { + char className[256]; + char classClass[256]; + } x11; }; /*! @brief Window configuration. diff --git a/src/x11_window.c b/src/x11_window.c index dcda51ea..cdaac5f8 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -614,13 +614,25 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, updateNormalHints(window, wndconfig->width, wndconfig->height); // Set ICCCM WM_CLASS property - // HACK: Until a mechanism for specifying the application name is added, the - // initial window title is used as the window class name - if (strlen(wndconfig->title)) { XClassHint* hint = XAllocClassHint(); - hint->res_name = (char*) wndconfig->title; - hint->res_class = (char*) wndconfig->title; + + if (strlen(_glfw.hints.init.x11.className) && + strlen(_glfw.hints.init.x11.classClass)) + { + hint->res_name = (char*) _glfw.hints.init.x11.className; + hint->res_class = (char*) _glfw.hints.init.x11.classClass; + } + else if (strlen(wndconfig->title)) + { + hint->res_name = (char*) wndconfig->title; + hint->res_class = (char*) wndconfig->title; + } + else + { + hint->res_name = (char*) "glfw-application"; + hint->res_class = (char*) "GLFW-Application"; + } XSetClassHint(_glfw.x11.display, window->x11.handle, hint); XFree(hint);