News:

Simutrans Tools
Know our tools that can help you to create add-ons, install and customize Simutrans.

[r7312] SDL2 Text input not working

Started by firefrorefiddle, September 09, 2014, 07:34:06 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

firefrorefiddle

I compiled Simutrans from trunk. When I choose SDL as a backend, keyboard shortcuts work. When I choose SDL2 and relink, they don't anymore.

After commenting out the following lines, it works again:

simsys_s2.cc:637 SDL_StartTextInput();
simsys_s2.cc:642 SDL_StopTextInput();

Obviously, sdl disables normal keyboard input if TextInput is started.

This is compiling on a normal PC, with no special options. My config.default contains only:

BACKEND = sdl2
COLOUR_DEPTH = 16
OSTYPE = linux
OPTIMISE = 1

This bug is potentially game breaking because without keyboard input, it is impossible to switch underground levels. It is not urgent to me, however, because of above workaround.

Ters

Without those two lines, entering text will not work, at least on some platforms.

Michael 'Cruzer'

I can reproduce some issues with that to. Text input works quite fine (tested on Mac OS X 10.9 and Ubuntu 14.04) which is because on every focus of a textbox SDL_StartTextInput() is called and everytime textbox looses focus SDL_StopTextInput() is called.

But SDL_StopTextInput() also blocks every keyboard actions from now on. So after SDL_StopTextInput() is called once, keyboard shortcuts don't work anymore. I've got it work by uncommenting

simsys_s2.cc:642 SDL_StopTextInput();

the other line can be still be there. Which will result that on touch based devices the keyboard still appears on focus, but the user must always manually hide the keyboard (if possible at platform, which is possible at least for Windows and iOS, which are the only touch platforms supported by now). On other platforms it will just prevent that keyboard shortcuts will ever be blocked.

(But I am not happy with the solution. SDL2 documentation says to always use this functions in combination.)
Founder and Ex-Maintainer of pak192.comic. Provider of Simutrans Hosting rental service.

Ters

It might better to use these functions only on platforms where keyboard shortcuts makes little or no sense.

prissi

Is there an easy (and portable) way to find out if we need this? I fear not ...

Ters

I would think that most of these platforms would need targeted builds, just like Windows vs. Linux vs. Mac, although Windows and possibly also Mac will be able to run apps for corresponding handhelds on the desktop as well. The "portable way of detecting" this would then probably be something like #ifdef ANDROID just like we have #ifdef _WIN32 today.

What probably causes this problem is that Simutrans, unlike most games I know of and game programming tutorials, bind action to letters rather than virtual key codes. The arguments for doing so are valid, but while much more portable across keyboard layouts, isn't that portable when a traditional keyboard become options. Or does SDL stop all keyboard event processing? If so, they've misnamed the functions.

Michael 'Cruzer'

I guess the only way would be something like a TOUCH_SUPPORT flag in makefile and #ifdef TOUCH_SUPPORT around those two lines. Otherwise just don't call stop ever and accept that user always manually must close keyboards on such systems may also be an option.
Founder and Ex-Maintainer of pak192.comic. Provider of Simutrans Hosting rental service.

Ters

Quote from: Michael 'Cruzer' on September 12, 2014, 10:47:45 AM
Otherwise just don't call stop ever and accept that user always manually must close keyboards on such systems may also be an option.

This might cause problems down the line, even though it works now. Third party developers doing things like this have been much of the reason why new versions of Windows have gotten many complaints.

Michael 'Cruzer'

Quote from: Ters on September 12, 2014, 02:37:07 PM
This might cause problems down the line, even though it works now. Third party developers doing things like this have been much of the reason why new versions of Windows have gotten many complaints.

Yes, you are right in that case. That's why I mentioned it "not happy with the solution. SDL2 documentation says to always use this functions in combination." at the post above.
Founder and Ex-Maintainer of pak192.comic. Provider of Simutrans Hosting rental service.

Philip

Quote from: prissi on September 11, 2014, 10:15:45 PM
Is there an easy (and portable) way to find out if we need this? I fear not ...

There's SDL_HasScreenKeyboardSupport(), which is probably a better guess than defining it in the Makefile. (There's also SDL_IsTextInputActive(), but I don't think that's the one we want).

I think what the SDL2 people would want us to do is to use SDL_KEYDOWN events rather than SDL_TEXTINPUT events (and incidentally handle multi-character SDL_TEXTINPUT events). However, it looks like we'd have to do our own shift handling then, which seems unnecessarily difficult.

The easy fix would be to call    SDL_EventState( SDL_TEXTINPUT, SDL_ENABLE ); after each call to SDL_StopTextInput(). Why don't we do that?

Ters

Quote from: Philip on September 12, 2014, 03:41:57 PM
I think what the SDL2 people would want us to do is to use SDL_KEYDOWN events rather than SDL_TEXTINPUT events (and incidentally handle multi-character SDL_TEXTINPUT events). However, it looks like we'd have to do our own shift handling then, which seems unnecessarily difficult.
I don't think the SDL2 people would want us to do it one way or the other. It's probably more that binding to keys rather than letters are the norm, which makes for action packed games. When using WASD instead of arrow keys, they want the keys that are WASD on English query, not the keys that actually have W, A, S and D on a Dvorak layout. That telling user to make the WASD-keys make no sense for a Dvorak user, is of less importance and they will soon learn which keys they are supposed to use, as they will continually use them. Simutrans is just different from the majority.

