[orca] Fix for the following bugs:



commit b5807772606e3307def48d3edab332f8af6d411d
Author: Joanmarie Diggs <joanmarie diggs gmail com>
Date:   Sun Jan 2 20:45:26 2011 -0500

    Fix for the following bugs:
    
    * bug #639668 - [Refactor] Eliminate the presentation manager
      and focus tracking presenter; create an event manager and
      script manager
    
    * bug #639669 - [Refactor] Remove script mapping from settings.py
      and clean up that code
    
    * bug #639670 - [Refactor] Move default.py into the scripts module
    
    * bug #639671 - [Refactor] Remove event recount and COMM_FAILURE
      handling

 docs/doc-set/internals.html                        |    2 +-
 docs/doc-set/script_guide.sgml                     |    2 +-
 po/POTFILES.in                                     |    4 +-
 src/orca/Makefile.am                               |    5 +-
 src/orca/app_gui_prefs.py                          |   14 +-
 src/orca/event_manager.py                          |  519 +++++++++
 src/orca/focus_tracking_presenter.py               | 1187 --------------------
 src/orca/mouse_review.py                           |    5 +-
 src/orca/orca.py                                   |  166 +---
 src/orca/orca_gui_prefs.py                         |   17 +-
 src/orca/presentation_manager.py                   |   86 --
 src/orca/script.py                                 |   16 +-
 src/orca/script_manager.py                         |  249 ++++
 src/orca/scripts/Makefile.am                       |    1 +
 src/orca/scripts/apps/Banshee/script.py            |    2 +-
 src/orca/scripts/apps/Eclipse/script.py            |    2 +-
 src/orca/scripts/apps/Instantbird/script.py        |    2 +-
 src/orca/scripts/apps/Thunderbird/script.py        |    5 +-
 src/orca/scripts/apps/__init__.py                  |   36 +
 src/orca/scripts/apps/acroread/script.py           |   21 +-
 src/orca/scripts/apps/ddu/script.py                |    2 +-
 src/orca/scripts/apps/ekiga/script.py              |    2 +-
 src/orca/scripts/apps/empathy/script.py            |    2 +-
 src/orca/scripts/apps/evolution/script.py          |    4 +-
 src/orca/scripts/apps/gajim/script.py              |    2 +-
 src/orca/scripts/apps/gcalctool/script.py          |    2 +-
 src/orca/scripts/apps/gdmlogin/script.py           |    2 +-
 src/orca/scripts/apps/gedit/script.py              |    5 +-
 src/orca/scripts/apps/gnome-keyring-ask/script.py  |    2 +-
 src/orca/scripts/apps/gnome-mud/script.py          |    2 +-
 src/orca/scripts/apps/gnome-panel/script.py        |    2 +-
 .../apps/gnome-screensaver-dialog/script.py        |    2 +-
 src/orca/scripts/apps/gnome-search-tool/script.py  |    2 +-
 .../scripts/apps/gnome-system-monitor/script.py    |    2 +-
 src/orca/scripts/apps/gnome-terminal/script.py     |    2 +-
 .../scripts/apps/gnome-window-properties/script.py |    2 +-
 src/orca/scripts/apps/gnome_segv2/script.py        |    2 +-
 .../scripts/apps/gtk-window-decorator/script.py    |    2 +-
 src/orca/scripts/apps/liferea/script.py            |    2 +-
 src/orca/scripts/apps/metacity/script.py           |    2 +-
 src/orca/scripts/apps/nautilus/script.py           |    2 +-
 .../scripts/apps/notification-daemon/script.py     |    2 +-
 src/orca/scripts/apps/notify-osd/script.py         |    2 +-
 src/orca/scripts/apps/packagemanager/script.py     |    2 +-
 src/orca/scripts/apps/pidgin/script.py             |    2 +-
 src/orca/scripts/apps/planner/script.py            |    2 +-
 src/orca/scripts/apps/rhythmbox/script.py          |    2 +-
 src/orca/scripts/apps/soffice/script.py            |   13 +-
 src/orca/scripts/apps/yelp/script.py               |    6 +-
 src/orca/{ => scripts}/default.py                  |  104 +-
 src/orca/scripts/self_voicing.py                   |    4 +-
 src/orca/scripts/toolkits/CALLY/script.py          |    2 +-
 src/orca/scripts/toolkits/GAIL.py                  |    4 +-
 src/orca/scripts/toolkits/Gecko/script.py          |   28 +-
 .../scripts/toolkits/J2SE-access-bridge/script.py  |    8 +-
 src/orca/scripts/toolkits/VCL.py                   |    2 +-
 src/orca/scripts/toolkits/WebKitGtk/script.py      |    2 +-
 src/orca/scripts/toolkits/__init__.py              |    6 +
 src/orca/settings.py                               |  195 ----
 src/orca/settings_manager.py                       |   57 +
 src/orca/structural_navigation.py                  |    2 +-
 61 files changed, 1056 insertions(+), 1777 deletions(-)
---
diff --git a/docs/doc-set/internals.html b/docs/doc-set/internals.html
index 08bc78b..43c10ba 100644
--- a/docs/doc-set/internals.html
+++ b/docs/doc-set/internals.html
@@ -599,7 +599,7 @@ python -V
       upon the <code class="literal">orca/scripts/apps/pidgin/script.py</code> for
       the Pidgin application is as follows:</p><pre class="programlisting">
 ...
-import orca.default as default
+import orca.scripts.default as default
 ...
 class Script(default.Script):
 ...
diff --git a/docs/doc-set/script_guide.sgml b/docs/doc-set/script_guide.sgml
index 3cc5c26..82495c4 100644
--- a/docs/doc-set/script_guide.sgml
+++ b/docs/doc-set/script_guide.sgml
@@ -446,7 +446,7 @@
 
 <programlisting>
 ...
-import orca.default as default
+import orca.scripts.default as default
 ...
 class Script(default.Script):
 ...
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 4a5699a..a96dd12 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -8,11 +8,10 @@ src/orca/braille_generator.py
 src/orca/braille.py
 src/orca/chat.py
 src/orca/chnames.py
-src/orca/default.py
 src/orca/espeechfactory.py
+src/orca/event_manager.py
 src/orca/find.py
 src/orca/flat_review.py
-src/orca/focus_tracking_presenter.py
 src/orca/generator.py
 src/orca/gnomespeechfactory.py
 src/orca/gsmag.py
@@ -61,6 +60,7 @@ src/orca/scripts/apps/soffice/speech_generator.py
 src/orca/scripts/apps/soffice/structural_navigation.py
 src/orca/scripts/apps/Thunderbird/script.py
 src/orca/scripts/apps/Thunderbird/speech_generator.py
+src/orca/scripts/default.py
 src/orca/scripts/toolkits/Gecko/bookmarks.py
 src/orca/scripts/toolkits/Gecko/braille_generator.py
 src/orca/scripts/toolkits/Gecko/script.py
diff --git a/src/orca/Makefile.am b/src/orca/Makefile.am
index ff6efee..891ecac 100644
--- a/src/orca/Makefile.am
+++ b/src/orca/Makefile.am
@@ -22,13 +22,12 @@ orca_python_PYTHON = \
 	dbusserver.py \
 	debug.py \
 	dectalk.py \
-	default.py \
 	desktop_keyboardmap.py \
 	espeechfactory.py \
+	event_manager.py \
 	eventsynthesizer.py \
 	find.py \
 	flat_review.py \
-	focus_tracking_presenter.py \
 	formatting.py \
 	generator.py \
 	gnomespeechfactory.py \
@@ -58,11 +57,11 @@ orca_python_PYTHON = \
 	outloud.py \
 	phonnames.py \
 	orca_platform.py \
-	presentation_manager.py \
 	pronunciation_dict.py \
 	punctuation_settings.py \
 	rolenames.py \
 	script.py \
+	script_manager.py \
 	script_utilities.py \
 	settings.py \
 	settings_manager.py \
diff --git a/src/orca/app_gui_prefs.py b/src/orca/app_gui_prefs.py
index 2f2ba70..9fbe66b 100644
--- a/src/orca/app_gui_prefs.py
+++ b/src/orca/app_gui_prefs.py
@@ -33,20 +33,21 @@ import sys
 import app_prefs
 import braille
 import debug
-import default
-import focus_tracking_presenter
 import input_event
 import keybindings
+import orca
 import orca_gtkbuilder
 import orca_gui_prefs
 import orca_prefs
 import orca_state
 import orca_platform
-import settings
 import speech
 
 from orca_i18n import _  # for gettext support
 
+_scriptManager = getattr(orca, '_scriptManager')
+_settingsManager = getattr(orca, '_settingsManager')
+
 applicationName = None
 appScript = None
 
@@ -140,12 +141,11 @@ class OrcaSetupGUI(orca_gui_prefs.OrcaSetupGUI):
     def writeUserPreferences(self):
         """Write out the user's application-specific Orca preferences.
         """
-        moduleName = settings.getScriptModuleName(self.app)
+        moduleName = _scriptManager.getModuleName(self.app)
         app_prefs.writePreferences(self.prefsDict, moduleName,
                                    self.appScript, self.keyBindingsModel,
                                    self.pronunciationModel)
