If you make a modal QDialog, call dialog.show(), then you want to do other stuff for a while. "Other stuff" includes calling processEvents(), in my case so that painting will occur. Calling processEvents() triggers the QEvent::User event that was posted for the modal session, and starts the modal behavior instead of waiting for QDialog::exec().
Lines 744-754 in qcocoaeventdispatcher.mm define a new event() override that gets run by my call to processEvents(). It calls processEvents() to start the modal behavior.
My use case seems to be allowed by this bit from the QDialog docs in the section on Modal Dialogs:
"An alternative is to call setModal(true) or setWindowModality(), then show(). Unlike exec(), show() returns control to the caller immediately. Calling setModal(true) is especially useful for progress dialogs, where the user must have the ability to interact with the dialog, e.g. to cancel a long running operation. If you use show() and setModal(true) together to perform a long operation, you must call QApplication::processEvents() periodically during processing to enable the user to interact with the dialog. (See QProgressDialog.)"
I did not check to see if this change breaks QProgressDialog.
As a further note, isn't it dangerous to use QEvent::User for this purpose? Won't that potentially break applications that create user events with that ID?
I have attached a simple application that shows the problem.