Quote from: Philip on September 12, 2014, 03:41:57 PM
The easy fix would be to call    SDL_EventState( SDL_TEXTINPUT, SDL_ENABLE ); after each call to SDL_StopTextInput(). Why don't we do that?
Likely because no one has thought of it before.

Philip

Quote from: Ters on September 12, 2014, 06:48:09 PM
I don't think the SDL2 people would want us to do it one way or the other. It's probably more that binding to keys rather than letters are the norm, which makes for action packed games. When using WASD instead of arrow keys, they want the keys that are WASD on English query, not the keys that actually have W, A, S and D on a Dvorak layout. That telling user to make the WASD-keys make no sense for a Dvorak user, is of less importance and they will soon learn which keys they are supposed to use, as they will continually use them. Simutrans is just different from the majority.

I don't think SDL2 does that, though. event.key.keysym.sym is 'o' for the Dvorak O key (labelled as S on an English keyboard). However, it does set event.key.keysym.scancode to SDL_SCANCODE_S.

So we wouldn't change anything for dvorak users by moving to handling SDL_KEYDOWN events rather than SDL_TEXTINPUT events. It would still be a bit of work because we'd have to handle shift ourselves. I honestly don't see how SDL's default behaviour makes sense: devices can have both an external (bluetooth, say) keyboard and an on-screen keyboard, and ignoring the external keyboard just because the on-screen keyboard isn't shown is clearly broken.

I must admit I tried without success to get an XIM input method to work with SDL, but  apart from that the extra call to SDL_EventState seems to work well.

Ters

Quote from: Philip on September 13, 2014, 08:48:44 PM
I don't think SDL2 does that, though. event.key.keysym.sym is 'o' for the Dvorak O key (labelled as S on an English keyboard). However, it does set event.key.keysym.scancode to SDL_SCANCODE_S.

I wasn't aware of the fact that SDL2 reports keys in three different ways. What I wrote was based on the assumption that it only had event.key.keysym.scancode for SDL_KEYDOWN.

Quote from: Philip on September 13, 2014, 08:48:44 PM
So we wouldn't change anything for dvorak users by moving to handling SDL_KEYDOWN events rather than SDL_TEXTINPUT events. It would still be a bit of work because we'd have to handle shift ourselves.

Figuring out what the upper case of all the various letters beyond the 26 in the English alphabet is hard enough. I'm not sure if standard C/C++ has routines for that. Yet the main problem would be non-letters. These require knowledge about the actual keyboard layout.

TurfIt

We're relying on SDL_TEXTINPUT for all normal key input. SDL_KEYDOWN is working somewhat for CTRL-keys, and other special keys.
So, calling SDL_StopTextInput() obviously kills things. r7292 "(Cruzer) show keyboard in SDL2 when doing text input" was added why?

Getting anything to work in SDL2 was/is a nightmare compared with SDL1. In SDL1, there was a .unicode member returned from SDL_KEYDOWN. They removed it in SDL2 leaving us only with the textinput method. SDL_StartTextInput gets called during the init, Stop only when Simutrans closes. Atleast until 7292 broke things by calling stop when switching focus from a gui element - the textinput needs to remain active always.

See http://forum.simutrans.com/index.php?topic=12094.msg122958#msg122958 for the original SDL2 headbashing session...


Ters

Quote from: TurfIt on September 13, 2014, 09:27:16 PM
r7292 "(Cruzer) show keyboard in SDL2 when doing text input" was added why?

As explained in this discussion, as well as the discussion leading up to that commit: in order to get keyboardless devices (phones and pads) to pop up a virtual keyboard when a text field is given focus, and to hide that keyboard again when the text field loses focus.

prissi

#15
Yes, but on device with a keyboard (the majority) the keyboard becomes useless. Probably this needs a clever detection if a softkeyboard is needed or not.

For now you can set hide_keyboard = 1 in simuconf.tab

Philip

Quote from: prissi on September 14, 2014, 09:00:16 PM
Yes, but on device with a keyboard (the majority) the keyboard becomes useless. Probably this needs a clever detection if a softkeyboard is needed or not.

For now you can set hide_keyboard = 1 in simuconf.tab

May I ask what you think is wrong with just re-enabling TEXTINPUT events after StopTextInput()? It seems to work fine here, though I haven't tested it with an on-screen keyboard.

prissi

No idea, has anybody such a device and build?

prissi

Added reanbling SDL_TEXTINPUT in r10167

Yona-TYT

Quote from: prissi on October 17, 2021, 08:45:55 AM
Added reanbling SDL_TEXTINPUT in r10167
And to think that I found this thread by pure chance.  (I was researching entry events in sdl2).  ;D ;D ;D