-        ftp = focus_tracking_presenter.FocusTrackingPresenter()
-        ftp.loadAppSettings(self.appScript)
+        _settingsManager.loadAppSettings(self.appScript)
 
     def _getAppNameForAttribute(self, attributeName):
         """Converts the given Atk attribute name into the application's
@@ -209,7 +209,7 @@ class OrcaSetupGUI(orca_gui_prefs.OrcaSetupGUI):
 
         # Get the key bindings for the default script.
         #
-        defScript = default.Script(None)
+        defScript = _scriptManager.getDefaultScript()
         self.defKeyBindings = defScript.getKeyBindings()
 
         iterApp = self._createNode(applicationName)
diff --git a/src/orca/event_manager.py b/src/orca/event_manager.py
new file mode 100644
index 0000000..be7dc60
--- /dev/null
+++ b/src/orca/event_manager.py
@@ -0,0 +1,519 @@
+# Orca
+#
+# Copyright 2011. Orca Team.
+# Author: Joanmarie Diggs <joanmarie diggs gmail com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
+# Boston MA  02110-1301 USA.
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2011. Orca Team."
+__license__   = "LGPL"
+
+import gobject
+import pyatspi
+import Queue
+import threading
+import time
+
+import braille
+import debug
+import input_event
+import orca
+import orca_state
+import settings
+import speech
+
+from orca_i18n import _
+
+_scriptManager = None
+
+class EventManager:
+
+    def __init__(self):
+
+        self._listenerCounts = {}
+        self.registry = pyatspi.Registry
+        self._enqueueCount = 0
+        self._dequeueCount = 0
+        self._eventQueue     = Queue.Queue(0)
+        self._gidleId        = 0
+        self._gidleLock      = threading.Lock()
+        self.noFocusTimestamp = 0.0
+
+    def activate(self):
+        """Called when this presentation manager is activated."""
+
+        global _scriptManager
+        _scriptManager = getattr(orca, '_scriptManager')
+
+        # Tell BrlTTY which commands we care about.
+        #
+        braille.setupKeyRanges(orca_state.activeScript.brailleBindings.keys())
+
+        self._registerListener("window:activate")
+        self._registerListener("window:deactivate")
+        self._registerListener("object:children-changed:remove")
+
+        win = orca_state.activeScript.utilities.activeWindow()
+        if win:
+            # Generate a fake window activation event so the application
+            # can tell the user about itself.
+            #
+            class _FakeEvent:
+                def __init__(self, source, eventType,
+                             detail1, detail2, any_data):
+                    self.source = source
+                    self.type = eventType
+                    self.detail1 = detail1
+                    self.detail2 = detail2
+                    self.any_data = any_data
+                    self.host_application = None
+
+            class _FakeData:
+                def __init__(self):
+                    pass
+                def value(self):
+                    return None
+
+            fe = _FakeEvent(win, "window:activate", 0, 0, _FakeData())
+            self._enqueue(fe)
+
+    def deactivate(self):
+        """Called when this event manager is deactivated."""
+
+        for eventType in self._listenerCounts.keys():
+            self.registry.deregisterEventListener(self._enqueue, eventType)
+        self._listenerCounts = {}
+
+    def _ignore(self, event):
+        """Returns True if this event should be ignored."""
+
+        if not event or not event.source:
+            return True
+
+        ignoredList = ['object:state-changed:defunct',
+                       'object:property-change:accessible-parent']
+        ignoredList.extend(settings.ignoredEventsList)
+        if filter(event.type.startswith, ignoredList):
+            return True
+
+        # This should ultimately be changed as there are valid reasons
+        # to handle these events at the application level.
+        if event.type.startswith('object:children-changed:remove') \
+           and event.source != self.registry.getDesktop(0):
+            return True
+
+        return False
+
+    def _addToQueue(self, event, asyncMode):
+        debugging = settings.debugEventQueue
+        if debugging:
+            debug.println(debug.LEVEL_ALL, "           acquiring lock...")
+        self._gidleLock.acquire()
+
+        if debugging:
+            debug.println(debug.LEVEL_ALL, "           ...acquired")
+            debug.println(debug.LEVEL_ALL, "           calling queue.put...")
+            debug.println(debug.LEVEL_ALL, "           (full=%s)" \
+                          % self._eventQueue.full())
+
+        self._eventQueue.put(event)
+        if debugging:
+            debug.println(debug.LEVEL_ALL, "           ...put complete")
+
+        if asyncMode and not self._gidleId:
+            if settings.gilSleepTime:
+                time.sleep(settings.gilSleepTime)
+            self._gidleId = gobject.idle_add(self._dequeue)
+
+        if debugging:
+            debug.println(debug.LEVEL_ALL, "           releasing lock...")
+        self._gidleLock.release()
+        if settings.debugEventQueue:
+            debug.println(debug.LEVEL_ALL, "           ...released")
+
+    def _queuePrintln(self, e, isEnqueue=True):
+        """Convenience method to output queue-related debugging info."""
+
+        if isinstance(e, input_event.KeyboardEvent):
+            data = "'%s' (%d)" % (e.event_string, e.hw_code)
+        elif isinstance(e, input_event.BrailleEvent):
+            data = "'%s'" % repr(e.event)
+        elif not debug.eventDebugFilter or debug.eventDebugFilter.match(e.type):
+            data = ""
+        else:
+            return
+
+        eType = str(e.type).upper()
+        if isEnqueue:
+            string = "----------> QUEUEING %s %s" % (eType, data)
+        else:
+            string = "DEQUEUED %s %s <----------" % (eType, data)
+
+        debug.println(debug.LEVEL_ALL, string)
+
+    def _enqueue(self, e):
+        """Handles the enqueueing of all events destined for scripts.
+
+        Arguments:
+        - e: an at-spi event.
+        """
+
+        if settings.debugEventQueue:
+            if self._enqueueCount:
+                msg = "_enqueue entered before exiting (count = %d)" \
+                    % self._enqueueCount
+                debug.println(debug.LEVEL_ALL, msg)
+            self._enqueueCount += 1
+
+        inputEvents = (input_event.KeyboardEvent, input_event.BrailleEvent)
+        isObjectEvent = not isinstance(e, inputEvents)
+        if isObjectEvent and self._ignore(e):
+            if settings.debugEventQueue:
+                self._enqueueCount -= 1
+            return
+
+        self._queuePrintln(e)
+
+        asyncMode = settings.asyncMode
+        if isObjectEvent:
+            app = e.source.getApplication()
+            try:
+                toolkitName = app.toolkitName
+            except:
+                toolkitName = None
+            if toolkitName in settings.synchronousToolkits:
+                asyncMode = False
+            script = _scriptManager.getScript(app, e.source)
+            script.eventCache[e.type] = (e, time.time())
+
+        self._addToQueue(e, asyncMode)
+        if not asyncMode:
+            self._dequeue()
+
+        if settings.debugEventQueue:
+            self._enqueueCount -= 1
+
+    def _dequeue(self):
+        """Handles all events destined for scripts. Called by the GTK
+        idle thread."""
+
+        rerun = True
+
+        if settings.debugEventQueue:
+            debug.println(debug.LEVEL_ALL,
+                          "event_manager._dequeue %d" % self._dequeueCount)
+            self._dequeueCount += 1
+
+        try:
+            event = self._eventQueue.get_nowait()
+            self._queuePrintln(event, isEnqueue=False)
+            inputEvents = (input_event.KeyboardEvent, input_event.BrailleEvent)
+            if isinstance(event, inputEvents):
+                self._processInputEvent(event)
+            else:
+                debugging = not debug.eventDebugFilter \
+                            or debug.eventDebugFilter.match(event.type)
+                if debugging:
+                    debug.println(debug.eventDebugLevel,
+                                  "\nvvvvv PROCESS OBJECT EVENT %s vvvvv" \
+                                  % event.type)
+                self._processObjectEvent(event)
+                if debugging:
+                    debug.println(debug.eventDebugLevel,
+                                  "^^^^^ PROCESS OBJECT EVENT %s ^^^^^\n" \
+                                  % event.type)
+
+            # [[[TODO: HACK - it would seem logical to only do this if we
+            # discover the queue is empty, but this inroduces a hang for
+            # some reason if done inside an acquire/release block for a
+            # lock.  So...we do it here.]]]
+            #
+            noFocus = \
+                not orca_state.activeScript \
+                or (not orca_state.locusOfFocus \
+                    and self.noFocusTimestamp != orca_state.noFocusTimestamp)
+
+            self._gidleLock.acquire()
+            if self._eventQueue.empty():
+                if noFocus:
+                    if settings.gilSleepTime:
+                        time.sleep(settings.gilSleepTime)
+                    # Translators: this is intended to be a short phrase to
+                    # speak and braille to tell the user that no component
+                    # has keyboard focus.
+                    #
+                    message = _("No focus")
+                    if settings.brailleVerbosityLevel == \
+                            settings.VERBOSITY_LEVEL_VERBOSE:
+                        braille.displayMessage(message)
+                    if settings.speechVerbosityLevel == \
+                            settings.VERBOSITY_LEVEL_VERBOSE:
+                        speech.speak(message)
+                    self.noFocusTimestamp = orca_state.noFocusTimestamp
+                self._gidleId = 0
+                rerun = False # destroy and don't call again
+            self._gidleLock.release()
+        except Queue.Empty:
+            debug.println(debug.LEVEL_SEVERE,
+                          "event_manager._dequeue: the event queue is empty!")
+            rerun = False # destroy and don't call again
+        except:
+            debug.printException(debug.LEVEL_SEVERE)
+
+        if settings.debugEventQueue:
+            self._dequeueCount -= 1
+            debug.println(debug.LEVEL_ALL,
+                          "Leaving _dequeue. Count: %d" % self._dequeueCount)
+
+        return rerun
+
+    def _registerListener(self, eventType):
+        """Tells this module to listen for the given event type.
+
+        Arguments:
+        - eventType: the event type.
+        """
+
+        if eventType in self._listenerCounts:
+            self._listenerCounts[eventType] += 1
+        else:
+            self.registry.registerEventListener(self._enqueue, eventType)
+            self._listenerCounts[eventType] = 1
+
+    def _deregisterListener(self, eventType):
+        """Tells this module to stop listening for the given event type.
+
+        Arguments:
+        - eventType: the event type.
+        """
+
+        self._listenerCounts[eventType] -= 1
+        if self._listenerCounts[eventType] == 0:
+            self.registry.deregisterEventListener(self._enqueue, eventType)
+            del self._listenerCounts[eventType]
+
+    def registerListeners(self, script):
+        """Tells the FocusTrackingPresenter to listen for all
+        the event types of interest to the script.
+
+        Arguments:
+        - script: the script.
+        """
+
+        for eventType in script.listeners.keys():
+            self._registerListener(eventType)
+
+    def deregisterListeners(self, script):
+        """Tells the FocusTrackingPresenter to stop listening for all the
+        event types of interest to the script.
+
+        Arguments:
+        - script: the script.
+        """
+
+        for eventType in script.listeners.keys():
+            self._deregisterListener(eventType)
+
+    def _processInputEvent(self, event):
+        """Processes the given input event based on the keybinding from the
+        currently-active script.
+
+        Arguments:
+        - event: an instance of BrailleEvent or a KeyboardEvent
+        """
+
+        if not orca_state.activeScript:
+            return
+
+        if isinstance(event, input_event.KeyboardEvent):
+            function = orca_state.activeScript.processKeyboardEvent
+            data = "'%s' (%d)" % (event.event_string, event.hw_code)
+        elif isinstance(event, input_event.BrailleEvent):
+            function = orca_state.activeScript.processBrailleEvent
+            data = "'%s'" % repr(event.event)
+        else:
+            return
+
+        eType = str(event.type).upper()
+        debug.println(debug.eventDebugLevel,
+                      "\nvvvvv PROCESS %s %s vvvvv" % (eType, data))
+        try:
+            function(event)
+        except:
+            debug.printException(debug.LEVEL_WARNING)
+            debug.printStack(debug.LEVEL_WARNING)
+        debug.println(debug.eventDebugLevel,
+                      "^^^^^ PROCESS %s %s ^^^^^\n" % (eType, data))
+
+    @staticmethod
+    def _getScriptForEvent(event):
+        """Returns the script associated with event."""
+
+        if event.type.startswith("mouse:"):
+            return orca_state.activeScript
+
+        script = None
+        try:
+            app = event.host_application or event.source.getApplication()
+        except:
+            debug.printException(debug.LEVEL_WARNING)
+        else:
+            script = _scriptManager.getScript(app, event.source)
+
+        return script
+
+    def _isActivatableEvent(self, event, script=None):
+        """Determines if the event is one which should cause us to
+        change which script is currently active.
+
+        Returns a (boolean, string) tuple indicating whether or not
+        this is an activatable event, and our reason (for the purpose
+        of debugging).
+        """
+
+        if not script:
+            script = self._getScriptForEvent(event)
+
+        if not script:
+            return False, "There is no script for this event."
+
+        if script == orca_state.activeScript:
+            return False, "The script for this event is already active."
+
+        if not script.isActivatableEvent(event):
+            return False, "The script says not to activate for this event."
+
+        eType = event.type
+        if eType.startswith('window:activate'):
+            return True, "window:activate event"
+
+        if eType.startswith('focus') \
+           or (eType.startswith('object:state-changed:focused')
+               and event.detail1):
+            return True, "Event source claimed focus."
+
+        # This condition appears with gnome-screensave-dialog.
+        # See bug 530368.
+        if eType.startswith('object:state-changed:showing') \
+           and event.source.getRole() == pyatspi.ROLE_PANEL \
+           and event.source.getState().contains(pyatspi.STATE_MODAL):
+            return True, "Modal panel is showing."
+
+        return False, "No reason found to activate a different script."
+
+    def _processObjectEvent(self, event):
+        """Handles all object events destined for scripts.
+
+        Arguments:
+        - e: an at-spi event.
+        """
+
+        debug.printObjectEvent(debug.LEVEL_FINEST, event)
+        eType = event.type
+
+        if eType.startswith("object:children-changed:remove"):
+            if event.source == self.registry.getDesktop(0):
+                _scriptManager.reclaimScripts()
+                if settings.debugMemoryUsage:
+                    orca.cleanupGarbage()
+                return
+
+        # Clean up any flat review context so that Orca does not get
+        # confused (see bgo#609633)
+        #
+        if eType.startswith("window:deactivate") \
+           and orca_state.activeScript \
+           and orca_state.activeScript.flatReviewContext \
+           and orca_state.activeScript.app == event.host_application:
+            orca_state.activeScript.drawOutline(-1, 0, 0, 0)
+            orca_state.activeScript.flatReviewContext = None
+
+        try:
+            state = event.source.getState()
+        except LookupError:
+            debug.printException(debug.LEVEL_WARNING)
+            debug.println(debug.LEVEL_WARNING,
+                          "LookupError while processing event: %s" % eType)
+            if eType.startswith("window:deactivate"):
+                orca.setLocusOfFocus(event, None)
+                orca_state.activeWindow = None
+            return
+        except:
+            debug.printException(debug.LEVEL_WARNING)
+            return
+
+        if state and state.contains(pyatspi.STATE_DEFUNCT):
+            debug.println(debug.LEVEL_FINEST, "IGNORING DEFUNCT OBJECT")
+            if eType.startswith("window:deactivate"):
+                orca.setLocusOfFocus(event, None)
+                orca_state.activeWindow = None
+            return
+
+        if state and state.contains(pyatspi.STATE_ICONIFIED):
+            debug.println(debug.LEVEL_FINEST, "IGNORING ICONIFIED OBJECT")
+            return
+
+        if not debug.eventDebugFilter or debug.eventDebugFilter.match(eType) \
+           and not eType.startswith("mouse:"):
+            debug.printDetails(debug.LEVEL_FINEST, "    ", event.source)
+
+        script = self._getScriptForEvent(event)
+        setNewActiveScript, reason = self._isActivatableEvent(event, script)
+        if setNewActiveScript:
+            app = event.host_application or event.source.getApplication()
+            _scriptManager.setActiveScript(script, reason)
+
+        script.processObjectEvent(event)
+
+    def processKeyboardEvent(self, keyboardEvent):
+        """Processes the given keyboard event based on the keybinding from the
+        currently active script. This method is called synchronously from the
+        at-spi registry and should be performant.  In addition, it must return
+        True if it has consumed the event (and False if not).
+
+        Arguments:
+        - keyboardEvent: an instance of input_event.KeyboardEvent
+
+        Returns True if the event should be consumed.
+        """
+
+        consume = False
+        if orca_state.activeScript \
+           and orca_state.activeScript.consumesKeyboardEvent(keyboardEvent):
+            consume = not orca_state.bypassNextCommand
+            if consume:
+                self._enqueue(keyboardEvent)
+
+        return consume
+
+    def processBrailleEvent(self, brailleEvent):
+        """Called whenever a cursor key is pressed on the Braille display.
+
+        Arguments:
+        - brailleEvent: an instance of input_event.BrailleEvent
+
+        Returns True if the command was consumed; otherwise False
+        """
+
+        if orca_state.activeScript \
+           and orca_state.activeScript.consumesBrailleEvent(brailleEvent):
+            self._enqueue(brailleEvent)
+            return True
+        else:
+            return False
diff --git a/src/orca/mouse_review.py b/src/orca/mouse_review.py
index 8407a2b..62e52d7 100644
--- a/src/orca/mouse_review.py
+++ b/src/orca/mouse_review.py
@@ -44,6 +44,8 @@ import speech
 import braille
 import settings
 
+_scriptManager = getattr(orca, '_scriptManager')
+
 class BoundingBox:
     """A bounding box, currently it is used to test if a given point is
     inside the bounds of the box.
