[orca/orca-gnome3: 73/87] Working gsmag and mag as plugins



commit 3cc904e588871b14cf2edad3398e31c083096353
Author: José Ignacio �lvarez Ruiz <jialvarez emergya es>
Date:   Wed Mar 30 23:47:08 2011 +0200

    Working gsmag and mag as plugins

 src/orca/baseplugins/Makefile.am |    2 +
 src/orca/baseplugins/gsmag.py    |  882 +++++++++++++++++++
 src/orca/baseplugins/mag.py      | 1809 ++++++++++++++++++++++++++++++++++++++
 src/orca/orca.py                 |   54 +-
 src/orca/orca_gui_prefs.py       |   68 ++-
 5 files changed, 2804 insertions(+), 11 deletions(-)
---
diff --git a/src/orca/baseplugins/Makefile.am b/src/orca/baseplugins/Makefile.am
index 5286ace..b2e358d 100644
--- a/src/orca/baseplugins/Makefile.am
+++ b/src/orca/baseplugins/Makefile.am
@@ -2,6 +2,8 @@ orca_pathdir=$(pyexecdir)
 
 orca_python_PYTHON = \
         dateandtime.py \
+	gsmag.py \
+	mag.py \
 	speech.py
 
 orca_pythondir=$(pyexecdir)/orca/baseplugins
