I've attached an alternate patch to Orca to fix the caps lock problem
that does not require any change to any other package.  It's a bit of
a hack.  It calls xkbcomp to get the entire keyboard state, makes the
change we need, and calls xkbcomp again to write the modified keyboard
map.

On the positive side, it should in theory just work for everyone, and
there's no need to delay the fix while we wait on an upstream patch.
My recommendation is to go ahead and apply (and Orca-fy) the patch to
orca.py while we wait for upstream to add the new caps mode, and for
the various distros that work with orca to ship with the new mode.
Then we can ship the simpler patch that just enables the new caps lock
mode.

I'll get the upstream patch started ASAP, after a meeting I'm about to
attend.  However, it will probably be a while before Orca can count on
having the new caps mode.  In the meantime, this hack should work
well.

Bill

On Wed, Nov 9, 2011 at 9:54 AM, Don Marang <[email protected]> wrote:
> Great work!  It appears that the right people are prepared to implement this
> change for orca and Ubuntu.
>
> Do I read this right that a change is also required from another package,
> setxkbmap?  Has the developers of this package been notified?  I have no
> visibility into their development.  Are they receptive or will we need to
> nag to get this change implemented?
>
>
> Don Marang
>
> On 11/8/2011 5:33 PM, Bill Cox wrote:
>
> The old xmodmap program seems to be beginning to break down.  It's
> considered obsolete and has been replaced with setxkbmap.  Orca uses
> xmodmap to disable the caps lock key, but in newer versions of
> xmodmap, that also causes it to no longer work as a modifier key.  I
> believe this is why we're seeing the caps lock key Unbuntu Oneiric
> toggling whenever pressed.
>
> On my system, I got it working with a patch to Orca to use setxkbmap,
> and by editing some configuration files in the xkeyboard-config
> package to add a new caps lock configuration, which I called "orca".
> Done this way, this option shows up in the Keyboard settings dialog
> along with the other settings for the caps lock key, which is kind of
> cool.  I have Orca enable the orca mode with:
>
> setxkbmap -option caps:orca
>
> and disable it with:
>
> setxkbmap -option
>
> I've attached diff files created with diff -Naur.  The orca.py patch
> is fairly simple.  The down side is that it requires the new orca mode
> in the xkb configuration, so these patches have to be in sync.
>
> Bill
>
> --
> You received this message because you are subscribed to the Google
> Groups Vinux Development Forum.
> To post to this group, send email to [email protected]
> To unsubscribe from this group, send email to
> [email protected]
> For more options, visit this group at
> http://groups.google.com/group/vinux-development?hl=en?hl=en
>
> Vinux Home Page: http://vinuxproject.org/
> Vinux Wiki Documentation: http://wiki.vinuxproject.org/
>
--- orca.py.saved	2011-11-08 17:11:33.584217326 -0500
+++ orca.py	2011-11-09 15:03:18.153468609 -0500
@@ -29,6 +29,8 @@
 
 import getopt
 import os
+import subprocess
+import re
 import signal
 import sys
 import time
@@ -1415,6 +1417,45 @@
         settings.silenceSpeech = True
     return True
 