@@ -293,13 +295,14 @@ class MouseReviewer:
 
         Returns _ItemContext of the component under the mouse.
         """
+
         # Inspect accessible under mouse
         desktop = pyatspi.Registry.getDesktop(0)
         top_window = [None, -1]
         for app in desktop:
             if not app:
                 continue
-            script = orca.getScriptForApp(app)
+            script = _scriptManager.getScript(app)
             if not script:
                 continue
             for frame in app:
diff --git a/src/orca/orca.py b/src/orca/orca.py
index 387574a..1560cb0 100644
--- a/src/orca/orca.py
+++ b/src/orca/orca.py
@@ -512,6 +512,12 @@ if _settingsManager is None:
     print "Could not load the settings manager. Exiting."
     sys.exit(1)
 
+from event_manager import EventManager
+_eventManager = EventManager()
+
+from script_manager import ScriptManager
+_scriptManager = ScriptManager()
+
 try:
     # If we don't have an active desktop, we will get a RuntimeError.
     import mouse_review
@@ -542,8 +548,8 @@ from input_event import KeyboardEvent
 from input_event import MouseButtonEvent
 from input_event import keyEventToString
 
+import gc
 if settings.debugMemoryUsage:
-    import gc
     gc.set_debug(gc.DEBUG_UNCOLLECTABLE
                  | gc.DEBUG_COLLECTABLE
                  | gc.DEBUG_INSTANCES
@@ -571,88 +577,19 @@ _restoreOrcaKeys = False
 
 ########################################################################
 #                                                                      #
-# METHODS FOR HANDLING PRESENTATION MANAGERS                           #
-#                                                                      #
-# A presentation manager is what reacts to AT-SPI object events as     #
-# well as user input events (keyboard and Braille) to present info     #
-# to the user.                                                         #
-#                                                                      #
-########################################################################
-
-# The known presentation managers (set up in start())
-#
-_PRESENTATION_MANAGERS = None
-
-# The current presentation manager, which is an index into the
-# _PRESENTATION_MANAGERS list.
-#
-_currentPresentationManager = -1
-
-def _switchToPresentationManager(index):
-    """Switches to the given presentation manager.
-
-    Arguments:
-    - index: an index into _PRESENTATION_MANAGERS
-    """
-
-    global _currentPresentationManager
-
-    if _currentPresentationManager >= 0:
-        _PRESENTATION_MANAGERS[_currentPresentationManager].deactivate()
-
-    _currentPresentationManager = index
-
-    # Wrap the presenter index around.
-    #
-    if _currentPresentationManager >= len(_PRESENTATION_MANAGERS):
-        _currentPresentationManager = 0
-    elif _currentPresentationManager < 0:
-        _currentPresentationManager = len(_PRESENTATION_MANAGERS) - 1
-
-    _PRESENTATION_MANAGERS[_currentPresentationManager].activate()
-
-def _switchToNextPresentationManager(script=None, inputEvent=None):
-    """Switches to the next presentation manager.
-
-    Arguments:
-    - inputEvent: the InputEvent instance that caused this to be called.
-
-    Returns True indicating the event should be consumed.
-    """
-
-    _switchToPresentationManager(_currentPresentationManager + 1)
-    return True
-
-def getScriptForApp(app):
-    """Get the script for the given application object from the current
-    presentation manager.
-
-    Arguments:
-    - app: An application accessible.
-
-    Returns a Script instance.
-    """
-
-    script = None
-    if _currentPresentationManager >= 0:
-        script = \
-            _PRESENTATION_MANAGERS[_currentPresentationManager].getScript(app)
-    return script
-
-########################################################################
-#                                                                      #
 # METHODS TO HANDLE APPLICATION LIST AND FOCUSED OBJECTS               #
 #                                                                      #
 ########################################################################
 
-def setLocusOfFocus(event, obj, notifyPresentationManager=True, force=False):
+def setLocusOfFocus(event, obj, notifyScript=True, force=False):
     """Sets the locus of focus (i.e., the object with visual focus) and
-    notifies the current presentation manager of the change.
+    notifies the script of the change should the script wish to present
+    the change to the user.
 
     Arguments:
     - event: if not None, the Event that caused this to happen
     - obj: the Accessible with the new locus of focus.
-    - notifyPresentationManager: if True, propagate this event
+    - notifyScript: if True, propagate this event
     - force: if True, don't worry if this is the same object as the
       current locusOfFocus
     """
@@ -710,29 +647,9 @@ def setLocusOfFocus(event, obj, notifyPresentationManager=True, force=False):
             debug.println(debug.LEVEL_FINE,
                           "                event=None")
 
-    if notifyPresentationManager and _currentPresentationManager >= 0:
-        _PRESENTATION_MANAGERS[_currentPresentationManager].\
-            locusOfFocusChanged(event,
-                                oldLocusOfFocus,
-                                orca_state.locusOfFocus)
-
-def visualAppearanceChanged(event, obj):
-    """Called (typically by scripts) when the visual appearance of an object
-    changes and notifies the current presentation manager of the change.  This
-    method should not be called for objects whose visual appearance changes
-    solely because of focus -- setLocusOfFocus is used for that.  Instead, it
-    is intended mostly for objects whose notional 'value' has changed, such as
-    a checkbox changing state, a progress bar advancing, a slider moving, text
-    inserted, caret moved, etc.
-
-    Arguments:
-    - event: if not None, the Event that caused this to happen
-    - obj: the Accessible whose visual appearance changed.
-    """
-
-    if _currentPresentationManager >= 0:
-        _PRESENTATION_MANAGERS[_currentPresentationManager].\
-            visualAppearanceChanged(event, obj)
+    if notifyScript and orca_state.activeScript:
+        orca_state.activeScript.locusOfFocusChanged(
+            event, oldLocusOfFocus, orca_state.locusOfFocus)
 
 def _onChildrenChanged(e):
     """Tracks children-changed events on the desktop to determine when
@@ -856,11 +773,6 @@ def exitListShortcutsMode(self, inputEvent=None):
 #                                                                      #
 # METHODS FOR PRE-PROCESSING AND MASSAGING KEYBOARD EVENTS.            #
 #                                                                      #
-# All keyboard events are funnelled through here first.  Orca itself   #
-# might have global keybindings (e.g., to switch between presenters),  #
-# but it will typically pass the event onto the currently active       #
-# active presentation manager.                                         #
-#                                                                      #
 ########################################################################
 
 # Keybindings that Orca itself cares about.
@@ -1231,9 +1143,9 @@ def _processKeyboardEvent(event):
     """The primary key event handler for Orca.  Keeps track of various
     attributes, such as the lastInputEvent.  Also calls keyEcho as well
     as any local keybindings before passing the event on to the active
-    presentation manager.  This method is called synchronously from the
-    AT-SPI registry and should be performant.  In addition, it
-    must return True if it has consumed the event (and False if not).
+    script.  This method is called synchronously from the AT-SPI registry
+    and should be performant.  In addition, it must return True if it has
+    consumed the event (and False if not).
 
     Arguments:
     - event: an AT-SPI DeviceEvent
@@ -1369,9 +1281,8 @@ def _processKeyboardEvent(event):
             if (not consumed):
                 consumed = _keyBindings.consumeKeyboardEvent( \
                   None, keyboardEvent)
-            if (not consumed) and (_currentPresentationManager >= 0):
-                consumed = _PRESENTATION_MANAGERS[_currentPresentationManager].\
-                           processKeyboardEvent(keyboardEvent)
+            if (not consumed):
+                consumed = _eventManager.processKeyboardEvent(keyboardEvent)
             if (not consumed) and settings.learnModeEnabled:
                 if keyboardEvent.type == pyatspi.KEY_PRESSED_EVENT:
                     clickCount = orca_state.activeScript.getClickCount()
@@ -1437,8 +1348,7 @@ def _processBrailleEvent(event):
     orca_state.lastInputEvent = event
 
     try:
-        consumed = _PRESENTATION_MANAGERS[_currentPresentationManager].\
-                   processBrailleEvent(event)
+        consumed = _eventManager.processBrailleEvent(event)
     except:
         debug.printException(debug.LEVEL_SEVERE)
 
@@ -1559,8 +1469,8 @@ def loadUserSettings(script=None, inputEvent=None, isProfileLoad=False):
     braille.shutdown()
     mag.shutdown()
 
-    if _currentPresentationManager >= 0:
-        _PRESENTATION_MANAGERS[_currentPresentationManager].deactivate()
+    _eventManager.deactivate()
+    _scriptManager.deactivate()
 
     reloaded = False
     if _userSettings:
@@ -1650,8 +1560,8 @@ def loadUserSettings(script=None, inputEvent=None, isProfileLoad=False):
     _storeXmodmap(_orcaModifiers)
     _createOrcaXmodmap()
 
-    if _currentPresentationManager >= 0:
-        _PRESENTATION_MANAGERS[_currentPresentationManager].activate()
+    _scriptManager.activate()
+    _eventManager.activate()
 
     showMainWindowGUI()
 
@@ -1916,15 +1826,13 @@ def getListOfShortcuts(typeOfShortcuts):
     Returns a list of shortcuts; depending on the value of argument.
     """
 
-    import default
-
     numShortcuts = len(orca_state.listOfShortcuts)
     shortcuts = []
     shortcut = ""
     clickCount = ""
     brlKeyName = ""     
     brlHandler = None
-    defScript = default.Script(None)
+    defScript = _scriptManager.getDefaultScript()
     defKeyBindings = defScript.getKeyBindings()
     defBrlBindings = defScript.getBrailleBindings()
     kbindings = keybindings.KeyBindings()
@@ -2092,8 +2000,6 @@ def start(registry):
     """Starts Orca.
     """
 
-    global _PRESENTATION_MANAGERS
-
     if not _initialized:
         init(registry)
 
@@ -2103,13 +2009,6 @@ def start(registry):
         signal.signal(signal.SIGALRM, settings.timeoutCallback)
         signal.alarm(settings.timeoutTime)
 
-    if not _PRESENTATION_MANAGERS:
-        import focus_tracking_presenter
-        _PRESENTATION_MANAGERS = \
-            [focus_tracking_presenter.FocusTrackingPresenter()]
-
-    _switchToPresentationManager(0) # focus_tracking_presenter
-
     if settings.timeoutCallback and (settings.timeoutTime > 0):
         signal.alarm(0)
 
@@ -2166,8 +2065,8 @@ def shutdown(script=None, inputEvent=None):
     pyatspi.Registry.deregisterEventListener(_onMouseButton,
                                              "mouse:button")
 
-    if _currentPresentationManager >= 0:
-        _PRESENTATION_MANAGERS[_currentPresentationManager].deactivate()
+    _eventManager.deactivate()
+    _scriptManager.deactivate()
 
     # Shutdown all the other support.
     #
@@ -2251,6 +2150,17 @@ def multipleOrcas():
     ppid = os.getppid()
     return len(filter(lambda p: p not in [pid, ppid], orcas)) > 0
 
+def cleanupGarbage():
+    """Cleans up garbage on the heap."""
+    gc.collect()
+    for obj in gc.garbage:
+        try:
+            if isinstance(obj, pyatspi.Accessibility.Accessible):
+                gc.garbage.remove(obj)
+                obj.__del__()
+        except:
+            pass
+
 def main():
     """The main entry point for Orca.  The exit codes for Orca will
     loosely be based on signals, where the exit code will be the
diff --git a/src/orca/orca_gui_prefs.py b/src/orca/orca_gui_prefs.py
index c0aefaa..73a0bfe 100644
--- a/src/orca/orca_gui_prefs.py
+++ b/src/orca/orca_gui_prefs.py
@@ -44,7 +44,6 @@ import orca_gtkbuilder
 import orca_state
 import orca_platform
 import settings
-import default    # for the default keyBindings
 import input_event
 import keybindings
 import pronunciation_dict
@@ -56,7 +55,7 @@ import text_attribute_names
 import orca_gui_profile
 
 _settingsManager = getattr(orca, '_settingsManager')
-
+_scriptManager = getattr(orca, '_scriptManager')
 
 try:
     import louis
@@ -1032,7 +1031,7 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
 
         model = view.get_model()
         view.set_model(None)
-        defScript = default.Script(None)
+        defScript = _scriptManager.getDefaultScript()
 
         [attrList, attrDict] = \
            defScript.utilities.stringToKeysAndDict(setAttributes)
@@ -1073,7 +1072,7 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         model = view.get_model()
         view.set_model(None)
 
-        defScript = default.Script(None)
+        defScript = _scriptManager.getDefaultScript()
         [attrList, attrDict] = \
             defScript.utilities.stringToKeysAndDict(setAttributes)
         [allAttrList, allAttrDict] = defScript.utilities.stringToKeysAndDict(
@@ -1233,7 +1232,7 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         # Initially setup the list store model based on the values of all
         # the known text attributes.
         #
-        defScript = default.Script(None)
+        defScript = _scriptManager.getDefaultScript()
         [allAttrList, allAttrDict] = defScript.utilities.stringToKeysAndDict(
             _settingsManager.getSetting('allTextAttributes'))
         for i in range(0, len(allAttrList)):
@@ -2434,7 +2433,7 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         - interrupt: if True, interrupt any speech currently being spoken
         """
 
