google / extra-keyboards-for-chrome-os

Extra keyboard layouts and input methods for Chrome OS
Apache License 2.0
201 stars 123 forks source link

GUI interface to create own keyboard layout #98

Closed 7fe closed 3 years ago

7fe commented 3 years ago

So I am in the process of creating a GUI to create these keyboard layouts any advice or code input would be appreciated I have the GUI and download link set up I just need to go through the process of wiring everything together. There is a slight bug with the # key that I have been able to figure out yet.

<!doctype html><!--

Is this open source? Yes

--><title>Keyboard Layout Creator</title>
<style>table{border-collapse:collapse;}
td{border:1px solid black;}
td[contenteditable=no]{background:lightgrey;}
</style><center><script>
//w = function(x){document.write(x);}
//w("<pre>"+decodeURI(document.location.hash)+"</pre><br>");

//https://caniuse.com/#feat=datauri detect data URI support

keys = {
 "`":"~",
 "1":"!"
};
//document.write(keys);
write = function(x){document.write(x);};
</script>

<!--input type=text placeholder="LOCALEID (8 Char Only)" id=LOCALID title="Microsoft.klc only 8 Char Only"-->
<script>
var KBD = (""+decodeURI(document.location.hash)).slice(1,9).trim();
document.getElementById('KBD').value = KBD;
KBD = KBD || "KBD";
var name = (""+decodeURI(document.location.hash)).slice(9,35).trim();
document.getElementById('name').value = name;
name = name || "Writer Dvorak";
// has to do with region location default to English is the 
var LOCALID = "";
//KBD = document.getElementById('KBD').value || "KBD";
</script>
<table contenteditable><tr>
    <td id="1">`</td>
    <td id=2>1</td>
    <td id=3>2</td>
    <td id=4>3</td>
    <td id=5>4</td>
    <td id=6>5</td>
    <td id=7>6</td>
    <td id=8>7</td>
    <td id=9>8</td>
    <td id=10>9</td>
    <td id=11>0</td>
    <td id="12" ahk="*SC0c" >-</td>
    <td id="13" ahk="*SC0d">=</td>
  </tr>
</table>
<table contenteditable>
  <tr>
    <td contenteditable=no>Tab</td>
    <td ahk="*SC010">;</td>
    <td ahk="*SC011">,</td>
    <td ahk="*SC012">.</td>
    <td ahk="*SC013">p</td>
    <td ahk="*SC014">y</td>
    <td ahk="*SC015">f</td>
    <td ahk="*SC016">g</td>
    <td ahk="*SC017">c</td>
    <td ahk="*SC018">r</td>
    <td ahk="*SC019">l</td>
    <td>[</td>
    <td>]</td>
    <td>\</td>
  </tr>
</table>
<table contenteditable>
  <tr>
    <td contenteditable=no>Caps</td>
    <td ahk="*SC01e">a</td>
    <td ahk="*SC01f">o</td>
    <td ahk="*SC020">e</td>
    <td ahk="*SC021">i</td>
    <td ahk="*SC022">u</td>
    <td ahk="*SC023">d</td>
    <td ahk="*SC024">h</td>
    <td ahk="*SC025">t</td>
    <td ahk="*SC026">n</td>
    <td ahk="*SC027">s</td>
    <td ahk="*SC028">'</td>
  </tr>
</table>
<table contenteditable>
  <tr>
    <td contenteditable=no style="font-size:60%;">Shift</td>
    <td>\</td>
    <td>z</td>
    <td>q</td>
    <td>j</td>
    <td>k</td>
    <td>f</td>
    <td>b</td>
    <td>m</td>
    <td>w</td>
    <td>v</td>
    <td>/</td>
  </tr>
</table>
<label>
<input type=checkbox onclick="document.getElementById('shift').style.display='block';">Shift</label><br>
<div id=shift>
<table contenteditable=""><tbody><tr>
    <td id="1">&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td id="12" ahk="*SC0c">&nbsp;</td>
    <td id="13" ahk="*SC0d">&nbsp;</td>
  </tr>
</tbody></table>
<table contenteditable="">
  <tbody><tr>
    <td contenteditable="no">Tab</td>
    <td ahk="*SC010">&nbsp;</td>
    <td ahk="*SC011">&nbsp;</td>
    <td ahk="*SC012">&nbsp;</td>
    <td ahk="*SC013">&nbsp;</td>
    <td ahk="*SC014">&nbsp;</td>
    <td ahk="*SC015">&nbsp;</td>
    <td ahk="*SC016">&nbsp;</td>
    <td ahk="*SC017">&nbsp;</td>
    <td ahk="*SC018">&nbsp;</td>
    <td ahk="*SC019">&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
  </tr>
</tbody></table>
<table contenteditable="">
  <tbody><tr>
    <td contenteditable="no">Caps</td>
    <td ahk="*SC01e">&nbsp;</td>
    <td ahk="*SC01f">&nbsp;</td>
    <td ahk="*SC020">&nbsp;</td>
    <td ahk="*SC021">&nbsp;</td>
    <td ahk="*SC022">&nbsp;</td>
    <td ahk="*SC023">&nbsp;</td>
    <td ahk="*SC024">&nbsp;</td>
    <td ahk="*SC025">&nbsp;</td>
    <td ahk="*SC026">&nbsp;</td>
    <td ahk="*SC027">&nbsp;</td>
    <td ahk="*SC028">&nbsp;</td>
  </tr>
</tbody></table>
<table contenteditable="">
  <tbody><tr>
    <td contenteditable="no">Shift</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
  </tr>
</tbody></table>
</div>
<label>
<input type=checkbox onclick="document.getElementById('altgr').style.display='block';">AltGR </label><br>
<div id="altgr">
<table contenteditable=""><tbody><tr>
    <td id="1">&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td id="12" ahk="*SC0c">&nbsp;</td>
    <td id="13" ahk="*SC0d">&nbsp;</td>
  </tr>
</tbody></table>
<table contenteditable="">
  <tbody><tr>
    <td contenteditable="no">Tab</td>
    <td ahk="*SC010">&nbsp;</td>
    <td ahk="*SC011">&nbsp;</td>
    <td ahk="*SC012">&nbsp;</td>
    <td ahk="*SC013">&nbsp;</td>
    <td ahk="*SC014">&nbsp;</td>
    <td ahk="*SC015">&nbsp;</td>
    <td ahk="*SC016">&nbsp;</td>
    <td ahk="*SC017">&nbsp;</td>
    <td ahk="*SC018">&nbsp;</td>
    <td ahk="*SC019">&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
  </tr>
</tbody></table>
<table contenteditable="">
  <tbody><tr>
    <td contenteditable="no">Caps</td>
    <td ahk="*SC01e">&nbsp;</td>
    <td ahk="*SC01f">&nbsp;</td>
    <td ahk="*SC020">&nbsp;</td>
    <td ahk="*SC021">&nbsp;</td>
    <td ahk="*SC022">&nbsp;</td>
    <td ahk="*SC023">&nbsp;</td>
    <td ahk="*SC024">&nbsp;</td>
    <td ahk="*SC025">&nbsp;</td>
    <td ahk="*SC026">&nbsp;</td>
    <td ahk="*SC027">&nbsp;</td>
    <td ahk="*SC028">&nbsp;</td>
  </tr>
</tbody></table>
<table contenteditable="">
  <tbody><tr>
    <td contenteditable="no" style="font-size:60%;">Shift</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
  </tr>
</tbody></table>
</div>
<input type=checkbox onclick="document.getElementById('ctrl').style.display='block';">Ctrl</label><br>
<div id="ctrl">
<table contenteditable=""><tbody><tr>
    <td id="1">&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td id="12" ahk="*SC0c">&nbsp;</td>
    <td id="13" ahk="*SC0d">&nbsp;</td>
  </tr>
</tbody></table>
<table contenteditable="">
  <tbody><tr>
    <td contenteditable="no">Tab</td>
    <td ahk="*SC010">&nbsp;</td>
    <td ahk="*SC011">&nbsp;</td>
    <td ahk="*SC012">&nbsp;</td>
    <td ahk="*SC013">&nbsp;</td>
    <td ahk="*SC014">&nbsp;</td>
    <td ahk="*SC015">&nbsp;</td>
    <td ahk="*SC016">&nbsp;</td>
    <td ahk="*SC017">&nbsp;</td>
    <td ahk="*SC018">&nbsp;</td>
    <td ahk="*SC019">&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
  </tr>
</tbody></table>
<table contenteditable="">
  <tbody><tr>
    <td contenteditable="no">Caps</td>
    <td ahk="*SC01e">&nbsp;</td>
    <td ahk="*SC01f">&nbsp;</td>
    <td ahk="*SC020">&nbsp;</td>
    <td ahk="*SC021">&nbsp;</td>
    <td ahk="*SC022">&nbsp;</td>
    <td ahk="*SC023">&nbsp;</td>
    <td ahk="*SC024">&nbsp;</td>
    <td ahk="*SC025">&nbsp;</td>
    <td ahk="*SC026">&nbsp;</td>
    <td ahk="*SC027">&nbsp;</td>
    <td ahk="*SC028">&nbsp;</td>
  </tr>
</tbody></table>
<table contenteditable="">
  <tbody><tr>
    <td contenteditable="no" style="font-size:60%;">Shift</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
  </tr>
</tbody></table>
</div>
<!--label><input type=checkbox>Shift</label> 
<label><input type=checkbox>AltGr</label--> <script>

//document.location.href = document.location.href + "";
</script>
<script>
function submit(){
  KBD = document.getElementById('KBD').value.substr(0,8);
  name = document.getElementById('name').value.substr(0,26);
  document.location.hash = KBD.padEnd(8) + name.padEnd(8);
}
</script>
<script id="ahk" style="display:none;">
id = function(id){return document.getElementById(id);};
$ = function(x){return document.querySelectorAll(x)[0];}
ahk = function(i){
  if(i)
    return $(i).getAttribute('ahk')+"::Send {blind}{"+$(i).textContent.slice(-1)+"}";
  else "";
};
//ahkaltgr()
numbersign = '#';
write(`<a title="background.js" download="background.js"
href="data:;charset=utf-8,${encodeURI(`
/* This file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
var AltGr = { PLAIN: "plain", ALTERNATE: "alternate" };
var Shift = { PLAIN: "plain", SHIFTED: "shifted" };

var contextID = -1;
var altGrState = AltGr.PLAIN;
var shiftState = Shift.PLAIN;
var lastRemappedKeyEvent = undefined;

var lut = {
"Digit1": { "plain": {"plain": "1", "shifted": "!"}, "alternate": {"plain": "", "shifted":""}, "code": "Digit1"},
"Digit2": { "plain": {"plain": "2", "shifted": "@"}, "alternate": {"plain": "", "shifted":""}, "code": "Digit2"},
"Digit3": { "plain": {"plain": "3", "shifted": ""}, "alternate": {"plain": "", "shifted":""}, "code": "Digit3"},
"Digit4": { "plain": {"plain": "4", "shifted": "$"}, "alternate": {"plain": "", "shifted":""}, "code": "Digit4"},
"Digit5": { "plain": {"plain": "5", "shifted": "%"}, "alternate": {"plain": "€", "shifted":"€"}, "code": "Digit5"},
"Digit6": { "plain": {"plain": "6", "shifted": "^"}, "alternate": {"plain": "", "shifted":""}, "code": "Digit6"},
"Digit7": { "plain": {"plain": "7", "shifted": "&"}, "alternate": {"plain": "", "shifted":""}, "code": "Digit7"},
"Digit8": { "plain": {"plain": "8", "shifted": "*"}, "alternate": {"plain": "", "shifted":""}, "code": "Digit8"},
"Digit9": { "plain": {"plain": "9", "shifted": "("}, "alternate": {"plain": "", "shifted":""}, "code": "Digit9"},
"Digit0": { "plain": {"plain": "0", "shifted": ")"}, "alternate": {"plain": "", "shifted":""}, "code": "Digit0"},
"Minus": { "plain": {"plain": "-", "shifted": "_"}, "alternate": {"plain": "", "shifted":""}, "code": "Minus"},
"Equal": { "plain": {"plain": "=", "shifted": "+"}, "alternate": {"plain": "", "shifted":""}, "code": "Equal"},
"KeyQ": { "plain": {"plain": "ŝ", "shifted": "Ŝ"}, "alternate": {"plain": "q", "shifted":"Q"}, "code": "KeyQ"},
"KeyW": { "plain": {"plain": "ĝ", "shifted": "Ĝ"}, "alternate": {"plain": "w", "shifted":"W"}, "code": "KeyW"},
"KeyE": { "plain": {"plain": "e", "shifted": "E"}, "alternate": {"plain": "", "shifted":""}, "code": "KeyE"},
"KeyR": { "plain": {"plain": "r", "shifted": "R"}, "alternate": {"plain": "", "shifted":""}, "code": "KeyR"},
"KeyT": { "plain": {"plain": "t", "shifted": "T"}, "alternate": {"plain": "", "shifted":""}, "code": "KeyT"},
"KeyY": { "plain": {"plain": "ŭ", "shifted": "Ŭ"}, "alternate": {"plain": "y", "shifted":"Y"}, "code": "KeyY"},
"KeyU": { "plain": {"plain": "u", "shifted": "U"}, "alternate": {"plain": "", "shifted":""}, "code": "KeyU"},
"KeyI": { "plain": {"plain": "i", "shifted": "I"}, "alternate": {"plain": "", "shifted":""}, "code": "KeyI"},
"KeyO": { "plain": {"plain": "o", "shifted": "O"}, "alternate": {"plain": "{", "shifted":"{"}, "code": "KeyO"},
"KeyP": { "plain": {"plain": "p", "shifted": "P"}, "alternate": {"plain": "}", "shifted":"}"}, "code": "KeyP"},
"BracketLeft": { "plain": {"plain": "ĵ", "shifted": "Ĵ"}, "alternate": {"plain": "[", "shifted":"{"}, "code": "BracketLeft"},
"BracketRight": { "plain": {"plain": "ĥ", "shifted": "Ĥ"}, "alternate": {"plain": "]", "shifted":"}"}, "code": "BracketRight"},
"KeyA": { "plain": {"plain": "a", "shifted": "A"}, "alternate": {"plain": "‘", "shifted":"‘"}, "code": "KeyA"},
"KeyS": { "plain": {"plain": "s", "shifted": "S"}, "alternate": {"plain": "’", "shifted":"’"}, "code": "KeyS"},
"KeyD": { "plain": {"plain": "d", "shifted": "D"}, "alternate": {"plain": "“", "shifted":"“"}, "code": "KeyD"},
"KeyF": { "plain": {"plain": "f", "shifted": "F"}, "alternate": {"plain": "”", "shifted":"”"}, "code": "KeyF"},
"KeyG": { "plain": {"plain": "g", "shifted": "G"}, "alternate": {"plain": "", "shifted":""}, "code": "KeyG"},
"KeyH": { "plain": {"plain": "h", "shifted": "H"}, "alternate": {"plain": "", "shifted":""}, "code": "KeyH"},
"KeyJ": { "plain": {"plain": "j", "shifted": "J"}, "alternate": {"plain": "", "shifted":""}, "code": "KeyJ"},
"KeyK": { "plain": {"plain": "k", "shifted": "K"}, "alternate": {"plain": "", "shifted":""}, "code": "KeyK"},
"KeyL": { "plain": {"plain": "l", "shifted": "L"}, "alternate": {"plain": "", "shifted":""}, "code": "KeyL"},
"Semicolon": { "plain": {"plain": ";", "shifted": ":"}, "alternate": {"plain": "", "shifted":""}, "code": "Semicolon"},
"Quote": { "plain": {"plain": "'", "shifted": "\""}, "alternate": {"plain": "", "shifted":""}, "code": "Quote"},
"KeyZ": { "plain": {"plain": "z", "shifted": "Z"}, "alternate": {"plain": "", "shifted":""}, "code": "KeyZ"},
"KeyX": { "plain": {"plain": "ĉ", "shifted": "Ĉ"}, "alternate": {"plain": "x", "shifted":"X"}, "code": "KeyX"},
"KeyC": { "plain": {"plain": "c", "shifted": "C"}, "alternate": {"plain": "", "shifted":""}, "code": "KeyC"},
"KeyV": { "plain": {"plain": "v", "shifted": "V"}, "alternate": {"plain": "", "shifted":""}, "code": "KeyV"},
"KeyB": { "plain": {"plain": "b", "shifted": "B"}, "alternate": {"plain": "", "shifted":""}, "code": "KeyB"},
"KeyN": { "plain": {"plain": "n", "shifted": "N"}, "alternate": {"plain": "–", "shifted":"–"}, "code": "KeyN"},
"KeyM": { "plain": {"plain": "m", "shifted": "M"}, "alternate": {"plain": "—", "shifted":"—"}, "code": "KeyM"},
"Comma": { "plain": {"plain": ",", "shifted": "<"}, "alternate": {"plain": "", "shifted":""}, "code": "Comma"},
"Period": { "plain": {"plain": ".", "shifted": ">"}, "alternate": {"plain": "", "shifted":""}, "code": "Period"},
"Slash": { "plain": {"plain": "/", "shifted": "?"}, "alternate": {"plain": "", "shifted":""}, "code": "Slash"},
};

chrome.input.ime.onFocus.addListener(function(context) {
  contextID = context.contextID;
});

function updateAltGrState(keyData) {
  altGrState = (keyData.code == "AltRight") ? ((keyData.type == "keydown") ? AltGr.ALTERNATE : AltGr.PLAIN)
                                              : altGrState;
}

function updateShiftState(keyData) {
  shiftState = ((keyData.shiftKey && !(keyData.capsLock)) || (!(keyData.shiftKey) && keyData.capsLock)) ? 
                 Shift.SHIFTED : Shift.PLAIN;
}

function isPureModifier(keyData) {
  return (keyData.key == "Shift") || (keyData.key == "Ctrl") || (keyData.key == "Alt");
}

function isRemappedEvent(keyData) {
  // hack, should check for a sender ID (to be added to KeyData)
  return lastRemappedKeyEvent != undefined &&
         (lastRemappedKeyEvent.key == keyData.key &&
          lastRemappedKeyEvent.code == keyData.code &&
          lastRemappedKeyEvent.type == keyData.type
         ); // requestID would be different so we are not checking for it  
}

chrome.input.ime.onKeyEvent.addListener(
    function(engineID, keyData) {
      var handled = false;

      if (isRemappedEvent(keyData)) {
        lastRemappedKeyEvent = undefined;
        return handled;
      }

      updateAltGrState(keyData);
      updateShiftState(keyData);

      if (lut[keyData.code]) {
          var remappedKeyData = keyData;
          remappedKeyData.key = lut[keyData.code][altGrState][shiftState];
          remappedKeyData.code = lut[keyData.code].code;

        if (chrome.input.ime.sendKeyEvents != undefined) {
          chrome.input.ime.sendKeyEvents({"contextID": contextID, "keyData": [remappedKeyData]});
          handled = true;
          lastRemappedKeyEvent = remappedKeyData;
        } else if (keyData.type == "keydown" && !isPureModifier(keyData)) {
          chrome.input.ime.commitText({"contextID": contextID, "text": remappedKeyData.key});
          handled = true;
        }
      }

      return handled;
});

`)}">background.js</a>`)
</script>
ghost commented 3 years ago

I didn't look through your html code. But the background.js file that you can download has 2 errors.

first error at line 1 you don't open your comment you only close it.

second error at line 56: when you have a quote inside two quotes (like " " ") you need to escape the inside quote with a backslash (" \" ") or you could use apostrophes (like ' " '). (Without the spaces)

djbclark commented 3 years ago

This is a sweet idea, and if there is updated code with the pointed out problems fixed, please make it available for alpha testers!