[Mono-winforms-list] patch for enabling primitive XIM text input

Atsushi Eno atsushi at ximian.com
Thu Mar 27 03:33:51 EDT 2008


Hi,

Thanks for the details. Though I don't think I completely understand the 
second issue
(XIM event order matter), I am persuaded. Your patch is in svn (along 
with my patch
of course too).

I'm also getting into libX11 code, so if you have pointers to relevant 
sources (probably
in src/xlibi18n/* or modules/im/* ?) please give us them :)

Atsushi Eno

Doug Rintoul wrote:
> Atsushi Eno wrote:
>   
>> Hello,
>>
>>     
>>> The first problem has to do with the tracking of the control, shift, 
>>> and alt key. These keys will currently get "stuck" because if 
>>> FosterParent filters the key release event, a key release event for 
>>> these keys are never put on the hwnd Queue. For example, if you press 
>>> CTRL-space to enable an IM, winforms still thinks the control key is 
>>> still pressed, even after you release it. Using the left and right 
>>> cursor keys to move around a input field will move a word at a time, 
>>> rather than a letter at a time.
>>>
>>>       
>> Ah, good point! It should be fixed too. But I somewhat doubt if your 
>> change
>> especially that KeyRelease event is always passed works fine.
>> It could result in inconsistent key event processing (KeyPress could be
>> filtered and KeyRelease always isn't) and such inconsistency trapped me
>> couple of days. So, IMHO there should be some condition to determine
>> whether to filter KeyRelease or not.
>>
>>     
> Key filtering is totaling at the whim of the IM. If the the IM processes 
> a key event it will tell the calling procedure the event is filtered. I 
> am assuming you mean there should be a condition on whether we should 
> process a key event in winforms even when the IM has filtered the event. 
> If so, then you are correct. I think my patch currently works because 
> few apps use key release events and so dual processing by both the IM 
> and winforms is not an issue. However keypress events for mod could be a 
> problem if the IM filters event. The keypress event would never be 
> processed by winforms and thus the key state would never be registered. 
> In this case we cannot do dual processing of all keypress events. So 
> some condition needs to be determine as to when we pass the key press 
> and key release events onto winform.
>
> Unfortunately, winforms currently relies on key press and key release 
> events to track the modification key states. Perhaps it is enough to 
> test if the event is a key press or a key release mod key event (alt, 
> ctrl, shift, menu, etc) and then pass the event on to winforms for 
> processing even if the IM filters the event. The only other alternative 
> I can see is to redesign winforms so that it queries X for the current 
> state of the modifier keys whenever it needs that information.
>   
>>> The second issue has to do with the way that IME compose messages are 
>>> handle. A bit of background is required here. I am one of the authors 
>>> of KMFL (kmfl.sourceforge.net), which provides Tavaultesoft Keyman 
>>> services to Linux. The way KMFL is designed is that KMFL can generate 
>>> multiple compose messages in response to a single key stroke. The 
>>> problem is that XIM does not use a FIFO to queue XIM compose 
>>> messages, but a stack. So unless XIM compose events are processed 
>>> immediately upon receipt, the recipient window will receive the XIM 
>>> compose messages in the reverse order that they are generated. The 
>>> fix is rather easy to implement. We just allow the application to 
>>> process the keypress messages upon receipt rather than queuing a 
>>> whole bunch and then returning. Note that the GTK XIM connector and 
>>> the QT XIM interface work correctly with KMFL, so they implement a 
>>> similar solution.
>>>
>>>       
>> I'm not sure what you meant here. Do you mean such event processing 
>> like below
>> could happen? :
>>
>>    - KeyPress for 'A' occurs, and then it is stored in X event queue 
>> ... well, "stack" ...
>>      as pending.
>>    - KeyPress for 'B' occurs, and then it is stored as pending.
>>    - XNextEvent() is called, and X returns KeyPress 'B' because it is 
>> not FIFO.
>>
>>     
> This is sort of what happens. It has been awhile since I poked around 
> the XIM code in X. I just went back to familiarized myself with the 
> situation. The actual problem is with the XIM commit code in X11. Here 
> is an example of what actually happens:
>
> 1. The user presses 7. The input method is to generate the string 
> "seven" in response to this. The IM will actually generate each 
> character as a separate compose event. I realize that in this case the 
> IM could have generated one compose event containing the string "seven", 
> but this is not always the case. The way the kmfl engine is designed, it 
> needs to be able to generate separate compose events in response to one 
> keypress.
> 2. The IM calls the XIM commit callback to commit the first letter "s"
> 3. The XIM commit callback pushes the commit string on the IC commit 
> info stack and then fabricates a KeyPress event with a keycode of 0 and 
> pushes this event onto the event queue. Control is then transfered to 
> winforms.
> 4. winforms receives the fabricated event and puts the event onto the 
> hwnd queue via UpdateMessageQueue (UpdateMessageQueue was called by 
> GetMessage).
> 5. UpdateMessageQueue then calls XPending and XNextEvent in a loop to 
> get the next event. XNextEvent passes control back to X which in turn 
> passes control back to the IM.
> 6. The IM calls the XIM commit callback to commit the second letter "e"
> 7. Steps 3, 4 and 5 are repeated.
> 8. Steps 2, 3, 4 and 5 are repeated for the rest of the letters. Note 
> that the IC commit info stack now has "neves" on it.
> 9. Control is now passed back to winforms GetMessage. GetMessage calls 
> Keyboard.KeyEvent to process the first fabricated keypress.
> 10. KeyEvent calls LookupString which in turn calls Xutf8LookupString. 
> Xutf8LookupString returns the first compose sequence off the C commit 
> info stack, in this case "n" which is in turn sent to the app via 
> SendImeComposition.
> 11. Step 10 is repeated for each of the compose character and thus neves 
> is sent to the application.
>
>   
>> Gtk and Qt of course have different event processing model from 
>> winforms, so it
>> could be just that the issue with kfml does not occur. I'm not sure 
>> your change is
>> valid from our perspective (UpdateMessageQueue() may have to lookup 
>> every X
>> events; I have no idea as I'm just digging into winforms only for XIM 
>> support ;).
>>     
> Not sure I understand. Every event is still processed by 
> UpdateMessageQueue. Just not in a loop for keypress events.
>   
>> Besides I'm not sure why giving up processing pending event 
>> immediately in
>> UpdateMessageQueue() could fix the situation. To my understanding, events
>> are anyways retrieved as LIFO (if I believe you) and if kfml anyways 
>> regenerate
>> other messages as a result of KeyPress, they will be retrieved 
>> immediately
>> anyways, won't they?
>>     
> What my patch does is remove step 5. Control is passed back up the chain 
> to GetMessage and thus Keyboard.KeyEvent to pop the commit string off 
> the commit info stack before the IM and X can put another commit string 
> onto the stack.
>   
>>> There is a third issue, the importance of which is debatable. For 
>>> other frameworks (QT, GTK), each window in an application gets its 
>>> own input method, independent of the other windows in an application. 
>>> For example, in a text editor, even though you enable the input 
>>> method, for the main editor, the IM is not enabled for the search 
>>> box. This may not seem important at first, but it can be an issue for 
>>> multilingual application where different fields can have different 
>>> input methods associated with them. The patch I created last November 
>>> did support this feature; however it does add a lot of complexity to 
>>> the mix.
>>>
>>>       
>> Hmm, I don't think Windows Forms allow such input method switching.
>> It just controls whether IM could be enabled (default) or not. Of course
>> it is possible to have different XICs for each window but I doubt we have
>> any configuration point (other than custom configuration, environment
>> variables or whatever).
>>
>>     
> Winforms itself does not allow for such switching but an IM framework 
> such as SCIM does. For example, I could have one field in which I want 
> to type IPA characters and another field in which I want to type Greek. 
> I enable the IM for the first field and switch to the IPA keyboard. I 
> then switch to the second field and enable the IM and switch it to 
> greek. For other frameworks such as GTK and QT, if I click on the first 
> field, the input context is automatically switch back to IPA.
>
> Stimulating stuff. Hopefully we can address these issues and come up 
> with a working solution.
>
> Doug Rintoul.
> SIL Intl.
> _______________________________________________
> Mono-winforms-list maillist  -  Mono-winforms-list at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-winforms-list
>
>   



More information about the Mono-winforms-list mailing list