Ticket #3233: 0001-Adding-new-layout-for-olpc-non-membrane-keyboard.patch

File 0001-Adding-new-layout-for-olpc-non-membrane-keyboard.patch, 31.3 KB (added by manuq, 12 years ago)
  • new file images/OLPCM_Rhand_ENTER.svg

    From 3eaab22eeca85db1da1abfb28008030682ff3719 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?Manuel=20Qui=C3=B1ones?= <manuq@laptop.org>
    Date: Wed, 23 Nov 2011 16:43:26 -0300
    Subject: [PATCH] Adding new layout for olpc non-membrane keyboard
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    This fixes bug #3233 .
    
    A new hand graphic was made for the Enter key in the olpcm model.
    There are other special characters in that model that may require new
    hand graphics, but adding the Enter is enough for the default lessions.
    
    Signed-off-by: Manuel Quiñones <manuq@laptop.org>
    ---
     images/OLPCM_Rhand_ENTER.svg |   40 +++++++++++
     keyboard.py                  |  157 ++++++++----------------------------------
     keybuilder.py                |    2 +-
     layouts/__init__.py          |    1 +
     layouts/olpc.py              |  148 +++++++++++++++++++++++++++++++++++++++
     layouts/olpcm.py             |  139 +++++++++++++++++++++++++++++++++++++
     lessonbuilder.py             |    2 +-
     lessonscreen.py              |    2 +-
     8 files changed, 361 insertions(+), 130 deletions(-)
     create mode 100644 images/OLPCM_Rhand_ENTER.svg
     create mode 100644 layouts/__init__.py
     create mode 100644 layouts/olpc.py
     create mode 100644 layouts/olpcm.py
    
    diff --git a/images/OLPCM_Rhand_ENTER.svg b/images/OLPCM_Rhand_ENTER.svg
    new file mode 100644
    index 0000000..c805b1c
    - +  
     1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
     2<!-- Created with Inkscape (http://www.inkscape.org/) -->
     3
     4<svg
     5   xmlns:dc="http://purl.org/dc/elements/1.1/"
     6   xmlns:cc="http://creativecommons.org/ns#"
     7   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     8   xmlns:svg="http://www.w3.org/2000/svg"
     9   xmlns="http://www.w3.org/2000/svg"
     10   version="1.0"
     11   width="3146"
     12   height="1214"
     13   viewBox="-140.708 -446.507 3146 1214"
     14   id="svg4539"
     15   xml:space="preserve"
     16   style="display:inline"><metadata
     17   id="metadata4556"><rdf:RDF><cc:Work
     18       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
     19         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata>
     20  <defs
     21   id="defs4541" />
     22 
     23 
     24 
     25<g
     26   id="layer3"
     27   style="display:inline"><g
     28     transform="matrix(0.9769353,-0.21353555,0.21353555,0.9769353,25.457565,338.81883)"
     29     id="XMLID_76_"
     30     style="display:inline"><g
     31       id="g8462" /><g
     32       id="g8464"><path
     33         d="m 2536.617,785.13959 c -12.8163,26.04975 -24.2198,51.87168 -35.5898,71.62684 -24.7813,42.8412 -43.838,96.85436 -58.3345,137.05167 -10.2821,28.2928 -11.6954,26.1767 -18.0132,58.8338 -6.7993,34.6164 9.7098,90.4556 18.8985,124.3226 18.1175,67.7898 15.6181,62.8026 24.2733,133.2103 2.2349,19.0287 -2.6883,39.8983 -0.2076,59.424 4.6136,38.7158 26.0188,78.1587 42.5812,119.3481 102.2198,254.483 211.0823,550.6756 305.1532,807.4905 -107.1062,65.8825 -247.0465,124.9235 -402.5153,150.6571 -91.5459,-228.9145 -181.7022,-480.3993 -270.8303,-725.9243 -13.2872,-36.2692 -23.6439,-77.99 -40.9115,-96.6205 -17.5293,-18.5732 -45.4678,-13.703 -77.5227,-22.6413 -31.5762,-8.6304 -69.823,-33.9453 -113.4287,-51.0801 -42.8354,-16.7535 -92.4357,-22.9551 -120.1209,-36.422 -33.8211,-16.3859 -67.9369,-61.1607 -105.2561,-89.1534 -42.8982,-32.1338 -97.1516,-45.1531 -124.1471,-85.0242 -14.115,-20.5561 -16.7011,-47.4809 -28.4216,-69.6607 -25.1781,-47.277 -68.0657,-95.0836 -63.4315,-154.3747 65.6704,-41.0201 135.8098,10.7262 170.6851,71.554 10.0604,17.7317 11.0569,41.1542 22.52,57.7543 28.7216,42.1061 107.037,54.5397 159.1747,64.1737 21.3714,-55.6655 3.4236,-138.5937 -19.7098,-187.8305 -47.986,-101.9466 -113.5227,-162.00141 -164.6858,-263.38977 -23.6953,-46.77813 -91.9399,-174.12264 -23.7767,-199.33134 46.2893,-17.12746 64.1962,22.66867 83.3211,64.25806 63.2732,98.04392 129.3004,172.20347 202.7675,235.34844 4.081,-30.59574 0.4072,-28.35931 -8.6846,-56.74868 -30.8927,-96.05989 -81.6763,-164.27004 -109.5562,-259.75197 11.1048,-47.92359 78.2113,-49.67154 107.734,-20.24906 46.7916,64.40787 75.454,149.32169 113.7973,234.82003 11.1423,25.19176 31.4574,46.13302 56.4573,61.14798 12.7043,-51.29697 -13.1424,-90.84102 -12.7307,-152.57195 0.2872,-62.93351 -17.9479,-122.20993 -2.5238,-170.49899 20.513,-23.7043 66.7897,-26.56619 87.5465,0.72937 16.8812,22.42899 51.0785,154.59646 57.4636,214.14573 22.8961,55.36226 39.5742,71.74456 67.3275,113.03894 l 0,0 0,0 c 60.8732,-29.15188 134.5701,-103.92662 168.5026,-154.70241 3.2055,-4.79908 6.2724,-10.49999 9.2888,-16.79143"
     34         transform="matrix(0.97693529,0.21353555,-0.21353555,0.97693529,5.3619769,-802.69477)"
     35         id="path10018"
     36         style="fill:none;stroke:#9c6b54;stroke-width:16;stroke-linecap:round" /><path
     37         d="m 2433.7108,751.30775 c 23.3512,-48.70355 43.6852,-132.7951 102.011,-107.84931 53.6887,23.02294 26.9621,88.77883 3.0222,137.3833 -0.7134,1.43266 -1.4224,2.8656 -2.127,4.29785"
     38         transform="matrix(0.97693529,0.21353555,-0.21353555,0.97693529,5.3619769,-802.69477)"
     39         id="path8466"
     40         style="color:#000000;fill:none;stroke:#fcb054;stroke-width:16;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /></g></g></g></svg>
     41 No newline at end of file
  • keyboard.py

    diff --git a/keyboard.py b/keyboard.py
    index 45389f7..35daeed 100644
    a b import rsvg 
    2323import os, glob, re
    2424import pango
    2525from port import json
     26import subprocess
     27from layouts.olpc import OLPC_LAYOUT
     28from layouts.olpcm import OLPCM_LAYOUT
    2629
    2730# Tweaking variables.
    2831HAND_YOFFSET = -15
    KEY_PROPS = [ 
    8992    { 'name': 'key-pressed', 'default': False },
    9093]
    9194
    92 # This is the OLPC XO-1 keyboard layout.
    93 #
    94 # The keyboard layout is described by the following data structure. The structure
    95 # has three levels: Layout, Groups, and Keys.  A Layout contains a list of Groups,
    96 # each of which contains a list of Keys.  Groups are intended to be a way to collect
    97 # related keys (e.g. nearby each other on the keyboard with similar properties)
    98 # together.
    99 #
    100 # Entirely new keyboard layouts can be created just by copying this structure and
    101 # modifying the following values, without changing the code.
    102 OLPC_LAYOUT = {
    103     'layout-name': "olpc",
     95def _is_olpcm_model():
     96    """Check via setxkbmap if the keyboard model is olpcm.
    10497
    105     'layout-width': 775,
    106     'layout-height': 265,
     98    Keyboard model code is 'olpcm' for non-membrane, mechanical
     99    keyboard, and 'olpc' for membrane keyboard.
    107100
    108     'group-layout': 'horizontal',
     101    """
     102    code = None
     103    p = subprocess.Popen(["setxkbmap", "-query"], stdout=subprocess.PIPE)
     104    out, err = p.communicate()
     105    for line in out.splitlines():
     106        if line.startswith('model:'):
     107            code = line.split()[1]
     108    return code == 'olpcm'
    109109
    110     'key-width': 45,
    111     'key-height': 45,
    112     'key-gap': 5,
     110def get_layout():
     111    if _is_olpcm_model():
     112        return OLPCM_LAYOUT
     113    else:
     114        return OLPC_LAYOUT
    113115
    114     'groups': [
    115         {
    116             'group-name': "numbers",
    117             'group-x': 10,
    118             'group-y': 10,
    119            
    120             'keys': [
    121                 {'key-scan':0x31,'key-finger':'LP','key-hand-image':'OLPC_Lhand_tilde.svg','key-width':35},
    122                 {'key-scan':0x0a,'key-finger':'LP','key-hand-image':'OLPC_Lhand_1.svg'},
    123                 {'key-scan':0x0b,'key-finger':'LR','key-hand-image':'OLPC_Lhand_2.svg'},
    124                 {'key-scan':0x0c,'key-finger':'LM','key-hand-image':'OLPC_Lhand_3.svg'},
    125                 {'key-scan':0x0d,'key-finger':'LI','key-hand-image':'OLPC_Lhand_4.svg'},
    126                 {'key-scan':0x0e,'key-finger':'LI','key-hand-image':'OLPC_Lhand_5.svg'},
    127                 {'key-scan':0x0f,'key-finger':'RI','key-hand-image':'OLPC_Rhand_6.svg'},
    128                 {'key-scan':0x10,'key-finger':'RI','key-hand-image':'OLPC_Rhand_7.svg'},
    129                 {'key-scan':0x11,'key-finger':'RM','key-hand-image':'OLPC_Rhand_8.svg'},
    130                 {'key-scan':0x12,'key-finger':'RR','key-hand-image':'OLPC_Rhand_9.svg'},
    131                 {'key-scan':0x13,'key-finger':'RP','key-hand-image':'OLPC_Rhand_0.svg'},
    132                 {'key-scan':0x14,'key-finger':'RP','key-hand-image':'OLPC_Rhand_minus.svg'},
    133                 {'key-scan':0x15,'key-finger':'RP','key-hand-image':'OLPC_Rhand_plus.svg','key-width':65},
    134                 {'key-scan':0x16,'key-finger':'RP','key-label':"erase",'key-width':95}
    135             ]
    136         },
    137         {
    138             'group-name': "top",
    139             'group-x': 10,
    140             'group-y': 60,
    141            
    142             'keys': [
    143                 {'key-scan':0x17,'key-finger':'LP','key-label':"tab"},
    144                 {'key-scan':0x18,'key-finger':'LP','key-hand-image':'OLPC_Lhand_Q.svg'},
    145                 {'key-scan':0x19,'key-finger':'LR','key-hand-image':'OLPC_Lhand_W.svg'},
    146                 {'key-scan':0x1a,'key-finger':'LM','key-hand-image':'OLPC_Lhand_E.svg'},
    147                 {'key-scan':0x1b,'key-finger':'LI','key-hand-image':'OLPC_Lhand_R.svg'},
    148                 {'key-scan':0x1c,'key-finger':'LI','key-hand-image':'OLPC_Lhand_T.svg'},
    149                 {'key-scan':0x1d,'key-finger':'RI','key-hand-image':'OLPC_Rhand_Y.svg'},
    150                 {'key-scan':0x1e,'key-finger':'RI','key-hand-image':'OLPC_Rhand_U.svg'},
    151                 {'key-scan':0x1f,'key-finger':'RM','key-hand-image':'OLPC_Rhand_I.svg'},
    152                 {'key-scan':0x20,'key-finger':'RR','key-hand-image':'OLPC_Rhand_O.svg'},
    153                 {'key-scan':0x21,'key-finger':'RP','key-hand-image':'OLPC_Rhand_P.svg'},
    154                 {'key-scan':0x22,'key-finger':'RP','key-hand-image':'OLPC_Rhand_bracketL.svg'},
    155                 {'key-scan':0x23,'key-finger':'RP','key-hand-image':'OLPC_Rhand_bracketR.svg','key-width':55},
    156                 {'key-scan':0x24,'key-finger':'RP','key-hand-image':'OLPC_Rhand_ENTER.svg','key-label':"enter",'key-width':95,'key-height':95}
    157             ]
    158         },
    159         {
    160             'group-name': "home",
    161             'group-x': 10,
    162             'group-y': 110,
    163            
    164             'keys': [
    165                 {'key-scan':0x25,'key-finger':'LP','key-label':"ctrl",'key-width':55},
    166                 {'key-scan':0x26,'key-finger':'LP','key-hand-image':'OLPC_Lhand_A.svg'},
    167                 {'key-scan':0x27,'key-finger':'LR','key-hand-image':'OLPC_Lhand_S.svg'},
    168                 {'key-scan':0x28,'key-finger':'LM','key-hand-image':'OLPC_Lhand_D.svg'},
    169                 {'key-scan':0x29,'key-finger':'LI','key-hand-image':'OLPC_Lhand_F.svg'},
    170                 {'key-scan':0x2a,'key-finger':'LI','key-hand-image':'OLPC_Lhand_G.svg'},
    171                 {'key-scan':0x2b,'key-finger':'RI','key-hand-image':'OLPC_Rhand_H.svg'},
    172                 {'key-scan':0x2c,'key-finger':'RI','key-hand-image':'OLPC_Rhand_J.svg'},
    173                 {'key-scan':0x2d,'key-finger':'RM','key-hand-image':'OLPC_Rhand_K.svg'},
    174                 {'key-scan':0x2e,'key-finger':'RR','key-hand-image':'OLPC_Rhand_L.svg'},
    175                 {'key-scan':0x2f,'key-finger':'RP','key-hand-image':'OLPC_Rhand_SEMICOLON.svg'},
    176                 {'key-scan':0x30,'key-finger':'RP','key-hand-image':'OLPC_Rhand_APOSTROPHE.svg'},
    177                 {'key-scan':0x33,'key-finger':'RP'}
    178             ]
    179         },
    180         {
    181             'group-name': "bottom",
    182             'group-x': 10,
    183             'group-y': 160,
    184            
    185             'keys': [
    186                 {'key-scan':0x32,'key-finger':'LP','key-hand-image':'OLPC_Lhand_SHIFT.svg','key-label':"shift",'key-width':75},
    187                 {'key-scan':0x34,'key-finger':'LP','key-hand-image':'OLPC_Lhand_Z.svg'},
    188                 {'key-scan':0x35,'key-finger':'LR','key-hand-image':'OLPC_Lhand_X.svg'},
    189                 {'key-scan':0x36,'key-finger':'LM','key-hand-image':'OLPC_Lhand_C.svg'},
    190                 {'key-scan':0x37,'key-finger':'LI','key-hand-image':'OLPC_Lhand_V.svg'},
    191                 {'key-scan':0x38,'key-finger':'LI','key-hand-image':'OLPC_Lhand_B.svg'},
    192                 {'key-scan':0x39,'key-finger':'RI','key-hand-image':'OLPC_Rhand_N.svg'},
    193                 {'key-scan':0x3a,'key-finger':'RI','key-hand-image':'OLPC_Rhand_M.svg'},
    194                 {'key-scan':0x3b,'key-finger':'RM','key-hand-image':'OLPC_Rhand_COMMA.svg'},
    195                 {'key-scan':0x3c,'key-finger':'RR','key-hand-image':'OLPC_Rhand_PERIOD.svg'},
    196                 {'key-scan':0x3d,'key-finger':'RP','key-hand-image':'OLPC_Rhand_QUESTIONMARK.svg'},
    197                 {'key-scan':0x3e,'key-finger':'RP','key-hand-image':'OLPC_Rhand_SHIFT.svg','key-label':"shift",'key-width':75},
    198                 {'key-scan':0x6f,'key-finger':'RP','key-label':""}, # Up
    199                 {'key-label':""}, # Language key
    200             ]
    201         },
    202         {
    203             'group-name': "space",
    204             'group-x': 10,
    205             'group-y': 210,
    206            
    207             'keys': [
    208                 {'key-label':"fn",'key-width':35},
    209                 {'key-label':"",'key-width':55}, # LHand
    210                 {'key-scan':0x40,'key-label':"alt",'key-width':55}, # LAlt
    211                 {'key-scan':0x41,'key-finger':'RT','key-hand-image':'OLPC_Rhand_SPACE.svg','key-width':325}, # Spacebar
    212                 {'key-scan':0x6c,'key-label':"altgr",'key-width':55}, # AltGr
    213                 {'key-label':"",'key-width':55}, # RHand
    214                 {'key-scan':0x71,'key-label':""}, # Left
    215                 {'key-scan':0x74,'key-label':""}, # Down
    216                 {'key-scan':0x72,'key-label':""}, # Right
    217             ]
    218         }
    219     ]
    220 }
    221116
    222117class KeyboardImages:
    223118    def __init__(self, width, height):
    class KeyboardImages: 
    227122        self.images = {}
    228123
    229124    def load_images(self):
    230         for filename in glob.iglob('images/OLPC_*.svg'):
    231             image = gtk.gdk.pixbuf_new_from_file_at_scale(filename, self.width, self.height, False)
     125
     126        # This is for not changing all the numbers of olpcm layout,
     127        # that was made based on the original olpc layout.
     128        scale_width = self.width
     129        if _is_olpcm_model():
     130            scale_width = int(scale_width * 1.1625)
     131
     132        for filename in glob.iglob('images/OLPC*.svg'):
     133            image = gtk.gdk.pixbuf_new_from_file_at_scale(filename, scale_width,
     134                                                          self.height, False)
    232135            name = os.path.basename(filename)
    233136            self.images[name] = image
    234137
  • keybuilder.py

    diff --git a/keybuilder.py b/keybuilder.py
    index 38ec6d1..bceab0d 100755
    a b try: 
    3535    k.load_letter_map(sys.argv[1])
    3636except:
    3737    pass
    38 k.set_layout(keyboard.OLPC_LAYOUT)
     38k.set_layout(keyboard.get_layout())
    3939
    4040savebtn = gtk.Button()
    4141savebtn.add(gtk.Label('Save Keys'))
  • new file layouts/__init__.py

    diff --git a/layouts/__init__.py b/layouts/__init__.py
    new file mode 100644
    index 0000000..8b13789
    - +  
     1
  • new file layouts/olpc.py

    diff --git a/layouts/olpc.py b/layouts/olpc.py
    new file mode 100644
    index 0000000..4772316
    - +  
     1# Copyright 2008 by Kate Scheppke and Wade Brainerd. 
     2# This file is part of Typing Turtle.
     3#
     4# Typing Turtle is free software: you can redistribute it and/or modify
     5# it under the terms of the GNU General Public License as published by
     6# the Free Software Foundation, either version 3 of the License, or
     7# (at your option) any later version.
     8#
     9# Typing Turtle is distributed in the hope that it will be useful,
     10# but WITHOUT ANY WARRANTY; without even the implied warranty of
     11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12# GNU General Public License for more details.
     13#
     14# You should have received a copy of the GNU General Public License
     15# along with Typing Turtle.  If not, see <http://www.gnu.org/licenses/>.
     16#!/usr/bin/env python
     17# vi:sw=4 et
     18
     19
     20# This is the OLPC XO membrane keyboard layout.
     21#
     22# The keyboard layout is described by the following data structure. The structure
     23# has three levels: Layout, Groups, and Keys.  A Layout contains a list of Groups,
     24# each of which contains a list of Keys.  Groups are intended to be a way to collect
     25# related keys (e.g. nearby each other on the keyboard with similar properties)
     26# together.
     27#
     28# Entirely new keyboard layouts can be created just by copying this structure and
     29# modifying the following values, without changing the code.
     30OLPC_LAYOUT = {
     31    'layout-name': "olpc",
     32
     33    'layout-width': 775,
     34    'layout-height': 265,
     35
     36    'group-layout': 'horizontal',
     37
     38    'key-width': 45,
     39    'key-height': 45,
     40    'key-gap': 5,
     41
     42    'groups': [
     43        {
     44            'group-name': "numbers",
     45            'group-x': 10,
     46            'group-y': 10,
     47           
     48            'keys': [
     49                {'key-scan':0x31,'key-finger':'LP','key-hand-image':'OLPC_Lhand_tilde.svg','key-width':35},
     50                {'key-scan':0x0a,'key-finger':'LP','key-hand-image':'OLPC_Lhand_1.svg'},
     51                {'key-scan':0x0b,'key-finger':'LR','key-hand-image':'OLPC_Lhand_2.svg'},
     52                {'key-scan':0x0c,'key-finger':'LM','key-hand-image':'OLPC_Lhand_3.svg'},
     53                {'key-scan':0x0d,'key-finger':'LI','key-hand-image':'OLPC_Lhand_4.svg'},
     54                {'key-scan':0x0e,'key-finger':'LI','key-hand-image':'OLPC_Lhand_5.svg'},
     55                {'key-scan':0x0f,'key-finger':'RI','key-hand-image':'OLPC_Rhand_6.svg'},
     56                {'key-scan':0x10,'key-finger':'RI','key-hand-image':'OLPC_Rhand_7.svg'},
     57                {'key-scan':0x11,'key-finger':'RM','key-hand-image':'OLPC_Rhand_8.svg'},
     58                {'key-scan':0x12,'key-finger':'RR','key-hand-image':'OLPC_Rhand_9.svg'},
     59                {'key-scan':0x13,'key-finger':'RP','key-hand-image':'OLPC_Rhand_0.svg'},
     60                {'key-scan':0x14,'key-finger':'RP','key-hand-image':'OLPC_Rhand_minus.svg'},
     61                {'key-scan':0x15,'key-finger':'RP','key-hand-image':'OLPC_Rhand_plus.svg','key-width':65},
     62                {'key-scan':0x16,'key-finger':'RP','key-label':"erase",'key-width':95}
     63            ]
     64        },
     65        {
     66            'group-name': "top",
     67            'group-x': 10,
     68            'group-y': 60,
     69           
     70            'keys': [
     71                {'key-scan':0x17,'key-finger':'LP','key-label':"tab"},
     72                {'key-scan':0x18,'key-finger':'LP','key-hand-image':'OLPC_Lhand_Q.svg'},
     73                {'key-scan':0x19,'key-finger':'LR','key-hand-image':'OLPC_Lhand_W.svg'},
     74                {'key-scan':0x1a,'key-finger':'LM','key-hand-image':'OLPC_Lhand_E.svg'},
     75                {'key-scan':0x1b,'key-finger':'LI','key-hand-image':'OLPC_Lhand_R.svg'},
     76                {'key-scan':0x1c,'key-finger':'LI','key-hand-image':'OLPC_Lhand_T.svg'},
     77                {'key-scan':0x1d,'key-finger':'RI','key-hand-image':'OLPC_Rhand_Y.svg'},
     78                {'key-scan':0x1e,'key-finger':'RI','key-hand-image':'OLPC_Rhand_U.svg'},
     79                {'key-scan':0x1f,'key-finger':'RM','key-hand-image':'OLPC_Rhand_I.svg'},
     80                {'key-scan':0x20,'key-finger':'RR','key-hand-image':'OLPC_Rhand_O.svg'},
     81                {'key-scan':0x21,'key-finger':'RP','key-hand-image':'OLPC_Rhand_P.svg'},
     82                {'key-scan':0x22,'key-finger':'RP','key-hand-image':'OLPC_Rhand_bracketL.svg'},
     83                {'key-scan':0x23,'key-finger':'RP','key-hand-image':'OLPC_Rhand_bracketR.svg','key-width':55},
     84                {'key-scan':0x24,'key-finger':'RP','key-hand-image':'OLPC_Rhand_ENTER.svg','key-label':"enter",'key-width':95,'key-height':95}
     85            ]
     86        },
     87        {
     88            'group-name': "home",
     89            'group-x': 10,
     90            'group-y': 110,
     91           
     92            'keys': [
     93                {'key-scan':0x25,'key-finger':'LP','key-label':"ctrl",'key-width':55},
     94                {'key-scan':0x26,'key-finger':'LP','key-hand-image':'OLPC_Lhand_A.svg'},
     95                {'key-scan':0x27,'key-finger':'LR','key-hand-image':'OLPC_Lhand_S.svg'},
     96                {'key-scan':0x28,'key-finger':'LM','key-hand-image':'OLPC_Lhand_D.svg'},
     97                {'key-scan':0x29,'key-finger':'LI','key-hand-image':'OLPC_Lhand_F.svg'},
     98                {'key-scan':0x2a,'key-finger':'LI','key-hand-image':'OLPC_Lhand_G.svg'},
     99                {'key-scan':0x2b,'key-finger':'RI','key-hand-image':'OLPC_Rhand_H.svg'},
     100                {'key-scan':0x2c,'key-finger':'RI','key-hand-image':'OLPC_Rhand_J.svg'},
     101                {'key-scan':0x2d,'key-finger':'RM','key-hand-image':'OLPC_Rhand_K.svg'},
     102                {'key-scan':0x2e,'key-finger':'RR','key-hand-image':'OLPC_Rhand_L.svg'},
     103                {'key-scan':0x2f,'key-finger':'RP','key-hand-image':'OLPC_Rhand_SEMICOLON.svg'},
     104                {'key-scan':0x30,'key-finger':'RP','key-hand-image':'OLPC_Rhand_APOSTROPHE.svg'},
     105                {'key-scan':0x33,'key-finger':'RP'}
     106            ]
     107        },
     108        {
     109            'group-name': "bottom",
     110            'group-x': 10,
     111            'group-y': 160,
     112           
     113            'keys': [
     114                {'key-scan':0x32,'key-finger':'LP','key-hand-image':'OLPC_Lhand_SHIFT.svg','key-label':"shift",'key-width':75},
     115                {'key-scan':0x34,'key-finger':'LP','key-hand-image':'OLPC_Lhand_Z.svg'},
     116                {'key-scan':0x35,'key-finger':'LR','key-hand-image':'OLPC_Lhand_X.svg'},
     117                {'key-scan':0x36,'key-finger':'LM','key-hand-image':'OLPC_Lhand_C.svg'},
     118                {'key-scan':0x37,'key-finger':'LI','key-hand-image':'OLPC_Lhand_V.svg'},
     119                {'key-scan':0x38,'key-finger':'LI','key-hand-image':'OLPC_Lhand_B.svg'},
     120                {'key-scan':0x39,'key-finger':'RI','key-hand-image':'OLPC_Rhand_N.svg'},
     121                {'key-scan':0x3a,'key-finger':'RI','key-hand-image':'OLPC_Rhand_M.svg'},
     122                {'key-scan':0x3b,'key-finger':'RM','key-hand-image':'OLPC_Rhand_COMMA.svg'},
     123                {'key-scan':0x3c,'key-finger':'RR','key-hand-image':'OLPC_Rhand_PERIOD.svg'},
     124                {'key-scan':0x3d,'key-finger':'RP','key-hand-image':'OLPC_Rhand_QUESTIONMARK.svg'},
     125                {'key-scan':0x3e,'key-finger':'RP','key-hand-image':'OLPC_Rhand_SHIFT.svg','key-label':"shift",'key-width':75},
     126                {'key-scan':0x6f,'key-finger':'RP','key-label':""}, # Up
     127                {'key-label':""}, # Language key
     128            ]
     129        },
     130        {
     131            'group-name': "space",
     132            'group-x': 10,
     133            'group-y': 210,
     134           
     135            'keys': [
     136                {'key-label':"fn",'key-width':35},
     137                {'key-label':"",'key-width':55}, # LHand
     138                {'key-scan':0x40,'key-label':"alt",'key-width':55}, # LAlt
     139                {'key-scan':0x41,'key-finger':'RT','key-hand-image':'OLPC_Rhand_SPACE.svg','key-width':325}, # Spacebar
     140                {'key-scan':0x6c,'key-label':"altgr",'key-width':55}, # AltGr
     141                {'key-label':"",'key-width':55}, # RHand
     142                {'key-scan':0x71,'key-label':""}, # Left
     143                {'key-scan':0x74,'key-label':""}, # Down
     144                {'key-scan':0x72,'key-label':""}, # Right
     145            ]
     146        }
     147    ]
     148}
  • new file layouts/olpcm.py

    diff --git a/layouts/olpcm.py b/layouts/olpcm.py
    new file mode 100644
    index 0000000..a180b58
    - +  
     1# Copyright 2008 by Kate Scheppke and Wade Brainerd. 
     2# This file is part of Typing Turtle.
     3#
     4# Typing Turtle is free software: you can redistribute it and/or modify
     5# it under the terms of the GNU General Public License as published by
     6# the Free Software Foundation, either version 3 of the License, or
     7# (at your option) any later version.
     8#
     9# Typing Turtle is distributed in the hope that it will be useful,
     10# but WITHOUT ANY WARRANTY; without even the implied warranty of
     11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12# GNU General Public License for more details.
     13#
     14# You should have received a copy of the GNU General Public License
     15# along with Typing Turtle.  If not, see <http://www.gnu.org/licenses/>.
     16#!/usr/bin/env python
     17# vi:sw=4 et
     18
     19
     20# This is the OLPC XO non-membrane, mechanical keyboard layout.
     21#
     22# Check olpc.py in the same directory for instructions.
     23OLPCM_LAYOUT = {
     24    'layout-name': "olpcm",
     25
     26    'layout-width': 645,
     27    'layout-height': 265,
     28
     29    'group-layout': 'horizontal',
     30
     31    'key-width': 45,
     32    'key-height': 45,
     33    'key-gap': 5,
     34
     35    'groups': [
     36        {
     37            'group-name': "numbers",
     38            'group-x': 10,
     39            'group-y': 10,
     40
     41            'keys': [
     42                {'key-scan':0x31,'key-finger':'LP','key-hand-image':'OLPC_Lhand_tilde.svg','key-width':35},
     43                {'key-scan':0x0a,'key-finger':'LP','key-hand-image':'OLPC_Lhand_1.svg'},
     44                {'key-scan':0x0b,'key-finger':'LR','key-hand-image':'OLPC_Lhand_2.svg'},
     45                {'key-scan':0x0c,'key-finger':'LM','key-hand-image':'OLPC_Lhand_3.svg'},
     46                {'key-scan':0x0d,'key-finger':'LI','key-hand-image':'OLPC_Lhand_4.svg'},
     47                {'key-scan':0x0e,'key-finger':'LI','key-hand-image':'OLPC_Lhand_5.svg'},
     48                {'key-scan':0x0f,'key-finger':'RI','key-hand-image':'OLPC_Rhand_6.svg'},
     49                {'key-scan':0x10,'key-finger':'RI','key-hand-image':'OLPC_Rhand_7.svg'},
     50                {'key-scan':0x11,'key-finger':'RM','key-hand-image':'OLPC_Rhand_8.svg'},
     51                {'key-scan':0x12,'key-finger':'RR','key-hand-image':'OLPC_Rhand_9.svg'},
     52                {'key-scan':0x13,'key-finger':'RP','key-hand-image':'OLPC_Rhand_0.svg'},
     53                {'key-scan':0x14,'key-finger':'RP','key-hand-image':'OLPC_Rhand_minus.svg','key-width':35},
     54                {'key-scan':0x16,'key-finger':'RP','key-label':"erase",'key-width':45}
     55            ]
     56        },
     57        {
     58            'group-name': "top",
     59            'group-x': 10,
     60            'group-y': 60,
     61
     62            'keys': [
     63                {'key-scan':0x17,'key-finger':'LP','key-label':"tab"},
     64                {'key-scan':0x18,'key-finger':'LP','key-hand-image':'OLPC_Lhand_Q.svg'},
     65                {'key-scan':0x19,'key-finger':'LR','key-hand-image':'OLPC_Lhand_W.svg'},
     66                {'key-scan':0x1a,'key-finger':'LM','key-hand-image':'OLPC_Lhand_E.svg'},
     67                {'key-scan':0x1b,'key-finger':'LI','key-hand-image':'OLPC_Lhand_R.svg'},
     68                {'key-scan':0x1c,'key-finger':'LI','key-hand-image':'OLPC_Lhand_T.svg'},
     69                {'key-scan':0x1d,'key-finger':'RI','key-hand-image':'OLPC_Rhand_Y.svg'},
     70                {'key-scan':0x1e,'key-finger':'RI','key-hand-image':'OLPC_Rhand_U.svg'},
     71                {'key-scan':0x1f,'key-finger':'RM','key-hand-image':'OLPC_Rhand_I.svg'},
     72                {'key-scan':0x20,'key-finger':'RR','key-hand-image':'OLPC_Rhand_O.svg'},
     73                {'key-scan':0x21,'key-finger':'RP','key-hand-image':'OLPC_Rhand_P.svg'},
     74                {'key-scan':0x22,'key-finger':'RP','key-hand-image':'OLPC_Rhand_bracketL.svg', 'key-width':35},
     75                {'key-scan':0x23,'key-finger':'RP','key-hand-image':'OLPC_Rhand_bracketR.svg','key-width':35},
     76            ]
     77        },
     78        {
     79            'group-name': "home",
     80            'group-x': 10,
     81            'group-y': 110,
     82
     83            'keys': [
     84                {'key-scan':0x25,'key-finger':'LP','key-label':"ctrl",'key-width':55},
     85                {'key-scan':0x26,'key-finger':'LP','key-hand-image':'OLPC_Lhand_A.svg'},
     86                {'key-scan':0x27,'key-finger':'LR','key-hand-image':'OLPC_Lhand_S.svg'},
     87                {'key-scan':0x28,'key-finger':'LM','key-hand-image':'OLPC_Lhand_D.svg'},
     88                {'key-scan':0x29,'key-finger':'LI','key-hand-image':'OLPC_Lhand_F.svg'},
     89                {'key-scan':0x2a,'key-finger':'LI','key-hand-image':'OLPC_Lhand_G.svg'},
     90                {'key-scan':0x2b,'key-finger':'RI','key-hand-image':'OLPC_Rhand_H.svg'},
     91                {'key-scan':0x2c,'key-finger':'RI','key-hand-image':'OLPC_Rhand_J.svg'},
     92                {'key-scan':0x2d,'key-finger':'RM','key-hand-image':'OLPC_Rhand_K.svg'},
     93                {'key-scan':0x2e,'key-finger':'RR','key-hand-image':'OLPC_Rhand_L.svg'},
     94                {'key-scan':0x2f,'key-finger':'RP','key-hand-image':'OLPC_Rhand_SEMICOLON.svg', 'key-width':35},
     95                {'key-scan':0x24,'key-finger':'RP','key-hand-image':'OLPCM_Rhand_ENTER.svg','key-label':"enter",'key-width':75},
     96            ]
     97        },
     98        {
     99            'group-name': "bottom",
     100            'group-x': 10,
     101            'group-y': 160,
     102
     103            'keys': [
     104                {'key-scan':0x32,'key-finger':'LP','key-hand-image':'OLPC_Lhand_SHIFT.svg','key-label':"shift",'key-width':75},
     105                {'key-scan':0x34,'key-finger':'LP','key-hand-image':'OLPC_Lhand_Z.svg'},
     106                {'key-scan':0x35,'key-finger':'LR','key-hand-image':'OLPC_Lhand_X.svg'},
     107                {'key-scan':0x36,'key-finger':'LM','key-hand-image':'OLPC_Lhand_C.svg'},
     108                {'key-scan':0x37,'key-finger':'LI','key-hand-image':'OLPC_Lhand_V.svg'},
     109                {'key-scan':0x38,'key-finger':'LI','key-hand-image':'OLPC_Lhand_B.svg'},
     110                {'key-scan':0x39,'key-finger':'RI','key-hand-image':'OLPC_Rhand_N.svg'},
     111                {'key-scan':0x3a,'key-finger':'RI','key-hand-image':'OLPC_Rhand_M.svg'},
     112                {'key-scan':0x3b,'key-finger':'RM','key-hand-image':'OLPC_Rhand_COMMA.svg', 'key-width':35},
     113                {'key-scan':0x3c,'key-finger':'RR','key-hand-image':'OLPC_Rhand_PERIOD.svg', 'key-width':35},
     114                {'key-scan':0x3d,'key-finger':'RP','key-hand-image':'OLPC_Rhand_QUESTIONMARK.svg', 'key-width':35},
     115                {'key-scan':0x3e,'key-finger':'RP','key-hand-image':'OLPC_Rhand_SHIFT.svg','key-label':"shift",'key-width':75},
     116            ]
     117        },
     118        {
     119            'group-name': "space",
     120            'group-x': 10,
     121            'group-y': 210,
     122
     123            'keys': [
     124                {'key-label':"fn",'key-width':45},
     125                {'key-label':"",'key-width':45}, # LHand
     126                {'key-scan':0x33,'key-finger':'RP','key-width':35},
     127                {'key-scan':0x40,'key-label':"alt",'key-width':45}, # LAlt
     128                {'key-scan':0x41,'key-finger':'RT','key-hand-image':'OLPC_Rhand_SPACE.svg','key-width':155}, # Spacebar
     129                {'key-scan':0x6c,'key-label':"altgr",'key-width':35}, # AltGr
     130                {'key-scan':0x15,'key-finger':'RP','key-hand-image':'OLPC_Rhand_plus.svg','key-width':35},
     131                {'key-scan':0x30,'key-finger':'RP','key-hand-image':'OLPC_Rhand_APOSTROPHE.svg','key-width':35},
     132                {'key-scan':0x71,'key-label':"",'key-width':35}, # Left
     133                {'key-scan':0x74,'key-label':"",'key-width':35}, # Down
     134                {'key-scan':0x6f,'key-label':"",'key-width':35}, # Up
     135                {'key-scan':0x72,'key-label':"",'key-width':35}, # Right
     136            ]
     137        }
     138    ]
     139}
  • lessonbuilder.py

    diff --git a/lessonbuilder.py b/lessonbuilder.py
    index 7f85c1c..b33a34e 100755
    a b def build_key_steps( 
    311311    except:
    312312        kb.load_letter_map('lessons/en_US.key')
    313313
    314     kb.set_layout(keyboard.OLPC_LAYOUT)
     314    kb.set_layout(keyboard.get_layout())
    315315
    316316    keynames = new_keys[0]
    317317    if len(new_keys) >= 2:
  • lessonscreen.py

    diff --git a/lessonscreen.py b/lessonscreen.py
    index e7d66e7..6eed243 100644
    a b class LessonScreen(gtk.VBox): 
    137137        except:
    138138            pass
    139139
    140         self.keyboard.set_layout(keyboard.OLPC_LAYOUT)
     140        self.keyboard.set_layout(keyboard.get_layout())
    141141
    142142        self.pack_start(hbox, False, False, 10)
    143143        self.pack_start(frame, True, True)