diff --git a/src/orca/baseplugins/gsmag.py b/src/orca/baseplugins/gsmag.py
new file mode 100644
index 0000000..635eff2
--- /dev/null
+++ b/src/orca/baseplugins/gsmag.py
@@ -0,0 +1,882 @@
+# Orca
+#
+# Copyright 2011 Consorcio Fernando de los Rios.
+# Author: J. Ignacio Alvarez <jialvarez emergya es>
+#
+# 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.
+
+"""Plugin that implements the GNOME Shell magnifier"""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2011 Consorcio Fernando de los Rios."
+__license__   = "LGPL"
+
+from orca.pluglib.interfaces import IPluginManager, IPlugin, ICommand, \
+    IPresenter, IConfigurable, IDependenciesChecker, PluginManagerError
+
+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
+
+import orca.input_event
+import orca.keybindings
+ 
+import time
+
+class gsMagPlugin(IPlugin, IPresenter, ICommand):
+    name = 'GNOME Shell Magnifier'
+    description = 'Enable the GNOME Shell magnifier to mag screen' 
+    version = '0.9'
+    authors = ['J. Ignacio Alvarez <jialvarez emergya es>']
+    website = 'http://www.emergya.es'
+    icon = 'gtk-missing-image'
+
+    def __init__(self):
+        pass
+
+    def enable(self):
+        print 'GNOME Shell Magnifier plugin started'
+
+        import dbus
+        self._bus = dbus.SessionBus()
+        _proxy_obj = self._bus.get_object("org.gnome.Magnifier",
+                                     "/org/gnome/Magnifier")
+        self._magnifier = dbus.Interface(_proxy_obj, "org.gnome.Magnifier")
+        self._zoomer = None
+       
+        global orca
+        global debug
+        global eventsynthesizer
+        global settings
+        global orca_state
+        global gconf
+        global _
+
+        import orca.orca as orca
+        import orca.debug as debug
+        import orca.eventsynthesizer as eventsynthesizer
+        import orca.settings as settings
+        import orca.orca_state as orca_state
+        import gconf
+        
+        from orca.orca_i18n import _
+        
+        # Some GConf settings that gs-mag uses
+        #
+        global A11Y_MAG_PREFS_DIR
+        global MOUSE_MODE_KEY
+        global GS_MAG_NONE
+        global GS_MAG_CENTERED
+        global GS_MAG_PUSH
+        global GS_MAG_PROPORTIONAL
+        global CROSSHAIRS_SHOW_KEY
+
+        A11Y_MAG_PREFS_DIR  = "/desktop/gnome/accessibility/magnifier"
+        MOUSE_MODE_KEY      = A11Y_MAG_PREFS_DIR + "/mouse_tracking"
+        GS_MAG_NONE         = 0
+        GS_MAG_CENTERED     = 1
+        GS_MAG_PUSH         = 2
+        GS_MAG_PROPORTIONAL = 3
+        CROSSHAIRS_SHOW_KEY = A11Y_MAG_PREFS_DIR + "/show_cross_hairs"
+        
+        self._gconfClient = gconf.client_get_default()
+        
+        # If True, the magnifier is active
+        #
+        self._isActive = False
+        
+        # Whether or not we're in the process of making "live update" changes
+        # to the location of the magnifier.
+        #
+        self._liveUpdatingMagnifier = False
+        
+        # The current modes of tracking, for use with "live update" changes.
+        #
+        self._controlTracking = None
+        self._edgeMargin = None
+        self._mouseTracking = None
+        self._pointerFollowsZoomer = None
+        self._pointerFollowsFocus = None
+        self._textTracking = None
+       
+        global gtk
+        import gtk
+        _display = gtk.gdk.display_get_default()
+        _screen = _display.get_default_screen()
+        self._screenWidth = _screen.get_width()
+        self._screenHeight = _screen.get_height()
+        
+        # If True, this module has been initialized.
+        #
+        self._initialized = False
+        self._fullScreenCapable = False
+        self._wasActiveOnInit = False
+        self._crossHairsShownOnInit = False
+        
+        # The width and height, in unzoomed system coordinates of the rectangle that,
+        # when magnified, will fill the viewport of the magnifier - this needs to be
+        # sync'd with the magnification factors of the zoom area.
+        #
+        self._roiWidth = 0
+        self._roiHeight = 0
+        
+        # The current region of interest as specified by the upper left corner.
+        #
+        _roi = None
+        
+        # Minimum/maximum values for the center of the ROI
+        # in source screen coordinates.
+        #
+        self._minROIX = 0
+        self._maxROIX = 0
+        self._minROIY = 0
+        self._maxROIY = 0
+
+        _settingsManager = getattr(orca, '_settingsManager')
+
+        plugins = _settingsManager.getPlugins(_settingsManager.getSetting('activeProfile')[1])
+        print 'estoy en el enable del gsmag y plugins = ', plugins
+
+        self.isActive = plugins['gsmag']['active']
+
+        settings.enableMagnifier = True
+        self.shutdown()
+        self.init()
+
+    ########################################################################
+    #                                                                      #
+    # Methods for magnifying objects                                       #
+    #                                                                      #
+    ########################################################################
+    
+    def _setROICenter(self, x, y):
+        """Centers the region of interest around the given point.
+    
+        Arguments:
+        - x: integer in unzoomed system coordinates representing x component
+        - y: integer in unzoomed system coordinates representing y component
+        """
+        self._zoomer.shiftContentsTo(x, y)
+    
+    def _setROICursorPush(self, x, y, width, height, edgeMargin = 0):
+        """Nudges the ROI if the caret or control is not visible.
+    
+        Arguments:
+        - x: integer in unzoomed system coordinates representing x component
+        - y: integer in unzoomed system coordinates representing y component
+        - width: integer in unzoomed system coordinates representing the width
+        - height: integer in unzoomed system coordinates representing the height
+        - edgeMargin: a percentage representing how close to the edge we can get
+                      before we need to push
+        """
+    
+        # The edge margin should not exceed 50%. (50% is a centered alignment).
+        # [[[WDW - probably should not make a D-Bus call each time.]]]
+        #
+        edgeMargin = min(edgeMargin, 50)/100.00
+        edgeMarginX = edgeMargin * self._screenWidth/settings.magZoomFactor
+        edgeMarginY = edgeMargin * self._screenHeight/settings.magZoomFactor
+    
+        # Determine if the accessible is partially to the left, right,
+        # above, or below the current region of interest (ROI).
+        # [[[WDW - probably should not make a D-Bus call each time.]]]
+        #
+        [roiLeft, roiTop, roiRight, roiBottom] = self._zoomer.getRoi()
+        roiWidth = roiRight - roiLeft
+        roiHeight = roiBottom - roiTop
+        leftOfROI = (x - edgeMarginX) <= roiLeft
+        rightOfROI = (x + width + edgeMarginX) >= (roiLeft + roiWidth)
+        aboveROI = (y - edgeMarginY)  <= roiTop
+        belowROI = (y + height + edgeMarginY) >= (roiTop + roiHeight)
+    
+        # The algorithm is devised to move the ROI as little as possible, yet
+        # favor the top left side of the object [[[TODO: WDW - the left/right
+        # top/bottom favoring should probably depend upon the locale.  Also,
+        # I had the notion of including a floating point snap factor between
+        # 0.0 and 1.0 that would determine how to position the object in the
+        # window relative to the ROI edges.  A snap factor of -1 would mean to
+        # snap to the closest edge.  A snap factor of 0.0 would snap to the
+        # left most or top most edge, a snap factor of 1.0 would snap to the
+        # right most or bottom most edge.  Any number in between would divide
+        # the two.]]]
+        #
+        x1 = roiLeft
+        x2 = roiLeft + roiWidth
+        y1 = roiTop
+        y2 = roiTop + roiHeight
+    
+        if leftOfROI:
+            x1 = max(0, x - edgeMarginX)
+            x2 = x1 + roiWidth
+        elif rightOfROI:
+            x = min(self._screenWidth, x + edgeMarginX)
+            if width > roiWidth:
+                x1 = x
+                x2 = x1 + roiWidth
+            else:
+                x2 = x + width
+                x1 = x2 - roiWidth
+    
+        if aboveROI:
+            y1 = max(0, y - edgeMarginY)
+            y2 = y1 + roiHeight
+        elif belowROI:
+            y = min(self._screenHeight, y + edgeMarginY)
+            if height > roiHeight:
+                y1 = y
+                y2 = y1 + roiHeight
+            else:
+                y2 = y + height
+                y1 = y2 - roiHeight
+    
+        self._setROICenter((x1 + x2) / 2, (y1 + y2) / 2)
+    
+    def magnifyAccessible(self, event, obj, extents=None):
+        """Sets the region of interest to the upper left of the given
+        accessible, if it implements the Component interface.  Otherwise,
+        does nothing.
+    
+        Arguments:
+        - event: the Event that caused this to be called
+        - obj: the accessible
+        """
+        if not self._initialized:
+            return
+    
+        haveSomethingToMagnify = False
+    
+        if extents:
+            [x, y, width, height] = extents
+            haveSomethingToMagnify = True
+        elif event and event.type.startswith("object:text-caret-moved"):
+            try:
+                text = obj.queryText()
+                if text and (text.caretOffset >= 0):
+                    offset = text.caretOffset
+                    if offset == text.characterCount:
+                        offset -= 1
+                    [x, y, width, height] = \
+                        text.getCharacterExtents(offset, 0)
+                    haveSomethingToMagnify = (width + height > 0)
+            except:
+                haveSomethingToMagnify = False
+    
+            if haveSomethingToMagnify:
+                if self._textTracking == settings.MAG_TRACKING_MODE_CENTERED:
+                    self._setROICenter(x, y)
+                elif self._textTracking == settings.MAG_TRACKING_MODE_PUSH:
+                    self._setROICursorPush(x, y, width, height, self._edgeMargin)
+                return
+    
+        if not haveSomethingToMagnify:
+            try:
+                extents = obj.queryComponent().getExtents(0)
+                [x, y, width, height] = \
+                    [extents.x, extents.y, extents.width, extents.height]
+                haveSomethingToMagnify = True
+            except:
+                haveSomethingToMagnify = False
+    
+        if haveSomethingToMagnify:
+            if self._pointerFollowsFocus:
+                _lastMouseEventWasRoute = True
+                eventsynthesizer.generateMouseEvent(x, y + height - 1, "abs")
+    
+            if self._controlTracking == settings.MAG_TRACKING_MODE_CENTERED:
+                centerX = x + width/2
+                centerY = y + height/2
+    
+                # Be sure that the upper-left corner of the object will still
+                # be visible on the screen.
+                # [[[WDW - probably should not make a getRoi call each time]]]
+                #
+                [roiLeft, roiTop, roiRight, roiBottom] = self._zoomer.getRoi()
+                roiWidth = roiRight - roiLeft
+                roiHeight = roiBottom - roiTop
+                if width > roiWidth:
+                    centerX = x
+                if height > roiHeight:
+                    centerY = y
+    
+                self._setROICenter(centerX, centerY)
+            elif self._controlTracking == settings.MAG_TRACKING_MODE_PUSH:
+                self._setROICursorPush(x, y, width, height)
+    
+    ########################################################################
+    #                                                                      #
+    # Methods for updating live tracking settings                          #
+    #                                                                      #
+    ########################################################################
+    
+    def updateControlTracking(self, newMode):
+        """Updates the control tracking mode.
+    
+        Arguments:
+        -newMode: The new mode to use.
+        """
+        self._controlTracking = newMode
+        
+    def updateEdgeMargin(self, amount):
+        """Updates the edge margin
+    
+        Arguments:
+        -amount: The new margin to use, in pixels.
+        """
+        self._edgeMargin = amount
+    
+    def updateMouseTracking(self, newMode):
+        """Updates the mouse tracking mode.
+    
+        Arguments:
+        -newMode: The new mode to use.
+        """
+        self._mouseTracking = newMode
+    
+        # Comparing Orca and GS-mag, modes are the same, but different values:
+        # Orca:  centered=0, proportional=1, push=2, none=3
+        # GS-mag: none=0, centered=1, push=2, proportional=3
+        # Use Orca's values as index into following array (hack).
+        #
+        gsMagModes = \
+            [GS_MAG_CENTERED, GS_MAG_PROPORTIONAL, GS_MAG_PUSH, GS_MAG_NONE]
+        self._gconfClient.set_int(MOUSE_MODE_KEY, gsMagModes[newMode])
+    
+    def updatePointerFollowsFocus(self, enabled):
+        """Updates the pointer follows focus setting.
+    
+        Arguments:
+        -enabled: whether or not pointer follows focus should be enabled.
+        """
+        self._pointerFollowsFocus = enabled
+    
+    def updatePointerFollowsZoomer(self, enabled):
+        """Updates the pointer follows zoomer setting.
+    
+        Arguments:
+        -enabled: whether or not pointer follows zoomer should be enabled.
+        """
+        self._pointerFollowsZoomer = enabled
+    
+    def updateTextTracking(self, newMode):
+        """Updates the text tracking mode.
+    
+        Arguments:
+        -newMode: The new mode to use.
+        """
+        self._textTracking = newMode
+    
+    def finishLiveUpdating(self):
+        """Restores things that were altered via a live update."""
+    
+        self._liveUpdatingMagnifier = False
+        self._mouseTracking = settings.magMouseTrackingMode
+        self._controlTracking = settings.magControlTrackingMode
+        self._textTracking = settings.magTextTrackingMode
+        self._edgeMargin = settings.magEdgeMargin
+        self._pointerFollowsFocus = settings.magPointerFollowsFocus
+        self._pointerFollowsZoomer = settings.magPointerFollowsZoomer
+    
+        if settings.enableMagnifier:
+            self.setupMagnifier(settings.magZoomerType)
+            self.init()
+        else:
+            self.shutdown()
+    
+    ########################################################################
+    #                                                                      #
+    # Methods for updating appearance settings                             #
+    #                                                                      #
+    ########################################################################
+    
+    def applySettings(self):
+        """Looks at the user settings and applies them to the magnifier."""
+        self.__setupMagnifier(settings.magZoomerType)
+        self.__setupZoomer(settings.magZoomerType)
+    
+        self._mouseTracking = settings.magMouseTrackingMode
+        self._controlTracking = settings.magControlTrackingMode
+        self._textTracking = settings.magTextTrackingMode
+        self._edgeMargin = settings.magEdgeMargin
+        self._pointerFollowsZoomer = settings.magPointerFollowsZoomer
+        self._pointerFollowsFocus = settings.magPointerFollowsFocus
+    
+    def hideSystemPointer(self, hidePointer):
+        """Hide or show the system pointer.
+    
+        Arguments:
+        -hidePointer: If True, hide the system pointer, otherwise show it.
+        """
+        try:
+            if hidePointer:
+                self._magnifier.hideCursor()
+            else:
+                self._magnifier.showCursor()
+        except:
+            debug.printException(debug.LEVEL_FINEST)
+    
+    def __setupMagnifier(self, position, restore=None):
+        """Creates the magnifier in the position specified.
+    
+        Arguments:
+        - position: the position/type of zoomer (full, left half, etc.)
+        - restore:  a dictionary of all of the settings which should be restored
+        """
+
+        if not restore:
+            restore = {}
+    
+        # Find out if we're using composite.
+        #
+        try:
+            self._fullScreenCapable = self._magnifier.fullScreenCapable()
+        except:
+            debug.printException(debug.LEVEL_WARNING)
+    
+        # If we are running in full screen mode, try to hide the original cursor
+        # (assuming the user wants to). See bug #533095 for more details.
+        # Depends upon new functionality in gnome-mag, so just catch the
+        # exception if this functionality isn't there.
+        #
+        hideCursor = restore.get('magHideCursor', settings.magHideCursor)
+        if hideCursor \
+           and self._fullScreenCapable \
+           and position == settings.MAG_ZOOMER_TYPE_FULL_SCREEN:
+            self.hideSystemPointer(True)
+        else:
+            self.hideSystemPointer(False)
+    
+        orca_state.zoomerType = position
+        updateTarget = True
+    
+        value = restore.get('magCrossHairColor', settings.magCrossHairColor)
+        self.setMagnifierObjectColor("crosswire-color", value, False)
+    
+        enableCrossHair = restore.get('enableMagCrossHair',
+                                      settings.enableMagCrossHair)
+        self.setMagnifierCrossHair(enableCrossHair, False)
+    
+        value = restore.get('enableMagCrossHairClip',
+                            settings.enableMagCrossHairClip)
+        self.setMagnifierCrossHairClip(value, False)
+    
+        orca_state.mouseEnhancementsEnabled = enableCrossHair
+    
+    def __setupZoomer(self, position, left=None, top=None, right=None,
+                      bottom=None, restore=None):
+        """Creates a zoomer in the magnifier.
+        The position of the zoomer onscreen is based on the given arguments.  If
+        none are supplied, defaults to the settings for the given zoomer position.
+    
+        Arguments:
+        - position: position of the zoomer view port (top half, left half, custom)
+        - left:     left edge of zoomer's viewport (for custom -- optional)
+        - top:      top edge of zoomer's viewport (for custom -- optional)
+        - right:    right edge of zoomer's viewport (for custom -- optional)
+        - bottom:   bottom edge of zoomer's viewport (for custom -- optional)
+        - restore:  dictionary of the settings; used for zoom factor (optional)
+        """
+    
+        if not restore:
+            restore = {}
+    
+        # full screen is the default.
+        #
+        prefLeft = 0
+        prefTop = 0
+        prefRight = prefLeft + self._screenWidth
+        prefBottom = prefTop + self._screenHeight
+    
+        if position == settings.MAG_ZOOMER_TYPE_TOP_HALF:
+            prefBottom = prefTop + self._screenHeight/2
+        elif position == settings.MAG_ZOOMER_TYPE_BOTTOM_HALF:
+            prefTop = self._screenHeight/2
+            prefBottom = prefTop + self._screenHeight/2
+        elif position == settings.MAG_ZOOMER_TYPE_LEFT_HALF:
+            prefRight = prefLeft + self._screenWidth/2
+        elif position == settings.MAG_ZOOMER_TYPE_RIGHT_HALF:
+            prefLeft = self._screenWidth/2
+            prefRight = prefLeft + self._screenWidth/2
+        elif position == settings.MAG_ZOOMER_TYPE_CUSTOM:
+            prefLeft = settings.magZoomerLeft if left == None else left
+            prefTop = settings.magZoomerTop if top == None else top
+            prefRight = settings.magZoomerRight if right == None else right
+            prefBottom = settings.magZoomerBottom if bottom == None else bottom
+    
+        magFactor = restore.get('magZoomFactor', settings.magZoomFactor)
+        viewWidth = prefRight - prefLeft
+        viewHeight = prefBottom - prefTop
+        self._roiWidth = viewWidth / magFactor
+        self._roiHeight = viewHeight / magFactor
+    
+        debug.println(debug.LEVEL_ALL,
+                      "Magnifier zoomer ROI size desired: width=%d, height=%d)" \
+                      % (self._roiWidth, self._roiHeight))
+    
+        # If there are zoom regions, use the first one; otherwise create one.
+        #
+        zoomerPaths = self._magnifier.getZoomRegions()
+        if len(zoomerPaths) > 0:
+            self._zoomer = self._bus.get_object('org.gnome.Magnifier', zoomerPaths[0])
+            self._zoomer.setMagFactor(magFactor, magFactor)
+            self._zoomer.moveResize([prefLeft, prefTop, prefRight, prefBottom])
+        else:
+            zoomerPath = self._magnifier.createZoomRegion(
+                magFactor, magFactor,
+    	        [0, 0, self._roiWidth, self._roiHeight],
+    	        [prefLeft, prefTop, prefRight, prefBottom])
+            self._zoomer = self._bus.get_object('org.gnome.Magnifier', zoomerPath)
+            self._magnifier.addZoomRegion(zoomerPath)
+    
+        self.__updateROIDimensions()
+    
+    def __updateROIDimensions(self):
+        """Updates the ROI width, height, and maximum and minimum values.
+        """
+        roi = self._zoomer.getRoi()
+        self._roiWidth = roi[2] - roi[0]
+        self._roiHeight = roi[3] - roi[1]
+    
+        self._minROIX = self._roiWidth / 2
+        self._minROIY = self._roiHeight / 2
+    
+        self._maxROIX = self._screenWidth - (self._roiWidth / 2)
+        self._maxROIY = self._screenHeight - (self._roiHeight / 2)
+    
+        debug.println(debug.LEVEL_ALL,
+                      "Magnifier ROI min/max center: (%d, %d), (%d, %d)" \
+                      % (self._minROIX, self._minROIY, self._maxROIX, self._maxROIY))
+    
+    def setupMagnifier(self, position, left=None, top=None, right=None,
+                       bottom=None, restore=None):
+        """Creates the magnifier in the position specified.
+    
+        Arguments:
+        - position: the position/type of zoomer (full, left half, etc.)
+        - left:     the left edge of the zoomer (only applicable for custom)
+        - top:      the top edge of the zoomer (only applicable for custom)
+        - right:    the right edge of the zoomer (only applicable for custom)
+        - bottom:   the top edge of the zoomer (only applicable for custom)
+        - restore:  a dictionary of all of the settings that should be restored
+        """
+        self._liveUpdatingMagnifier = True
+        self.__setupMagnifier(position, restore)
+        self.__setupZoomer(position, left, top, right, bottom, restore)
+    
+    def setMagnifierCursor(self, enabled, customEnabled, size, updateScreen=True):
+        """Sets the cursor.
+    
+        Arguments:
+        - enabled:        Whether or not the cursor should be enabled
+        - customEnabled:  Whether or not a custom size has been enabled
+        - size:           The size it should be set to
+        - updateScreen:   Whether or not to update the screen
+        """
+        # [[[WDW - To be implemented]]]
+        pass
+    
+    def setMagnifierCrossHair(self, enabled, updateScreen=True):
+        """Sets the cross-hair.
+    
+        Arguments:
+        - enabled: Whether or not the cross-hair should be enabled
+        - updateScreen:  Whether or not to update the screen.
+        """
+    
+        if not self._initialized:
+            return
+    
+        size = 0
+        if enabled:
+            size = settings.magCrossHairSize
+    
+        self._magnifier.setCrosswireSize(size)
+        self._gconfClient.set_bool(CROSSHAIRS_SHOW_KEY, enabled)
+    
+    def setMagnifierCrossHairClip(self, enabled, updateScreen=True):
+        """Sets the cross-hair clip.
+    
+        Arguments:
+        - enabled: Whether or not the cross-hair clip should be enabled
+        - updateScreen:   Whether or not to update the screen (ignored)
+        """
+    
+        if not self._initialized:
+            return
+    
+        self._magnifier.setCrosswireClip(enabled)
+    
+    def setMagnifierObjectColor(self, magProperty, colorSetting, updateScreen=True):
+        """Sets the specified zoomer property to the specified color.
+    
+        Arguments:
+        - magProperty:  The property to set (as a string).  Only 'crosswire-color'.
+        - colorSetting: The Orca color setting to apply
+        - updateScreen:  Whether or not to update the screen
+        """
+    
+        colorPreference = gtk.gdk.color_parse(colorSetting)
+        # Convert the colorPreference string to something we can use.
+        # The main issue here is that the color preferences are saved
+        # as 4 byte values per color.  We only need 2 bytes, so we
+        # get rid of the bottom 8 bits.  Default 'ff' for alpha.
+        #
+        colorPreference.red   = colorPreference.red   >> 8
+        colorPreference.blue  = colorPreference.blue  >> 8
+        colorPreference.green = colorPreference.green >> 8
+        colorString = "0x%02X%02X%02Xff" \
+                      % (colorPreference.red,
+                         colorPreference.green,
+                         colorPreference.blue)
+    
+        # [[[JS - Handle only 'crosswire-color' for now]]]
+        # Shift left 8 bits to put in alpha value.
+        if magProperty == 'crosswire-color':
+            crossWireColor = int(colorString, 16)
+            self._magnifier.setCrosswireColor(crossWireColor & 0xffffffff)
+    
+        # [[[WDW - To be implemented]]]
+        else:
+            pass
+    
+    def setMagnifierObjectSize(self, magProperty, size, updateScreen=True):
+        """Sets the specified magnifier property to the specified size.
+    
+        Arguments:
+        - magProperty:   The property to set (as a string)
+        - size:          The size to apply
+        - updateScreen:  Whether or not to update the screen
+        """
+    
+        # [[[JS - Handle only 'crosswire-size' for now]]]
+        if magProperty == 'crosswire-size':
+            self._magnifier.setCrosswireSize(size)
+    
+        # [[[WDW - To be implemented]]]
+        else:
+            pass
+    
+    def setZoomerBrightness(self, red=0, green=0, blue=0, updateScreen=True):
+        """Increases/Decreases the brightness level by the specified
+        increments.  Increments are floats ranging from -1 (black/no
+        brightenss) to 1 (white/100% brightness).  0 means no change.
+    
+        Arguments:
+        - red:    The amount to alter the red brightness level
+        - green:  The amount to alter the green brightness level
+        - blue:   The amount to alter the blue brightness level
+        - updateScreen:   Whether or not to update the screen
+        """
+        # [[[WDW - To be implemented]]]
+        pass
+    
+    def setZoomerContrast(self, red=0, green=0, blue=0, updateScreen=True):
+        """Increases/Decreases the contrast level by the specified
+        increments.  Increments are floats ranging from -1 (grey/no
+        contrast) to 1 (white/back/100% contrast).  0 means no change.
+    
+        Arguments:
+        - red:    The amount to alter the red contrast level
+        - green:  The amount to alter the green contrast level
+        - blue:   The amount to alter the blue contrast level
+        - updateScreen:  Whether or not to update the screen
+        """
+        # [[[WDW - To be implemented]]]
+        pass
+    
+    def setZoomerColorFilter(self, colorFilter, updateScreen=True):
+        """Sets the zoomer's color filter.
+    
+        Arguments:
+        - colorFilter: The color filter to apply
+        - updateScreen:  Whether or not to update the screen
+        """
+        # [[[WDW - To be implemented]]]
+        pass
+    
+    def setZoomerColorInversion(self, enabled, updateScreen=True):
+        """Sets the color inversion.
+    
+        Arguments:
+        - enabled: Whether or not color inversion should be enabled
+        - updateScreen:   Whether or not to update the screen
+        """
+        # [[[WDW - To be implemented]]]
+        pass
+    
+    def setZoomerMagFactor(self, x, y, updateScreen=True):
+        """Sets the magnification level.
+    
+        Arguments:
+        - x: The horizontal magnification level
+        - y: The vertical magnification level
+        - updateScreen:  Whether or not to update the screen
+        """
+        self._zoomer.setMagFactor(x, y)
+    
+    def setZoomerObjectColor(self, magProperty, colorSetting, updateScreen=True):
+        """Sets the specified zoomer property to the specified color.
+    
+        Arguments:
+        - magProperty:  The property to set (as a string)
+        - colorSetting: The Orca color setting to apply
+        - updateScreen:  Whether or not to update the screen
+        """
+        # [[[WDW - To be implemented]]]
+        pass
+    
+    def setZoomerObjectSize(self, magProperty, size, updateScreen=True):
+        """Sets the specified zoomer property to the specified size.
+    
+        Arguments:
+        - magProperty:   The property to set (as a string)
+        - size:          The size to apply
+        - updateScreen:  Whether or not to update the screen
+        """
+        # [[[WDW - To be implemented]]]
+        pass
+    
+    def setZoomerSmoothingType(self, smoothingType, updateScreen=True):
+        """Sets the zoomer's smoothing type.
+    
+        Arguments:
+        - smoothingType: The type of smoothing to use
+        - updateScreen:  Whether or not to update the screen
+        """
+        # [[[WDW - To be implemented]]]
+        pass
+    
+    ########################################################################
+    #                                                                      #
+    # Methods for changing settings via keyboard/mouse events              #
+    #                                                                      #
+    ########################################################################
+    
+    def cycleZoomerType(self, script=None, inputEvent=None):
+        """Allows the user to cycle through the available zoomer types."""
+        # [[[WDW - To be implemented]]]
+        pass
+    
+    def decreaseMagnification(self, script=None, inputEvent=None):
+        """Decreases the magnification level."""
+        # [[[WDW - To be implemented]]]
+        pass
+    
+    def increaseMagnification(self, script=None, inputEvent=None):
+        """Increases the magnification level."""
+        # [[[WDW - To be implemented]]]
+        pass
+    
+    def toggleColorEnhancements(self, script=None, inputEvent=None):
+        """Toggles the color enhancements on/off."""
+        # [[[WDW - To be implemented]]]
+        pass
+    
+    def toggleMouseEnhancements(self, script=None, inputEvent=None):
+        """Toggles the mouse enhancements on/off."""
+        # [[[WDW - To be implemented]]]
+        pass
+    
+    def toggleMagnifier(self, script=None, inputEvent=None):
+        """Toggles the magnifier."""
+        if not self._magnifier.isActive():
+            init()
+            # Translators: this is the message spoken when a user enables the
+            # magnifier.  In addition to screen magnification, the user's
+            # preferred colors and mouse customizations are loaded.
+            #
+            orca_state.activeScript.presentMessage(_("Magnifier enabled."))
+        else:
+            shutdown()
+            # Translators: this is the message spoken when a user disables the
+            # magnifier, restoring the screen contents to their normal colors
+            # and sizes.
+            #
+            orca_state.activeScript.presentMessage(_("Magnifier disabled."))
+    
+    ########################################################################
+    #                                                                      #
+    # Methods for obtaining magnifier capabilities                         #
+    #                                                                      #
+    ########################################################################
+    
+    def isFilteringCapable(self):
+        """Returns True if we're able to take advantage of libcolorblind's color
+        filtering.
+        """
+        # [[[WDW - To be implemented]]]
+        return False
+    
+    def isFullScreenCapable(self):
+        """Returns True if we are capable of doing full screen (i.e. whether
+        composite is being used.
+        """
+        return True
+    
+    ########################################################################
+    #                                                                      #
+    # Methods for starting and stopping the magnifier                      #
+    #                                                                      #
+    ########################################################################
+    
+    def init(self):
+        """Initializes the magnifier, bringing the magnifier up on the
+        display.
+    
+        Returns True if the initialization procedure was run or False if this
+        module has already been initialized.
+        """
+        if self._initialized:
+            return False
+    
+        try:
+            self._initialized = True
+            self._wasActiveOnInit = self._magnifier.isActive()
+            self._crossHairsShownOnInit = self._gconfClient.get_bool(CROSSHAIRS_SHOW_KEY)
+            self.applySettings()
+            self._magnifier.setActive(True)
+            self._isActive = self._magnifier.isActive()
+            return True
+    
+        except:
+            self._initialized = False
+            raise
+        
+    def shutdown(self):
+        """Shuts down the magnifier module.
+        Returns True if the shutdown procedure was run or False if this
+        module has not been initialized.
+        """
+
+        #if not self._initialized:
+        #    return False
+    
+        self._magnifier.setActive(self._wasActiveOnInit)
+        self._gconfClient.set_bool(CROSSHAIRS_SHOW_KEY, self._crossHairsShownOnInit)
+        self._isActive = self._magnifier.isActive()
+        if not self._isActive:
+            self.hideSystemPointer(False)
+    
+        self._initialized = False
+        return True
+
+    def disable(self):
+        settings.enableMagnifier = False
+        self.isActive = False
+        self.shutdown()
+
+IPlugin.register(gsMagPlugin)
diff --git a/src/orca/baseplugins/mag.py b/src/orca/baseplugins/mag.py
new file mode 100644
index 0000000..46b1d7b
--- /dev/null
+++ b/src/orca/baseplugins/mag.py
@@ -0,0 +1,1809 @@
+# Orca
+#
+# Copyright 2011 Consorcio Fernando de los Rios.
+# Author: J. Ignacio Alvarez <jialvarez emergya es>
+#
+# 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.
+
+"""Plugin that implements Orca magnifier"""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2011 Consorcio Fernando de los Rios."
+__license__   = "LGPL"
+
+from orca.pluglib.interfaces import IPluginManager, IPlugin, ICommand, \
+    IPresenter, IConfigurable, IDependenciesChecker, PluginManagerError
+
+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
+
+import orca.input_event
+import orca.keybindings
+
+try:
+    # This can fail due to gtk not being available.  We want to
+    # be able to recover from that if possible.  The main driver
+    # for this is to allow "orca --text-setup" to work even if
+    # the desktop is not running.
+    #
+    import gtk
+except:
+    pass
+
+import time
+
+try:
+    global bonobo
+    global ORBit
+
+    import bonobo as bonobo
+    import ORBit as ORBit
+    ORBit.load_typelib('GNOME_Magnifier')
+    import GNOME.Magnifier
+except ImportError, v:
+    print "Exception importing GNOME Magnifier: " + str(v)
+    GNOME.Magnifier = None
+    pass
+
+class magPlugin(IPlugin, IPresenter, ICommand):
+    name = 'Orca magnifier'
+    description = 'Magnify the screen' 
+    version = '0.9'
+    authors = ['J. Ignacio Alvarez <jialvarez emergya es>']
+    website = 'http://www.emergya.es'
+    icon = 'gtk-missing-image'
+
+    def __init__(self):
+        pass
+
+    def enable(self):
+
+        global pyatspi
+        global debug
+        global eventsynthesizer
+        global settings
+        global orca
+        global orca_state
+        global _
+        
+        import pyatspi
+        import orca.debug as debug
+        import orca.eventsynthesizer as eventsynthesizer
+        import orca.settings as settings
+        import orca.orca as orca
+        import orca.orca_state as orca_state
+        
+        from orca.orca_i18n import _  # for gettext support
+        
+        self._magnifierAvailable = False
+        global _settingsManager
+        _settingsManager = getattr(orca, '_settingsManager')
+
+        if GNOME.Magnifier:
+            self._magnifierAvailable = True
+        
+        # If True, this module has been initialized.
+        #
+        self._initialized = False
+        
+        # The Magnifier and its property bag
+        #
+        self._magnifier = None
+        self._magnifierPBag = None
+        
+        # The width and height, in unzoomed system coordinates of the rectangle that,
+        # when magnified, will fill the viewport of the magnifier - this needs to be
+        # sync'd with the magnification factors of the zoom area.
+        #
+        self._roiWidth = 0
+        self._roiHeight = 0
+        
+        # Minimum/maximum values for the center of the ROI
+        # in source screen coordinates.
+        #
+        self._minROIX = 0
+        self._maxROIX = 0
+        self._minROIY = 0
+        self._maxROIY = 0
+        
+        # The current region of interest.
+        #
+        # A GNOME.Magnifier.RectBounds object which consists of x1, y1, x2, y2 values
+        # that are in source screen coordinates.
+        #
+        self._roi = None
+        
+        # The area of the source display that is not covered by the magnifier.
+        #
+        # A GNOME.Magnifier.RectBounds object which consists of x1, y1, x2, y2 values
+        # that are in source screen coordinates.  If the COMPOSITE support is enabled
+        # in gnome-mag, then this typically becomes the entire source screen.  If it
+        # it not enabled, however, and the target and source displays are the same,
+        # this ends up becoming the portion of the screen that is not covered by the
+        # magnifier.
+        #
+        self._sourceDisplayBounds = None
+        
+        # The area on the target display where we are placing the magnifier.
+        #
+        # A GNOME.Magnifier.RectBounds object which consists of x1, y1, x2, y2 values
+        # that are in target screen coordinates.
+        #
+        self._targetDisplayBounds = None
+        
+        # The ZoomRegion we care about and its property bag.  We only use one
+        # ZoomRegion and we make it occupy the whole magnifier.
+        #
+        self._zoomer = None
+        self._zoomerPBag = None
+        
+        # The time of the last mouse event.
+        #
+        self._lastMouseEventTime = time.time()
+        
+        # Whether or not the last mouse event was the result of our routing the
+        # pointer.
+        #
+        self._lastMouseEventWasRoute = False
+        
+        # If True, we're using gnome-mag >= 0.13.1 that allows us to control
+        # where to draw the cursor and crosswires.
+        #
+        self._pollMouseDisabled = False
+        
+        # Whether or not composite is being used.
+        #
+        self._fullScreenCapable = True
+        
+        # Whether or not we're in the process of making "live update" changes
+        # to the location of the magnifier.
+        #
+        self._liveUpdatingMagnifier = False
+        
+        # The original source display bounds.
+        #
+        self._originalSourceDisplayBounds = None
+        
+        # The current modes of tracking, for use with "live update" changes.
+        #
+        self._mouseTracking = None
+        self._controlTracking = None
+        self._textTracking = None
+        self._edgeMargin = None
+        self._pointerFollowsZoomer = None
+        self._pointerFollowsFocus = None
+
+        _settingsManager = getattr(orca, '_settingsManager')
+
+        plugins = _settingsManager.getPlugins(_settingsManager.getSetting('activeProfile')[1])
+        print 'estoy en el enable del mag y plugins = ', plugins
+
+        self.isActive = plugins['mag']['active']
+
+        settings.enableMagnifier = True
+        self.shutdown()
+        self.init()
+        
+    def __setROI(self, rect):
+        """Sets the region of interest.
+    
+        Arguments:
+        - rect: A GNOME.Magnifier.RectBounds object.
+        """
+    
+        debug.println(debug.LEVEL_ALL, "mag.py:__setROI: (%d, %d), (%d, %d)" \
+                      % (rect.x1, rect.y1, rect.x2, rect.y2))
+    
+        self._roi = rect
+    
+        self._zoomer.setROI(self._roi)
+        self._zoomer.markDirty(self._roi)  # [[[TODO: WDW - for some reason, this seems
+                                 # necessary.]]]
+    def __setROICenter(self, x, y):
+        """Centers the region of interest around the given point.
+    
+        Arguments:
+        - x: integer in unzoomed system coordinates representing x component
+        - y: integer in unzoomed system coordinates representing y component
+        """
+    
+        if not self._initialized:
+            return
+    
+        if x < self._minROIX:
+            x = self._minROIX
+        elif x > self._maxROIX:
+            x = self._maxROIX
+    
+        if y < self._minROIY:
+            y = self._minROIY
+        elif y > self._maxROIY:
+            y = self._maxROIY
+    
+        x1 = x - (self._roiWidth / 2)
+        y1 = y - (self._roiHeight / 2)
+    
+        x2 = x1 + self._roiWidth
+        y2 = y1 + self._roiHeight
+    
+        self.__setROI(GNOME.Magnifier.RectBounds(x1, y1, x2, y2))
+    
+    def __setROIPush(self, x, y):
+        """Nudges the ROI if the pointer bumps into the edge of it.  The point
+        given is assumed to be the point where the mouse pointer is.
+    
+        Arguments:
+        - x: integer in unzoomed system coordinates representing x component
+        - y: integer in unzoomed system coordinates representing y component
+        """
+    
+        #needNewROI = False
+        newROI = GNOME.Magnifier.RectBounds(self._roi.x1, self._roi.y1, self._roi.x2, self._roi.y2)
+        if x < self._roi.x1:
+            #needNewROI = True
+            newROI.x1 = x
+            newROI.x2 = x + self._roiWidth
+        elif x > self._roi.x2:
+            #needNewROI = True
+            newROI.x2 = x
+            newROI.x1 = x - self._roiWidth
+        if y < self._roi.y1:
+            #needNewROI = True
+            newROI.y1 = y
+            newROI.y2 = y + self._roiHeight
+        elif y > self._roi.y2:
+            #needNewROI = True
+            newROI.y2 = y
+            newROI.y1 = y - self._roiHeight
+    
+        # Well...we'll always update the ROI so the new gnome-mag API
+        # will redraw the crosswires for us.
+        #
+        #if needNewROI:
+        if True:
+            self.__setROI(newROI)
+    
+    def __setROICursorPush(self, x, y, width, height, edgeMargin = 0):
+        """Nudges the ROI if the caret or control is not visible.
+    
+        Arguments:
+        - x: integer in unzoomed system coordinates representing x component
+        - y: integer in unzoomed system coordinates representing y component
+        - width: integer in unzoomed system coordinates representing the width
+        - height: integer in unzoomed system coordinates representing the height
+        - edgeMargin: a percentage representing how close to the edge we can get
+                      before we need to push
+        """
+    
+        # The edge margin should not exceed 50%. (50% is a centered alignment).
+        #
+        edgeMargin = min(edgeMargin, 50)/100.00
+        magZoomFactor = _settingsManager.getSetting('magZoomFactor')
+        edgeMarginX = edgeMargin * self._sourceDisplayBounds.x2/magZoomFactor
+        edgeMarginY = edgeMargin * self._sourceDisplayBounds.y2/magZoomFactor
+    
+        # Determine if the accessible is partially to the left, right,
+        # above, or below the current region of interest (ROI).
+        #
+        leftOfROI = (x - edgeMarginX) <= self._roi.x1
+        rightOfROI = (x + width + edgeMarginX) >= self._roi.x2
+        aboveROI = (y - edgeMarginY)  <= self._roi.y1
+        belowROI = (y + height + edgeMarginY) >= self._roi.y2
+    
+        # If it is already completely showing, do nothing.
+        #
+        visibleX = not(leftOfROI or rightOfROI)
+        visibleY = not(aboveROI or belowROI)
+        if visibleX and visibleY:
+            self._zoomer.markDirty(self._roi)
+    
+        # The algorithm is devised to move the ROI as little as possible, yet
+        # favor the top left side of the object [[[TODO: WDW - the left/right
+        # top/bottom favoring should probably depend upon the locale.  Also,
+        # I had the notion of including a floating point snap factor between
+        # 0.0 and 1.0 that would determine how to position the object in the
+        # window relative to the ROI edges.  A snap factor of -1 would mean to
+        # snap to the closest edge.  A snap factor of 0.0 would snap to the
+        # left most or top most edge, a snap factor of 1.0 would snap to the
+        # right most or bottom most edge.  Any number in between would divide
+        # the two.]]]
+        #
+        x1 = self._roi.x1
+        x2 = self._roi.x2
+        y1 = self._roi.y1
+        y2 = self._roi.y2
+    
+        if leftOfROI:
+            x1 = max(self._sourceDisplayBounds.x1, x - edgeMarginX)
+            x2 = x1 + self._roiWidth
+        elif rightOfROI:
+            x = min(self._sourceDisplayBounds.x2, x + edgeMarginX)
+            if width > self._roiWidth:
+                x1 = x
+                x2 = x1 + self._roiWidth
+            else:
+                x2 = x + width
+                x1 = x2 - self._roiWidth
+    
+        if aboveROI:
+            y1 = max(self._sourceDisplayBounds.y1, y - edgeMarginY)
+            y2 = y1 + self._roiHeight
+        elif belowROI:
+            y = min(self._sourceDisplayBounds.y2, y + edgeMarginY)
+            if height > self._roiHeight:
+                y1 = y
+                y2 = y1 + self._roiHeight
+            else:
+                y2 = y + height
+                y1 = y2 - self._roiHeight
+    
+        self.__setROI(GNOME.Magnifier.RectBounds(x1, y1, x2, y2))
+    
+    def __setROIProportional(self, x, y):
+        """Positions the ROI proportionally to where the pointer is on the screen.
+    
+        Arguments:
+        - x: integer in unzoomed system coordinates representing x component
+        - y: integer in unzoomed system coordinates representing y component
+        """
+    
+        if not self._initialized:
+            return
+    
+        if not self._sourceDisplayBounds:
+            self.__setROICenter(x, y)
+        else:
+            halfScreenWidth  = (self._sourceDisplayBounds.x2 \
+                                - self._sourceDisplayBounds.x1) / 2.0
+            halfScreenHeight = (self._sourceDisplayBounds.y2 \
+                                - self._sourceDisplayBounds.y1) / 2.0
+    
+            proportionX = (halfScreenWidth  - x) / halfScreenWidth
+            proportionY = (halfScreenHeight - y) / halfScreenHeight
+    
+            centerX = x + int(proportionX * self._roiWidth  / 2.0)
+            centerY = y + int(proportionY * self._roiHeight / 2.0)
+    
+            self.__setROICenter(centerX, centerY)
+    
+    # Used for tracking the pointer.
+    #
+    def __onMouseEvent(self, e):
+        """
+        Arguments:
+        - e: at-spi event from the at-api registry
+        """
+    
+        isNewMouseMovement = (time.time() - self._lastMouseEventTime > 1)
+        self._lastMouseEventTime = time.time()
+    
+        [x, y] = [e.detail1, e.detail2]
+    
+        if self._pointerFollowsZoomer and isNewMouseMovement \
+           and not self._lastMouseEventWasRoute:
+            mouseIsVisible = (self._roi.x1 < x < self._roi.x2) and (self._roi.y1 < y < self._roi.y2)
+            if not mouseIsVisible and orca_state.locusOfFocus:
+                if self._mouseTracking == settings.MAG_TRACKING_MODE_CENTERED:
+                    x = (self._roi.x1 + self._roi.x2) / 2
+                    y = (self._roi.y1 + self._roi.y2) / 2
+                elif self._mouseTracking != settings.MAG_TRACKING_MODE_NONE:
+                    try:
+                        extents = \
+                            orca_state.locusOfFocus.queryComponent().getExtents(0)
+                    except:
+                        extents = None
+                    if extents:
+                        x = extents.x
+                        y = extents.y + extents.height - 1
+    
+                eventsynthesizer.generateMouseEvent(x, y, "abs")
+                self._lastMouseEventWasRoute = True
+    
+        # If True, we're using gnome-mag >= 0.13.1 that allows us to
+        # control where to draw the cursor and crosswires.
+        #
+        if self._pollMouseDisabled:
+            self._zoomer.setPointerPos(x, y)
+    
+        if self._lastMouseEventWasRoute:
+            # If we just moved the mouse pointer to the menu item or control
+            # with focus, we don't want to do anything.
+            #
+            self._lastMouseEventWasRoute = False
+            self._zoomer.markDirty(self._roi)
+            return
+    
+        if self._mouseTracking == settings.MAG_TRACKING_MODE_PUSH:
+            self.__setROIPush(x, y)
+        elif self._mouseTracking == settings.MAG_TRACKING_MODE_PROPORTIONAL:
+            self.__setROIProportional(x, y)
+        elif self._mouseTracking == settings.MAG_TRACKING_MODE_CENTERED:
+            self.__setROICenter(x, y)
+    
+    def __getValueText(self, slot, value):
+        valueText = ""
+        if slot == "cursor-hotspot":
+            valueText = "(%d, %d)" % (value.x, value.y)
+        elif slot == "source-display-bounds":
+            valueText = "(%d, %d),(%d, %d)" \
+                        % (value.x1, value.y1, value.x2, value.y2)
+        elif slot == "target-display-bounds":
+            valueText = "(%d, %d),(%d, %d)" \
+                        % (value.x1, value.y1, value.x2, value.y2)
+        elif slot == "viewport":
+            valueText = "(%d, %d),(%d, %d)" \
+                        % (value.x1, value.y1, value.x2, value.y2)
+        return valueText
+    
+    def __dumpPropertyBag(self, obj):
+        pbag = obj.getProperties()
+        slots = pbag.getKeys("")
+        print "  Available slots: ", pbag.getKeys("")
+        for slot in slots:
+            # These crash the magnifier since it doesn't know how to marshall
+            # them to us.
+            #
+            if slot in ["cursor-set", "smoothing-type"]:
+                continue
+            print "    About '%s':" % slot
+            print "    Doc Title:", pbag.getDocTitle(slot)
+            print "    Type:", pbag.getType(slot)
+            value = pbag.getDefault(slot).value()
+            print "    Default value:", value, self.__getValueText(slot, value)
+            value = pbag.getValue(slot).value()
+            print "    Current value:", value, self.__getValueText(slot, value)
+            print
+    
+    def __setupMagnifier(self, position, left=None, top=None, right=None, bottom=None,
+                         restore=None):
+        """Creates the magnifier in the position specified.
+    
+        Arguments:
+        - position: the position/type of zoomer (full, left half, etc.)
+        - left:     the left edge of the zoomer (only applicable for custom)
+        - top:      the top edge of the zoomer (only applicable for custom)
+        - right:    the right edge of the zoomer (only applicable for custom)
+        - bottom:   the top edge of the zoomer (only applicable for custom)
+        - restore:  a dictionary of all of the settings which should be restored
+        """
+    
+        self._magnifier.clearAllZoomRegions()
+    
+        if not restore:
+            restore = {}
+    
+        # Define where the magnifier will live.
+        #
+        try:
+            self._magnifier.TargetDisplay = \
+                _settingsManager.getSetting('magTargetDisplay')
+        except:
+            pass
+    
+        # Define what will be magnified.
+        #
+        try:
+            self._magnifier.SourceDisplay = \
+                _settingsManager.getSetting('magSourceDisplay')
+        except:
+            pass
+    
+        # Find out if we're using composite.
+        #
+        try:
+            self._fullScreenCapable = self._magnifier.fullScreenCapable()
+        except:
+            debug.printException(debug.LEVEL_WARNING)
+    
+        # If we are running in full screen mode, try to hide the original cursor
+        # (assuming the user wants to). See bug #533095 for more details.
+        # Depends upon new functionality in gnome-mag, so just catch the 
+        # exception if this functionality isn't there.
+        #
+        hideCursor = restore.get('magHideCursor',
+                                 _settingsManager.getSetting('magHideCursor'))
+        if hideCursor \
+           and self._fullScreenCapable \
+           and self._magnifier.SourceDisplay == self._magnifier.TargetDisplay \
+           and position == settings.MAG_ZOOMER_TYPE_FULL_SCREEN:
+            self.hideSystemPointer(True)
+        else:
+            self.hideSystemPointer(False)
+    
+        self._magnifierPBag = self._magnifier.getProperties()
+        sdb = self._magnifierPBag.getValue("source-display-bounds").value()
+        if not self._originalSourceDisplayBounds:
+            self._originalSourceDisplayBounds = sdb
+        elif self._liveUpdatingMagnifier:
+            sdb = self._originalSourceDisplayBounds
+    
+        # Find out where the user wants to place the target display.
+        #
+        if self._fullScreenCapable and \
+           position == settings.MAG_ZOOMER_TYPE_FULL_SCREEN:
+            prefLeft = 0
+            prefTop = 0
+            prefRight = sdb.x2
+            prefBottom = sdb.y2
+        elif position == settings.MAG_ZOOMER_TYPE_TOP_HALF:
+            prefLeft = 0
+            prefTop = 0
+            prefRight = sdb.x2
+            prefBottom = sdb.y2 / 2
+        elif position == settings.MAG_ZOOMER_TYPE_BOTTOM_HALF:
+            prefLeft = 0
+            prefTop = sdb.y2 / 2
+            prefRight = sdb.x2
+            prefBottom = sdb.y2
+        elif position == settings.MAG_ZOOMER_TYPE_LEFT_HALF:
+            prefLeft = 0
+            prefTop = 0
+            prefRight = sdb.x2 / 2
+            prefBottom = sdb.y2
+        elif position == settings.MAG_ZOOMER_TYPE_RIGHT_HALF:
+            prefLeft = sdb.x2 / 2
+            prefTop = 0
+            prefRight = sdb.x2
+            prefBottom = sdb.y2
+        else:
+            prefLeft   = left or _settingsManager.getSetting('magZoomerLeft')
+            prefTop    = top or _settingsManager.getSetting('magZoomerTop')
+            prefRight  = right or _settingsManager.getSetting('magZoomerRight')
+            prefBottom = bottom or _settingsManager.getSetting('magZoomerBottom')
+        orca_state.zoomerType = position
+        updateTarget = True
+    
+        # If we're not using composite, bad things will happen if we allow the
+        # target display to occupy more than 50% of the full screen.  Also, if
+        # it occupies the same space as something that should be magnified (e.g.
+        # the Applications menu), that item will not be magnified. Therefore,
+        # we're going to prefer the right half of the screen for the target
+        # display -- unless gnome-mag is already running and not in "full screen"
+        # mode.
+        #
+        if not self._fullScreenCapable \
+           and self._magnifier.SourceDisplay == self._magnifier.TargetDisplay:
+            # At this point, the target display bounds have not been set. if they
+            # are all 0, then we know that gnome-mag isn't already running.
+            #
+            magAlreadyRunning = False
+            tdb = self._magnifierPBag.getValue("target-display-bounds").value()
+            if tdb.x1 or tdb.x2 or tdb.y1 or tdb.y2:
+                magAlreadyRunning = True
+    
+            # At this point, because we haven't set the target display bounds,
+            # gnome-mag has not modified the source display bounds. Therefore,
+            # we can use the current source display bounds to get the
+            # dimensions of the full screen -- assuming gnome-mag has not
+            # already been launched with a split screen. Comparing the values
+            # of the source and target display bounds lets us know if gnome-mag
+            # has been started in "full screen" mode.
+            #
+            magFullScreen = magAlreadyRunning \
+                            and (tdb.x1 == sdb.x1) and (tdb.x2 == sdb.x2) \
+                            and (tdb.y1 == sdb.y1) and (tdb.y2 == sdb.y2)
+    
+            sourceArea = (sdb.x2 - sdb.x1) * (sdb.y2 - sdb.y1)
+            prefArea = (prefRight - prefLeft) * (prefBottom - prefTop)
+            if prefArea > sourceArea/2:
+                debug.println(
+                    debug.LEVEL_WARNING,
+                    "Composite is not being used. The preferred target area is\n"\
+                    "greater than 50% of the source area.  These settings can\n"\
+                    "render the contents of the screen inaccessible.")
+                if not magAlreadyRunning or magFullScreen:
+                    debug.println(
+                        debug.LEVEL_WARNING,
+                        "Setting the target display to the screen's right half.")
+                    prefRight  = sdb.x2
+                    prefLeft   = sdb.x2/2
+                    prefTop    = sdb.y1
+                    prefBottom = sdb.y2
+                elif sdb.y2 > 0:
+                    updateTarget = False
+                    debug.println(
+                        debug.LEVEL_WARNING,
+                        "Gnome-mag is already running.  Using those settings.")
+    
+        # Now, tell the magnifier where we want it to live on the target display.
+        # The coordinates are in screen coordinates of the target display.
+        # This will have the side effect of setting up other stuff for us, such
+        # as source-display-bouinds.
+        #
+        if updateTarget:
+            tdb = self._magnifierPBag.getValue("target-display-bounds").value()
+            self._magnifierPBag.setValue(
+                "target-display-bounds",
+                ORBit.CORBA.Any(
+                    ORBit.CORBA.TypeCode(
+                        tdb.__typecode__.repo_id),
+                    GNOME.Magnifier.RectBounds(prefLeft,
+                                               prefTop,
+                                               prefRight,
+                                               prefBottom)))
+    
+        bonobo.pbclient_set_string(self._magnifierPBag, "cursor-set", "default")
+    
+        enableCursor = restore.get(
+            'enableMagCursor', _settingsManager.getSetting('enableMagCursor'))
+        explicitSize = restore.get(
+            'enableMagCursorExplicitSize',
+            _settingsManager.getSetting('enableMagCursorExplicitSize'))
+        size = restore.get(
+            'magCursorSize', _settingsManager.getSetting('magCursorSize'))
+        self.setMagnifierCursor(enableCursor, explicitSize, size, False)
+    
+        value = restore.get(
+            'magCursorColor', _settingsManager.getSetting('magCursorColor'))
+        self.setMagnifierObjectColor("cursor-color", value, False)
+    
+        value = restore.get(
+            'magCrossHairColor', _settingsManager.getSetting('magCrossHairColor'))
+        self.setMagnifierObjectColor("crosswire-color", value, False)
+    
+        enableCrossHair = restore.get(
+            'enableMagCrossHair', _settingsManager.getSetting('enableMagCrossHair'))
+        self.setMagnifierCrossHair(enableCrossHair, False)
+    
+        value = restore.get(
+            'enableMagCrossHairClip', 
+            _settingsManager.getSetting('enableMagCrossHairClip'))
+        self.setMagnifierCrossHairClip(value, False)
+    
+        orca_state.mouseEnhancementsEnabled = enableCursor or enableCrossHair
+    
+    def __setupZoomer(self, restore=None):
+        """Creates a zoomer in the magnifier
+        Arguments:
+        - restore:  a dictionary of all of the settings which should be restored
+        """
+    
+        if not restore:
+            restore = {}
+    
+        self._targetDisplayBounds = self._magnifierPBag.getValue(
+            "target-display-bounds").value()
+    
+        debug.println(debug.LEVEL_ALL,
+                      "Magnifier target bounds preferences: (%d, %d), (%d, %d)" \
+                      % (_settingsManager.getSetting('magZoomerLeft'),
+                         _settingsManager.getSetting('magZoomerTop'),
+                         _settingsManager.getSetting('magZoomerRight'),
+                         _settingsManager.getSetting('magZoomerBottom')))
+    
+        debug.println(debug.LEVEL_ALL,
+                      "Magnifier target bounds actual: (%d, %d), (%d, %d)" \
+                      % (self._targetDisplayBounds.x1, self._targetDisplayBounds.y1, \
+                         self._targetDisplayBounds.x2, self._targetDisplayBounds.y2))
+    
+        # If the COMPOSITE support is not enabled in gnome-mag, then the
+        # source-display-bounds will be adjusted to accomodate portion of the
+        # display not being covered by the magnifier (assuming there is only
+        # one display).  Otherwise, the source-display-bounds will be the
+        # entire source screen.
+        #
+        self._sourceDisplayBounds = self._magnifierPBag.getValue(
+            "source-display-bounds").value()
+    
+        debug.println(debug.LEVEL_ALL,
+                      "Magnifier source bounds actual: (%d, %d), (%d, %d)" \
+                      % (self._sourceDisplayBounds.x1, self._sourceDisplayBounds.y1, \
+                         self._sourceDisplayBounds.x2, self._sourceDisplayBounds.y2))
+    
+        # If there is nothing we can possibly magnify, switch to the right half.
+        #
+        if ((self._sourceDisplayBounds.x2 - self._sourceDisplayBounds.x1) == 0) \
+            or ((self._sourceDisplayBounds.y2 - self._sourceDisplayBounds.y1) == 0):
+            debug.println(
+                debug.LEVEL_SEVERE,
+                "There is nothing to magnify.  This is usually caused\n" \
+                "by a preferences setting that tries to take up the\n" \
+                "full screen for magnification, but the underlying\n"
+                "system does not support full screen magnification.\n"
+                "The causes of that are generally that COMPOSITE\n" \
+                "support has not been enabled in gnome-mag or the\n" \
+                "X Window System Server.  As a result of this issue,\n" \
+                "defaulting to the right half of the screen.\n")
+            self._fullScreenCapable = False
+            self.__setupMagnifier(settings.MAG_ZOOMER_TYPE_CUSTOM,
+                             self._targetDisplayBounds.x1/2,
+                             self._targetDisplayBounds.y1,
+                             self._targetDisplayBounds.x2,
+                             self._targetDisplayBounds.y2)
+            self._sourceDisplayBounds = self._magnifierPBag.getValue(
+                "source-display-bounds").value()
+            self._targetDisplayBounds = self._magnifierPBag.getValue(
+                "target-display-bounds").value()
+    
+        # Now, we create a zoom region to occupy the whole magnifier (i.e.,
+        # the viewport is in target region coordinates and we make the
+        # viewport be the whole target region).  Note, since we're starting
+        # at (0, 0), the viewportWidth and viewportHeight are the same as
+        # the x2, y2 values for a rectangular region.
+        #
+        viewportWidth = self._targetDisplayBounds.x2 - self._targetDisplayBounds.x1
+        viewportHeight = self._targetDisplayBounds.y2 - self._targetDisplayBounds.y1
+    
+        debug.println(debug.LEVEL_ALL,
+                      "Magnifier zoomer viewport desired: (0, 0), (%d, %d)" \
+                      % (viewportWidth, viewportHeight))
+    
+        # Now, let's see what the ROI looks like.
+        #
+        zoomFactor = _settingsManager.getSetting('magZoomFactor')
+        debug.println(debug.LEVEL_ALL,
+                     "Magnifier source width: %d (viewport can show %d)" \
+                      % (self._sourceDisplayBounds.x2 - self._sourceDisplayBounds.x1,
+                      viewportWidth / zoomFactor))
+        debug.println(debug.LEVEL_ALL,
+                      "Magnifier source height: %d (viewport can show %d)" \
+                      % (self._sourceDisplayBounds.y2 - self._sourceDisplayBounds.y1,
+                       viewportHeight / zoomFactor))
+    
+        # Adjust the ROI in the event the source window is too small for the
+        # target window.  This usually happens when someone expects COMPOSITE
+        # to be enabled, but it isn't.  As a result, they usually have a very
+        # big grey magnifier on their screen.
+        #
+        self._roiWidth  = min(self._sourceDisplayBounds.x2 - self._sourceDisplayBounds.x1,
+                         viewportWidth / zoomFactor)
+        self._roiHeight = min(self._sourceDisplayBounds.y2 - self._sourceDisplayBounds.y1,
+                         viewportHeight / zoomFactor)
+    
+        debug.println(debug.LEVEL_ALL,
+                      "Magnifier zoomer ROI size desired: width=%d, height=%d)" \
+                      % (self._roiWidth, self._roiHeight))
+    
+        # Create the zoomer with a magnification factor, an initial ROI, and
+        # where in magnifier we want it to be (we want it to be in the whole
+        # magnifier). Initially set the viewport so that it does not appear.
+        # After we set all of the color properties, reset the viewport to
+        # the correct position.  This will prevent the user from seeing the
+        # individual property changes (e.g. brightness, contrast) upon load.
+        #
+        self._zoomer = self._magnifier.createZoomRegion(
+            zoomFactor, zoomFactor,
+            GNOME.Magnifier.RectBounds(0, 0, self._roiWidth, self._roiHeight),
+            GNOME.Magnifier.RectBounds(0, 0, 1, 1))
+    
+        self._zoomerPBag = self._zoomer.getProperties()
+        bonobo.pbclient_set_boolean(self._zoomerPBag, "is-managed", True)
+    
+        value = restore.get('magZoomFactor', zoomFactor)
+        self.setZoomerMagFactor(value, value, False)
+    
+        value = restore.get(
+            'enableMagZoomerColorInversion',
+            _settingsManager.getSetting('enableMagZoomerColorInversion'))
+        self.setZoomerColorInversion(value, False)
+    
+        brightness = restore.get(
+            'magBrightnessLevel', _settingsManager.getSetting('magBrightnessLevel'))
+        r = brightness + \
+            restore.get('magBrightnessLevelRed',
+                        _settingsManager.getSetting('magBrightnessLevelRed'))
+        g = brightness + \
+            restore.get('magBrightnessLevelGreen',
+                        _settingsManager.getSetting('magBrightnessLevelGreen'))
+        b = brightness + \
+            restore.get('magBrightnessLevelBlue',
+                        _settingsManager.getSetting('magBrightnessLevelBlue'))
+        self.setZoomerBrightness(r, g, b, False)
+    
+        contrast = restore.get(
+            'magContrastLevel', _settingsManager.getSetting('magContrastLevel'))
+        r = contrast + \
+            restore.get('magContrastLevelRed',
+                        _settingsManager.getSetting('magContrastLevelRed'))
+        g = contrast + \
+            restore.get('magContrastLevelGreen',
+                        _settingsManager.getSetting('magContrastLevelGreen'))
+        b = contrast + \
+            restore.get('magContrastLevelBlue',
+                        _settingsManager.getSetting('magContrastLevelBlue'))
+        self.setZoomerContrast(r, g, b, False)
+    
+        value = restore.get('magColorFilteringMode',
+                            _settingsManager.getSetting('magColorFilteringMode'))
+        self.setZoomerColorFilter(value, False)
+    
+        value = restore.get(
+            'magZoomerType', _settingsManager.getSetting('magZoomerType'))
+        if value == settings.MAG_ZOOMER_TYPE_FULL_SCREEN:
+            size = 0
+        else:
+            size = restore.get('magZoomerBorderSize',
+                               _settingsManager.getSetting('magZoomerBorderSize'))
+        color = restore.get('magZoomerBorderColor',
+                            _settingsManager.getSetting('magZoomerBorderColor'))
+        self.setZoomerObjectSize("border-size", size, False)
+        self.setZoomerObjectColor("border-color", color, False)
+    
+        value = restore.get('magSmoothingMode',
+                            _settingsManager.getSetting('magSmoothingMode'))
+        self.setZoomerSmoothingType(value, False)
+    
+        # Now it's safe to display the viewport.
+        #
+        bounds = GNOME.Magnifier.RectBounds(0, 0, viewportWidth, viewportHeight)
+        self._zoomer.moveResize(bounds)
+    
+        # Try to use gnome-mag >= 0.13.1 to allow us to control where to
+        # draw the cursor and crosswires.
+        #
+        try:
+            bonobo.pbclient_set_boolean(self._zoomerPBag, "poll-mouse", False)
+            self._pollMouseDisabled = True
+        except:
+            self._pollMouseDisabled = False
+    
+        self.__updateROIDimensions()
+        self._magnifier.addZoomRegion(self._zoomer)
+    
+    def __updateROIDimensions(self):
+        """Updates the ROI width, height, and maximum and minimum values.
+        """
+    
+        viewport = self._zoomerPBag.getValue("viewport").value()
+    
+        debug.println(debug.LEVEL_ALL,
+                      "Magnifier viewport actual: (%d, %d), (%d, %d)" \
+                      % (viewport.x1, viewport.y1, viewport.x2, viewport.y2))
+    
+        magx = self._zoomerPBag.getValue("mag-factor-x").value()
+        magy = self._zoomerPBag.getValue("mag-factor-y").value()
+    
+        self._roiWidth  = min(self._sourceDisplayBounds.x2 - self._sourceDisplayBounds.x1,
+                         (viewport.x2 - viewport.x1) / magx)
+        self._roiHeight = min(self._sourceDisplayBounds.y2 - self._sourceDisplayBounds.y1,
+                         (viewport.y2 - viewport.y1) / magy)
+    
+        debug.println(debug.LEVEL_ALL,
+                      "Magnifier zoomer ROI size actual: width=%d, height=%d)" \
+                      % (self._roiWidth, self._roiHeight))
+    
+        self._minROIX = self._sourceDisplayBounds.x1 + (self._roiWidth / 2)
+        self._minROIY = self._sourceDisplayBounds.y1 + (self._roiHeight / 2)
+    
+        self._maxROIX = self._sourceDisplayBounds.x2 - (self._roiWidth / 2)
+        self._maxROIY = self._sourceDisplayBounds.y2 - (self._roiHeight / 2)
+    
+        debug.println(debug.LEVEL_ALL,
+                      "Magnifier ROI min/max center: (%d, %d), (%d, %d)" \
+                      % (self._minROIX, self._minROIY, self._maxROIX, self._maxROIY))
+    
+    def applySettings(self):
+        """Looks at the user settings and applies them to the magnifier."""
+    
+        self.__setupMagnifier(_settingsManager.getSetting('magZoomerType'))
+        self.__setupZoomer()
+      
+        self._mouseTracking = _settingsManager.getSetting('magMouseTrackingMode')
+        self._controlTracking = _settingsManager.getSetting('magControlTrackingMode')
+        self._textTracking = _settingsManager.getSetting('magTextTrackingMode')
+        self._edgeMargin = _settingsManager.getSetting('magEdgeMargin')
+        self._pointerFollowsZoomer = \
+            _settingsManager.getSetting('magPointerFollowsZoomer')
+        self._pointerFollowsFocus = \
+            _settingsManager.getSetting('magPointerFollowsFocus')
+    
+        #print "MAGNIFIER PROPERTIES:", self._magnifier
+        #__dumpPropertyBag(self._magnifier)
+        #print "ZOOMER PROPERTIES:", self._zoomer
+        #__dumpPropertyBag(self._zoomer)
+    
+    def magnifyAccessible(self, event, obj, extents=None):
+        """Sets the region of interest to the upper left of the given
+        accessible, if it implements the Component interface.  Otherwise,
+        does nothing.
+    
+        Arguments:
+        - event: the Event that caused this to be called
+        - obj: the accessible
+        """
+    
+        if not self._initialized:
+            return
+    
+        # Avoid jerking the display around if the mouse is what ended up causing
+        # this event.  We guess this by seeing if this request has come in within
+        # a close period of time.  [[[TODO: WDW - this is a hack and really
+        # doesn't belong here.  Plus, the delta probably should be adjustable.]]]
+        #
+        currentTime = time.time()
+        if (currentTime - self._lastMouseEventTime) < 0.2: # 200 milliseconds
+            return
+    
+        haveSomethingToMagnify = False
+    
+        if extents:
+            [x, y, width, height] = extents
+            haveSomethingToMagnify = True
+        elif event and event.type.startswith("object:text-caret-moved"):
+            try:
+                text = obj.queryText()
+                if text and (text.caretOffset >= 0):
+                    offset = text.caretOffset
+                    if offset == text.characterCount:
+                        offset -= 1
+                    [x, y, width, height] = \
+                        text.getCharacterExtents(offset, 0)
+                    haveSomethingToMagnify = (width + height > 0)
+                        
+            except:
+                haveSomethingToMagnify = False
+    
+            if haveSomethingToMagnify:
+                if self._textTracking == settings.MAG_TRACKING_MODE_CENTERED:
+                    self.__setROICenter(x, y)
+                elif self._textTracking == settings.MAG_TRACKING_MODE_PUSH:
+                    self.__setROICursorPush(x, y, width, height, self._edgeMargin)
+                return
+    
+        if not haveSomethingToMagnify:
+            try:
+                extents = obj.queryComponent().getExtents(0)
+                [x, y, width, height] = \
+                    [extents.x, extents.y, extents.width, extents.height]
+                haveSomethingToMagnify = True
+            except:
+                haveSomethingToMagnify = False
+    
+        if haveSomethingToMagnify:
+            if self._pointerFollowsFocus:
+                self._lastMouseEventWasRoute = True
+                eventsynthesizer.generateMouseEvent(x, y + height - 1, "abs")
+    
+            if self._controlTracking == settings.MAG_TRACKING_MODE_CENTERED:
+                centerX = x + width/2
+                centerY = y + height/2
+    
+                # Be sure that the upper-left corner of the object will still
+                # be visible on the screen.
+                #
+                if width > self._roiWidth:
+                    centerX = x
+                if height > self._roiHeight:
+                    centerY = y
+    
+                self.__setROICenter(centerX, centerY)
+            elif self._controlTracking == settings.MAG_TRACKING_MODE_PUSH:
+                self.__setROICursorPush(x, y, width, height)
+    
+    def init(self):
+        """Initializes the magnifier, bringing the magnifier up on the
+        display.
+    
+        Returns True if the initialization procedure was run or False if this
+        module has already been initialized.
+        """
+    
+        if not self._magnifierAvailable or not settings.enableMagnifier or not \
+                self.isActive:
+            return False
+
+        if self._initialized:
+            return False
+    
+        self._magnifier = bonobo.get_object("OAFIID:GNOME_Magnifier_Magnifier:0.9",
+                                       "GNOME/Magnifier/Magnifier")
+    
+        try:
+            self._initialized = True
+            self.applySettings()
+            pyatspi.Registry.registerEventListener(self.__onMouseEvent, "mouse:abs")
+    
+            # Zoom to the upper left corner of the display for now.
+            #
+            self.__setROICenter(0, 0)
+    
+            return True
+        except:
+            self._initialized = False
+            self._magnifier.dispose()
+            raise
+    
+    def shutdown(self):
+        """Shuts down the magnifier module.
+        Returns True if the shutdown procedure was run or False if this
+        module has not been initialized.
+        """
+    
+        if not self._magnifierAvailable:
+            return False
+    
+        if not self._initialized:
+            return False
+    
+        pyatspi.Registry.deregisterEventListener(self.__onMouseEvent,"mouse:abs")
+    
+        # Someone might have killed the magnifier on us.  They shouldn't
+        # have done so, but we need to be able to recover if they did.
+        # See http://bugzilla.gnome.org/show_bug.cgi?id=375396.
+        #
+        try:
+            self.hideSystemPointer(False)
+            self._magnifier.clearAllZoomRegions()
+            self._magnifier.dispose()
+        except:
+            debug.printException(debug.LEVEL_WARNING)
+    
+        self._magnifier = None
+    
+        self._initialized = False
+    
+        return True
+    
+    ######################################################################
+    #                                                                    #
+    #              Convenience functions for "live" changes              #
+    #                                                                    #
+    ######################################################################
+    
+    def setupMagnifier(self, position, left=None, top=None, right=None, bottom=None,
+                       restore=None):
+        """Creates the magnifier in the position specified.
+    
+        Arguments:
+        - position: the position/type of zoomer (full, left half, etc.)
+        - left:     the left edge of the zoomer (only applicable for custom)
+        - top:      the top edge of the zoomer (only applicable for custom)
+        - right:    the right edge of the zoomer (only applicable for custom)
+        - bottom:   the top edge of the zoomer (only applicable for custom)
+        - restore:  a dictionary of all of the settings that should be restored
+        """
+    
+        if not self._initialized:
+            return
+    
+        self._liveUpdatingMagnifier = True
+        self.__setupMagnifier(position, left, top, right, bottom, restore)
+        self.__setupZoomer(restore)
+    
+    def setMagnifierCursor(self, enabled, customEnabled, size, updateScreen=True):
+        """Sets the cursor.
+    
+        Arguments:
+        - enabled:        Whether or not the cursor should be enabled
+        - customEnabled:  Whether or not a custom size has been enabled
+        - size:           The size it should be set to
+        - updateScreen:   Whether or not to update the screen
+        """
+    
+        if not self._initialized:
+            return
+        try:
+            mag = self._zoomerPBag.getValue("mag-factor-x").value()
+        except:
+            mag = _settingsManager.getSetting('magZoomFactor')
+    
+        if enabled:
+            scale = 1.0 * mag
+        else:
+            scale = 0.0
+    
+        if not (enabled and customEnabled):
+            size = 0
+    
+        bonobo.pbclient_set_float(self._magnifierPBag, "cursor-scale-factor", scale)
+        bonobo.pbclient_set_long(self._magnifierPBag, "cursor-size", size)
+    
+        if updateScreen:
+            self._zoomer.markDirty(self._roi)
+    
+    def setMagnifierCrossHair(self, enabled, updateScreen=True):
+        """Sets the cross-hair.
+    
+        Arguments:
+        - enabled: Whether or not the cross-hair should be enabled
+        - updateScreen:  Whether or not to update the screen
+        """
+    
+        if not self._initialized:
+            return
+    
+        size = 0
+        if enabled:
+            size = _settingsManager.getSetting('magCrossHairSize')
+    
+        bonobo.pbclient_set_long(self._magnifierPBag, "crosswire-size", size)
+    
+        if updateScreen:
+            self._zoomer.markDirty(self._roi)
+    
+    def setMagnifierCrossHairClip(self, enabled, updateScreen=True):
+        """Sets the cross-hair clip.
+    
+        Arguments:
+        - enabled: Whether or not the cross-hair clip should be enabled
+        - updateScreen:   Whether or not to update the screen
+        """
+    
+        if not self._initialized:
+            return
+    
+        bonobo.pbclient_set_boolean(self._magnifierPBag, "crosswire-clip", enabled)
+    
+        if updateScreen:
+            self._zoomer.markDirty(self._roi)
+    
+    def setZoomerColorInversion(self, enabled, updateScreen=True):
+        """Sets the color inversion.
+    
+        Arguments:
+        - enabled: Whether or not color inversion should be enabled
+        - updateScreen:   Whether or not to update the screen
+        """
+    
+        if not self._initialized:
+            return
+    
+        bonobo.pbclient_set_boolean(self._zoomerPBag, "inverse-video", enabled)
+    
+        if updateScreen:
+            self._zoomer.markDirty(self._roi)
+    
+    def setZoomerBrightness(self, red=0, green=0, blue=0, updateScreen=True):
+        """Increases/Decreases the brightness level by the specified
+        increments.  Increments are floats ranging from -1 (black/no
+        brightenss) to 1 (white/100% brightness).  0 means no change.
+    
+        Arguments:
+        - red:    The amount to alter the red brightness level
+        - green:  The amount to alter the green brightness level
+        - blue:   The amount to alter the blue brightness level
+        - updateScreen:   Whether or not to update the screen
+        """
+    
+        if not self._initialized:
+            return
+    
+        self._zoomer.setBrightness(red, green, blue)
+    
+        if updateScreen:
+            self._zoomer.markDirty(self._roi)
+    
+    def setZoomerContrast(self, red=0, green=0, blue=0, updateScreen=True):
+        """Increases/Decreases the contrast level by the specified
+        increments.  Increments are floats ranging from -1 (grey/no
+        contrast) to 1 (white/back/100% contrast).  0 means no change.
+    
+        Arguments:
+        - red:    The amount to alter the red contrast level
+        - green:  The amount to alter the green contrast level
+        - blue:   The amount to alter the blue contrast level
+        - updateScreen:  Whether or not to update the screen
+        """
+    
+        if not self._initialized:
+            return
+    
+        self._zoomer.setContrast(red, green, blue)
+    
+        if updateScreen:
+            self._zoomer.markDirty(self._roi)
+    
+    def setMagnifierObjectSize(self, magProperty, size, updateScreen=True):
+        """Sets the specified magnifier property to the specified size.
+    
+        Arguments:
+        - magProperty:   The property to set (as a string)
+        - size:          The size to apply
+        - updateScreen:  Whether or not to update the screen
+        """
+    
+        if not self._initialized:
+            return
+    
+        bonobo.pbclient_set_long(self._magnifierPBag, magProperty, size)
+    
+        if updateScreen:
+            self._zoomer.markDirty(self._roi)
+    
+    def setZoomerObjectSize(self, magProperty, size, updateScreen=True):
+        """Sets the specified zoomer property to the specified size.
+    
+        Arguments:
+        - magProperty:   The property to set (as a string)
+        - size:          The size to apply
+        - updateScreen:  Whether or not to update the screen
+        """
+    
+        if not self._initialized:
+            return
+    
+        if magProperty == "border-size":
+            try:
+                left = right = top = bottom = 0
+                if orca_state.zoomerType == settings.MAG_ZOOMER_TYPE_RIGHT_HALF:
+                    left = size
+                elif orca_state.zoomerType == settings.MAG_ZOOMER_TYPE_LEFT_HALF:
+                    right = size
+                elif orca_state.zoomerType == settings.MAG_ZOOMER_TYPE_TOP_HALF:
+                    bottom = size
+                elif orca_state.zoomerType == settings.MAG_ZOOMER_TYPE_BOTTOM_HALF:
+                    top = size
+                elif orca_state.zoomerType == settings.MAG_ZOOMER_TYPE_CUSTOM:
+                    if self._targetDisplayBounds.x1 > self._sourceDisplayBounds.x1:
+                        left = size
+                    if self._targetDisplayBounds.x2 < self._sourceDisplayBounds.x2:
+                        right = size
+                    if self._targetDisplayBounds.y1 > self._sourceDisplayBounds.y1:
+                        top = size
+                    if self._targetDisplayBounds.y2 < self._sourceDisplayBounds.y2:
+                        bottom = size
+                    
+                bonobo.pbclient_set_long(self._zoomerPBag, "border-size-left", left)
+                bonobo.pbclient_set_long(self._zoomerPBag, "border-size-top", top)
+                bonobo.pbclient_set_long(self._zoomerPBag, "border-size-right", right)
+                bonobo.pbclient_set_long(self._zoomerPBag, "border-size-bottom", bottom)
+            except:
+                bonobo.pbclient_set_long(self._zoomerPBag, "border-size", size)
+        else:
+            bonobo.pbclient_set_long(self._zoomerPBag, magProperty, size)
+    
+        if updateScreen:
+            self._zoomer.markDirty(self._roi)
+    
+    def setZoomerObjectColor(self, magProperty, colorSetting, updateScreen=True):
+        """Sets the specified zoomer property to the specified color.
+    
+        Arguments:
+        - magProperty:  The property to set (as a string)
+        - colorSetting: The Orca color setting to apply
+        - updateScreen:  Whether or not to update the screen
+        """
+    
+        if not self._initialized:
+            return
+    
+        colorPreference = gtk.gdk.color_parse(colorSetting)
+    
+        # Convert the colorPreference string to something we can use.
+        # The main issue here is that the color preferences are saved
+        # as 4 byte values per color.  We only need 2 bytes, so we
+        # get rid of the bottom 8 bits.
+        #
+        colorPreference.red   = colorPreference.red   >> 8
+        colorPreference.blue  = colorPreference.blue  >> 8
+        colorPreference.green = colorPreference.green >> 8
+        colorString = "0x%02X%02X%02X" \
+                      % (colorPreference.red,
+                         colorPreference.green,
+                         colorPreference.blue)
+    
+        toChange = self._zoomerPBag.getValue(magProperty)
+        self._zoomerPBag.setValue(magProperty,
+                             ORBit.CORBA.Any(toChange.typecode(),
+                                             long(colorString, 0)))
+        if updateScreen:
+            self._zoomer.markDirty(self._roi)
+    
+    def setMagnifierObjectColor(self, magProperty, colorSetting, updateScreen=True):
+        """Sets the specified magnifier property to the specified color.
+    
+        Arguments:
+        - magProperty:  The property to set (as a string)
+        - colorSetting: The Orca color setting to apply
+        - updateScreen:  Whether or not to update the screen
+        """
+    
+        if not self._initialized:
+            return
+    
+        colorPreference = gtk.gdk.color_parse(colorSetting)
+    
+        # Convert the colorPreference string to something we can use.
+        # The main issue here is that the color preferences are saved
+        # as 4 byte values per color.  We only need 2 bytes, so we
+        # get rid of the bottom 8 bits.
+        #
+        colorPreference.red   = colorPreference.red   >> 8
+        colorPreference.blue  = colorPreference.blue  >> 8
+        colorPreference.green = colorPreference.green >> 8
+        colorString = "0x%02X%02X%02X" \
+                      % (colorPreference.red,
+                         colorPreference.green,
+                         colorPreference.blue)
+    
+        toChange = self._magnifierPBag.getValue(magProperty)
+        self._magnifierPBag.setValue(magProperty,
+                                ORBit.CORBA.Any(toChange.typecode(),
+                                                long(colorString, 0)))
+        if updateScreen:
+            self._zoomer.markDirty(self._roi)
+    
+    def setZoomerMagFactor(self, x, y, updateScreen=True):
+        """Sets the magnification level.
+    
+        Arguments:
+        - x: The horizontal magnification level
+        - y: The vertical magnification level
+        - updateScreen:  Whether or not to update the screen
+        """
+    
+        if not self._initialized:
+            return
+    
+        [oldX, oldY] = self._zoomer.getMagFactor()
+    
+        self._zoomer.setMagFactor(x, y)
+    
+        if updateScreen:
+            self.__updateROIDimensions()
+            if (oldX > x) and (x < 1.5):
+                self._minROIX = self._sourceDisplayBounds.x1
+                self._minROIY = self._sourceDisplayBounds.y1
+                self.__setROI(GNOME.Magnifier.RectBounds(self._minROIX,
+                                                    self._minROIY,
+                                                    self._minROIX + self._roiWidth,
+                                                    self._minROIY + self._roiHeight))
+            else:
+                extents = orca_state.locusOfFocus.queryComponent().getExtents(0)
+                self.__setROICenter(extents.x, extents.y)
+    
+    def setZoomerSmoothingType(self, smoothingType, updateScreen=True):
+        """Sets the zoomer's smoothing type.
+    
+        Arguments:
+        - smoothingType: The type of smoothing to use
+        - updateScreen:  Whether or not to update the screen
+        """
+    
+        if not self._initialized:
+            return
+    
+        if smoothingType == settings.MAG_SMOOTHING_MODE_BILINEAR:
+            string = "bilinear"
+        else:
+            string = "None"
+    
+        try:
+            bonobo.pbclient_set_string(self._zoomerPBag, "smoothing-type", string)
+        except:
+            pass
+    
+        if updateScreen:
+            self._zoomer.markDirty(self._roi)
+    
+    def setZoomerColorFilter(self, colorFilter, updateScreen=True):
+        """Sets the zoomer's color filter.
+    
+        Arguments:
+        - colorFilter: The color filter to apply
+        - updateScreen:  Whether or not to update the screen
+        """
+    
+        if not self._initialized or not self.isFilteringCapable():
+            return
+    
+        if colorFilter == settings.MAG_COLOR_FILTERING_MODE_SATURATE_RED:
+            toApply = self._zoomer.COLORBLIND_FILTER_T_SELECTIVE_SATURATE_RED
+        elif colorFilter == settings.MAG_COLOR_FILTERING_MODE_SATURATE_GREEN:
+            toApply = self._zoomer.COLORBLIND_FILTER_T_SELECTIVE_SATURATE_GREEN
+        elif colorFilter == settings.MAG_COLOR_FILTERING_MODE_SATURATE_BLUE:
+            toApply = self._zoomer.COLORBLIND_FILTER_T_SELECTIVE_SATURATE_BLUE
+        elif colorFilter == settings.MAG_COLOR_FILTERING_MODE_DESATURATE_RED:
+            toApply = self._zoomer.COLORBLIND_FILTER_T_SELECTIVE_DESSATURATE_RED
+        elif colorFilter == settings.MAG_COLOR_FILTERING_MODE_DESATURATE_GREEN:
+            toApply = self._zoomer.COLORBLIND_FILTER_T_SELECTIVE_DESSATURATE_GREEN
+        elif colorFilter == settings.MAG_COLOR_FILTERING_MODE_DESATURATE_BLUE:
+            toApply = self._zoomer.COLORBLIND_FILTER_T_SELECTIVE_DESSATURATE_BLUE
+        elif colorFilter == settings.MAG_COLOR_FILTERING_MODE_NEGATIVE_HUE_SHIFT:
+            toApply = self._zoomer.COLORBLIND_FILTER_T_HUE_SHIFT_NEGATIVE
+        elif colorFilter == settings.MAG_COLOR_FILTERING_MODE_POSITIVE_HUE_SHIFT:
+            toApply = self._zoomer.COLORBLIND_FILTER_T_HUE_SHIFT_POSITIVE
+        else:
+            toApply = self._zoomer.COLORBLIND_FILTER_T_NO_FILTER
+    
+        colorFilter = self._zoomerPBag.getValue("color-blind-filter")
+        self._zoomerPBag.setValue(
+             "color-blind-filter",
+             ORBit.CORBA.Any(
+                 colorFilter.typecode(),
+                 toApply))
+    
+        if updateScreen:
+            self._zoomer.markDirty(self._roi)
+    
+    def hideSystemPointer(self, hidePointer):
+        """Hide or show the system pointer.
+    
+        Arguments:
+        -hidePointer: If True, hide the system pointer, otherwise show it.
+        """
+    
+        # Depends upon new functionality in gnome-mag, so just catch the
+        # exception if this functionality isn't there.
+        #
+        try:
+            if hidePointer:
+                self._magnifier.hideCursor()
+            else:
+                self._magnifier.showCursor()
+        except:
+            debug.printException(debug.LEVEL_FINEST)
+    
+    def isFullScreenCapable(self):
+        """Returns True if we are capable of doing full screen (i.e. whether
+        composite is being used.
+        """
+    
+        try:
+            capable = self._magnifier.fullScreenCapable()
+        except:
+            capable = False
+    
+        return capable
+    
+    def isFilteringCapable(self):
+        """Returns True if we're able to take advantage of libcolorblind's color
+        filtering.
+        """
+    
+        try:
+            capable = self._magnifier.supportColorblindFilters()
+        except:
+            capable = False
+    
+        return capable
+    
+    def updateMouseTracking(self, newMode):
+        """Updates the mouse tracking mode.
+    
+        Arguments:
+        -newMode: The new mode to use.
+        """
+    
+        self._mouseTracking = newMode
+    
+    def updateControlTracking(self, newMode):
+        """Updates the control tracking mode.
+    
+        Arguments:
+        -newMode: The new mode to use.
+        """
+    
+        self._controlTracking = newMode
+    
+    def updateTextTracking(self, newMode):
+        """Updates the text tracking mode.
+    
+        Arguments:
+        -newMode: The new mode to use.
+        """
+    
+        self._textTracking = newMode
+    
+    def updateEdgeMargin(self, amount):
+        """Updates the edge margin
+    
+        Arguments:
+        -amount: The new margin to use, in pixels.
+        """
+    
+        self._edgeMargin = amount
+    
+    def updatePointerFollowsFocus(self, enabled):
+        """Updates the pointer follows focus setting.
+    
+        Arguments:
+        -enabled: whether or not pointer follows focus should be enabled.
+        """
+    
+        self._pointerFollowsFocus = enabled
+    
+    def updatePointerFollowsZoomer(self, enabled):
+        """Updates the pointer follows zoomer setting.
+    
+        Arguments:
+        -enabled: whether or not pointer follows zoomer should be enabled.
+        """
+    
+        self._pointerFollowsZoomer = enabled
+    
+    def finishLiveUpdating(self):
+        """Restores things that were altered via a live update."""
+    
+        self._liveUpdatingMagnifier = False
+        self._mouseTracking = _settingsManager.getSetting('magMouseTrackingMode')
+        self._controlTracking = _settingsManager.getSetting('magControlTrackingMode')
+        self._textTracking = _settingsManager.getSetting('magTextTrackingMode')
+        self._edgeMargin = _settingsManager.getSetting('magEdgeMargin')
+        self._pointerFollowsFocus = _settingsManager.getSetting('magPointerFollowsFocus')
+        self._pointerFollowsZoomer = \
+            _settingsManager.getSetting('magPointerFollowsZoomer')
+    
+        if _settingsManager.getSetting('enableMagnifier'):
+            self.setupMagnifier(_settingsManager.getSetting('magZoomerType'))
+            self.init()
+        else:
+            self.shutdown()
+    
+    ######################################################################
+    #                                                                    #
+    #                        Input Event Handlers                        #
+    #                                                                    #
+    ######################################################################
+    
+    def toggleColorEnhancements(self, script=None, inputEvent=None):
+        """Toggles the color enhancements on/off."""
+    
+        if not self._initialized:
+            return
+    
+        # We don't want to stomp on a command-altered magnification level.
+        #
+        [levelX, levelY] = self._zoomer.getMagFactor()
+        
+        normal = {'enableMagZoomerColorInversion': False,
+                  'magBrightnessLevelRed': 0,
+                  'magBrightnessLevelGreen': 0,
+                  'magBrightnessLevelBlue': 0,
+                  'magContrastLevelRed': 0,
+                  'magContrastLevelGreen': 0,
+                  'magContrastLevelBlue': 0,
+                  'magColorFilteringMode': settings.MAG_COLOR_FILTERING_MODE_NONE,
+                  'magSmoothingMode': settings.MAG_SMOOTHING_MODE_BILINEAR,
+                  'magZoomerBorderColor': '#000000',
+                  'magZoomFactor': levelX}
+    
+        if orca_state.colorEnhancementsEnabled:
+            self.__setupZoomer(restore = normal)
+            # Translators: "color enhancements" are changes users can
+            # make to the appearance of the screen to make things easier
+            # to see, such as inverting the colors or applying a tint.
+            #
+            orca_state.activeScript.presentMessage(
+                _("Color enhancements disabled."))
+        else:
+            toRestore = {'magZoomFactor': levelX}
+            self.__setupZoomer(restore = toRestore)
+            # Translators: "color enhancements" are changes users can
+            # make to the appearance of the screen to make things easier
+            # to see, such as inverting the colors or applying a tint.
+            #
+            orca_state.activeScript.presentMessage(_("Color enhancements enabled."))
+    
+        orca_state.colorEnhancementsEnabled = \
+                                        not orca_state.colorEnhancementsEnabled
+    
+        return True
+    
+    def toggleMouseEnhancements(self, script=None, inputEvent=None):
+        """Toggles the mouse enhancements on/off."""
+    
+        if not self._initialized:
+            return
+    
+        if orca_state.mouseEnhancementsEnabled:
+            self.setMagnifierCrossHair(False, False)
+            self.setMagnifierObjectColor("cursor-color", "#000000", False)
+            self.setMagnifierCursor(True, False, 0)
+            # Translators: "mouse enhancements" are changes users can
+            # make to the appearance of the mouse pointer to make it
+            # easier to see, such as increasing its size, changing its
+            # color, and surrounding it with crosshairs.
+            #
+            orca_state.activeScript.presentMessage(
+                _("Mouse enhancements disabled."))
+        else:
+            # We normally toggle "on" what the user has enabled by default.
+            # However, if the user's default settings are to disable all mouse
+            # enhancements "on" and "off" are the same thing.  If that is the
+            # case and this command is being used, the user probably expects
+            # to see *something* change. We don't know what, so enable both
+            # the cursor and the cross-hairs.
+            #
+            cursorEnable = _settingsManager.getSetting('enableMagCursor')
+            crossHairEnable = _settingsManager.getSetting('enableMagCrossHair')
+            if not (cursorEnable or crossHairEnable):
+                cursorEnable = True
+                crossHairEnable = True
+    
+            self.setMagnifierCursor(
+                cursorEnable,
+                _settingsManager.getSetting('enableMagCursorExplicitSize'),
+                _settingsManager.getSetting('magCursorSize'),
+                False)
+            self.setMagnifierObjectColor(
+                "cursor-color",
+                _settingsManager.getSetting('magCursorColor'),
+                False)
+            self.setMagnifierObjectColor(
+                "crosswire-color",
+                _settingsManager.getSetting('magCrossHairColor'),
+                False)
+            self.setMagnifierCrossHairClip(
+                _settingsManager.getSetting('enableMagCrossHairClip'),
+                False)
+            self.setMagnifierCrossHair(crossHairEnable)
+            # Translators: "mouse enhancements" are changes users can
+            # make to the appearance of the mouse pointer to make it
+            # easier to see, such as increasing its size, changing its
+            # color, and surrounding it with crosshairs.
+            #
+            orca_state.activeScript.presentMessage(_("Mouse enhancements enabled."))
+    
+        orca_state.mouseEnhancementsEnabled = \
+                                        not orca_state.mouseEnhancementsEnabled
+        return True
+    
+    def increaseMagnification(self, script=None, inputEvent=None):
+        """Increases the magnification level."""
+    
+        if not self._initialized:
+            return
+    
+        [levelX, levelY] = self._zoomer.getMagFactor()
+    
+        # Move in increments that are sensible based on the current level of
+        # magnification.
+        #
+        if 1 <= levelX < 4:
+            increment = 0.25
+        elif 4 <= levelX < 7:
+            increment = 0.5
+        else:
+            increment = 1
+    
+        newLevel = levelX + increment
+        if newLevel <= 16:
+            self.setZoomerMagFactor(newLevel, newLevel)
+            orca_state.activeScript.presentMessage(str(newLevel))
+    
+        return True
+    
+    def decreaseMagnification(self, script=None, inputEvent=None):
+        """Decreases the magnification level."""
+    
+        if not self._initialized:
+            return
+    
+        [levelX, levelY] = self._zoomer.getMagFactor()
+    
+        # Move in increments that are sensible based on the current level of
+        # magnification.
+        #
+        if 1 <= levelX < 4:
+            increment = 0.25
+        elif 4 <= levelX < 7:
+            increment = 0.5
+        else:
+            increment = 1
+    
+        newLevel = levelX - increment
+        if newLevel >= 1:
+            self.setZoomerMagFactor(newLevel, newLevel)
+            orca_state.activeScript.presentMessage(str(newLevel))
+    
+        return True
+    
+    def toggleMagnifier(self, script=None, inputEvent=None):
+        """Toggles the magnifier."""
+    
+        if not self._initialized:
+            self.init()
+            # Translators: this is the message spoken when a user enables the
+            # magnifier.  In addition to screen magnification, the user's
+            # preferred colors and mouse customizations are loaded.
+            #
+            orca_state.activeScript.presentMessage(_("Magnifier enabled."))
+        else:
+            self.shutdown()
+            # Translators: this is the message spoken when a user disables the
+            # magnifier, restoring the screen contents to their normal colors
+            # and sizes.
+            #
+            orca_state.activeScript.presentMessage(_("Magnifier disabled."))
+    
+        return True
+    
+    def cycleZoomerType(self, script=None, inputEvent=None):
+        """Allows the user to cycle through the available zoomer types."""
+    
+        if not self._initialized:
+            return
+    
+        # There are 6 possible zoomer types
+        #
+        orca_state.zoomerType += 1
+    
+        if orca_state.zoomerType >= 6:
+            orca_state.zoomerType = 0
+    
+        if orca_state.zoomerType == settings.MAG_ZOOMER_TYPE_FULL_SCREEN \
+           and not self._fullScreenCapable:
+            orca_state.zoomerType += 1
+    
+        # We don't want to stomp on any command-altered settings
+        #
+        toRestore = {}
+    
+        [levelX, levelY] = self._zoomer.getMagFactor()
+        if levelX != _settingsManager.getSetting('magZoomFactor'):
+            toRestore['magZoomFactor'] = levelX
+    
+        if not orca_state.colorEnhancementsEnabled:
+            toRestore.update(\
+                {'enableMagZoomerColorInversion': False,
+                 'magBrightnessLevelRed': 0,
+                 'magBrightnessLevelGreen': 0,
+                 'magBrightnessLevelBlue': 0,
+                 'magContrastLevelRed': 0,
+                 'magContrastLevelGreen': 0,
+                 'magContrastLevelBlue': 0,
+                 'magColorFilteringMode': settings.MAG_COLOR_FILTERING_MODE_NONE,
+                 'magSmoothingMode': settings.MAG_SMOOTHING_MODE_BILINEAR,
+                 'magZoomerBorderColor': '#000000'})
+    
+        self.setupMagnifier(orca_state.zoomerType, restore = toRestore)
+    
+        if not orca_state.mouseEnhancementsEnabled:
+            self.setMagnifierCrossHair(False)
+            self.setMagnifierObjectColor("cursor-color",
+                                    _settingsManager.getSetting('magCursorColor'),
+                                    False)
+            self.setMagnifierCursor(False, False, 0)
+    
+        if orca_state.zoomerType == settings.MAG_ZOOMER_TYPE_FULL_SCREEN:
+            if self._fullScreenCapable:
+                # Translators: magnification will use the full screen.
+                #
+                zoomerType = _("Full Screen")
+            else:
+                # Translators: the user attempted to switch to full screen
+                # magnification, but his/her system doesn't support it.
+                #
+                zoomerType = _("Full Screen mode unavailable")
+        elif orca_state.zoomerType == settings.MAG_ZOOMER_TYPE_TOP_HALF:
+            # Translators: magnification will use the top half of the screen.
+            #
+            zoomerType = _("Top Half")
+        elif orca_state.zoomerType == settings.MAG_ZOOMER_TYPE_BOTTOM_HALF:
+            # Translators: magnification will use the bottom half of the screen.
+            #
+            zoomerType = _("Bottom Half")
+        elif orca_state.zoomerType == settings.MAG_ZOOMER_TYPE_LEFT_HALF:
+            # Translators: magnification will use the left half of the screen.
+            #
+            zoomerType = _("Left Half")
+        elif orca_state.zoomerType == settings.MAG_ZOOMER_TYPE_RIGHT_HALF:
+            # Translators: magnification will use the right half of the screen.
+            #
+            zoomerType = _("Right Half")
+        elif orca_state.zoomerType == settings.MAG_ZOOMER_TYPE_CUSTOM:
+            # Translators: the user has selected a custom area of the screen
+            # to use for magnification.
+            #
+            zoomerType = _("Custom")
+        else:
+            # This shouldn't happen, but just in case....
+            zoomerType = ""
+    
+        orca_state.activeScript.presentMessage(zoomerType)
+        
+        return True       
+    
+    def disable(self):
+        settings.enableMagnifier = False
+        self.isActive = False
+        self.shutdown()
+
+IPlugin.register(magPlugin)
diff --git a/src/orca/orca.py b/src/orca/orca.py
index f7db0be..0be6dfc 100644
--- a/src/orca/orca.py
+++ b/src/orca/orca.py
@@ -540,12 +540,20 @@ if settings.useDBus:
     import dbus.mainloop.glib
     dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
     import dbusserver