+def _setXmodmap(xkbmap):
+    """Set the keyboard map using xkbcomp."""
+    p = subprocess.Popen(['xkbcomp', '-w0', '-', os.environ['DISPLAY']],
+        stdin=subprocess.PIPE, stdout=None, stderr=None)
+    p.communicate(xkbmap)
+
+def _setCapsLockAsOrcaModifier(enable):
+    """Enable or disable use of the caps lock key as an Orca modifier key."""
+    interpretCapsLineProg = re.compile(
+        r'^\s*interpret\s+Caps[_+]Lock[_+]AnyOfOrNone\s*\(all\)\s*{\s*$', re.I)
+    capsModLineProg = re.compile(
+        r'^\s*action\s*=\s*SetMods\s*\(\s*modifiers\s*=\s*Lock\s*,\s*clearLocks\s*\)\s*;\s*$', re.I)
+    normalCapsLineProg = re.compile(
+        r'^\s*action\s*=\s*LockMods\s*\(\s*modifiers\s*=\s*Lock\s*\)\s*;\s*$', re.I)
+    normalCapsLine = '        action= LockMods(modifiers=Lock);'
+    capsModLine =    '        action= SetMods(modifiers=Lock,clearLocks);'
+    global _originalXmodmap
+    lines = _originalXmodmap.split('\n')
+    foundCapsInterpretSection = False
+    for i in range(len(lines)):
+        line = lines[i]
+        if not foundCapsInterpretSection:
+            if interpretCapsLineProg.match(line):
+                foundCapsInterpretSection = True
+        else:
+            if enable:
+                if normalCapsLineProg.match(line):
+                    lines[i] = capsModLine
+                    _setXmodmap('\n'.join(lines))
+                    return
+            else:
+                if capsModLineProg.match(line):
+                    lines[i] = normalCapsLine
+                    _setXmodmap('\n'.join(lines))
+                    return
+            if line.find('}'):
+                # Failed to find the line we need to change
+                return
+
 def _createOrcaXmodmap():
     """Makes an Orca-specific Xmodmap so that the keys behave as we
     need them to do. This is especially the case for the Orca modifier.
@@ -1424,21 +1465,12 @@
 
     cmd = []
     if "Caps_Lock" in settings.orcaModifierKeys:
-        cmd.append("clear Lock")
+        _setCapsLockAsOrcaModifier(True)
         _capsLockCleared = True
     elif _capsLockCleared:
-        cmd.append("add Lock = Caps_Lock")
+        _setCapsLockAsOrcaModifier(False)
         _capsLockCleared = False
 
-    # Clear other keysyms so that we always treat the Orca modifier as
-    # the Orca modifier (e.g. remove KP_0 from KP_Insert).
-    #
-    for keyName in settings.orcaModifierKeys:
-        if keyName in ["Caps_Lock", "KP_Insert", "Insert"]:
-            cmd.append("keysym %s = %s" % (keyName, keyName))
-
-    os.system("echo '%s' | xmodmap - > /dev/null 2>&1" % "\n".join(cmd))
-
 def _storeXmodmap(keyList):
     """Save the original xmodmap for the keys in keyList before we alter it.
 
@@ -1447,12 +1479,7 @@
     """
 
     global _originalXmodmap
-
-    items = "|".join(keyList)
-    cmd = "xmodmap -pke | grep -E '(%s)'" % items
-    filehandle = os.popen(cmd)
-    _originalXmodmap = filehandle.read()
-    filehandle.close()
+    _originalXmodmap = subprocess.check_output(['xkbcomp', os.environ['DISPLAY'], '-'])
 
 def _restoreXmodmap(keyList=[]):
     """Restore the original xmodmap values for the keys in keyList.
@@ -1462,21 +1489,11 @@
       to restore the entire saved xmodmap.
     """
 
-    toRestore = []
-    lines = _originalXmodmap.split("\n")
-    if not keyList:
-        toRestore = lines
-
-    for key in keyList:
-        line = filter(lambda k: " %s" % key in k, lines)
-        toRestore.extend(line)
-
     global _capsLockCleared
-    if _capsLockCleared:
-        toRestore.append("add Lock = Caps_Lock")
-        _capsLockCleared = False
-
-    os.system("echo '%s' | xmodmap - > /dev/null 2>&1" % "\n".join(toRestore))
+    _capsLockCleared = False
+    p = subprocess.Popen(['xkbcomp', '-w0', '-', os.environ['DISPLAY']],
+        stdin=subprocess.PIPE, stdout=None, stderr=None)
+    p.communicate(_originalXmodmap)
 
 def loadUserSettings(script=None, inputEvent=None, skipReloadMessage=False):
     """Loads (and reloads) the user settings module, reinitializing
-- 
Ubuntu-accessibility mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-accessibility

Reply via email to