I've been chasing a bug for a few days, and finally have a good idea of what is going on. When a program brings up a modal dialog box in response to a WM_KILLFOCUS message, the program will freeze. I've attached a simple test case, all boilerplate except for: case WM_KILLFOCUS: MessageBox(hWnd, _T("Killing Focus"), _T("Note"), MB_OK); in the main event loop. If you run the program and then give focus to another application, the messagebox will pop up and then the program will become unresponsive.
What is happening is: - x11drv gets a FocusOut event and calls the event handler, which ends up SendMessage-ing a WM_KILLFOCUS to the program. - The programs's code creates a modal dialog like the MessageBox above, and enters the dialog's event loop, which winds up calling GetMessage which calls MsgWaitForMultipleObjectsEx to get more X11 events. - X11DRV_MsgWaitForMultipleObjectsEx executes this: if (data->current_event) mask = 0; /* don't process nested events */ where data->current_event is true since we're still handling the FocusOut event. Since we're not processing nested events, we'll never be able to process the usual events like keys or mouse events which could exit this nested event loop.
This type of error occurs in a few places in our application, where a WM_KILLFOCUS message to an edit box triggers some input validation and displays an error on failure. This works correctly in the normal case, where the user tabs out or clicks on another control in the dialog box containing the edit control -- since everything stays in the same top-level window, there is no FocusOut event from X11 and the WM_KILLFOCUS is generated internally by wine in response to, say, a KeyEvent. I think these key or mouse events are just posted to the windows message queue, and the X11 event handler has already exited by the time the application gets around to processing the ensuing WM_KILLFOCUS. But in the case where focus is lost by clicking outside the dialog containing the edit control, the WM_KILLFOCUS is generated by the FocusOut handler which is still executing, and we lock up.
I suspect this is related to bug 11595 "Notepad++ freezes if native application changes a file it has open (dogfood)". My guess is in that case, a FocusIn event triggers something like a WM_ACTIVATE, in which notepad++ notices a file is changed and displays a messagebox asking if you want to reload. Since wine is still processing the FocusIn event, the modal message loop's call to MsgWaitForMultipleObjectsEx will never process any useful events because it's a nested event. Our application's built-in text editor has this same problem.
I don't understand the event handling code well enough to propose a solution. As a test, I allowed nested event processing and it solved the problem without introducing any obvious errors, but I'm sure that check was in there for a reason. It's probably better to keep the application code from being executed from inside the event handler, if that's possible.
Eric