-        defScript = default.Script(None)
+        defScript = _scriptManager.getDefaultScript()
         defScript.speakMessage(text, interrupt=interrupt)
         try:
             defScript.displayBrailleMessage(text, flashTime=-1)
@@ -2620,7 +2619,7 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         """
 
         try:
-            defScript = default.Script(None)
+            defScript = _scriptManager.getDefaultScript()
             defScript.setupInputEventHandlers()
             keyBinds = keybindings.KeyBindings()
             keyBinds = settings.overrideKeyBindings(defScript, keyBinds)
@@ -2665,7 +2664,7 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         iterUnbound = self._getIterOf("Unbound") \
                       or self._createNode(_("Unbound"))
 
-        defScript = default.Script(None)
+        defScript = _scriptManager.getDefaultScript()
 
         # If we are in the app-specific preferences, we already have
         # populated our tree with bindings.  Otherwise, we need to
@@ -5364,7 +5363,7 @@ def showPreferencesUI():
         # Translators: Orca Preferences is the configuration GUI for Orca.
         #
         line = _("Starting Orca Preferences.")
-        defScript = default.Script(None)
+        defScript = _scriptManager.getDefaultScript()
         defScript.speakMessage(line)
         try:
             defScript.displayBrailleMessage(line, flashTime=-1)
diff --git a/src/orca/script.py b/src/orca/script.py
index fa6d7a2..f1a0f58 100644
--- a/src/orca/script.py
+++ b/src/orca/script.py
@@ -25,7 +25,7 @@ InputEventHandler.  The listeners field is a dictionary where the keys
 are AT-SPI event names and the values are function pointers.
 
 Instances of scripts are intended to be created solely by the
-focus_tracking_presenter.
+script manager.
 
 This Script class is not intended to be instantiated directly.
 Instead, it is expected that subclasses of the Script class will be
@@ -47,6 +47,7 @@ import flat_review
 import formatting
 import keybindings
 import orca_state
+import script_manager
 import script_utilities
 import settings
 import speech_generator
@@ -62,7 +63,7 @@ class Script:
     def __init__(self, app):
         """Creates a script for the given application, if necessary.
         This method should not be called by anyone except the
-        focus_tracking_presenter.
+        script manager.
 
         Arguments:
         - app: the Python Accessible application to create a script for
@@ -333,7 +334,7 @@ class Script:
 
         scriptSettings = settings
         if orca_state.activeScript != self:
-            name = settings.getScriptModuleName(self.app)
+            name = script_manager.getModuleName(self.app)
             if name:
                 for package in settings.settingsPackages:
                     name = package + "." + name
@@ -361,11 +362,6 @@ class Script:
         'listeners' field that was defined during the construction of
         this script.
 
-        In general, the primary purpose of handling object events is to
-        keep track of changes to the locus of focus and notify the
-        orca module of these changes via orca.setLocusOfFocus and
-        orca.visualAppearanceChanged.
-
         Note that this script may be passed events it doesn't care
         about, so it needs to react accordingly.
 
@@ -643,10 +639,6 @@ class Script:
         The primary purpose of this method is to present the changed
         information to the user.
 
-        NOTE: scripts should not call this method directly.  Instead,
-        a script should call orca.visualAppearanceChanged, which will
-        eventually result in this method being called.
-
         Arguments:
         - event: if not None, the Event that caused this to happen
         - obj: the Accessible whose visual appearance changed.
diff --git a/src/orca/script_manager.py b/src/orca/script_manager.py
new file mode 100644
index 0000000..3619d40
--- /dev/null
+++ b/src/orca/script_manager.py
@@ -0,0 +1,249 @@
+# Orca
+#
+# Copyright 2011. Orca Team.
+# Author: Joanmarie Diggs <joanmarie diggs gmail com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
+# Boston MA  02110-1301 USA.
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2011. Orca Team."
+__license__   = "LGPL"
+
+import debug
+import orca
+import orca_state
+
+from scripts import apps, toolkits
+
+_settingsManager = getattr(orca, '_settingsManager')
+_eventManager = getattr(orca, '_eventManager')
+
+class ScriptManager:
+
+    def __init__(self):
+        self.scripts = {}
+        self._appModules = apps.__all__
+        self._toolkitModules = toolkits.__all__
+        self._defaultScript = None
+        self._scriptPackages = \
+            ["orca-scripts",
+             "scripts",
+             "scripts.apps",
+             "scripts.toolkits"]
+        self._appNames = \
+            {'Bon Echo':         'Mozilla',
+             'Deer Park':        'Mozilla',
+             'Firefox':          'Mozilla',
+             'Minefield':        'Mozilla',
+             'Namoroka':         'Mozilla',
+             'Shiretoko':        'Mozilla',
+             'Lanikai':          'Thunderbird',
+             'Mail/News':        'Thunderbird',
+             'Miramar':          'Thunderbird',
+             'Shredder':         'Thunderbird',
+             'bug-buddy':        'gnome_segv2',
+             'epiphany-browser': 'epiphany',
+             'gaim':             'pidgin',
+             'gnome-calculator': 'gcalctool',
+             'gnome-help':       'yelp',
+             'Nereid':           'Banshee',
+             'vte':              'gnome-terminal'}
+
+        self.setActiveScript(None, "__init__")
+
+    def activate(self):
+        """Called when this script manager is activated."""
+
+        self._defaultScript  = None
+        self.setActiveScript(self.getScript(None), "activate")
+
+    def deactivate(self):
+        """Called when this script manager is deactivated."""
+
+        self._defaultScript  = None
+        self.setActiveScript(None, "deactivate")
+
+    def getModuleName(self, app):
+        """Returns the module name of the script to use for application app."""
+
+        if not (app and app.name):
+            return None
+
+        # Many python apps have an accessible name which ends in '.py'.
+        # Sometimes OOo has 'soffice.bin' as its name.
+        name = app.name.split('.')[0]
+        altNames = self._appNames.keys()
+
+        names = filter(lambda n: n.lower() == name.lower(), altNames)
+        if names:
+            name = self._appNames.get(names[0])
+        else:
+            for nameList in (self._appModules, self._toolkitModules):
+                names = filter(lambda n: n.lower() == name.lower(), nameList)
+                if names:
+                    name = names[0]
+                    break
+
+        debug.println(debug.LEVEL_FINEST, "mapped %s to %s" % (app.name, name))
+
+        return name
+
+    def _toolkitForObject(self, obj):
+        """Returns the name of the toolkit associated with obj."""
+
+        name = ''
+        if obj:
+            attrs = dict([attr.split(':', 1) for attr in obj.getAttributes()])
+            name = attrs.get('toolkit', '')
+
+        return name
+
+    def _newNamedScript(self, app, name):
+        """Attempts to locate and load the named module. If successful, returns
+        a script based on this module."""
+
+        if not (app and name):
+            return None
+
+        script = None
+        for package in self._scriptPackages:
+            moduleName = '.'.join((package, name))
+            debug.println(debug.LEVEL_FINE, "Looking for %s.py" % moduleName)
+            try:
+                module = __import__(moduleName, globals(), locals(), [''])
+            except ImportError:
+                debug.println(
+                    debug.LEVEL_FINE, "Could not import %s.py" % moduleName)
+                continue
+
+            debug.println(debug.LEVEL_FINE, "Found %s.py" % moduleName)
+            try:
+                script = module.Script(app)
+                debug.println(debug.LEVEL_FINE, "Loaded %s.py" % moduleName)
+                break
+            except:
+                debug.printException(debug.LEVEL_SEVERE)
+                debug.println(
+                    debug.LEVEL_SEVERE, "Could not load %s.py" % moduleName)
+
+        return script
+
+    def _createScript(self, app, obj=None):
+        """For the given application, create a new script instance."""
+
+        objToolkit = self._toolkitForObject(obj)
+        script = self._newNamedScript(app, objToolkit)
+        if script:
+            return script
+
+        moduleName = self.getModuleName(app)
+        script = self._newNamedScript(app, moduleName)
+        if script:
+            return script
+
+        if app and getattr(app, "toolkitName", None):
+            script = self._newNamedScript(app, app.toolkitName)
+
+        if not script:
+            script = self.getDefaultScript(app)
+
+        return script
+
+    def getDefaultScript(self, app=None):
+        if not self._defaultScript:
+            import scripts.default as default
+            self._defaultScript = default.Script(app)
+            _eventManager.registerListeners(self._defaultScript)
+
+        return self._defaultScript
+
+    def getScript(self, app, obj=None):
+        """Get a script for an app (and make it if necessary).  This is used
+        instead of a simple calls to Script's constructor.
+
+        Arguments:
+        - app: the Python app
+
+        Returns an instance of a Script.
+        """
+
+        script = None
+
+        objToolkit = self._toolkitForObject(obj)
+        if objToolkit:
+            script = self.scripts.get(objToolkit)
+            if not script:
+                script = self._createScript(app, obj)
+                if script:
+                    self.scripts[objToolkit] = script
+                    _eventManager.registerListeners(script)
+            if script:
+                return script
+
+        if not app:
+            script = self.getDefaultScript()
+        elif app in self.scripts:
+            script = self.scripts[app]
+        else:
+            script = self._createScript(app, obj)
+            self.scripts[app] = script
+            _eventManager.registerListeners(script)
+
+        return script
+
+    def setActiveScript(self, newScript, reason=None):
+        """Set the new active script.
+
+        Arguments:
+        - newScript: the new script to be made active.
+        """
+
+        if orca_state.activeScript == newScript:
+            return
+
+        if orca_state.activeScript:
+            orca_state.activeScript.deactivate()
+
+        orca_state.activeScript = newScript
+        if not newScript:
+            return
+
+        _settingsManager.loadAppSettings(newScript)
+        newScript.activate()
+        debug.println(debug.LEVEL_FINE, "ACTIVE SCRIPT: %s (reason=%s)" \
+                          % (newScript.name, reason))
+
+    def reclaimScripts(self):
+        """Compares the list of known scripts to the list of known apps,
+        deleting any scripts as necessary.
+        """
+
+        from pyatspi import Registry
+
+        try:
+            desktop = Registry.getDesktop(0)
+        except:
+            debug.printException(debug.LEVEL_FINEST)
+            return
+
+        appList = filter(lambda a: a not in desktop, self.scripts.keys())
+        for app in appList:
+            script = self.scripts.get(app)
+            _eventManager.deregisterListeners(script)
+            del app
+            del script
diff --git a/src/orca/scripts/Makefile.am b/src/orca/scripts/Makefile.am
index 261cec1..e01c6bd 100644
--- a/src/orca/scripts/Makefile.am
+++ b/src/orca/scripts/Makefile.am
@@ -4,6 +4,7 @@ orca_pathdir=$(pyexecdir)
 
 orca_python_PYTHON = \
 	__init__.py \
+	default.py \
 	self_voicing.py
 
 orca_pythondir=$(pyexecdir)/orca/scripts
diff --git a/src/orca/scripts/apps/Banshee/script.py b/src/orca/scripts/apps/Banshee/script.py
index a5c419f..e524367 100644
--- a/src/orca/scripts/apps/Banshee/script.py
+++ b/src/orca/scripts/apps/Banshee/script.py
@@ -1,4 +1,4 @@
-import orca.default as default
+import orca.scripts.default as default
 import orca.orca_state as orca_state
 
 from script_utilities import Utilities
diff --git a/src/orca/scripts/apps/Eclipse/script.py b/src/orca/scripts/apps/Eclipse/script.py
index 12f02f1..a0af800 100644
--- a/src/orca/scripts/apps/Eclipse/script.py
+++ b/src/orca/scripts/apps/Eclipse/script.py
@@ -25,7 +25,7 @@ __date__      = "$Date$"
 __copyright__ = "Copyright (c) 2010 Informal Informatica LTDA."
 __license__   = "LGPL"
 
-import orca.default as default
+import orca.scripts.default as default
 import pyatspi
 from script_utilities import Utilities
 
diff --git a/src/orca/scripts/apps/Instantbird/script.py b/src/orca/scripts/apps/Instantbird/script.py
index 64afc25..141c68e 100644
--- a/src/orca/scripts/apps/Instantbird/script.py
+++ b/src/orca/scripts/apps/Instantbird/script.py
@@ -28,7 +28,7 @@ __license__   = "LGPL"
 import pyatspi
 
 import orca.bookmarks as bookmarks
-import orca.default as default
+import orca.scripts.default as default
 import orca.orca as orca
 import orca.orca_state as orca_state
 import orca.scripts.toolkits.Gecko as Gecko
diff --git a/src/orca/scripts/apps/Thunderbird/script.py b/src/orca/scripts/apps/Thunderbird/script.py
index 606ab55..d145416 100644
--- a/src/orca/scripts/apps/Thunderbird/script.py
+++ b/src/orca/scripts/apps/Thunderbird/script.py
@@ -30,7 +30,7 @@ import pyatspi
 
 import orca.orca as orca
 import orca.debug as debug
-import orca.default as default
+import orca.scripts.default as default
 import orca.orca_state as orca_state
 import orca.speech as speech
 import orca.scripts.toolkits.Gecko as Gecko
@@ -214,8 +214,7 @@ class Script(Gecko.Script):
                 event.source.getState().contains(pyatspi.STATE_EDITABLE)
 
         if updatePosition:
