http://bugs.winehq.org/show_bug.cgi?id=19440
--- Comment #7 from Andrew Eikum aeikum@codeweavers.com 2010-06-02 10:40:09 --- Created an attachment (id=28519) --> (http://bugs.winehq.org/attachment.cgi?id=28519) Partial, and probably wrong, patch which fixes the bug
Reverting that commit does fix it.
The problem seems to be that the richedit control doesn't handle the VK_TAB WM_KEYDOWN message properly. You can see in the WM_KEYDOWN handler, around editor.c:2294, that the richedit control assumes its parent window is a dialog, since only dialogs handle WM_NEXTDLGCTL. In the case of Word Viewer, the richedit's parent actually uses DefWindowProc, NOT DefDlgProc, so this message gets ignored.
You can see better handling of the tab key in user32/dialog.c:IsDialogMessageW. In here, the WM_NEXTDLGCTL message is sent iff the target window is a dialog, and some manual focus-changing occurs if the target window is not a dialog. I think the richedit control should either be running this code, or have similar logic to this code.
Making a stripped-down copy of the user32 code inside of the richedit VK_TAB handler fixes the bug. However, the stripped-down code is missing some important features, such as detecting if the parent is a dialog (causes test failures) and examining the WM_GETDLGCODE value from the new focus window. The user32 VK_TAB handling code that I copied uses internal user32 data to implement these features. Even if it is possible to recreate the functionality using public functions, this kind of code duplication is bad.
So to avoid code duplication, we want to execute the code in IsDialogMessageW. Fabricating a WM_KEYDOWN message to send to the parent and pushing that through IsDialogMessageW does the trick. But it causes tests to fail, as the parent expects WM_NEXTDLGCTL messages. A test to check if those messages still get sent when the parent isn't a dialog is in order. If they don't, then this patch is probably on the right path. If they do, then I'm probably way off.