GNOME Bugzilla – Bug 335546
Dogtail does not handle modality of windows and dialogs
Last modified: 2011-02-07 06:03:57 UTC
Please describe the problem: When you run programs launching modal dialogs, you can still send actions or modify the status of widgets that are not in the modal dialog. The usual behavior of a widget out of a modal dialog is disabling event handling, so dogtail should also prevent modifications of widgets that are not in the modal dialog. Steps to reproduce: 1. Run gedit 2. In a python dogtail session: focus.application('gedit') focus.button('Open') click() 3. It opens the "Open file" dialog. It's modal in gedit, and then it should prevent us to do any action in the main gedit window. But, we can write in the dogtail session: focus.button('Save') click() 4. It opens the Save dialog. Actual results: It opens the save dialog from the main window, even when there's a modal dialog that should prevent this being launched. Expected results: The Save dialog shouldn't be launched, and really the click() action should be ignored by the Save button. Does this happen every time? Yes Other information: In GTK the implementation of modality is done using gtk_grab_add() method. If we want to know if a widget can get events, usually we use GTK_IS_SENSITIVE, and it should be handled in Gail side. But modality doesn't change sensitivity state. I don't know how we can know if a widget is in a not grabbed window.
From our IRC discussion: (i) it sounds like a modal dialog is detectable as such; SPI_STATE_MODAL is correctly set on the dialog node (but not on any children) (ii) within the modal implementation of gtk, it uses gtk_grab_add and gtk_grab_remove, and then seems to rely on window manager to discard eventsl; events coming in via the a11y layer don't get discarded.
Created attachment 64022 [details] [review] Implement modality of windows tracking support This patch implements modality tracking support in dogtail. * Added a config property called "modalTrack", that is by default enabled. If you want to restore the previous behavior you have to set this property to False. * Added new predicates to know if a node is a toplevel (IsATopLevel) and to know if a node is modal. * Added a new predicate that detects if a toplevel is not grabbed (and then should prevent actions on it). * Added detection of modality status in Action do() method. If the config.modalTrack is enabled, it checks the node can receive actions depending on the modality. If it's not so, it raises the InteractionBlockedByModalError exception. A doubt is: sensitivity and modality are now handled only on Action do(). Maybe it should also be handled in all other state changer methods (text edition, selection and so). Shouldn't modality and sensitivity be taken into account for those methods?
Created attachment 64869 [details] [review] New patch for modality This new patch follows the recommendations extracted from the discussion today in IRC. Mainly it does: * Remove all introduced predicates in previous patch, except IsATopLevel, as it does not make sense to put stateset properties there. * Now there's a new "modal" property getting the SPI_STATE_MODAL from the state set. * There's a new "canReceiveEvents" that evaluates sensitivity and modality. Modality is only checked if the modalTrack config property is set up. * Previously in dogtail we blocked events using "sensitive" property. The patch changes it to use "canReceiveEvents".
Thanks - I've reviewed both attachments and attachment 64869 [details] [review] looks better: with a caveat (see below) - marking it as "commented on". The precise Steps to Reproduce in the original report don't work for me as the "Open" dialog is non-modal (this is with gedit 2.12.2 on Fedora Core 5). However, I am able to reproduce the bug using the "Save As" dialog (which is modal) - confirming this bug (as NEW) There's one remaining problem with the patch: if Action.do fails due to canReceiveEvents failing, you always get a sensitivity error. The first attachment had a different kind of exception for this case. It also doesn't then block the action from happening, since it's checking for config.ensureSensitivity, rather than config.modalTrack So I think this ought to get fixed before this is committed. Your original patch had a separate exception subclasses which I think is worth keeping. I'm wondering what the best way of doing this cleanly is. It might be worth having the sensitivity and modal exception subclasses derive from a common base class, raising this when the action is attempted, and catching it if config allows - what do you think?
Created attachment 65772 [details] [review] Update to patch for modality This patch takes the recommendations from Dave Malcolm. It defines a parent class for the two interaction prevent exceptions (and reuse some code for this). And it also separates again the management of the two exceptions.
dogtail development has been stalled and it has been unmaintained for a few years now. Maintainers don't have future development plan so i am closing bugs as WONTFIX. Please feel free to reopen the bugs in future if anyone takes the responsibility for active development.