-            orca.setLocusOfFocus(
-                event, event.source, notifyPresentationManager=False)
+            orca.setLocusOfFocus(event, event.source, notifyScript=False)
             self.setCaretContext(event.source, event.detail1)
 
             # The Gecko script, should it be about to pass along this
diff --git a/src/orca/scripts/apps/__init__.py b/src/orca/scripts/apps/__init__.py
index e69de29..25ae238 100644
--- a/src/orca/scripts/apps/__init__.py
+++ b/src/orca/scripts/apps/__init__.py
@@ -0,0 +1,36 @@
+__all__ = ['acroread',
+           'Banshee',
+           'ddu',
+           'Eclipse',
+           'ekiga',
+           'empathy',
+           'epiphany',
+           'evolution',
+           'gajim',
+           'gcalctool',
+           'gdmlogin',
+           'gedit',
+           'gnome-keyring-ask',
+           'gnome-mud',
+           'gnome-panel',
+           'gnome-screensaver-dialog',
+           'gnome-search-tool',
+           'gnome_segv2',
+           'gnome-system-monitor',
+           'gnome-terminal',
+           'gnome-window-properties',
+           'gtk-window-decorator',
+           'Instantbird',
+           'liferea',
+           'metacity',
+           'Mozilla',
+           'nautilus',
+           'notification-daemon',
+           'notify-osd',
+           'packagemanager',
+           'pidgin',
+           'planner',
+           'rhythmbox',
+           'soffice',
+           'Thunderbird',
+           'yelp']
diff --git a/src/orca/scripts/apps/acroread/script.py b/src/orca/scripts/apps/acroread/script.py
index bab55ba..a21ce4b 100644
--- a/src/orca/scripts/apps/acroread/script.py
+++ b/src/orca/scripts/apps/acroread/script.py
@@ -28,7 +28,7 @@ __license__   = "LGPL"
 import pyatspi
 
 import orca.debug as debug
-import orca.default as default
+import orca.scripts.default as default
 import orca.input_event as input_event
 import orca.orca as orca
 import orca.rolenames as rolenames
@@ -437,19 +437,17 @@ class Script(default.Script):
                 newText = self.getTextLineAtCaret(newLocusOfFocus)
                 if newText == self.preFindLine:
                     orca.setLocusOfFocus(
-                        event, oldLocusOfFocus, notifyPresentationManager=False)
+                        event, oldLocusOfFocus, notifyScript=False)
                     return
             if newLocusOfFocus.getRole() == pyatspi.ROLE_DRAWING_AREA:
-                orca.setLocusOfFocus(
-                    event, oldLocusOfFocus, notifyPresentationManager=False)
+                orca.setLocusOfFocus(event, oldLocusOfFocus, notifyScript=False)
                 return
 
             utterances = \
                  self.speechGenerator.generateSpeech(newLocusOfFocus)
             speech.speak(utterances)
             self.displayBrailleForObject(newLocusOfFocus)
-            orca.setLocusOfFocus(
-                event, newLocusOfFocus, notifyPresentationManager=False)
+            orca.setLocusOfFocus(event, newLocusOfFocus, notifyScript=False)
             return
 
         # Eliminate unnecessary chattiness in the Search panel.
@@ -464,8 +462,7 @@ class Script(default.Script):
         #
         if newLocusOfFocus.getRole() in [self.ROLE_DOCUMENT,
                                          pyatspi.ROLE_DRAWING_AREA]:
-            orca.setLocusOfFocus(
-                event, newLocusOfFocus, notifyPresentationManager=False)
+            orca.setLocusOfFocus(event, newLocusOfFocus, notifyScript=False)
             return
 
         elif newLocusOfFocus.getRole() == self.ROLE_LINK:
@@ -481,8 +478,7 @@ class Script(default.Script):
                     self.utilities.adjustForRepeats(utterance))
             speech.speak(adjustedUtterances)
             self.displayBrailleForObject(newLocusOfFocus)
