[orca] Add provisional support for GNOME Shell magnifier service
- From: William Walker <wwalker src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [orca] Add provisional support for GNOME Shell magnifier service
- Date: Mon, 9 Nov 2009 18:08:26 +0000 (UTC)
commit b93d140c3258ff8a8d9f90161682bc07e66f8a95
Author: Willie Walker <william walker sun com>
Date: Mon Nov 9 13:08:14 2009 -0500
Add provisional support for GNOME Shell magnifier service
src/orca/Makefile.am | 1 +
src/orca/default.py | 5 +-
src/orca/gsmag.py | 556 +++++++++++++++++++++++++++++
src/orca/orca.py | 5 +-
src/orca/orca_gui_prefs.py | 5 +-
src/orca/scripts/apps/metacity.py | 5 +-
src/orca/scripts/toolkits/Gecko/script.py | 5 +-
7 files changed, 577 insertions(+), 5 deletions(-)
---
diff --git a/src/orca/Makefile.am b/src/orca/Makefile.am
index 04776f8..1f70384 100644
--- a/src/orca/Makefile.am
+++ b/src/orca/Makefile.am
@@ -28,6 +28,7 @@ orca_python_PYTHON = \
formatting.py \
generator.py \
gnomespeechfactory.py \
+ gsmag.py \
httpserver.py \
input_event.py \
keybindings.py \
diff --git a/src/orca/default.py b/src/orca/default.py
index f53794a..d8e53d9 100644
--- a/src/orca/default.py
+++ b/src/orca/default.py
@@ -43,7 +43,10 @@ import find
import flat_review
import input_event
import keybindings
-import mag
+try:
+ import gsmag as mag
+except:
+ import mag
import outline
import orca
import orca_prefs
diff --git a/src/orca/gsmag.py b/src/orca/gsmag.py
new file mode 100644
index 0000000..e6ba56a
--- /dev/null
+++ b/src/orca/gsmag.py
@@ -0,0 +1,556 @@
+# Orca
+#
+# Copyright 2009 Sun Microsystems Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library 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.
+
+"""Manages the GNOME Shell magnifier interface for orca. [[[TODO: WDW
+- this is very very early in development. One might even say it is
+pre-prototype.]]]"""
+
+__id__ = "$Id$"
+__version__ = "$Revision$"
+__date__ = "$Date$"
+__copyright__ = "Copyright (c) 2009 Sun Microsystems Inc."
+__license__ = "LGPL"
+
+import dbus
+_bus = dbus.SessionBus()
+_proxy_obj = _bus.get_object("org.gnome.Shell", "/org/gnome/Shell/Magnifier")
+_magnifier = dbus.Interface(_proxy_obj, "org.gnome.Shell.Magnifier")
+
+import eventsynthesizer
+import settings
+import speech
+
+# If True, the magnifier is active
+#
+_isActive = False
+
+# Whether or not we're in the process of making "live update" changes
+# to the location of the magnifier.
+#
+_liveUpdatingMagnifier = False
+
+# The current modes of tracking, for use with "live update" changes.
+#
+_controlTracking = None
+_edgeMargin = None
+_mouseTracking = None
+_pointerFollowsZoomer = None
+_pointerFollowsFocus = None
+_textTracking = None
+
+########################################################################
+# #
+# Methods for magnifying objects #
+# #
+########################################################################
+
+def _setROICenter(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
+ """
+ _magnifier.shiftContentsTo(x, y)
+
+def _setROICursorPush(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.]]]
+ #
+ (screenWidth, screenHeight) = _magnifier.getScreenSize()
+ edgeMargin = min(edgeMargin, 50)/100.00
+ edgeMarginX = edgeMargin * screenWidth/settings.magZoomFactor
+ edgeMarginY = edgeMargin * 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, roiWidth, roiHeight) = _magnifier.getROI()
+ 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(screenWidth - 1, 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(screenHeight - 1, y + edgeMarginY)
+ if height > roiHeight:
+ y1 = y
+ y2 = y1 + roiHeight
+ else:
+ y2 = y + height
+ y1 = y2 - roiHeight
+
+ _setROICenter((x1 + x2) / 2, (y1 + y2) / 2)
+
+def magnifyAccessible(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
+ """
+ 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 _textTracking == settings.MAG_TRACKING_MODE_CENTERED:
+ _setROICenter(x, y)
+ elif _textTracking == settings.MAG_TRACKING_MODE_PUSH:
+ _setROICursorPush(x, y, width, height, _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 _pointerFollowsFocus:
+ _lastMouseEventWasRoute = True
+ eventsynthesizer.generateMouseEvent(x, y + height - 1, "abs")
+
+ if _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 > _roiWidth:
+ centerX = x
+ if height > _roiHeight:
+ centerY = y
+
+ _setROICenter(centerX, centerY)
+ elif _controlTracking == settings.MAG_TRACKING_MODE_PUSH:
+ _setROICursorPush(x, y, width, height)
+
+########################################################################
+# #
+# Methods for updating live tracking settings #
+# #
+########################################################################
+
+def updateControlTracking(newMode):
+ """Updates the control tracking mode.
+
+ Arguments:
+ -newMode: The new mode to use.
+ """
+ global _controlTracking
+ _controlTracking = newMode
+
+def updateEdgeMargin(amount):
+ """Updates the edge margin
+
+ Arguments:
+ -amount: The new margin to use, in pixels.
+ """
+ global _edgeMargin
+ _edgeMargin = amount
+
+def updateMouseTracking(newMode):
+ """Updates the mouse tracking mode.
+
+ Arguments:
+ -newMode: The new mode to use.
+ """
+ global _mouseTracking
+ _mouseTracking = newMode
+
+def updatePointerFollowsFocus(enabled):
+ """Updates the pointer follows focus setting.
+
+ Arguments:
+ -enabled: whether or not pointer follows focus should be enabled.
+ """
+ global _pointerFollowsFocus
+ _pointerFollowsFocus = enabled
+
+def updatePointerFollowsZoomer(enabled):
+ """Updates the pointer follows zoomer setting.
+
+ Arguments:
+ -enabled: whether or not pointer follows zoomer should be enabled.
+ """
+ global _pointerFollowsZoomer
+ _pointerFollowsZoomer = enabled
+
+def updateTextTracking(newMode):
+ """Updates the text tracking mode.
+
+ Arguments:
+ -newMode: The new mode to use.
+ """
+ global _textTracking
+ _textTracking = newMode
+
+def finishLiveUpdating():
+ """Restores things that were altered via a live update."""
+
+ global _liveUpdatingMagnifier
+ global _controlTracking
+ global _edgeMargin
+ global _mouseTracking
+ global _pointerFollowsFocus
+ global _pointerFollowsZoomer
+ global _textTracking
+
+ _liveUpdatingMagnifier = False
+ _mouseTracking = settings.magMouseTrackingMode
+ _controlTracking = settings.magControlTrackingMode
+ _textTracking = settings.magTextTrackingMode
+ _edgeMargin = settings.magEdgeMargin
+ _pointerFollowsFocus = settings.magPointerFollowsFocus
+ _pointerFollowsZoomer = settings.magPointerFollowsZoomer
+
+ if settings.enableMagnifier:
+ setupMagnifier(settings.magZoomerType)
+ init()
+ else:
+ shutdown()
+
+########################################################################
+# #
+# Methods for updating appearance settings #
+# #
+########################################################################
+
+def applySettings():
+ """Looks at the user settings and applies them to the magnifier."""
+ # [[[WDW - To be implemented]]]
+ pass
+
+def hideSystemPointer(hidePointer):
+ """Hide or show the system pointer.
+
+ Arguments:
+ -hidePointer: If True, hide the system pointer, otherwise show it.
+ """
+ # [[[WDW - To be implemented]]]
+ pass
+
+def setupMagnifier(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
+ """
+ # [[[WDW - To be implemented]]]
+ global _liveUpdatingMagnifier
+ _liveUpdatingMagnifier = True
+
+def setMagnifierCursor(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(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
+ """
+ # [[[WDW - To be implemented]]]
+ pass
+
+def setMagnifierCrossHairClip(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
+ """
+ # [[[WDW - To be implemented]]]
+ pass
+
+def setMagnifierObjectColor(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
+ """
+ # [[[WDW - To be implemented]]]
+ pass
+
+def setMagnifierObjectSize(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
+ """
+ # [[[WDW - To be implemented]]]
+ pass
+
+def setZoomerBrightness(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(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(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(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(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
+ """
+ _magnifier.setMagFactor(x, y)
+
+def setZoomerObjectColor(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(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(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(script=None, inputEvent=None):
+ """Allows the user to cycle through the available zoomer types."""
+ # [[[WDW - To be implemented]]]
+ pass
+
+def decreaseMagnification(script=None, inputEvent=None):
+ """Decreases the magnification level."""
+ # [[[WDW - To be implemented]]]
+ pass
+
+def increaseMagnification(script=None, inputEvent=None):
+ """Increases the magnification level."""
+ # [[[WDW - To be implemented]]]
+ pass
+
+def toggleColorEnhancements(script=None, inputEvent=None):
+ """Toggles the color enhancements on/off."""
+ # [[[WDW - To be implemented]]]
+ pass
+
+def toggleMouseEnhancements(script=None, inputEvent=None):
+ """Toggles the mouse enhancements on/off."""
+ # [[[WDW - To be implemented]]]
+ pass
+
+def toggleMagnifier(script=None, inputEvent=None):
+ """Toggles the magnifier."""
+ if not _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.
+ #
+ speech.speak(_("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.
+ #
+ speech.speak(_("Magnifier disabled."))
+
+########################################################################
+# #
+# Methods for obtaining magnifier capabilities #
+# #
+########################################################################
+
+def isFilteringCapable():
+ """Returns True if we're able to take advantage of libcolorblind's color
+ filtering.
+ """
+ # [[[WDW - To be implemented]]]
+ return False
+
+def isFullScreenCapable():
+ """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():
+ global _isActive
+ _magnifier.setActive(True)
+ _magnifier.setMagFactor(settings.magZoomFactor, settings.magZoomFactor)
+ _magnifier.setScreenPosition("Full Screen")
+ _isActive = _magnifier.isActive()
+
+def shutdown():
+ global _isActive
+ _magnifier.setActive(False)
+ _isActive = _magnifier.isActive()
diff --git a/src/orca/orca.py b/src/orca/orca.py
index b185c17..0cf7484 100644
--- a/src/orca/orca.py
+++ b/src/orca/orca.py
@@ -67,7 +67,10 @@ import debug
import httpserver
import keynames
import keybindings
-import mag
+try:
+ import gsmag as mag
+except:
+ import mag
import orca_state
import platform
import settings
diff --git a/src/orca/orca_gui_prefs.py b/src/orca/orca_gui_prefs.py
index fe625ba..addb58a 100644
--- a/src/orca/orca_gui_prefs.py
+++ b/src/orca/orca_gui_prefs.py
@@ -34,7 +34,10 @@ import pango # for ellipsize property constants of CellRendererText
import locale
import acss
-import mag
+try:
+ import gsmag as mag
+except:
+ import mag
import orca
import orca_gtkbuilder
import orca_prefs
diff --git a/src/orca/scripts/apps/metacity.py b/src/orca/scripts/apps/metacity.py
index d8a897b..37d2799 100644
--- a/src/orca/scripts/apps/metacity.py
+++ b/src/orca/scripts/apps/metacity.py
@@ -27,7 +27,10 @@ __license__ = "LGPL"
import orca.braille as braille
import orca.default as default
-import orca.mag as mag
+try:
+ import orca.gsmag as mag
+except:
+ import orca.mag as mag
import orca.speech as speech
import pyatspi
diff --git a/src/orca/scripts/toolkits/Gecko/script.py b/src/orca/scripts/toolkits/Gecko/script.py
index 4bb4799..f4846e9 100644
--- a/src/orca/scripts/toolkits/Gecko/script.py
+++ b/src/orca/scripts/toolkits/Gecko/script.py
@@ -54,7 +54,10 @@ import orca.eventsynthesizer as eventsynthesizer
import orca.input_event as input_event
import orca.keybindings as keybindings
import orca.liveregions as liveregions
-import orca.mag as mag
+try:
+ import orca.gsmag as mag
+except:
+ import orca.mag as mag
import orca.orca as orca
import orca.orca_state as orca_state
import orca.rolenames as rolenames
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]