From 1495774a066cb027a3d96cf7d489185fdc429df3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Deuc=D0=B5?= <shurd@sasktel.net>
Date: Fri, 19 Mar 2021 13:56:29 -0400
Subject: [PATCH] Fix AltGr with SDL2

This is pretty insane since SDL2 completely ignores the keysym value
of the X11 keyboard event, so here's what we do...

1) When there's a keypress that includes right-alt, store the sym/mod
2) When we get text input, if it's the same as we would get if ALT
   wasn't pressed for the last keydown, parse through the mapping
   (ie: handle ALT keys)
3) If it's different, use that (gets AltGr modified value)

I get that AltGr is hard in a cross-platform way, but just pretending
it doesn't exist at all for key input is a very weird choice.
---
 src/conio/sdl_con.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/src/conio/sdl_con.c b/src/conio/sdl_con.c
index e585781acb..74e822bc27 100644
--- a/src/conio/sdl_con.c
+++ b/src/conio/sdl_con.c
@@ -795,6 +795,8 @@ void sdl_video_event_thread(void *data)
 	SDL_Event	ev;
 	int		old_w, old_h;
 	int		block_text = 0;
+	static SDL_Keycode last_sym = SDLK_UNKNOWN;
+	static Uint16 last_mod = 0;
 
 	pthread_mutex_lock(&vstatlock);
 	old_w = cvstat.winwidth;
@@ -816,6 +818,8 @@ void sdl_video_event_thread(void *data)
 		else {
 			switch (ev.type) {
 				case SDL_KEYDOWN:			/* Keypress */
+					last_mod = ev.key.keysym.mod;
+					last_sym = ev.key.keysym.sym;
 					if ((ev.key.keysym.mod & (KMOD_CTRL|KMOD_ALT|KMOD_GUI)) && !(ev.key.keysym.mod & KMOD_MODE)) {
 						block_text = 1;
 						if ((ev.key.keysym.mod & KMOD_ALT) &&
@@ -878,6 +882,10 @@ void sdl_video_event_thread(void *data)
 							break;
 						}
 					}
+					if (ev.key.keysym.mod & KMOD_RALT) {	// Possible AltGr, let textinput sort it out...
+						block_text = 0;
+						break;
+					}
 					if ((ev.key.keysym.mod & KMOD_SHIFT) && (ev.key.keysym.sym == '\t'))
 						block_text = 1;
 					if (block_text || ev.key.keysym.sym < 0 || ev.key.keysym.sym > 127) {
@@ -897,10 +905,17 @@ void sdl_video_event_thread(void *data)
 					}
 					break;
 				case SDL_TEXTINPUT:
-					if (!block_text)
-						sdl_add_keys((uint8_t *)ev.text.text);
+					if (!block_text) {
+						unsigned int charcode = sdl_get_char_code(last_sym, last_mod & ~(KMOD_ALT));
+						// If the key is exactly what we would expect, use sdl_get_char_code()
+						if (*(uint8_t *)ev.text.text == charcode)
+							sdl_add_key(sdl_get_char_code(last_sym, last_mod));
+						else
+							sdl_add_keys((uint8_t *)ev.text.text);
+					}
 					break;
 				case SDL_KEYUP:
+					last_mod = ev.key.keysym.mod;
 					if (!(ev.key.keysym.mod & (KMOD_CTRL|KMOD_ALT|KMOD_GUI)))
 						block_text = 0;
 					break;
-- 
GitLab