-    try:
-        import gsmag as mag
-    except:
-        import mag
-else:
-    import mag
+
+# NA: We're going to store the mag plugin
+# in a global variable called mag, so this
+# import isn't needed at this moment.
+#
+
+#try:
+#        import gsmag as mag
+#    except:
+#        import mag
+#else:
+#    import mag
+global mag
+mag = None
 
 import braille
 import httpserver
@@ -1512,8 +1520,17 @@ def loadUserSettings(script=None, inputEvent=None, skipReloadMessage=False):
     except:
         print 'Passing speech'
         pass
+
     braille.shutdown()
-    mag.shutdown()
+
+    # NA / TODO: Must do something smarter
+    # Hard code for speech plugin
+    #
+    try:
+        mag.shutdown()
+    except:
+        print 'Passing mag'
+        pass
 
     _scriptManager.deactivate()
 
@@ -1587,7 +1604,14 @@ def loadUserSettings(script=None, inputEvent=None, skipReloadMessage=False):
             debug.println(debug.LEVEL_WARNING,
                           "Could not initialize connection to braille.")
 
-    if settings.enableMagnifier:
+    if settings.enableMagnifier and 'mag' in activePlugins:
+        mag = _pluginManager.getPluginObject('mag')
+    elif settings.enableMagnifier and 'gsmag' in activePlugins:
+        mag = _pluginManager.getPluginObject('gsmag')
+
+    print activePlugins
+
+    if settings.enableMagnifier and ('mag' in activePlugins or 'gsmag' in activePlugins):
         try:
             mag.init()
             debug.println(debug.LEVEL_CONFIGURATION,
@@ -2126,6 +2150,11 @@ def shutdown(script=None, inputEvent=None):
     _eventManager.deactivate()
     _scriptManager.deactivate()
 
+    # Here, we're getting plugins for settingsManager
+    plugins = _settingsManager.getPlugins()
+    # What plugins will be enabled?
+    activePlugins = [plug for plug in plugins if plugins[plug]['active']]
+
     # Shutdown all the other support.
     #
     if settings.enableSpeech:
@@ -2133,6 +2162,15 @@ def shutdown(script=None, inputEvent=None):
     if settings.enableBraille:
         braille.shutdown()
     if settings.enableMagnifier or settings.enableMagLiveUpdating:
+        if  'mag' in activePlugins:
+            mag = _pluginManager.getPluginObject('mag')
+        elif 'gsmag' in activePlugins:
+            mag = _pluginManager.getPluginObject('gsmag')
+        else:
+            mag = _pluginManager.getPluginObject('mag')
+
+        print mag
+
         mag.shutdown()
 
     if settings.timeoutCallback and (settings.timeoutTime > 0):
diff --git a/src/orca/orca_gui_prefs.py b/src/orca/orca_gui_prefs.py
index c9692f0..7bdd7ab 100644
--- a/src/orca/orca_gui_prefs.py
+++ b/src/orca/orca_gui_prefs.py
@@ -2257,6 +2257,8 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         self._initPluginsTreeView()
 
         self.__updateSpeechTab(self.currentPluginsStatus['speech']['active'])
+        #self.__updateMagTab(self.currentPluginsStatus['mag']['active'])
+        #self.__updateGsmagTab(self.currentPluginsStatus['gsmag']['active'])
 
     def _initPluginsTreeView(self):
 
@@ -2330,16 +2332,46 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         plugin_name = self.plugins_store[path][4]
         self.currentPluginsStatus[plugin_name]['active'] = active
         self.plugins_store[path][0] = active
-        if active == True:
+
+        # NA: hardcode!!! change this by the correct value
+        # obtained by the name 'magPlugin' and 'gsmagPlugin'!
+        orca_magnifier = self.plugins_store[3][0]
+        gs_magnifier = self.plugins_store[2][0]
+
+        mag_exception = False
+
+        if plugin_name == 'gsmag':
+            if not self.__checkGsmag(active) or orca_magnifier:
+                self.plugins_store[path][0] = False
+                active = False
+                mag_exception = True
+
+        if plugin_name == 'mag':
+            if gs_magnifier:
+                self.plugins_store[path][0] = False
+                active = False
+                mag_exception = True
+
+        if active:
             _pluginManager.enablePlugin(plugin_name)
         else:
-            _pluginManager.disablePlugin(plugin_name)
+            if (plugin_name == 'gsmag' or plugin_name == 'mag') and not mag_exception:
+                _pluginManager.disablePlugin(plugin_name)
+            elif plugin_name != 'gsmag' and plugin_name != 'mag':
+                _pluginManager.disablePlugin(plugin_name)
 
         if plugin_name == 'speech':
             self.__updateSpeechTab(active)
             self.__reloadSpeechModule(active)
             self.applyButtonClicked(self.get_widget('notebook'))
-
+        elif plugin_name == 'gsmag' and not mag_exception:
+            self.__updateMagTab(active)
+            self.__reloadGsmagModule(active)
+            self.applyButtonClicked(self.get_widget('notebook'))
+        elif plugin_name == 'mag' and not mag_exception:
+            self.__updateMagTab(active)
+            self.__reloadMagModule(active)
+            self.applyButtonClicked(self.get_widget('notebook'))
 # nacho's
 #        if active:
 #            self.currentPluginsStatus[plugin_name]
@@ -2347,6 +2379,22 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
 #            self.currentPluginsStatus[plugin_name]
 #        self.plugins_store[path][0] = checkbox.get_active()
 
+    # NA: this is a hardcode feature,
+    # maybe we must to do this as IDependenciesChecker
+    def __checkGsmag(self, active):
+        if active == True:
+            try:
+                import dbus
+                _bus = dbus.SessionBus()
+                _proxy_obj = _bus.get_object("org.gnome.Magnifier",
+                                             "/org/gnome/Magnifier")
+                _magnifier = dbus.Interface(_proxy_obj, "org.gnome.Magnifier")
+                return True
+            except dbus.exceptions.DBusException:
+                return False
+
+        return True
+
     def __updateSpeechTab(self, active):
         notebook = self.get_widget('notebook')
         speechTab = notebook.get_nth_page(1)
@@ -2364,6 +2412,20 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
 #        speech = _pluginManager.getPluginObject('speech')
 #        if speech == None: import dummyspeech as speech
 
+    # We really need this method?
+    def __reloadMagModule(self, active):
+        mag.isActive = active
+
+    # We really need this method?
+    def __reloadGsmagModule(self, active):
+        gsmag.isActive = active
+
+    def __updateMagTab(self, active):
+        notebook = self.get_widget('notebook')
+        gsmagTab = notebook.get_nth_page(4)
+
+        self.get_widget("magnifierSupportCheckButton").set_active(active)
+
     def __initProfileCombo(self):
         """Adding available profiles and setting active as the active one"""
 



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