[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