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 - [email protected] > http://lists.ximian.com/mailman/listinfo/mono-winforms-list > > _______________________________________________ Mono-winforms-list maillist - [email protected] http://lists.ximian.com/mailman/listinfo/mono-winforms-list
