Open Jamiras opened 3 years ago
This appears to be a limitation of the way the DLL is integrating with the emulator, and the way windows handles tabbing between fields. In order to process a TAB as a move-to-the-next-field message, the message loop in the emulator must call IsDialogMessage
for the window where the tabbing would take place. You can see how fceumm handles all of its child windows here.
While it could be possible to provide a function for the client to call inside it's message loop so we could call IsDialogMessage
for each of our windows, this only works when the client has control over it's message loop. RALibretro uses SDL2 for it's window system, and the message loop is buried inside the SDL2 code. Allegro (used by Meka) is even worse. It doesn't call TranslateMessage
or IsDialogMessage
in it's message loop, which entirely prevents typing in our windows. To get around that, we have to parent our windows to the Meka console instead of the main emulator window.
A possible alternative is to subclass each of the input controls on an editor window and add code to handle the WM_KEYDOWN for VK_TAB that issues a WM_NEXTDLGCTL message. My attempts to implement a solution in this regard did move focus between fields, but the controls still generated the "ding" sound suggesting that they didn't support that key. While not an exact replacement for IsDialogMessage
, the IsDialogMessage
documentation says that TranslateMessage
and DispatchMessage
must not be called if IsDialogMessage
handles the message, so I suspect the one of those to be causing the secondary processing of the message using this implementation.
IsDialogMessage ends up producing an interesting problem here. That filters out some messages sent to the controls, such as Enter and Tab events. This a bit bad for the code notes editor as that ends up not able to enter in code notes and tabbing doesn't work as expected. There's other cases where this produces undesirable results. This can be avoided however, by simply responding to the WM_GETDLGCODE message sent: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-isdialogmessagew#remarks https://learn.microsoft.com/en-us/windows/win32/dlgbox/wm-getdlgcode
BizHawk's WIP implementation actually does IsDialogMessage for message pumping RA's windows (this is buried in WinForm's message pumping code, not really controllable). So tabbing between fields does work, but it leads to the issues described above due to WM_GETDLGCODE not being properly responded to.
Seems that while WM_GETDLGCODE is a "solution," it's not really the proper one (well, not in all cases). These issues ultimately seem to just come from improperly created dialogs. For example here:
https://github.com/RetroAchievements/RAIntegration/blob/73140a30a731a16d03e7cf7819af6bfa98cbd78d/src/RA_Shared.rc#L61
For Enter to be processed as a line break, ES_WANTRETURN
needs to be set. Since this was not set, Enter does not have any effect when IsDialogMessage
is used.
Although unfortunately in the case of tabbing, it seems WM_GETDLGCODE is the only solution (and that also requires subclassing the dialog in order to actually respond to it).
As a developer, I expect to be able to tab between fields in an editor. In particular, from the title to the description and points fields in the achievement editor.