-            orca.setLocusOfFocus(
-                event, newLocusOfFocus, notifyPresentationManager=False)
+            orca.setLocusOfFocus(event, newLocusOfFocus, notifyScript=False)
             return
 
         default.Script.locusOfFocusChanged(self, event,
@@ -549,7 +545,7 @@ class Script(default.Script):
             # selected when you arrow to them.  You have to press Space
             # to select the current radio button.  Watch for this.
             #
-            orca.visualAppearanceChanged(event, event.source)
+            self.visualAppearanceChanged(event, event.source)
             return
 
         elif event.type.startswith("object:state-changed:focused") \
@@ -561,8 +557,7 @@ class Script(default.Script):
                      self.speechGenerator.generateSpeech(event.source)
                 speech.speak(utterances)
                 self.displayBrailleForObject(event.source)
-                orca.setLocusOfFocus(
-                    event, event.source, notifyPresentationManager=False)
+                orca.setLocusOfFocus(event, event.source, notifyScript=False)
                 return
 
             elif event.source.getRole() == pyatspi.ROLE_TEXT:
diff --git a/src/orca/scripts/apps/ddu/script.py b/src/orca/scripts/apps/ddu/script.py
index 744ab2e..b75eb11 100644
--- a/src/orca/scripts/apps/ddu/script.py
+++ b/src/orca/scripts/apps/ddu/script.py
@@ -29,7 +29,7 @@ __license__   = "LGPL"
 
 import pyatspi
 
-import orca.default as default
+import orca.scripts.default as default
 import orca.orca_state as orca_state
 import orca.speech as speech
 
diff --git a/src/orca/scripts/apps/ekiga/script.py b/src/orca/scripts/apps/ekiga/script.py
index 1b3c638..7c7e260 100644
--- a/src/orca/scripts/apps/ekiga/script.py
+++ b/src/orca/scripts/apps/ekiga/script.py
@@ -27,7 +27,7 @@ __license__   = "LGPL"
 
 import pyatspi
 
-import orca.default as default
+import orca.scripts.default as default
 import orca.orca as orca
 import orca.orca_state as orca_state
 import orca.speech as speech
diff --git a/src/orca/scripts/apps/empathy/script.py b/src/orca/scripts/apps/empathy/script.py
index cd1d0b4..141f795 100644
--- a/src/orca/scripts/apps/empathy/script.py
+++ b/src/orca/scripts/apps/empathy/script.py
@@ -28,7 +28,7 @@ __license__   = "LGPL"
 import pyatspi
 
 import orca.chat as chat
-import orca.default as default
+import orca.scripts.default as default
 
 from script_utilities import Utilities
 
diff --git a/src/orca/scripts/apps/evolution/script.py b/src/orca/scripts/apps/evolution/script.py
index 164cced..2d7b54d 100644
--- a/src/orca/scripts/apps/evolution/script.py
+++ b/src/orca/scripts/apps/evolution/script.py
@@ -28,7 +28,7 @@ __license__   = "LGPL"
 import pyatspi
 
 import orca.debug as debug
-import orca.default as default
+import orca.scripts.default as default
 import orca.input_event as input_event
 import orca.rolenames as rolenames
 import orca.braille as braille
@@ -1333,7 +1333,7 @@ class Script(default.Script):
             #print "COMPLETED", context.utterance, context.currentOffset
             obj = context.obj[len(context.obj)-1]
             obj.queryText().setCaretOffset(context.currentOffset)
-            orca.setLocusOfFocus(None, obj, notifyPresentationManager=False)
+            orca.setLocusOfFocus(None, obj, notifyScript=False)
 
         # If there is a selection, clear it. See bug #489504 for more details.
         # This is not straight forward with Evolution. all the text is in
diff --git a/src/orca/scripts/apps/gajim/script.py b/src/orca/scripts/apps/gajim/script.py
index f098073..6643b3e 100644
--- a/src/orca/scripts/apps/gajim/script.py
+++ b/src/orca/scripts/apps/gajim/script.py
@@ -28,7 +28,7 @@ __license__   = "LGPL"
 import pyatspi
 
 import orca.chat as chat
-import orca.default as default
+import orca.scripts.default as default
 
 ########################################################################
 #                                                                      #
diff --git a/src/orca/scripts/apps/gcalctool/script.py b/src/orca/scripts/apps/gcalctool/script.py
index 8c5bfb9..0c6217b 100644
--- a/src/orca/scripts/apps/gcalctool/script.py
+++ b/src/orca/scripts/apps/gcalctool/script.py
@@ -25,7 +25,7 @@ __date__      = "$Date$"
 __copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.default as default
+import orca.scripts.default as default
 import orca.input_event as input_event
 import orca.orca_state as orca_state
 import orca.speech as speech
diff --git a/src/orca/scripts/apps/gdmlogin/script.py b/src/orca/scripts/apps/gdmlogin/script.py
index fbcb8a0..88b2375 100644
--- a/src/orca/scripts/apps/gdmlogin/script.py
+++ b/src/orca/scripts/apps/gdmlogin/script.py
@@ -25,7 +25,7 @@ __date__      = "$Date$"
 __copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.default as default
+import orca.scripts.default as default
 import orca.orca as orca
 
 ########################################################################
diff --git a/src/orca/scripts/apps/gedit/script.py b/src/orca/scripts/apps/gedit/script.py
index 29b6524..2aaf592 100644
--- a/src/orca/scripts/apps/gedit/script.py
+++ b/src/orca/scripts/apps/gedit/script.py
@@ -28,7 +28,7 @@ __license__   = "LGPL"
 import pyatspi
 
 import orca.debug as debug
-import orca.default as default
+import orca.scripts.default as default
 import orca.orca as orca
 import orca.orca_state as orca_state
 import orca.settings as settings
@@ -98,8 +98,7 @@ class Script(default.Script):
             #print "COMPLETED", context.utterance, context.currentOffset
             obj = context.obj[len(context.obj)-1]
             obj.queryText().setCaretOffset(context.currentOffset)
-            orca.setLocusOfFocus(
-                None, obj, notifyPresentationManager=False)
+            orca.setLocusOfFocus(None, obj, notifyScript=False)
 
     def textLines(self, obj):
         """Creates a generator that can be used to iterate over each line
diff --git a/src/orca/scripts/apps/gnome-keyring-ask/script.py b/src/orca/scripts/apps/gnome-keyring-ask/script.py
index d75189b..e74b580 100644
--- a/src/orca/scripts/apps/gnome-keyring-ask/script.py
+++ b/src/orca/scripts/apps/gnome-keyring-ask/script.py
@@ -25,7 +25,7 @@ __date__      = "$Date$"
 __copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.default as default
+import orca.scripts.default as default
 
 ########################################################################
 #                                                                      #
diff --git a/src/orca/scripts/apps/gnome-mud/script.py b/src/orca/scripts/apps/gnome-mud/script.py
index 6c54acc..b6db2ac 100644
--- a/src/orca/scripts/apps/gnome-mud/script.py
+++ b/src/orca/scripts/apps/gnome-mud/script.py
@@ -28,7 +28,7 @@ __license__   = "LGPL"
 import pyatspi
 
 import orca.debug as debug
-import orca.default as default
+import orca.scripts.default as default
 import orca.input_event as input_event
 import orca.keybindings as keybindings
 import orca.orca_state as orca_state
diff --git a/src/orca/scripts/apps/gnome-panel/script.py b/src/orca/scripts/apps/gnome-panel/script.py
index 72090b8..c0e0728 100644
--- a/src/orca/scripts/apps/gnome-panel/script.py
+++ b/src/orca/scripts/apps/gnome-panel/script.py
@@ -26,7 +26,7 @@ __date__      = "$Date$"
 __copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.default as default
+import orca.scripts.default as default
 import orca.debug as debug
 import orca.speech as speech
 import pyatspi
diff --git a/src/orca/scripts/apps/gnome-screensaver-dialog/script.py b/src/orca/scripts/apps/gnome-screensaver-dialog/script.py
index 16f7159..5adc724 100644
--- a/src/orca/scripts/apps/gnome-screensaver-dialog/script.py
+++ b/src/orca/scripts/apps/gnome-screensaver-dialog/script.py
@@ -27,7 +27,7 @@ __license__   = "LGPL"
 
 import pyatspi
 
-import orca.default as default
+import orca.scripts.default as default
 import orca.speech as speech
 
 class Script(default.Script):
diff --git a/src/orca/scripts/apps/gnome-search-tool/script.py b/src/orca/scripts/apps/gnome-search-tool/script.py
index 513cd20..bd321ff 100644
--- a/src/orca/scripts/apps/gnome-search-tool/script.py
+++ b/src/orca/scripts/apps/gnome-search-tool/script.py
@@ -26,7 +26,7 @@ __copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
 __license__   = "LGPL"
 
 import orca.debug as debug
-import orca.default as default
+import orca.scripts.default as default
 
 from orca.orca_i18n import _        # for gettext support
 from orca.orca_i18n import ngettext # for gettext support
diff --git a/src/orca/scripts/apps/gnome-system-monitor/script.py b/src/orca/scripts/apps/gnome-system-monitor/script.py
index fbcd467..ddedda4 100644
--- a/src/orca/scripts/apps/gnome-system-monitor/script.py
+++ b/src/orca/scripts/apps/gnome-system-monitor/script.py
@@ -27,7 +27,7 @@ __license__   = "LGPL"
 
 import pyatspi
 
-import orca.default as default
+import orca.scripts.default as default
 import orca.debug as debug
 
 ########################################################################
diff --git a/src/orca/scripts/apps/gnome-terminal/script.py b/src/orca/scripts/apps/gnome-terminal/script.py
index 5378b69..b7c2993 100644
--- a/src/orca/scripts/apps/gnome-terminal/script.py
+++ b/src/orca/scripts/apps/gnome-terminal/script.py
@@ -29,7 +29,7 @@ __license__   = "LGPL"
 
 import pyatspi
 
-import orca.default as default
+import orca.scripts.default as default
 import orca.input_event as input_event
 import orca.orca as orca
 import orca.orca_state as orca_state
diff --git a/src/orca/scripts/apps/gnome-window-properties/script.py b/src/orca/scripts/apps/gnome-window-properties/script.py
index 80c8fdc..c51bcda 100644
--- a/src/orca/scripts/apps/gnome-window-properties/script.py
+++ b/src/orca/scripts/apps/gnome-window-properties/script.py
@@ -25,7 +25,7 @@ __date__      = "$Date$"
 __copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.default as default
+import orca.scripts.default as default
 
 from formatting import Formatting
 
diff --git a/src/orca/scripts/apps/gnome_segv2/script.py b/src/orca/scripts/apps/gnome_segv2/script.py
index 9260f5e..f06d5d3 100644
--- a/src/orca/scripts/apps/gnome_segv2/script.py
+++ b/src/orca/scripts/apps/gnome_segv2/script.py
@@ -25,7 +25,7 @@ __date__      = "$Date$"
 __copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.default as default
+import orca.scripts.default as default
 
 ########################################################################
 #                                                                      #
diff --git a/src/orca/scripts/apps/gtk-window-decorator/script.py b/src/orca/scripts/apps/gtk-window-decorator/script.py
index 915a1a7..0718112 100644
--- a/src/orca/scripts/apps/gtk-window-decorator/script.py
+++ b/src/orca/scripts/apps/gtk-window-decorator/script.py
@@ -25,7 +25,7 @@ __date__      = "$Date$"
 __copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.default as default
+import orca.scripts.default as default
 import orca.speech as speech
 import pyatspi
 
diff --git a/src/orca/scripts/apps/liferea/script.py b/src/orca/scripts/apps/liferea/script.py
index 927cb2b..d1b2642 100644
--- a/src/orca/scripts/apps/liferea/script.py
+++ b/src/orca/scripts/apps/liferea/script.py
@@ -20,7 +20,7 @@
 """Custom script for liferea."""
 
 import orca.debug as debug
-import orca.default as default
+import orca.scripts.default as default
 import orca.orca_state as orca_state
 import orca.speech as speech
 import orca.eventsynthesizer as eventsynthesizer
diff --git a/src/orca/scripts/apps/metacity/script.py b/src/orca/scripts/apps/metacity/script.py
index b064d95..e7b37ff 100644
--- a/src/orca/scripts/apps/metacity/script.py
+++ b/src/orca/scripts/apps/metacity/script.py
@@ -25,7 +25,7 @@ __date__      = "$Date$"
 __copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.default as default
+import orca.scripts.default as default
 try:
     import orca.gsmag as mag
 except:
diff --git a/src/orca/scripts/apps/nautilus/script.py b/src/orca/scripts/apps/nautilus/script.py
index 22829b1..0191070 100644
--- a/src/orca/scripts/apps/nautilus/script.py
+++ b/src/orca/scripts/apps/nautilus/script.py
@@ -27,7 +27,7 @@ __license__   = "LGPL"
 
 import pyatspi
 import orca.debug as debug
-import orca.default as default
+import orca.scripts.default as default
 import orca.speech as speech
 
 from orca.orca_i18n import ngettext  # for ngettext support
diff --git a/src/orca/scripts/apps/notification-daemon/script.py b/src/orca/scripts/apps/notification-daemon/script.py
index 485ecbe..5c14c22 100644
--- a/src/orca/scripts/apps/notification-daemon/script.py
+++ b/src/orca/scripts/apps/notification-daemon/script.py
@@ -25,7 +25,7 @@ __date__      = ""
 __copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.default as default
+import orca.scripts.default as default
 import orca.speech as speech
 import pyatspi
 
diff --git a/src/orca/scripts/apps/notify-osd/script.py b/src/orca/scripts/apps/notify-osd/script.py
index 83bc0ef..78ca95d 100644
--- a/src/orca/scripts/apps/notify-osd/script.py
+++ b/src/orca/scripts/apps/notify-osd/script.py
@@ -25,7 +25,7 @@ __date__      = ""
 __copyright__ = "Copyright (c) 2009 Eitan Isaacson"
 __license__   = "LGPL"
 
-import orca.default as default
+import orca.scripts.default as default
 import orca.settings as settings
 import orca.speech as speech
 import orca.notification_messages as notification_messages
diff --git a/src/orca/scripts/apps/packagemanager/script.py b/src/orca/scripts/apps/packagemanager/script.py
index dbcc762..f017fb0 100644
--- a/src/orca/scripts/apps/packagemanager/script.py
+++ b/src/orca/scripts/apps/packagemanager/script.py
@@ -30,7 +30,7 @@ __license__   = "LGPL"
 import gtk
 import pyatspi
 
-import orca.default as default
+import orca.scripts.default as default
 import orca.orca as orca
 import orca.orca_state as orca_state
 import orca.settings as settings
diff --git a/src/orca/scripts/apps/pidgin/script.py b/src/orca/scripts/apps/pidgin/script.py
index a54286e..d5c0a0b 100644
--- a/src/orca/scripts/apps/pidgin/script.py
+++ b/src/orca/scripts/apps/pidgin/script.py
@@ -28,7 +28,7 @@ __license__   = "LGPL"
 
 import pyatspi
 
-import orca.default as default
+import orca.scripts.default as default
 import orca.speech as speech
 
 from orca.orca_i18n import _
diff --git a/src/orca/scripts/apps/planner/script.py b/src/orca/scripts/apps/planner/script.py
index 17a5cf6..860f9e0 100644
--- a/src/orca/scripts/apps/planner/script.py
+++ b/src/orca/scripts/apps/planner/script.py
@@ -25,7 +25,7 @@ __date__      = "$Date$"
 __copyright__ = "Copyright (c) 2006-2008 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.default as default
+import orca.scripts.default as default
 
 from braille_generator import BrailleGenerator
 from speech_generator import SpeechGenerator
diff --git a/src/orca/scripts/apps/rhythmbox/script.py b/src/orca/scripts/apps/rhythmbox/script.py
index d48d513..39b87d4 100644
--- a/src/orca/scripts/apps/rhythmbox/script.py
+++ b/src/orca/scripts/apps/rhythmbox/script.py
@@ -29,7 +29,7 @@ __license__   = "LGPL"
 
 import pyatspi
 
-import orca.default as default
+import orca.scripts.default as default
 import orca.orca as orca
 import orca.orca_state as orca_state
 
diff --git a/src/orca/scripts/apps/soffice/script.py b/src/orca/scripts/apps/soffice/script.py
index 06a200c..76bcd1c 100644
--- a/src/orca/scripts/apps/soffice/script.py
+++ b/src/orca/scripts/apps/soffice/script.py
@@ -41,7 +41,7 @@ import gtk
 import pyatspi
 
 import orca.debug as debug
-import orca.default as default
+import orca.scripts.default as default
 import orca.input_event as input_event
 import orca.orca as orca
 import orca.orca_state as orca_state
@@ -149,6 +149,8 @@ class Script(default.Script):
         attributes.replace("indent:0;", "indent:0mm;")
         _settingsManager.setSetting('enabledSpokenTextAttributes', attributes)
 
+        default.Script.activate(self)
+
     def deactivate(self):
         """Called when this script is deactivated."""
         _settingsManager.setSetting('readTableCellRow',
@@ -158,6 +160,8 @@ class Script(default.Script):
         _settingsManager.setSetting('enabledSpokenTextAttributes',
                                     self.savedEnabledSpokenTextAttributes)
 
+        default.Script.activate(self)
+
     def getListeners(self):
         """Sets up the AT-SPI event listeners for this script.
         """
@@ -1817,7 +1821,7 @@ class Script(default.Script):
             if presentEvent:
                 speech.stop()
             orca.setLocusOfFocus(
-                event, event.any_data, notifyPresentationManager=presentEvent)
+                event, event.any_data, notifyScript=presentEvent)
 
             # We'll tuck away the activeDescendant information for future
             # reference since the AT-SPI gives us little help in finding
@@ -1976,8 +1980,7 @@ class Script(default.Script):
                          pyatspi.ROLE_ROOT_PANE,
                          pyatspi.ROLE_FRAME]
             if self.utilities.hasMatchingHierarchy(event.source, rolesList):
-                orca.setLocusOfFocus(
-                    event, event.source, notifyPresentationManager=False)
+                orca.setLocusOfFocus(event, event.source, notifyScript=False)
                 if event.source != self.currentParagraph:
                     self.updateBraille(event.source)
                 return
@@ -1990,7 +1993,7 @@ class Script(default.Script):
             elif event.source.parent and \
                 event.source.parent.getRole() == pyatspi.ROLE_COMBO_BOX:
                 orca.setLocusOfFocus(
-                    None, event.source.parent, notifyPresentationManager=False)
+                    None, event.source.parent, notifyScript=False)
                 return
 
         # If we are in the sbase Table Wizard, try to reduce the numerous
diff --git a/src/orca/scripts/apps/yelp/script.py b/src/orca/scripts/apps/yelp/script.py
index f92c1d6..2eb7654 100644
--- a/src/orca/scripts/apps/yelp/script.py
+++ b/src/orca/scripts/apps/yelp/script.py
@@ -139,8 +139,7 @@ class Script(Gecko.Script):
             # presentation managers if this event is not for an empty anchor.
             #
             notify = self.utilities.isSameObject(event.source, obj)
-            orca.setLocusOfFocus(
-                event, obj, notifyPresentationManager=notify)
+            orca.setLocusOfFocus(event, obj, notifyScript=notify)
             self.setCaretPosition(obj, characterOffset)
 
         return Gecko.Script.onCaretMoved(self, event)
@@ -180,8 +179,7 @@ class Script(Gecko.Script):
             # We need to set the locusOfFocus to the document frame in
             # order to reliably get the caret context.
             #
-            orca.setLocusOfFocus(
-                event, event.source, notifyPresentationManager=False)
+            orca.setLocusOfFocus(event, event.source, notifyScript=False)
             [obj, characterOffset] = self.getCaretContext()
 
             # Often the first object is an anchor with no text. Try to
diff --git a/src/orca/default.py b/src/orca/scripts/default.py
similarity index 99%
rename from src/orca/default.py
rename to src/orca/scripts/default.py
index 163c612..09d6f4c 100644
--- a/src/orca/default.py
+++ b/src/orca/scripts/default.py
@@ -33,35 +33,35 @@ __license__   = "LGPL"
 import locale
 import time
 
-import orca
+import orca.orca as orca
 _settingsManager = getattr(orca, '_settingsManager')
 
 import pyatspi
-import braille
-import debug
-import eventsynthesizer
-import find
-import flat_review
-import input_event
-import keybindings
+import orca.braille as braille
+import orca.debug as debug
+import orca.eventsynthesizer as eventsynthesizer
+import orca.find as find
+import orca.flat_review as flat_review
+import orca.input_event as input_event
+import orca.keybindings as keybindings
 try:
-    import gsmag as mag
+    import orca.gsmag as mag
 except:
-    import mag
-import outline
-import orca_state
-import phonnames
-import script
-import settings
-import speech
-import speechserver
-import mouse_review
-import text_attribute_names
-import notification_messages
-
-from orca_i18n import _         # for gettext support
-from orca_i18n import ngettext  # for ngettext support
-from orca_i18n import C_        # to provide qualified translatable strings
+    import orca.mag as mag
+import orca.outline as outline
+import orca.orca_state as orca_state
+import orca.phonnames as phonnames
+import orca.script as script
+import orca.settings as settings
+import orca.speech as speech
+import orca.speechserver as speechserver
+import orca.mouse_review as mouse_review
+import orca.text_attribute_names as text_attribute_names
+import orca.notification_messages as notification_messages
+
+from orca.orca_i18n import _         # for gettext support
+from orca.orca_i18n import ngettext  # for ngettext support
+from orca.orca_i18n import C_        # to provide qualified translatable strings
 
 ########################################################################
 #                                                                      #
@@ -785,11 +785,11 @@ class Script(script.Script):
                 Script.enterListShortcutsMode,
                 # Translators: Orca has a "List Shortcuts Mode" that will allow
                 # the user to list a group of keyboard shortcuts. The Orca
-                # default shortcuts can be listed by pressing 1, and Orca 
+                # default shortcuts can be listed by pressing 1, and Orca
                 # shortcuts for the application under focus can be listed by
                 # pressing 2. User can press Up/ Down to navigate and hear
                 # the list, changeover to another list by pressing 1/2,
-                # and exit the "List Shortcuts Mode" by pressing Escape. 
+                # and exit the "List Shortcuts Mode" by pressing Escape.
                 #
                 _("Enters list shortcuts mode.  Press escape to exit " \
                   "list shortcuts mode."),False)
@@ -1071,7 +1071,7 @@ class Script(script.Script):
             input_event.InputEventHandler(
                 Script.presentTime,
                 # Translators: Orca can present the current time to the
-                # user when the user presses 
+                # user when the user presses
                 # a shortcut key.
                 #
                 _("Present current time."))
@@ -1080,7 +1080,7 @@ class Script(script.Script):
             input_event.InputEventHandler(
                 Script.presentDate,
                 # Translators: Orca can present the current date to the
-                # user when the user presses 
+                # user when the user presses
                 # a shortcut key.
                 #
                 _("Present current date."))
@@ -1172,7 +1172,7 @@ class Script(script.Script):
         numeric keypad for focus tracking and flat review.
         """
 
-        import desktop_keyboardmap
+        import orca.desktop_keyboardmap as desktop_keyboardmap
         keyBindings = keybindings.KeyBindings()
         keyBindings.load(desktop_keyboardmap.keymap, self.inputEventHandlers)
         return keyBindings
@@ -1182,7 +1182,7 @@ class Script(script.Script):
         the main keyboard keys for focus tracking and flat review.
         """
 
-        import laptop_keyboardmap
+        import orca.laptop_keyboardmap as laptop_keyboardmap
         keyBindings = keybindings.KeyBindings()
         keyBindings.load(laptop_keyboardmap.keymap, self.inputEventHandlers)
         return keyBindings
@@ -1203,7 +1203,7 @@ class Script(script.Script):
             for keyBinding in self.__getLaptopBindings().keyBindings:
                 keyBindings.add(keyBinding)
 
-        import common_keyboardmap
+        import orca.common_keyboardmap as common_keyboardmap
         keyBindings.load(common_keyboardmap.keymap, self.inputEventHandlers)
 
         if _settingsManager.getSetting('debugMemoryUsage'):
@@ -1496,6 +1496,11 @@ class Script(script.Script):
         utterances.extend(self.tutorialGenerator.getTutorial(obj, True))
         speech.speak(utterances)
 
+    def activate(self):
+        """Called when this script is activated."""
+
+        braille.setupKeyRanges(self.brailleBindings.keys())
+
     def updateBraille(self, obj, extraRegion=None):
         """Updates the braille display to show the give object.
 
@@ -2688,7 +2693,7 @@ class Script(script.Script):
             # will be spoken, Most will be spoken, or Some will be spoken.
             #
             brief = C_("spoken punctuation", "All")
-        else: 
+        else:
             # the all case, so cycle to none.
             newLevel = settings.PUNCTUATION_STYLE_NONE
             # Translators: This detailed message will be presented as the
@@ -3221,7 +3226,7 @@ class Script(script.Script):
             return
 
         self.pointOfReference['oldName'] = event.source.name
-        orca.visualAppearanceChanged(event, event.source)
+        self.visualAppearanceChanged(event, event.source)
 
     def onSelectionChanged(self, event):
         """Called when an object's selection changes.
@@ -3249,7 +3254,7 @@ class Script(script.Script):
             return
 
         if event.source.getRole() == pyatspi.ROLE_COMBO_BOX:
-            orca.visualAppearanceChanged(event, event.source)
+            self.visualAppearanceChanged(event, event.source)
 
         # We treat selected children as the locus of focus. When the
         # selection changed we want to update the locus of focus. If
@@ -3378,7 +3383,7 @@ class Script(script.Script):
                     found = True
                     break
             if found:
-                orca.visualAppearanceChanged(event, event.source)
+                self.visualAppearanceChanged(event, event.source)
 
     def onTextAttributesChanged(self, event):
         """Called when an object's text attributes change. Right now this
@@ -3724,7 +3729,7 @@ class Script(script.Script):
            and (value.currentValue == self.pointOfReference["oldValue"]):
             return
 
-        orca.visualAppearanceChanged(event, event.source)
+        self.visualAppearanceChanged(event, event.source)
         if event.source.getState().contains(pyatspi.STATE_FOCUSED):
             self.pointOfReference["oldValue"] = value.currentValue
 
@@ -4003,8 +4008,7 @@ class Script(script.Script):
             text.setCaretOffset(context.currentOffset)
         elif progressType == speechserver.SayAllContext.COMPLETED:
             #print "COMPLETED", context.utterance, context.currentOffset
-            orca.setLocusOfFocus(
-                None, context.obj, notifyPresentationManager=False)
+            orca.setLocusOfFocus(None, context.obj, notifyScript=False)
             text.setCaretOffset(context.currentOffset)
 
         # If there is a selection, clear it. See bug #489504 for more details.
@@ -5067,26 +5071,6 @@ class Script(script.Script):
             phoneticString = phonnames.getPhoneticName(character)
             speech.speak(phoneticString, voice)
 
-    def saveOldAppSettings(self):
-        """Save a copy of all the existing application specific settings
-        (as specified by the settings.userCustomizableSettings dictionary)."""
-
-        generalSettings = \
-            _settingsManager.getGeneralSettings(_settingsManager.profile)
-        generalSettings.update(_settingsManager.customizedSettings)
-        return generalSettings
-
-    def restoreOldAppSettings(self, prefsDict):
-        """Restore a copy of all the previous saved application settings.
-
-        Arguments:
-        - prefsDict: the dictionary containing the old application settings.
-        """
-
-        for key in settings.userCustomizableSettings:
-            if key in prefsDict:
-                setattr(settings, key, prefsDict[key])
-
     def _saveSpokenTextRange(self, startOffset, endOffset):
         """Save away the start and end offset of the range of text that
         was spoken. It will be used by speakTextSelectionState, to try
@@ -5791,7 +5775,7 @@ class Script(script.Script):
 
         if _settingsManager.getSetting('enableSpeech'):
             voice = voice or self.voices.get(settings.SYSTEM_VOICE)
-            speech.speak(string, voice, interrupt) 
+            speech.speak(string, voice, interrupt)
 
     @staticmethod
     def presentItemsInSpeech(items):
@@ -5813,7 +5797,7 @@ class Script(script.Script):
         """ Speaks some information about an unicode character.
         At the Momment it just anounces the character unicode number but
         this information may be changed in the future
-        
+
         Arguments:
         - character: the character to speak information of
         """
diff --git a/src/orca/scripts/self_voicing.py b/src/orca/scripts/self_voicing.py
index d7695be..b75fc5c 100644
--- a/src/orca/scripts/self_voicing.py
+++ b/src/orca/scripts/self_voicing.py
@@ -25,7 +25,7 @@ __date__      = "$Date$"
 __copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.default as default
+import orca.scripts.default as default
 
 class Script(default.Script):
     """A script to do nothing.  This is for self-voicing apps."""
@@ -33,7 +33,7 @@ class Script(default.Script):
     def __init__(self, app):
         """Creates a script for the given application, if necessary.
         This method should not be called by anyone except the
-        focus_tracking_presenter.
+        script manager.
 
         Arguments:
         - app: the Python Accessible application to create a script for
diff --git a/src/orca/scripts/toolkits/CALLY/script.py b/src/orca/scripts/toolkits/CALLY/script.py
index 055b302..808599f 100644
--- a/src/orca/scripts/toolkits/CALLY/script.py
+++ b/src/orca/scripts/toolkits/CALLY/script.py
@@ -25,7 +25,7 @@ __date__      = "$Date$"
 __copyright__ = "Copyright (c) 2010 Igalia, S.L."
 __license__   = "LGPL"
 
-import orca.default as default
+import orca.scripts.default as default
 import orca.debug as debug
 import gtk.gdk as gdk
 
diff --git a/src/orca/scripts/toolkits/GAIL.py b/src/orca/scripts/toolkits/GAIL.py
index 8046df7..795cf2b 100644
--- a/src/orca/scripts/toolkits/GAIL.py
+++ b/src/orca/scripts/toolkits/GAIL.py
@@ -25,7 +25,7 @@ __date__      = "$Date$"
 __copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.default
+import orca.scripts.default as default
 
-class Script(orca.default.Script):
+class Script(default.Script):
     pass
diff --git a/src/orca/scripts/toolkits/Gecko/script.py b/src/orca/scripts/toolkits/Gecko/script.py
index 6e3b3f4..ea4f110 100644
--- a/src/orca/scripts/toolkits/Gecko/script.py
+++ b/src/orca/scripts/toolkits/Gecko/script.py
@@ -50,7 +50,7 @@ import urlparse
 
 import orca.braille as braille
 import orca.debug as debug
-import orca.default as default
+import orca.scripts.default as default
 import orca.eventsynthesizer as eventsynthesizer
 import orca.input_event as input_event
 import orca.keybindings as keybindings
@@ -299,6 +299,8 @@ class Script(default.Script):
             _settingsManager.getSetting('allTextAttributes')
         _settingsManager.setSetting('allTextAttributes', self.allTextAttributes)
 
+        default.Script.activate(self)
+
     def deactivate(self):
         """Called when this script is deactivated."""
         _settingsManager.setSetting('enabledBrailledTextAttributes',
@@ -308,6 +310,8 @@ class Script(default.Script):
         _settingsManager.setSetting('allTextAttributes',
                                     self.savedAllTextAttributes)
 
+        default.Script.deactivate(self)
+
     def getBookmarks(self):
         """Returns the "bookmarks" class for this script.
         """
@@ -1260,7 +1264,7 @@ class Script(default.Script):
             locusOfFocusState = pyatspi.StateSet()
             locusOfFocusState = locusOfFocusState.raw()
 
-        notifyPresentationManagers = False
+        notify = False
 
         # Find out if the caret really moved. Firefox 3.1 gives us caret-moved
         # events when certain focusable objects first get focus. If we haven't
@@ -1317,7 +1321,7 @@ class Script(default.Script):
                         if uriInfo and not uriInfo[5]:
                             return
                         else:
-                            notifyPresentationManagers = True
+                            notify = True
                 elif eventSourceRole == pyatspi.ROLE_SECTION:
                     # Google Calendar's Day grid seems to issue these quite
                     # a bit. If we don't ignore them, we'll loop.
@@ -1359,11 +1363,8 @@ class Script(default.Script):
             else:
                 [obj, characterOffset] = [event.source, event.detail1]
             self.setCaretContext(obj, characterOffset)
-            orca.setLocusOfFocus(
-                event,
-                obj,
-                notifyPresentationManager=notifyPresentationManagers)
-            if notifyPresentationManagers:
+            orca.setLocusOfFocus(event, obj, notifyScript=notify)
+            if notify:
                 # No point in double-brailling the locusOfFocus.
                 #
                 return
@@ -1619,8 +1620,7 @@ class Script(default.Script):
             if not self.utilities.isSameObject(event.source, obj):
                 if not self.utilities.isSameObject(
                         obj, orca_state.locusOfFocus):
-                    orca.setLocusOfFocus(
-                        event, obj, notifyPresentationManager=False)
+                    orca.setLocusOfFocus(event, obj, notifyScript=False)
                     # If an alert got focus, let's do the best we can to 
                     # try to automatically speak its contents while also
                     # making sure the locus of focus and caret context
@@ -1697,7 +1697,7 @@ class Script(default.Script):
            and not self.isAriaWidget(event.source) \
            and not isinstance(orca_state.lastInputEvent,
                               input_event.MouseButtonEvent):
-            orca.visualAppearanceChanged(event, event.source)
+            self.visualAppearanceChanged(event, event.source)
             return
 
         # If an autocomplete appears beneath an entry, we don't want
@@ -1918,8 +1918,7 @@ class Script(default.Script):
 
         if (obj.getRole() == pyatspi.ROLE_CHECK_BOX) \
             and obj.getState().contains(pyatspi.STATE_FOCUSED):
-            orca.setLocusOfFocus(
-                event, obj, notifyPresentationManager=False)
+            orca.setLocusOfFocus(event, obj, notifyScript=False)
 
         default.Script.visualAppearanceChanged(self, event, obj)
 
@@ -5441,8 +5440,7 @@ class Script(default.Script):
         # Reset focus if need be.
         #
         if obj != orca_state.locusOfFocus:
-            orca.setLocusOfFocus(
-                None, obj, notifyPresentationManager=False)
+            orca.setLocusOfFocus(None, obj, notifyScript=False)
 
             # We'd like the object to have focus if it can take focus.
             # Otherwise, we bubble up until we find a parent that can
diff --git a/src/orca/scripts/toolkits/J2SE-access-bridge/script.py b/src/orca/scripts/toolkits/J2SE-access-bridge/script.py
index e0a1798..6b14345 100644
--- a/src/orca/scripts/toolkits/J2SE-access-bridge/script.py
+++ b/src/orca/scripts/toolkits/J2SE-access-bridge/script.py
@@ -27,7 +27,7 @@ __license__   = "LGPL"
 
 import pyatspi
 
-import orca.default as default
+import orca.scripts.default as default
 import orca.input_event as input_event
 import orca.orca as orca
 import orca.orca_state as orca_state
@@ -169,14 +169,14 @@ class Script(default.Script):
         # and keep focus on the combobox.
         #
         if event.source.getRole() == pyatspi.ROLE_COMBO_BOX:
-            orca.visualAppearanceChanged(event, event.source)
+            self.visualAppearanceChanged(event, event.source)
             return
 
         if event.source.getRole() == pyatspi.ROLE_LIST:
             combobox = self.utilities.ancestorWithRole(
                 event.source, [pyatspi.ROLE_COMBO_BOX], [pyatspi.ROLE_PANEL])
             if combobox:
-                orca.visualAppearanceChanged(event, combobox)
+                self.visualAppearanceChanged(event, combobox)
                 return
 
         default.Script.onActiveDescendantChanged(self, event)
@@ -249,7 +249,7 @@ class Script(default.Script):
         #
         if (event.source.getRole() == pyatspi.ROLE_LABEL) and \
             event.type.startswith("object:state-changed:expanded"):
-            orca.visualAppearanceChanged(event, event.source)
+            self.visualAppearanceChanged(event, event.source)
             return
 
         # This is a workaround for a java-access-bridge bug (Bug 355011)
diff --git a/src/orca/scripts/toolkits/VCL.py b/src/orca/scripts/toolkits/VCL.py
index e1545b8..2fd136d 100644
--- a/src/orca/scripts/toolkits/VCL.py
+++ b/src/orca/scripts/toolkits/VCL.py
@@ -25,7 +25,7 @@ __date__      = "$Date$"
 __copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import orca.default
+import orca.scripts.default
 
 class Script(orca.default.Script):
     pass
diff --git a/src/orca/scripts/toolkits/WebKitGtk/script.py b/src/orca/scripts/toolkits/WebKitGtk/script.py
index 1222d81..1489c04 100644
--- a/src/orca/scripts/toolkits/WebKitGtk/script.py
+++ b/src/orca/scripts/toolkits/WebKitGtk/script.py
@@ -27,7 +27,7 @@ __license__   = "LGPL"
 
 import pyatspi
 
-import orca.default as default
+import orca.scripts.default as default
 import orca.orca as orca
 import orca.orca_state as orca_state
 import orca.speech as speech
diff --git a/src/orca/scripts/toolkits/__init__.py b/src/orca/scripts/toolkits/__init__.py
index e69de29..53d6887 100644
--- a/src/orca/scripts/toolkits/__init__.py
+++ b/src/orca/scripts/toolkits/__init__.py
@@ -0,0 +1,6 @@
+__all__ = ['CALLY',
+           'GAIL.py',
+           'Gecko',
+           'J2SE-access-bridge',
+           'VCL.py',
+           'WebKitGtk']
diff --git a/src/orca/settings.py b/src/orca/settings.py
index 9c1e8e4..0e019e9 100644
--- a/src/orca/settings.py
+++ b/src/orca/settings.py
@@ -28,7 +28,6 @@ __copyright__ = "Copyright (c) 2004-2009 Sun Microsystems Inc."
 __license__   = "LGPL"
 
 import os
-import re
 
 screenWidth = 640
 screenHeight = 480
@@ -79,7 +78,6 @@ except:
 
 import pyatspi
 
-import debug
 from acss import ACSS
 from orca_i18n import _           # for gettext support
 from orca_i18n import C_          # to provide qualified translatable strings
@@ -1045,194 +1043,6 @@ def overrideKeyBindings(script, keyBindings):
 def overridePronunciations(script, pronunciations):
     return pronunciations
 
-# Which packages to search, and the order in which to search,
-# for application settings.  These packages are expected to be on
-# the PYTHONPATH and/or subpackages of the "orca" package.
-# REMEMBER: to make something a package, the directory has to
-# have a __init__.py file in it.
-#
-settingsPackages          = ["app-settings"]
-
-# Which packages to search, and the order in which to search,
-# for custom scripts.  These packages are expected to be on
-# the PYTHONPATH and/or subpackages of the "orca" package.
-# REMEMBER: to make something a package, the directory has to
-# have a __init__.py file in it.
-#
-scriptPackages          = ["orca-scripts", "scripts",
-                           "scripts.apps", "scripts.toolkits"]
-
-# A list that helps us map application names to script module
-# names.  The key is the name of an application, and the value is
-# the name of a script module.  There are some default values here,
-# but one may call the setScriptMapping method of this module to
-# extend or override any mappings.
-#
-_scriptMappings = []
-
-def setScriptMapping(regExpression, moduleName):
-    """Tells this module what script module to look for a given
-    application name.  The mappings are stored as a list and each
-    new mapping is added to the beginning of the list, meaning it
-    takes precedence over all other mappings.
-
-    Arguments:
-    - regExpression: a regular expression used to match against an
-                     application name
-    - moduleName:    the name of the Python module containing the script
-                     class definition for the application
-    """
-
-    _scriptMappings.insert(0, [regExpression, moduleName])
-
-def getScriptModuleName(app):
-    """Returns the module name of the script to use for a given
-    application.  Any script mapping set via the setScriptMapping
-    method is searched first, with the ultimate fallback being the
-    name of the application itself.
-
-    Arguments:
-    - app: the application to find a script module name for
-    """
-
-    if not app.name:
-        return None
-
-    for mapping in _scriptMappings:
-        regExpression = mapping[0]
-        moduleName = mapping[1]
-        if regExpression.match(app.name):
-            debug.println(
-                debug.LEVEL_FINEST,
-                "Script mapping for %s is %s" % (app.name, moduleName))
-            return moduleName
-
-    return app.name
-
-# Translators: the regular expression here represents a string to
-# match in the localized application name as seen by at-poke.  For
-# most cases, the application name is the name of the binary used to
-# start the application, but this is an unreliable assumption.  The
-# only reliable way to do the translation is by running the
-# application and then viewing its name in the main window of at-poke.
-# I wish the AT-SPI spec'd this out as machine readable (unlocalized)
-# names, but it's what we're stuck with (unfortunately).
-#
-setScriptMapping(re.compile(_('[\S\s]*StarOffice[\s\S]*')), "soffice")
-
-# Translators: see the regular expression note above.  This is for
-# OpenOffice and StarOffice.
-#
-setScriptMapping(re.compile(_('soffice.bin')), "soffice")
-
-# Translators: see the regular expression note above.  This is for
-# OpenOffice and StarOffice.
-#
-setScriptMapping(re.compile(_('soffice')), "soffice")
-
-# Translators: see the regular expression note above.  This is for the
-# Evolution mail application.
-#
-setScriptMapping(re.compile(_('[Ee]volution')), "evolution")
-
-# Translators: see the regular expression note above.  This is for a
-# version of Mozilla Firefox, which chooses to create strange names
-# for itself at the drop of a hat.
-#
-setScriptMapping(re.compile(_('Deer Park')), "Mozilla")
-
-# Translators: see the regular expression note above.  This is for a
-# version of Mozilla Firefox, which chooses to create strange names
-# for itself at the drop of a hat.
-#
-setScriptMapping(re.compile(_('Bon Echo')), "Mozilla")
-
-# Translators: see the regular expression note above.  This is for a
-# version of Mozilla Firefox, which chooses to create strange names
-# for itself at the drop of a hat.
-#
-setScriptMapping(re.compile(_('Minefield')), "Mozilla")
-
-# Translators: see the regular expression note above.  This is for a
-# version of Mozilla Firefox, which chooses to create strange names
-# for itself at the drop of a hat. [[[TODO - JD: Not marked for
-# translation due to string freeze. I'm not convinced it needs to
-# be translated either.]]]
-#
-#setScriptMapping(re.compile(_('Shiretoko')), "Mozilla")
-setScriptMapping(re.compile('Shiretoko'), "Mozilla")
-
-setScriptMapping(re.compile('Namoroka'), "Mozilla")
-
-# This is a temporary fix for the schema/FF 3.0 not being accessible
-# issue. (See GNOME bugs #535827 and #555466.)
-#
-setScriptMapping(re.compile('[Ff]irefox'), "Mozilla")
-
-# Translators: see the regular expression note above.  This is for a
-# version of Thunderbird, which chooses to now call itself by a different
-# name.
-#
-#setScriptMapping(re.compile(_('Shredder')), "Thunderbird")
-#
-# Don't localize this. It seems to be messing us up. See bug 584103.
-#
-setScriptMapping(re.compile('Shredder'), "Thunderbird")
-
-# Translators: see the regular expression note above.  This is for
-# the Thunderbird e-mail application.
-#
-setScriptMapping(re.compile(_('Mail/News')), "Thunderbird")
-
-# This is for a 3.1 version of Thunderbird, which chooses to now call itself
-# by a different name, Lanikai.
-setScriptMapping(re.compile('Lanikai'), "Thunderbird")
-
-# This is for a 3.3 version of Thunderbird, which chooses to now call itself
-# by a different name, Miramar.
-setScriptMapping(re.compile('Miramar'), "Thunderbird")
-
-# Translators: see the regular expression note above.  This is for
-# gnome_segv2, which calls itself bug-buddy in at-poke.
-#
-setScriptMapping(re.compile(_('bug-buddy')), "gnome_segv2")
-
-# Translators: see the regular expression note above.  This is for
-# the underlying terminal support in gnome-terminal.
-#
-setScriptMapping(re.compile(_('vte')), "gnome-terminal")
-
-# Translators: see the regular expression note above.  This is for
-# supporting gaim, which has recently be renamed to pidgin.
-#
-setScriptMapping(re.compile(_('gaim')), "pidgin")
-setScriptMapping(re.compile('Pidgin'), "pidgin")
-
-# Translators: see the regular expression note above.  This is for
-# supporting yelp, which sometimes identifies itself as gnome-help.
-# [[[TODO - JD: Not marked for translation due to string freeze,
-# plus gnome-help doesn't translate its app name as far as we can
-# determine.  So, translating this string really seems like extra
-# busy work for our translators.]]]
-#
-#setScriptMapping(re.compile(_('gnome-help')), "yelp")
-setScriptMapping(re.compile('gnome-help'), "yelp")
-
-# Gnome-calculator is symbolically linked to gcalctool so we associate it here.
-setScriptMapping(re.compile('gnome-calculator'), "gcalctool")
-
-# This is for development builds of Banshee
-setScriptMapping(re.compile('Nereid'), "Banshee")
-
-# Strip off the extra 'py' that the Device Driver Utility includes
-# as part of its accessible name.
-#
-setScriptMapping(re.compile('ddu.py'), "ddu")
-
-# Strip off the extra 'py' that Gajim includes as part of its name.
-#
-setScriptMapping(re.compile('gajim.py'), "gajim")
-
 # Show deprecated messeges in debug output.
 # Set this to True to help find potential pyatspi porting problems
 #
@@ -1243,11 +1053,6 @@ deprecatedMessages = False
 #
 focusHistoryLength = 5
 
-# Listen to all AT-SPI events, regardless to if we are using them or not.
-# This is useful for development and debugging.
-#
-listenAllEvents = False
-
 # This is a list of events that Orca should immidiately drop and never look at.
 #
 ignoredEventsList = ['object:bounds-changed']
diff --git a/src/orca/settings_manager.py b/src/orca/settings_manager.py
index f59c16a..4207fcd 100644
--- a/src/orca/settings_manager.py
+++ b/src/orca/settings_manager.py
@@ -120,6 +120,10 @@ class SettingsManager(object):
             self.profile = self.general.get('startingProfile')[1]
         self.setProfile(self.profile)
 
+        # For handling the currently-"classic" application settings
+        self._settingsPackages = ["app-settings"]
+        self._knownAppSettings = {}
+
     def _loadBackend(self):
         """Load specific backend for manage user settings"""
 
@@ -472,6 +476,59 @@ class SettingsManager(object):
         self.saveSettings(general, pronunciations, keybindings)
         return True
 
+    def loadAppSettings(self, script):
+        """Load the users application specific settings for an app.
+        Note that currently the settings manager does not manage
+        application settings in Orca; instead the old/"classic" files
+        are used. This is scheduled to change.
+
+        Arguments:
+        - script: the current active script.
+        """
+
+        import orca
+        _scriptManager = getattr(orca, '_scriptManager')
+
+        app = script.app
+        moduleName = _scriptManager.getModuleName(app)
+        if not moduleName:
+            return
+
+        module = None
+        for package in self._settingsPackages:
+            name = '.'.join((package, moduleName))
+            debug.println(debug.LEVEL_FINEST, "Looking for %s.py" % name)
+            try:
+                module = __import__(name, globals(), locals(), [''])
+            except ImportError:
+                debug.println(
+                    debug.LEVEL_FINEST, "Could not import %s.py" % name)
+                continue
+            try:
+                reload(module)
+            except:
+                debug.println(debug.LEVEL_FINEST, "Could not load %s.py" % name)
+                module = None
+            else:
+                debug.println(debug.LEVEL_FINEST, "Loaded %s.py" % name)
+                break
+
+        if not module:
+            return
+
+        self._knownAppSettings[name] = module
+
+        keybindings = getattr(module, 'overrideAppKeyBindings', None)
+        if keybindings:
+            script.overrideAppKeyBindings = keybindings
+            script.keyBindings = keybindings(script, script.keyBindings)
+
+        pronunciations = getattr(module, 'overridePronunciations', None)
+        if pronunciations:
+            script.overridePronunciations = pronunciations
+            script.app_pronunciation_dict = \
+                pronunciations(script, script.app_pronunciation_dict)
+
 def getVoiceKey(voice):
     voicesKeys = getattr(settings, 'voicesKeys')
     for key in voicesKeys.keys():
diff --git a/src/orca/structural_navigation.py b/src/orca/structural_navigation.py
index f6b3574..cc99609 100644
--- a/src/orca/structural_navigation.py
+++ b/src/orca/structural_navigation.py
@@ -1781,7 +1781,7 @@ class StructuralNavigation:
         except:
             debug.printException(debug.LEVEL_SEVERE)
 
-        orca.setLocusOfFocus(None, obj, notifyPresentationManager=False)
+        orca.setLocusOfFocus(None, obj, notifyScript=False)
 
     def _presentLine(self, obj, offset):
         """Presents the first line of the object to the user.



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]