? build
? dogtail-cvs-atkselection-and-select-method.diff
? dogtail-modality-tracking-support.patch
? debian/files
? debian/python-dogtail
? debian/python-dogtail.postinst.debhelper
? debian/python-dogtail.prerm.debhelper
? debian/python-dogtail.substvars
? dogtail/__init__.pyc
? dogtail/config.pyc
? dogtail/distro.pyc
? dogtail/errors.pyc
? dogtail/i18n.pyc
? dogtail/logging.pyc
? dogtail/path.pyc
? dogtail/predicate.pyc
? dogtail/procedural.pyc
? dogtail/rawinput.pyc
? dogtail/tc.pyc
? dogtail/trayicon.pyc
? dogtail/tree.pyc
? dogtail/utils.pyc
? dogtail/version.pyc
Index: dogtail/config.py
===================================================================
RCS file: /cvs/gnome/dogtail/dogtail/config.py,v
retrieving revision 1.6
diff -u -r1.6 config.py
--- dogtail/config.py	5 Apr 2006 00:11:36 -0000	1.6
+++ dogtail/config.py	21 Apr 2006 09:44:18 -0000
@@ -57,6 +57,10 @@
     blinkOnActions (boolean):
     Whether we should blink a rectangle around a Node when an action is
     performed on it.
+
+    modalTrack (boolean):
+    Whether dogtail will respect modal states and avoid sending events or
+    actions to not grabbed windows.
     """
     __scriptName = staticmethod(_scriptName)
     __encoding = staticmethod(_encoding)
@@ -88,6 +92,7 @@
             'ensureSensitivity' : False,
             'debugTranslation' : False,
             'blinkOnActions' : False
+            'modalTrack' : True
     }
 
     options = {}
Index: dogtail/predicate.py
===================================================================
RCS file: /cvs/gnome/dogtail/dogtail/predicate.py,v
retrieving revision 1.8
diff -u -r1.8 predicate.py
--- dogtail/predicate.py	5 Apr 2006 00:11:36 -0000	1.8
+++ dogtail/predicate.py	21 Apr 2006 09:44:19 -0000
@@ -4,6 +4,7 @@
 __author__ = 'David Malcolm <dmalcolm@redhat.com>'
 
 import unittest
+import atspi
 
 from i18n import TranslatableString
 
@@ -349,6 +350,42 @@
 
     def makeScriptVariableName(self):
         return makeCamel(self.tabName)+"Tab"
+
+class IsATopLevel(Predicate):
+    """Predicate subclass that checks that a node is a toplevel (child of an app)"""
+    def satisfiedByNode(self, node):
+        if node.parent:
+            return node.parent.roleName=='application'
+        else:
+            return False
+        
+    def describeSearchResult(self):
+        return "toplevel"
+
+class IsModal(Predicate):
+    """Predicate subclass that checks that a node has a modal state"""
+    def satisfiedByNode(self, node):
+	if node.stateSet and node.stateSet.contains(atspi.SPI_STATE_MODAL):
+            return True
+        else:
+            return False
+    def describeSearchResult(self):
+        return "modal"
+
+class NotGrabbed(Predicate):
+    """Predicate subclass for toplevels that checks if the mode is not grabbed (it's not the
+    only child, it's not modal, and there's other toplevel that is modal in this
+    application)."""
+    def satisfiedByNode(self, node):
+        if node.stateSet and node.stateSet.contains(atspi.SPI_STATE_MODAL):
+            return False
+        if node.parent and node.parent.roleName=='application':
+            for child in node.parent.children:
+                if child.stateSet and child.stateSet.contains(atspi.SPI_STATE_MODAL):
+                    return True
+            return False
+    def describeSearchResult(self):
+        return "modal"
 
 class PredicateTests(unittest.TestCase):
     def testCapitalization(self):
Index: dogtail/tree.py
===================================================================
RCS file: /cvs/gnome/dogtail/dogtail/tree.py,v
retrieving revision 1.27
diff -u -r1.27 tree.py
--- dogtail/tree.py	17 Apr 2006 06:18:54 -0000	1.27
+++ dogtail/tree.py	21 Apr 2006 09:44:21 -0000
@@ -111,6 +111,17 @@
     def __str__(self):
         return self.message % (self.action.name, self.action.node.getLogString())
 
+class InteractionBlockedByModalError(Exception):
+    """
+    The widget is not sensitive.
+    """
+    message = "Cannot %s %s. Modal prevents interaction."
+    def __init__(self, action):
+        self.action = action
+    
+    def __str__(self):
+        return self.message % (self.action.name, self.action.node.getLogString())
+
 class ActionNotSupported(Exception):
     """
     The widget does not support the requested action.
@@ -172,6 +183,10 @@
             else:
                 nSE = NotSensitiveError(self)
                 print "Warning: " + str(nSE)
+	if config.modalTrack:
+            toplevel = self.node.findAncestor(predicate.IsATopLevel())
+            if toplevel.satisfies(predicate.NotGrabbed()):
+		raise InteractionBlockedByModal, self
         if config.blinkOnActions: self.node.blink()
         result = self.__action.doAction (self.__index)
         doDelay()
