Add back X11 legacy WM_NAME encodings Closes #4924. Based on patches of the past, such as this work by James Cloos in July 2010: https://github.com/exg/rxvt-unicode/commit/d7d98751b7385416ad1694b5f1fde6c312ba20d5, as well as code comments in the Perl module X11::Protocol::WM (https://metacpan.org/pod/X11::Protocol::WM) and even the code to Xlib itself, which taught me that we should never have been using `XStoreName`, all it does is call `XChangeProperty`, hardcoded to `XA_STRING`! What can I say, when the task is old school, the sources are too 😂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
diff --git a/src/video/x11/SDL_x11messagebox.c b/src/video/x11/SDL_x11messagebox.c
index 8eda7c8..069a2df 100644
--- a/src/video/x11/SDL_x11messagebox.c
+++ b/src/video/x11/SDL_x11messagebox.c
@@ -404,11 +404,10 @@ X11_MessageBoxCreateWindow( SDL_MessageBoxDataX11 *data )
int x, y;
XSizeHints *sizehints;
XSetWindowAttributes wnd_attr;
- Atom _NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_DIALOG, _NET_WM_NAME;
+ Atom _NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_DIALOG;
Display *display = data->display;
SDL_WindowData *windowdata = NULL;
const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
- char *title_locale = NULL;
if ( messageboxdata->window ) {
SDL_DisplayData *displaydata =
@@ -452,32 +451,7 @@ X11_MessageBoxCreateWindow( SDL_MessageBoxDataX11 *data )
X11_XSetTransientForHint( display, data->window, windowdata->xwindow );
}
- X11_XStoreName( display, data->window, messageboxdata->title );
- _NET_WM_NAME = X11_XInternAtom(display, "_NET_WM_NAME", False);
-
- title_locale = SDL_iconv_utf8_locale(messageboxdata->title);
- if (title_locale) {
- XTextProperty titleprop;
- Status status = X11_XStringListToTextProperty(&title_locale, 1, &titleprop);
- SDL_free(title_locale);
- if (status) {
- X11_XSetTextProperty(display, data->window, &titleprop, XA_WM_NAME);
- X11_XFree(titleprop.value);
- }
- }
-
-#ifdef X_HAVE_UTF8_STRING
- if (SDL_X11_HAVE_UTF8) {
- XTextProperty titleprop;
- Status status = X11_Xutf8TextListToTextProperty(display, (char **) &messageboxdata->title, 1,
- XUTF8StringStyle, &titleprop);
- if (status == Success) {
- X11_XSetTextProperty(display, data->window, &titleprop,
- _NET_WM_NAME);
- X11_XFree(titleprop.value);
- }
- }
-#endif
+ SDL_X11_SetWindowTitle(display, data->window, (char*)messageboxdata->title);
/* Let the window manager know this is a dialog box */
_NET_WM_WINDOW_TYPE = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h
index db8715a..ba08ea9 100644
--- a/src/video/x11/SDL_x11sym.h
+++ b/src/video/x11/SDL_x11sym.h
@@ -156,6 +156,9 @@ SDL_X11_SYM(SDL_X11_XESetWireToEventRetType,XESetWireToEvent,(Display* a,int b,S
SDL_X11_SYM(SDL_X11_XESetEventToWireRetType,XESetEventToWire,(Display* a,int b,SDL_X11_XESetEventToWireRetType c),(a,b,c),return)
SDL_X11_SYM(void,XRefreshKeyboardMapping,(XMappingEvent *a),(a),)
SDL_X11_SYM(int,XQueryTree,(Display* a,Window b,Window* c,Window* d,Window** e,unsigned int* f),(a,b,c,d,e,f),return)
+SDL_X11_SYM(Bool,XSupportsLocale,(void),(),return)
+SDL_X11_SYM(void,XSetWMName,(Display* a,Window b,XTextProperty* c),(a,b,c),return)
+SDL_X11_SYM(Status,XmbTextListToTextProperty,(Display* a,char** b,int c,XICCEncodingStyle d,XTextProperty* e),(a,b,c,d,e),return)
#if SDL_VIDEO_DRIVER_X11_XFIXES
SDL_X11_MODULE(XFIXES)
diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c
index 92eff83..6d2cd07 100644
--- a/src/video/x11/SDL_x11video.c
+++ b/src/video/x11/SDL_x11video.c
@@ -460,6 +460,14 @@ X11_VideoInit(_THIS)
X11_InitXfixes(_this);
#endif /* SDL_VIDEO_DRIVER_X11_XFIXES */
+#ifndef X_HAVE_UTF8_STRING
+ SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "X server doesn't support UTF8_STRING, a feature introduced in 2000! This is likely to become a hard error in a future libSDL2.");
+#endif
+
+ if (X11_XSupportsLocale() != True) {
+ return SDL_SetError("Current locale not supported by X server, cannot continue.");
+ }
+
if (X11_InitKeyboard(_this) != 0) {
return -1;
}
diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c
index 8c0d31d..48f0cc6 100644
--- a/src/video/x11/SDL_x11window.c
+++ b/src/video/x11/SDL_x11window.c
@@ -716,9 +716,11 @@ X11_GetWindowTitle(_THIS, Window xwindow)
0L, 8192L, False, XA_STRING, &real_type, &real_format,
&items_read, &items_left, &propdata);
if (status == Success && propdata) {
+ SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Failed to convert _WM_NAME title expecting UTF8! Title: %s", title);
title = SDL_iconv_string("UTF-8", "", SDL_static_cast(char*, propdata), items_read+1);
X11_XFree(propdata);
} else {
+ SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not get any window title response from Xorg, returning empty string!");
title = SDL_strdup("");
}
}
@@ -729,30 +731,11 @@ void
X11_SetWindowTitle(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Window xwindow = data->xwindow;
Display *display = data->videodata->display;
- Status status;
- const char *title = window->title ? window->title : "";
-
- Atom UTF8_STRING = data->videodata->UTF8_STRING;
- Atom _NET_WM_NAME = data->videodata->_NET_WM_NAME;
- Atom WM_NAME = data->videodata->WM_NAME;
-
- X11_XChangeProperty(display, data->xwindow, WM_NAME, UTF8_STRING, 8, 0, (const unsigned char *) title, SDL_strlen(title));
+ char *title = window->title ? window->title : "";
- status = X11_XChangeProperty(display, data->xwindow, _NET_WM_NAME, UTF8_STRING, 8, 0, (const unsigned char *) title, SDL_strlen(title));
-
- if (status != 1) {
- char *x11_error = NULL;
- char x11_error_locale[256];
- if (X11_XGetErrorText(display, status, x11_error_locale, sizeof(x11_error_locale)) == Success)
- {
- x11_error = SDL_iconv_string("UTF-8", "", x11_error_locale, SDL_strlen(x11_error_locale)+1);
- SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Error when setting X11 window title to %s: %s\n", title, x11_error);
- SDL_free(x11_error);
- }
- }
-
- X11_XFlush(display);
+ SDL_X11_SetWindowTitle(display, xwindow, title);
}
void
@@ -1888,6 +1871,39 @@ X11_FlashWindow(_THIS, SDL_Window * window, SDL_FlashOperation operation)
return 0;
}
+bool SDL_X11_SetWindowTitle(Display* display, Window xwindow, char* title) {
+ Atom _NET_WM_NAME = X11_XInternAtom(display, "_NET_WM_NAME", False);
+ XTextProperty titleprop;
+ int conv = X11_XmbTextListToTextProperty(display, (char**) &title, 1, XStdICCTextStyle, &titleprop);
+ Status status;
+
+ if (conv == 0) {
+ X11_XSetTextProperty(display, xwindow, &titleprop, XA_WM_NAME);
+ X11_XFree(titleprop.value);
+ // we know this can't be a locale error as we checked X locale validity in X11_VideoInit
+ } else if (conv <= 0) {
+ SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "X11 reporting it's out of memory");
+ return EXIT_FAILURE;
+ } else { // conv >= 0
+ SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "%d characters were not convertable to the current locale!", conv);
+ return EXIT_FAILURE;
+ }
+
+#ifdef X_HAVE_UTF8_STRING
+ status = X11_Xutf8TextListToTextProperty(display, (char **) &title, 1, XUTF8StringStyle, &titleprop);
+ if (status == Success) {
+ X11_XSetTextProperty(display, xwindow, &titleprop, _NET_WM_NAME);
+ X11_XFree(titleprop.value);
+ } else {
+ SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Failed to convert title to UTF8! Bad encoding, or bad Xorg encoding? Window title: «%s»", title);
+ return EXIT_FAILURE;
+ }
+#endif
+
+ X11_XFlush(display);
+ return EXIT_SUCCESS;
+}
+
#endif /* SDL_VIDEO_DRIVER_X11 */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h
index bf01e1a..dd66af7 100644
--- a/src/video/x11/SDL_x11window.h
+++ b/src/video/x11/SDL_x11window.h
@@ -117,6 +117,8 @@ extern int X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
extern void X11_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept);
extern int X11_FlashWindow(_THIS, SDL_Window * window, SDL_FlashOperation operation);
+bool SDL_X11_SetWindowTitle(Display* display, Window xwindow, char* string);
+
#endif /* SDL_x11window_h_ */
/* vi: set ts=4 sw=4 expandtab: */