Consolidate the X11 WM_CLASS and Wayland app ID envvars
Consolidate the X11_WMCLASS and WAYLAND_WMCLASS envvars into one SDL_HINT_APP_ID hint. This hint serves the same purpose on both windowing systems to allow desktop compositors to identify and group windows together, as well as associate applications with their desktop settings and icons. The common code for retrieving the value is now consolidated under core/unix/SDL_appid.c as it's common to *nix platforms, and the value is now retrieved at window creation time instead of being cached by the video driver at startup so that changes to the hint after video initialization and before window creation will be seen, as well as to accommodate cases where applications want to use different values for different windows.
This commit is contained in:
76
src/core/unix/SDL_appid.c
Normal file
76
src/core/unix/SDL_appid.c
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_appid.h"
|
||||
#include <unistd.h>
|
||||
|
||||
const char *SDL_GetExeName()
|
||||
{
|
||||
static const char *proc_name = NULL;
|
||||
|
||||
/* TODO: Use a fallback if BSD has no mounted procfs (OpenBSD has no procfs at all) */
|
||||
if (!proc_name) {
|
||||
#if defined(__LINUX__) || defined(__FREEBSD__) || defined (__NETBSD__)
|
||||
static char linkfile[1024];
|
||||
int linksize;
|
||||
|
||||
#if defined(__LINUX__)
|
||||
const char *proc_path = "/proc/self/exe";
|
||||
#elif defined(__FREEBSD__)
|
||||
const char *proc_path = "/proc/curproc/file";
|
||||
#elif defined(__NETBSD__)
|
||||
const char *proc_path = "/proc/curproc/exe";
|
||||
#endif
|
||||
linksize = readlink(proc_path, linkfile, sizeof(linkfile) - 1);
|
||||
if (linksize > 0) {
|
||||
linkfile[linksize] = '\0';
|
||||
proc_name = SDL_strrchr(linkfile, '/');
|
||||
if (proc_name) {
|
||||
++proc_name;
|
||||
} else {
|
||||
proc_name = linkfile;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return proc_name;
|
||||
}
|
||||
|
||||
const char *SDL_GetAppID()
|
||||
{
|
||||
/* Always check the hint, as it may have changed */
|
||||
const char *id_str = SDL_GetHint(SDL_HINT_APP_ID);
|
||||
|
||||
if (!id_str) {
|
||||
/* If the hint isn't set, try to use the application's executable name */
|
||||
id_str = SDL_GetExeName();
|
||||
}
|
||||
|
||||
if (!id_str) {
|
||||
/* Finally, use the default we've used forever */
|
||||
id_str = "SDL_App";
|
||||
}
|
||||
|
||||
return id_str;
|
||||
}
|
||||
30
src/core/unix/SDL_appid.h
Normal file
30
src/core/unix/SDL_appid.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_appid_h_
|
||||
#define SDL_appid_h_
|
||||
|
||||
extern const char *SDL_GetExeName();
|
||||
extern const char *SDL_GetAppID();
|
||||
|
||||
#endif /* SDL_appid_h_ */
|
||||
@@ -82,60 +82,6 @@ static int Wayland_VideoInit(SDL_VideoDevice *_this);
|
||||
static int Wayland_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect);
|
||||
static void Wayland_VideoQuit(SDL_VideoDevice *_this);
|
||||
|
||||
/* Find out what class name we should use
|
||||
* Based on src/video/x11/SDL_x11video.c */
|
||||
static char *get_classname(void)
|
||||
{
|
||||
/* !!! FIXME: this is probably wrong, albeit harmless in many common cases. From protocol spec:
|
||||
"The surface class identifies the general class of applications
|
||||
to which the surface belongs. A common convention is to use the
|
||||
file name (or the full path if it is a non-standard location) of
|
||||
the application's .desktop file as the class." */
|
||||
|
||||
char *spot;
|
||||
#if defined(__LINUX__) || defined(__FREEBSD__)
|
||||
char procfile[1024];
|
||||
char linkfile[1024];
|
||||
int linksize;
|
||||
#endif
|
||||
|
||||
/* First allow environment variable override */
|
||||
spot = SDL_getenv("SDL_VIDEO_WAYLAND_WMCLASS");
|
||||
if (spot) {
|
||||
return SDL_strdup(spot);
|
||||
} else {
|
||||
/* Fallback to the "old" envvar */
|
||||
spot = SDL_getenv("SDL_VIDEO_X11_WMCLASS");
|
||||
if (spot) {
|
||||
return SDL_strdup(spot);
|
||||
}
|
||||
}
|
||||
|
||||
/* Next look at the application's executable name */
|
||||
#if defined(__LINUX__) || defined(__FREEBSD__)
|
||||
#ifdef __LINUX__
|
||||
(void)SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/exe", getpid());
|
||||
#elif defined(__FREEBSD__)
|
||||
(void)SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/file", getpid());
|
||||
#else
|
||||
#error Where can we find the executable name?
|
||||
#endif
|
||||
linksize = readlink(procfile, linkfile, sizeof(linkfile) - 1);
|
||||
if (linksize > 0) {
|
||||
linkfile[linksize] = '\0';
|
||||
spot = SDL_strrchr(linkfile, '/');
|
||||
if (spot) {
|
||||
return SDL_strdup(spot + 1);
|
||||
} else {
|
||||
return SDL_strdup(linkfile);
|
||||
}
|
||||
}
|
||||
#endif /* __LINUX__ || __FREEBSD__ */
|
||||
|
||||
/* Finally use the default we've used forever */
|
||||
return SDL_strdup("SDL_App");
|
||||
}
|
||||
|
||||
static const char *SDL_WAYLAND_surface_tag = "sdl-window";
|
||||
static const char *SDL_WAYLAND_output_tag = "sdl-output";
|
||||
|
||||
@@ -945,9 +891,6 @@ int Wayland_VideoInit(SDL_VideoDevice *_this)
|
||||
|
||||
Wayland_InitMouse();
|
||||
|
||||
/* Get the surface class name, usually the name of the application */
|
||||
data->classname = get_classname();
|
||||
|
||||
WAYLAND_wl_display_flush(data->display);
|
||||
|
||||
Wayland_InitKeyboard(_this);
|
||||
@@ -1144,18 +1087,15 @@ SDL_bool Wayland_VideoReconnect(SDL_VideoDevice *_this)
|
||||
|
||||
void Wayland_VideoQuit(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *data = _this->driverdata;
|
||||
|
||||
Wayland_VideoCleanup(_this);
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
SDL_VideoData *data = _this->driverdata;
|
||||
if (data->shell.libdecor) {
|
||||
libdecor_unref(data->shell.libdecor);
|
||||
data->shell.libdecor = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
SDL_free(data->classname);
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_WAYLAND */
|
||||
|
||||
@@ -90,8 +90,6 @@ struct SDL_VideoData
|
||||
struct qt_windowmanager *windowmanager;
|
||||
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
|
||||
|
||||
char *classname;
|
||||
|
||||
int relative_mouse_mode;
|
||||
};
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "../../core/unix/SDL_appid.h"
|
||||
#include "../SDL_egl_c.h"
|
||||
#include "SDL_waylandevents_c.h"
|
||||
#include "SDL_waylandwindow.h"
|
||||
@@ -1328,7 +1329,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
if (data->shell_surface.libdecor.frame == NULL) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Failed to create libdecor frame!");
|
||||
} else {
|
||||
libdecor_frame_set_app_id(data->shell_surface.libdecor.frame, c->classname);
|
||||
libdecor_frame_set_app_id(data->shell_surface.libdecor.frame, data->app_id);
|
||||
libdecor_frame_map(data->shell_surface.libdecor.frame);
|
||||
}
|
||||
} else
|
||||
@@ -1390,7 +1391,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
}
|
||||
} else {
|
||||
data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface);
|
||||
xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, c->classname);
|
||||
xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, data->app_id);
|
||||
xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data);
|
||||
}
|
||||
}
|
||||
@@ -2047,6 +2048,9 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
data->outputs = NULL;
|
||||
data->num_outputs = 0;
|
||||
|
||||
/* Cache the app_id at creation time, as it may change before the window is mapped. */
|
||||
data->app_id = SDL_strdup(SDL_GetAppID());
|
||||
|
||||
data->requested_window_width = window->w;
|
||||
data->requested_window_height = window->h;
|
||||
data->floating_width = window->windowed.w;
|
||||
@@ -2311,6 +2315,7 @@ void Wayland_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
}
|
||||
|
||||
SDL_free(wind->outputs);
|
||||
SDL_free(wind->app_id);
|
||||
|
||||
if (wind->gles_swap_frame_callback) {
|
||||
wl_callback_destroy(wind->gles_swap_frame_callback);
|
||||
|
||||
@@ -111,6 +111,7 @@ struct SDL_WindowData
|
||||
|
||||
SDL_Window *keyboard_focus;
|
||||
|
||||
char *app_id;
|
||||
float windowed_scale_factor;
|
||||
float pointer_scale_x;
|
||||
float pointer_scale_y;
|
||||
|
||||
@@ -203,7 +203,7 @@ int X11_InitKeyboard(SDL_VideoDevice *_this)
|
||||
(void)setlocale(LC_ALL, "");
|
||||
X11_XSetLocaleModifiers(new_xmods);
|
||||
|
||||
data->im = X11_XOpenIM(data->display, NULL, data->classname, data->classname);
|
||||
data->im = X11_XOpenIM(data->display, NULL, NULL, NULL);
|
||||
|
||||
/* Reset the locale + X locale modifiers back to how they were,
|
||||
locale first because the X locale modifiers depend on it. */
|
||||
|
||||
@@ -45,47 +45,6 @@
|
||||
static int X11_VideoInit(SDL_VideoDevice *_this);
|
||||
static void X11_VideoQuit(SDL_VideoDevice *_this);
|
||||
|
||||
/* Find out what class name we should use */
|
||||
static char *get_classname(void)
|
||||
{
|
||||
char *spot;
|
||||
#if defined(__LINUX__) || defined(__FREEBSD__)
|
||||
char procfile[1024];
|
||||
char linkfile[1024];
|
||||
int linksize;
|
||||
#endif
|
||||
|
||||
/* First allow environment variable override */
|
||||
spot = SDL_getenv("SDL_VIDEO_X11_WMCLASS");
|
||||
if (spot) {
|
||||
return SDL_strdup(spot);
|
||||
}
|
||||
|
||||
/* Next look at the application's executable name */
|
||||
#if defined(__LINUX__) || defined(__FREEBSD__)
|
||||
#ifdef __LINUX__
|
||||
(void)SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/exe", getpid());
|
||||
#elif defined(__FREEBSD__)
|
||||
(void)SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/file", getpid());
|
||||
#else
|
||||
#error Where can we find the executable name?
|
||||
#endif
|
||||
linksize = readlink(procfile, linkfile, sizeof(linkfile) - 1);
|
||||
if (linksize > 0) {
|
||||
linkfile[linksize] = '\0';
|
||||
spot = SDL_strrchr(linkfile, '/');
|
||||
if (spot) {
|
||||
return SDL_strdup(spot + 1);
|
||||
} else {
|
||||
return SDL_strdup(linkfile);
|
||||
}
|
||||
}
|
||||
#endif /* __LINUX__ || __FREEBSD__ */
|
||||
|
||||
/* Finally use the default we've used forever */
|
||||
return SDL_strdup("SDL_App");
|
||||
}
|
||||
|
||||
/* X11 driver bootstrap functions */
|
||||
|
||||
static int (*orig_x11_errhandler)(Display *, XErrorEvent *) = NULL;
|
||||
@@ -409,9 +368,6 @@ int X11_VideoInit(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *data = _this->driverdata;
|
||||
|
||||
/* Get the window class name, usually the name of the application */
|
||||
data->classname = get_classname();
|
||||
|
||||
/* Get the process PID to be associated to the window */
|
||||
data->pid = getpid();
|
||||
|
||||
@@ -491,7 +447,6 @@ void X11_VideoQuit(SDL_VideoDevice *_this)
|
||||
X11_XDestroyWindow(data->display, data->clipboard_window);
|
||||
}
|
||||
|
||||
SDL_free(data->classname);
|
||||
#ifdef X_HAVE_UTF8_STRING
|
||||
if (data->im) {
|
||||
X11_XCloseIM(data->im);
|
||||
|
||||
@@ -69,7 +69,6 @@ struct SDL_VideoData
|
||||
{
|
||||
Display *display;
|
||||
Display *request_display;
|
||||
char *classname;
|
||||
pid_t pid;
|
||||
XIM im;
|
||||
Uint64 screensaver_activity;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "../../core/unix/SDL_appid.h"
|
||||
|
||||
#include "SDL_x11video.h"
|
||||
#include "SDL_x11mouse.h"
|
||||
@@ -634,8 +635,8 @@ int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
|
||||
/* Setup the class hints so we can get an icon (AfterStep) */
|
||||
classhints = X11_XAllocClassHint();
|
||||
classhints->res_name = data->classname;
|
||||
classhints->res_class = data->classname;
|
||||
classhints->res_name = (char *)SDL_GetExeName();
|
||||
classhints->res_class = (char *)SDL_GetAppID();
|
||||
|
||||
/* Set the size, input and class hints, and define WM_CLIENT_MACHINE and WM_LOCALE_NAME */
|
||||
X11_XSetWMProperties(display, w, NULL, NULL, NULL, 0, sizehints, wmhints, classhints);
|
||||
|
||||
Reference in New Issue
Block a user