SDL Backend: InputText causes underlying child window not receiving any InputQueueCharacters #6306

Closed
opened 2023-04-06 13:36:55 +00:00 by vdweller84 · 8 comments
vdweller84 commented 2023-04-06 13:36:55 +00:00 (Migrated from github.com)

ImGui version: 1.89.4
Backends: SDL, OpenGL

Hello,

I am making a Code Editor using ImGui . As a final touch, I want to add a search/replace popup with input fields.

The way the text editor works that I create a Child Window that processes, among others, InputQueueCharacters . Everything works OK:

image

for (int i = 0; i < io.InputQueueCharacters.Size; ++i) {
  ImWchar c = io.InputQueueCharacters[i];
  AddCharacter((uint32_t)c, shift);
}

However, when the Search/replace popup appears and I edit the Search text:

image

When I close the popup, then the underlying child window loses all InputQueueCharacters and I can't type anything.

Is there any way to somehow "activate" InputQueueCharacters again?

ImGui version: 1.89.4 Backends: SDL, OpenGL Hello, I am making a Code Editor using ImGui . As a final touch, I want to add a search/replace popup with input fields. The way the text editor works that I create a Child Window that processes, among others, InputQueueCharacters . Everything works OK: ![image](https://user-images.githubusercontent.com/96083791/230394027-eb207a4b-37d0-4966-8720-f1dea3a4004d.png) ``` for (int i = 0; i < io.InputQueueCharacters.Size; ++i) { ImWchar c = io.InputQueueCharacters[i]; AddCharacter((uint32_t)c, shift); } ``` However, when the Search/replace popup appears and I edit the Search text: ![image](https://user-images.githubusercontent.com/96083791/230394330-79afdc6e-0b35-4419-9549-762bd377d24e.png) When I close the popup, then the underlying child window loses all InputQueueCharacters and I can't type anything. Is there any way to somehow "activate" InputQueueCharacters again?
ocornut commented 2023-04-06 13:49:18 +00:00 (Migrated from github.com)

Your question is too ambiguous to be answered.
InputQueueCharacters[] is never "lost" it is filled during NewFrame().

We don't know what's behind. It is a InputTextMultiline() or your custom editor?
The widget has likely been deactivated and needs to be set active again.
Typically you'd call SetKeyboardFocusHere(-1) after your InputText() to reactivate it.

Note that we currently only preserve cursor/selection data for one input text, so if your filter is another InputText() that will lose cursor/selection of your main editor. But you seem to be implying you are NOT using InputText() for that filter, which itself is a little surprising.

Your question is too ambiguous to be answered. `InputQueueCharacters[]` is never "lost" it is filled during `NewFrame()`. We don't know what's behind. It is a `InputTextMultiline()` or your custom editor? The widget has likely been deactivated and needs to be set active again. Typically you'd call `SetKeyboardFocusHere(-1)` after your `InputText()` to reactivate it. Note that we currently only preserve cursor/selection data for one input text, so if your filter is another InputText() that will lose cursor/selection of your main editor. But you seem to be implying you are NOT using InputText() for that filter, which itself is a little surprising.
vdweller84 commented 2023-04-06 14:12:02 +00:00 (Migrated from github.com)

To elaborate:

My code editor is not an InputText widget of any kind. It is just a child window that processes keystrokes/mouse and draw text. It reads from InputQueueCharacters[] and adds characters accordingly.

However, if I enter text in a "real" InputText widget of any kind, I am then unable to do so, as InputQueueCharacters[] seems to be premanently empty for that child window. I can show the popup again and enter text normally to the InputText widget that it contains, but the underlying child window that processes InputQueueCharacters[] cannot do so any more when I close the popup.

Hope that helps!

To elaborate: My code editor is not an InputText widget of any kind. It is just a child window that processes keystrokes/mouse and draw text. It reads from `InputQueueCharacters[]` and adds characters accordingly. However, if I enter text in a "real" InputText widget of any kind, I am then unable to do so, as `InputQueueCharacters[]` seems to be premanently empty for that child window. I can show the popup again and enter text normally to the InputText widget that it contains, but the underlying child window that processes `InputQueueCharacters[]` cannot do so any more when I close the popup. Hope that helps!
vdweller84 commented 2023-04-06 14:21:21 +00:00 (Migrated from github.com)

To provide another example:

Here is a window that has nothing to do with the aforementioned example. Just a window with some widgets:
image

If I show ImGui's Debug/Metrics window and I click on an empty spot in the window and start typing keys, the "Chars" field of the Debug window shows characters.

However! If I click on an input field widget in this window and edit the text, and then I click back again on the window and press random keys, the "Chars" field shows nothing!

Could this be an SDL issue?

To provide another example: Here is a window that has nothing to do with the aforementioned example. Just a window with some widgets: ![image](https://user-images.githubusercontent.com/96083791/230405599-4a57656b-0fdb-4c32-8115-e2d99ae4b603.png) If I show ImGui's Debug/Metrics window and I click on an empty spot in the window and start typing keys, the "Chars" field of the Debug window shows characters. However! If I click on an input field widget in this window and edit the text, and then I click back again on the window and press random keys, the "Chars" field shows nothing! Could this be an SDL issue?
seanpringle commented 2023-04-06 16:25:19 +00:00 (Migrated from github.com)

I have the same problem after updating to 1.89, also on an app that watches the input character queue when nothing else has the focus, also using the SDL backend.

Imgui 1.89.4
Latest imgui_impl_sdl2.cpp
SDL 2.26.5
Ubuntu 20.04

Same symptoms: io.InputQueueCharacters works fine at first, but never resumes after any popup window with a real text input is opened, focused, unfocused and closed. I just discovered disabling the IME handler in imgui_impl_sdl2.cpp restores the old behaviour:

//io.SetPlatformImeDataFn = ImGui_ImplSDL2_SetPlatformImeData;

I know nothing about IME and am not setting SDL_HINT_IME_SHOW_UI, but the handler above calls SDL_StopTextInput() which seems like the root cause.

I have the same problem after updating to 1.89, also on an app that watches the input character queue when nothing else has the focus, also using the SDL backend. Imgui 1.89.4 Latest imgui_impl_sdl2.cpp SDL 2.26.5 Ubuntu 20.04 Same symptoms: `io.InputQueueCharacters` works fine at first, but never resumes after any popup window with a real text input is opened, focused, unfocused and closed. I just discovered disabling the IME handler in `imgui_impl_sdl2.cpp` restores the old behaviour: ```c++ //io.SetPlatformImeDataFn = ImGui_ImplSDL2_SetPlatformImeData; ``` I know nothing about IME and am not setting `SDL_HINT_IME_SHOW_UI`, but the handler above calls `SDL_StopTextInput()` which seems like the root cause.
ocornut commented 2023-04-06 17:03:52 +00:00 (Migrated from github.com)

Just saw @seanpringle's answer as I had another answer.
It looks like that could be the problem indeed.
@vdweller84 Could you try to comment the io.SetPlatformImeDataFn assignment and see if it changes something?

We made changes to that IME support but because no other stock widgets are reading from InputQueueCharacters[] this wasn't noticed. In theory, your custom widget should set g.WantTextInputNextFrame = 1; which will set io.WantTextInput which is the standard way to let backend know that text inputs are desired, as on e.g. mobile platform this would likely be wired to enabled an overlay keyboard.

So it is partly a bug in your custom widget BUT it is also a bug in the backend.

(My initial answer, which i am pasting below was assuming your custom widget was misbehaving by not setting nor checking ActiveId. Given the polish of your app I would guess that isn't the case.)

Just saw @seanpringle's answer as I had another answer. It looks like that could be the problem **indeed**. @vdweller84 Could you try to comment the `io.SetPlatformImeDataFn` assignment and see if it changes something? We made changes to that IME support but because no other stock widgets are reading from `InputQueueCharacters[]` this wasn't noticed. In theory, your custom widget should set `g.WantTextInputNextFrame = 1;` which will set `io.WantTextInput` which is the standard way to let backend know that text inputs are desired, as on e.g. mobile platform this would likely be wired to enabled an overlay keyboard. So it is partly a bug in your custom widget BUT it is also a bug in the backend. (My initial answer, which i am pasting below was assuming your custom widget was misbehaving by not setting nor checking ActiveId. Given the polish of your app I would guess that isn't the case.)
ocornut commented 2023-04-06 17:18:43 +00:00 (Migrated from github.com)

I have pushed a tentative fix in the form of a7703fe

I have pushed a tentative fix in the form of a7703fe
vdweller84 commented 2023-04-06 17:33:32 +00:00 (Migrated from github.com)

Just saw @seanpringle's answer as I had another answer. It looks like that could be the problem either. @vdweller84 Could you try to comment the io.SetPlatformImeDataFn assignment and see if it changes something?

We made changes to that IME support but because no other stock widgets are reading from InputQueueCharacters[] this wasn't noticed. In theory, your custom widget should set g.WantTextInputNextFrame = 1; which will set io.WantTextInput which is the standard way to let backend know that text inputs are desired, as on e.g. mobile platform this would likely be wired to enabled an overlay keyboard.

So it is partly a bug in your custom widget BUT it is also a bug in the backend.

(My initial answer, which i am pasting below was assuming your custom widget was misbehaving by not setting nor checking ActiveId. Given the polish of your app I would guess that isn't the case.)

@ocornut I can confirm that commenting the io.SetPlatformImeDataFn assignment causes text input to work again.

I may be misunderstanding something here , but there really is no custom "widget". The workflow here is something like this:

> Create Window

  > Create Child Window (text area goes here)
    > Handle Mouse/Keyboard
    > Tokenize lines/do other stuff
    > Use clipping rects and draw
  > End Child Window
  
  > Create horizontal/vertical sliders
  > Create Status bar

>End Window

I am highlighting the above process in case I am doing something incredibly stupid. I really do not set or check any ActiveID. The program works fine otherwise. If there is some more esoteric step I am missing, please do let me know.

> Just saw @seanpringle's answer as I had another answer. It looks like that could be the problem either. @vdweller84 Could you try to comment the `io.SetPlatformImeDataFn` assignment and see if it changes something? > > We made changes to that IME support but because no other stock widgets are reading from `InputQueueCharacters[]` this wasn't noticed. In theory, your custom widget should set `g.WantTextInputNextFrame = 1;` which will set `io.WantTextInput` which is the standard way to let backend know that text inputs are desired, as on e.g. mobile platform this would likely be wired to enabled an overlay keyboard. > > So it is partly a bug in your custom widget BUT it is also a bug in the backend. > > (My initial answer, which i am pasting below was assuming your custom widget was misbehaving by not setting nor checking ActiveId. Given the polish of your app I would guess that isn't the case.) @ocornut I can confirm that commenting the `io.SetPlatformImeDataFn` assignment causes text input to work again. I may be misunderstanding something here , but there really is no custom "widget". The workflow here is something like this: ``` > Create Window > Create Child Window (text area goes here) > Handle Mouse/Keyboard > Tokenize lines/do other stuff > Use clipping rects and draw > End Child Window > Create horizontal/vertical sliders > Create Status bar >End Window ``` I am highlighting the above process in case I am doing something incredibly stupid. I really do not set or check any ActiveID. The program works fine otherwise. If there is some more esoteric step I am missing, please do let me know.
ocornut commented 2023-04-06 17:38:45 +00:00 (Migrated from github.com)

I thought your code editor was a custom widget.

If you read from g.IO.InputCharacters[] that read likely needs to be gated behind a test, e.g. a focus test or ActiveId test, else you'd be snooping characters that another widget may want to read because it is active.

If you read those characters, you should be setting g.WantTextInputNextFrame = 1; (we should add SetNextFrameWantTextInput() wrapper) in order for backend to have a chance to display an on-screen keyboard if you want your code to behave in a standard manner.

However at core this was/is a bug in the SDL backend that I have fixed now.

I thought your code editor was a custom widget. If you read from `g.IO.InputCharacters[]` that read likely needs to be gated behind a test, e.g. a focus test or ActiveId test, else you'd be snooping characters that another widget may want to read because it is active. If you read those characters, you should be setting `g.WantTextInputNextFrame = 1;` (we should add `SetNextFrameWantTextInput()` wrapper) in order for backend to have a chance to display an on-screen keyboard if you want your code to behave in a standard manner. However at core this was/is a bug in the SDL backend that I have fixed now.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ocornut/imgui#6306
No description provided.