summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEitan Isaacson <eitan@monotonous.org>2011-05-02 10:23:17 -0700
committerEitan Isaacson <eitan@monotonous.org>2011-05-02 10:23:26 -0700
commitf5aed67a39df38f7becf4708a80f78797823c0d3 (patch)
tree1c0d2d7bc28f5e3c15f01bb98103da8e75490fbe
parent838a94e57bbbec96cdb476039934903fa40cf3b5 (diff)
parent18c12607e1412702053132862e08070b0278b0a6 (diff)
downloadcaribou-f5aed67a39df38f7becf4708a80f78797823c0d3.tar.gz
Merge branch 'geometry'
Major Caribou changes: * Couple keyboard layout with XKB state. * Simplify layout format * Create libcaribou, an introspectable C/GObject library for creating keyboard UIs. * DBusify UI, have main caribou app activate the keyboard via DBus.
-rw-r--r--.gitignore16
-rw-r--r--bin/Makefile.am3
-rw-r--r--bin/antler-keyboard.in37
-rw-r--r--bin/caribou-preferences.in53
-rw-r--r--bin/caribou.in68
-rw-r--r--caribou/Makefile.am10
-rw-r--r--caribou/__init__.py3
-rw-r--r--caribou/antler/Makefile.am10
-rw-r--r--caribou/antler/__init__.py (renamed from libcaribou/caribou-enum-types.c.tmpl)0
-rw-r--r--caribou/antler/keyboard_view.py164
-rw-r--r--caribou/antler/main.py30
-rw-r--r--caribou/antler/window.py (renamed from caribou/ui/window.py)173
-rw-r--r--caribou/common/Makefile.am11
-rw-r--r--caribou/common/__init__.py1
-rw-r--r--caribou/common/const.py43
-rw-r--r--caribou/common/settings.py179
-rw-r--r--caribou/daemon/Makefile.am8
-rw-r--r--caribou/daemon/__init__.py1
-rw-r--r--caribou/daemon/main.py165
-rw-r--r--caribou/i18n.py.in (renamed from caribou/ui/i18n.py.in)0
-rw-r--r--caribou/settings/Makefile.am11
-rw-r--r--caribou/settings/__init__.py5
-rw-r--r--caribou/settings/caribou_settings.py64
-rw-r--r--caribou/settings/preferences_window.py (renamed from caribou/ui/preferences_window.py)70
-rw-r--r--caribou/settings/setting_types.py (renamed from caribou/common/setting_types.py)10
-rw-r--r--caribou/settings/settings_manager.py (renamed from caribou/common/settings_manager.py)9
-rw-r--r--caribou/ui/Makefile.am16
-rw-r--r--caribou/ui/__init__.py1
-rw-r--r--caribou/ui/keyboard.py461
-rw-r--r--caribou/ui/main.py275
-rw-r--r--caribou/ui/opacity.py83
-rw-r--r--caribou/ui/scan.py216
-rw-r--r--configure.ac21
-rw-r--r--data/Makefile.am13
-rw-r--r--data/keyboards/Makefile.am10
-rw-r--r--data/keyboards/hebrew.xml272
-rw-r--r--data/keyboards/lexic_es.json300
-rw-r--r--data/keyboards/qwerty.xml274
-rw-r--r--data/keyboards/qwerty_en.json261
-rw-r--r--data/keyboards/qwerty_es.json1318
-rw-r--r--data/keyboards/qwerty_ja.xml782
-rw-r--r--data/layouts/Makefile.am1
-rw-r--r--data/layouts/touch/Makefile.am8
-rw-r--r--data/layouts/touch/ara.json122
-rw-r--r--data/layouts/touch/il.json122
-rw-r--r--data/layouts/touch/us.json212
-rw-r--r--data/org.gnome.Caribou.Antler.service.in3
-rw-r--r--libcaribou/Makefile.am122
-rw-r--r--libcaribou/caribou-enum-types.h.tmpl0
-rw-r--r--libcaribou/caribou-marshal.list1
-rw-r--r--libcaribou/caribou-virtual-keyboard.c175
-rw-r--r--libcaribou/caribou-virtual-keyboard.h52
-rw-r--r--libcaribou/caribou.h19
-rw-r--r--libcaribou/external-libs.vapi234
-rw-r--r--libcaribou/group-model.vala50
-rw-r--r--libcaribou/json-deserializer.vala126
-rw-r--r--libcaribou/key-model.vala71
-rw-r--r--libcaribou/keyboard-model.vala49
-rw-r--r--libcaribou/keyboard-service.vala35
-rw-r--r--libcaribou/level-model.vala41
-rw-r--r--libcaribou/libxklavier.vapi182
-rw-r--r--libcaribou/row-model.vala22
-rw-r--r--libcaribou/util.vala13
-rw-r--r--libcaribou/xadapter.vala213
-rw-r--r--po/POTFILES.in7
-rwxr-xr-xtools/fix_gir.py63
-rwxr-xr-xtools/make_schema.py84
67 files changed, 2463 insertions, 5011 deletions
diff --git a/.gitignore b/.gitignore
index f770bfb..2e70547 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,10 +9,12 @@ aclocal.m4
autom4te.cache
*.make
bin/caribou
+bin/caribou-preferences
+bin/antler-keyboard
install-sh
missing
py-compile
-caribou/ui/i18n.py
+caribou/i18n.py
mkinstalldirs
po/Makefile.in.in
po/POTFILES
@@ -33,8 +35,14 @@ libtool
ltmain.sh
m4
libcaribou/.libs/
-libcaribou/Caribou-1.0.gir
-libcaribou/Caribou-1.0.typelib
+libcaribou/*.gir
+libcaribou/*.typelib
*.lo
+*.o
libcaribou/libcaribou.la
-
+libcaribou/*.[ch]
+caribou-1.0.vapi
+caribou-internals-1.0.vapi
+caribou-internals.h
+*.stamp
+data/org.gnome.Caribou.Antler.service
diff --git a/bin/Makefile.am b/bin/Makefile.am
index cae01c9..88f281d 100644
--- a/bin/Makefile.am
+++ b/bin/Makefile.am
@@ -1,4 +1,5 @@
-bin_SCRIPTS = caribou
+bin_SCRIPTS = caribou caribou-preferences
+libexec_SCRIPTS = antler-keyboard
CLEANFILES = $(bin_SCRIPTS)
diff --git a/bin/antler-keyboard.in b/bin/antler-keyboard.in
new file mode 100644
index 0000000..b42734c
--- /dev/null
+++ b/bin/antler-keyboard.in
@@ -0,0 +1,37 @@
+#!/bin/bash
+#
+# Antler - a Caribou keyboard implementation
+#
+# Copyright (C) 2011 Eitan Isaacson <eitan@monotonous.org>
+#
+# This program 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 program 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 program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+script_dir="$(dirname "$(readlink -f ${BASH_SOURCE[0]})")"
+
+if [ $script_dir == "@prefix@@libexecdir@" ]
+then
+ export PYTHONPATH="@prefix@/lib/python@PYTHON_VERSION@/site-packages:${PYTHONPATH}"
+ export GI_TYPELIB_PATH="@prefix@@libdir@/girepository-1.0:${GI_TYPELIB_PATH}"
+ export LD_LIBRARY_PATH="@prefix@@libdir@:${LD_LIBRARY_PATH}"
+ export XDG_DATA_DIRS="@prefix@@datadir@:${XDG_DATA_DIRS}"
+else
+ export PYTHONPATH="$(dirname $script_dir):${PYTHONPATH}"
+ export GI_TYPELIB_PATH="$(dirname $script_dir)/licaribou:${GI_TYPELIB_PATH}"
+ export LD_LIBRARY_PATH="$(dirname $script_dir)/licaribou/.lib:${LD_LIBRARY_PATH}"
+fi
+
+@PYTHON@ -c "
+from caribou.antler.main import AntlerKeyboardService
+AntlerKeyboardService().run()"
diff --git a/bin/caribou-preferences.in b/bin/caribou-preferences.in
new file mode 100644
index 0000000..13948c8
--- /dev/null
+++ b/bin/caribou-preferences.in
@@ -0,0 +1,53 @@
+#!/bin/bash
+#
+# Antler - a Caribou keyboard implementation
+#
+# Copyright (C) 2011 Eitan Isaacson <eitan@monotonous.org>
+#
+# This program 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 program 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 program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+script_dir="$(dirname "$(readlink -f ${BASH_SOURCE[0]})")"
+
+if [ $script_dir == "@prefix@@libexecdir@" ]
+then
+ export PYTHONPATH="@prefix@/lib/python@PYTHON_VERSION@/site-packages:${PYTHONPATH}"
+ export GI_TYPELIB_PATH="@libdir@/girepository-1.0:${GI_TYPELIB_PATH}"
+ export LD_LIBRARY_PATH="@libdir@:${LD_LIBRARY_PATH}"
+ export XDG_DATA_DIRS="@prefix@@datadir@:${XDG_DATA_DIRS}"
+else
+ export PYTHONPATH="$(dirname $script_dir):${PYTHONPATH}"
+ export GI_TYPELIB_PATH="$(dirname $script_dir)/licaribou:${GI_TYPELIB_PATH}"
+ export LD_LIBRARY_PATH="$(dirname $script_dir)/licaribou/.lib:${LD_LIBRARY_PATH}"
+fi
+
+@PYTHON@ -c "
+import signal
+signal.signal(signal.SIGINT, signal.SIG_DFL)
+
+from caribou.settings.preferences_window import PreferencesWindow
+from caribou.settings import CaribouSettings
+from gi.repository import Gtk
+
+w = PreferencesWindow(CaribouSettings())
+
+w.connect('delete-event', lambda x, y: Gtk.main_quit())
+
+w.show_all()
+
+try:
+ Gtk.main()
+except KeyboardInterrupt:
+ Gtk.main_quit()
+"
diff --git a/bin/caribou.in b/bin/caribou.in
index fb31d47..7bebd0d 100644
--- a/bin/caribou.in
+++ b/bin/caribou.in
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/bin/bash
#
# Caribou - text entry and UI navigation application
#
@@ -24,61 +24,15 @@
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-from optparse import OptionParser
-import gettext
-import sys
-import pyatspi
-import os
+script_dir="$(dirname "$(readlink -f ${BASH_SOURCE[0]})")"
-# We can't rely on prefix if we're installed by relocated RPM. Instead, we
-# use __file__ and for now hope that lib is relative to bin.
-_dirname = os.path.dirname(__file__)
-sys.prefix = os.path.normpath(os.path.join(_dirname, '..'))
-libs = os.path.join(sys.prefix, 'lib',
- 'python@PYTHON_VERSION@', 'site-packages')
-# point to the proper site-packages path
-sys.path.insert(1, libs)
-
-# This might be run from the build dir.
-if os.path.abspath(_dirname) != "@prefix@/bin":
- srcdir = os.path.normpath(os.path.join(_dirname, '..'))
- sys.path.insert(1, srcdir)
- import caribou.common
- import caribou.ui
- caribou.data_path = os.path.abspath(os.path.join(_dirname,
- "@top_srcdir@",
- "data"))
-else:
- import caribou.common
- import caribou.ui
- caribou.data_path = os.path.join("@prefix@", "share", "caribou")
-
-import caribou.ui.window as window
-import caribou.ui.keyboard as keyboard
-import caribou.ui.main as main
-
-_ = gettext.gettext
-
-if __name__ == "__main__":
- import signal
-
- signal.signal(signal.SIGINT, signal.SIG_DFL)
-
- parser = OptionParser(usage="usage: %prog [options]",
- version="%prog @VERSION@")
- parser.add_option("-d", "--debug",
- action="store_true", dest="debug", default=False,
- help="print debug messages on stdout")
- (options, args) = parser.parse_args()
-
- main.debug = options.debug
-
- caribou = main.Caribou()
- caribou.window.hide()
-
- try:
- pyatspi.Registry.start()
- except KeyboardInterrupt:
- caribou.clean_exit()
- pyatspi.Registry.stop()
+if [ $script_dir == "@prefix@/bin" ]
+then
+ export PYTHONPATH="@prefix@/lib/python@PYTHON_VERSION@/site-packages:${PYTHONPATH}"
+ export GI_TYPELIB_PATH="@libdir@/girepository-1.0":${GI_TYPELIB_PATH}
+else
+ export PYTHONPATH="$(dirname $script_dir):${PYTHONPATH}"
+ export GI_TYPELIB_PATH="$(dirname $script_dir)/licaribou":${GI_TYPELIB_PATH}
+fi
+@PYTHON@ -c "from caribou.daemon.main import CaribouDaemon; CaribouDaemon().run()"
diff --git a/caribou/Makefile.am b/caribou/Makefile.am
index 962a2b4..713d8ad 100644
--- a/caribou/Makefile.am
+++ b/caribou/Makefile.am
@@ -1,11 +1,15 @@
cariboudir = $(pkgpythondir)/
caribou_PYTHON = \
- __init__.py
+ __init__.py \
+ i18n.py
SUBDIRS = \
- common/ \
- ui/
+ antler/ \
+ settings/ \
+ daemon/
+
+DISTCLEANFILES = i18n.py
clean-local:
rm -rf *.pyc *.pyo
diff --git a/caribou/__init__.py b/caribou/__init__.py
index 1aadcdc..cf8fdc7 100644
--- a/caribou/__init__.py
+++ b/caribou/__init__.py
@@ -1 +1,2 @@
-data_path = "data/"
+from i18n import _
+APP_NAME=_("Caribou")
diff --git a/caribou/antler/Makefile.am b/caribou/antler/Makefile.am
new file mode 100644
index 0000000..51efe0f
--- /dev/null
+++ b/caribou/antler/Makefile.am
@@ -0,0 +1,10 @@
+caribou_antlerdir = $(pkgpythondir)/antler/
+
+caribou_antler_PYTHON = \
+ __init__.py \
+ keyboard_view.py \
+ main.py \
+ window.py
+
+clean-local:
+ rm -rf *.pyc *.pyo
diff --git a/libcaribou/caribou-enum-types.c.tmpl b/caribou/antler/__init__.py
index e69de29..e69de29 100644
--- a/libcaribou/caribou-enum-types.c.tmpl
+++ b/caribou/antler/__init__.py
diff --git a/caribou/antler/keyboard_view.py b/caribou/antler/keyboard_view.py
new file mode 100644
index 0000000..6cea11b
--- /dev/null
+++ b/caribou/antler/keyboard_view.py
@@ -0,0 +1,164 @@
+from caribou.settings.preferences_window import PreferencesDialog
+from caribou.settings import CaribouSettings
+from gi.repository import Gtk
+from gi.repository import Gdk
+from gi.repository import Caribou
+import gobject
+
+PRETTY_LABELS = {
+ "BackSpace" : u'\u232b',
+ "space" : u' ',
+ "Return" : u'\u23ce',
+ 'Caribou_Prefs' : u'\u2328',
+ 'Caribou_ShiftUp' : u'\u2b06',
+ 'Caribou_ShiftDown' : u'\u2b07',
+ 'Caribou_Emoticons' : u'\u263a',
+ 'Caribou_Symbols' : u'123',
+ 'Caribou_Symbols_More' : u'{#*',
+ 'Caribou_Alpha' : u'Abc'
+}
+
+class AntlerKey(Gtk.Button):
+ def __init__(self, key):
+ gobject.GObject.__init__(self)
+ self.caribou_key = key
+ self.connect("pressed", self._on_pressed)
+ self.connect("released", self._on_released)
+ self.set_label(self._get_key_label())
+ if key.props.name == "Caribou_Prefs":
+ key.connect("key-clicked", self._on_prefs_clicked)
+ if key.get_extended_keys ():
+ self._sublevel = AntlerSubLevel(self)
+
+ def _on_prefs_clicked(self, key):
+ p = PreferencesDialog(CaribouSettings())
+ p.show_all()
+ p.run()
+ p.destroy()
+
+ def _get_key_label(self):
+ label = self.caribou_key.props.name
+ if PRETTY_LABELS.has_key(self.caribou_key.props.name):
+ label = PRETTY_LABELS[self.caribou_key.props.name]
+ elif self.caribou_key.props.name.startswith('Caribou_'):
+ label = self.caribou_key.name.replace('Caribou_', '')
+ else:
+ unichar = unichr(Gdk.keyval_to_unicode(self.caribou_key.props.keyval))
+ if not unichar.isspace() and unichar != u'\x00':
+ label = unichar
+
+ return label
+
+ def _on_pressed(self, button):
+ self.caribou_key.press()
+
+ def _on_released(self, button):
+ self.caribou_key.release()
+
+ def do_get_preferred_width_for_height(self, w):
+ return (w, w)
+
+ def do_get_request_mode(self):
+ return Gtk.SizeRequestMode.HEIGHT_FOR_WIDTH
+
+class AntlerSubLevel(Gtk.Window):
+ def __init__(self, key):
+ gobject.GObject.__init__(self, type=Gtk.WindowType.POPUP)
+
+ self.set_decorated(False)
+ self.set_resizable(False)
+ self.set_accept_focus(False)
+ self.set_position(Gtk.WindowPosition.MOUSE)
+ self.set_type_hint(Gdk.WindowTypeHint.DIALOG)
+
+ key.caribou_key.connect("notify::show-subkeys", self._on_show_subkeys)
+ self._key = key
+
+ layout = AntlerLayout()
+ layout.add_row(key.caribou_key.get_extended_keys())
+ self.add(layout)
+
+ def _on_show_subkeys(self, key, prop):
+ parent = self._key.get_toplevel()
+ if key.props.show_subkeys:
+ self.set_transient_for(parent)
+ parent.set_sensitive(False)
+ self.show_all()
+ else:
+ parent.set_sensitive(True)
+ self.hide()
+
+class AntlerLayout(Gtk.Grid):
+ KEY_SPAN = 4
+
+ def __init__(self, level=None):
+ gobject.GObject.__init__(self)
+ self.set_column_homogeneous(True)
+ self.set_row_homogeneous(True)
+ self.set_row_spacing(4)
+ self.set_column_spacing(4)
+ if level:
+ self.load_rows(level.get_rows ())
+
+ def add_row(self, row, row_num=0):
+ col_num = 0
+ for i, key in enumerate(row):
+ antler_key = AntlerKey(key)
+ self.attach(antler_key,
+ col_num + int(key.props.margin_left * self.KEY_SPAN),
+ row_num * self.KEY_SPAN,
+ int(self.KEY_SPAN * key.props.width),
+ self.KEY_SPAN)
+ col_num += int((key.props.width + key.props.margin_left ) * self.KEY_SPAN)
+
+
+ def load_rows(self, rows):
+ for row_num, row in enumerate(rows):
+ self.add_row(row.get_keys(), row_num)
+
+class AntlerKeyboardView(Gtk.Notebook):
+ def __init__(self):
+ gobject.GObject.__init__(self)
+ self.set_show_tabs(False)
+ self.keyboard_model = Caribou.KeyboardModel()
+ self.keyboard_model.connect("notify::active-group", self._on_group_changed)
+ self.layers = {}
+ for gname in self.keyboard_model.get_groups():
+ group = self.keyboard_model.get_group(gname)
+ self.layers[gname] = {}
+ group.connect("notify::active-level", self._on_level_changed)
+ for lname in group.get_levels():
+ level = group.get_level(lname)
+ layout = AntlerLayout(level)
+ layout.show()
+ self.layers[gname][lname] = self.append_page(layout, None)
+
+ self._set_to_active_layer()
+
+ def _on_level_changed(self, group, prop):
+ self._set_to_active_layer()
+
+ def _on_group_changed(self, kb, prop):
+ self._set_to_active_layer()
+
+ def _set_to_active_layer(self):
+ active_group_name = self.keyboard_model.props.active_group
+ active_group = self.keyboard_model.get_group(active_group_name)
+ active_level_name = active_group.props.active_level
+
+ self.set_current_page(self.layers[active_group_name][active_level_name])
+
+
+if __name__ == "__main__":
+ import signal
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+
+ w = Gtk.Window()
+ w.set_accept_focus(False)
+
+ kb = AntlerKeyboardView()
+ w.add(kb)
+
+ w.show_all()
+
+ Gtk.main()
diff --git a/caribou/antler/main.py b/caribou/antler/main.py
new file mode 100644
index 0000000..ce0eca3
--- /dev/null
+++ b/caribou/antler/main.py
@@ -0,0 +1,30 @@
+from gi.repository import Caribou
+from window import AntlerWindowEntry
+from keyboard_view import AntlerKeyboardView
+import gobject
+
+class AntlerKeyboardService(Caribou.KeyboardService):
+ def __init__(self):
+ gobject.GObject.__init__(self)
+ self.register_keyboard("Antler")
+ self.window = AntlerWindowEntry(AntlerKeyboardView())
+
+ def run(self):
+ loop = gobject.MainLoop()
+ loop.run()
+
+ def do_show(self):
+ self.window.show_all()
+
+ def do_hide(self):
+ self.window.hide()
+
+ def do_set_cursor_location (self, x, y, w, h):
+ self.window.set_cursor_location(x, y, w, h)
+
+ def do_set_entry_location (self, x, y, w, h):
+ self.window.set_entry_location(x, y, w, h)
+
+if __name__ == "__main__":
+ antler_keyboard_service = AntlerKeyboardService()
+ antler_keyboard_service.run()
diff --git a/caribou/ui/window.py b/caribou/antler/window.py
index 471ee1c..973824a 100644
--- a/caribou/ui/window.py
+++ b/caribou/antler/window.py
@@ -20,10 +20,6 @@
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-from caribou import data_path
-from opacity import ProximityWindowBase
-from caribou.common.settings_manager import SettingsManager
-
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import Clutter
@@ -31,12 +27,71 @@ import os
import sys
import gobject
-CARIBOU_LAYOUT_DIR = 'keyboards'
+Clutter.init("antler")
+
+class ProximityWindowBase(object):
+ def __init__(self, min_alpha=1.0, max_alpha=1.0, max_distance=100):
+ if self.__class__ == ProximityWindowBase:
+ raise TypeError, \
+ "ProximityWindowBase is an abstract class, " \
+ "must be subclassed with a Gtk.Window"
+ self.connect('map-event', self.__onmapped)
+ self.max_distance = max_distance
+ if max_alpha < min_alpha:
+ raise ValueError, "min_alpha can't be larger than max_alpha"
+ self.min_alpha = min_alpha
+ self.max_alpha = max_alpha
+
+ def __onmapped(self, obj, event):
+ if self.is_composited():
+ self.set_opacity(self.max_alpha)
+ if self.max_alpha != self.min_alpha:
+ # Don't waste CPU if the max and min are equal.
+ glib.timeout_add(80, self._proximity_check)
+
+ def _proximity_check(self):
+ px, py = self.get_pointer()
+
+ ww = self.get_allocated_width()
+ wh = self.get_allocated_height()
-Clutter.init("caribou")
+ distance = self._get_distance_to_bbox(px, py, ww, wh)
-class CaribouWindow(Gtk.Window, Clutter.Animatable, ProximityWindowBase):
- __gtype_name__ = "CaribouWindow"
+ opacity = (self.max_alpha - self.min_alpha) * \
+ (1 - min(distance, self.max_distance)/self.max_distance)
+ opacity += self.min_alpha
+
+ self.set_opacity(opacity)
+ return self.props.visible
+
+ def _get_distance_to_bbox(self, px, py, bw, bh):
+ if px < 0:
+ x_distance = float(abs(px))
+ elif px > bw:
+ x_distance = float(px - bw)
+ else:
+ x_distance = 0.0
+
+ if py < 0:
+ y_distance = float(abs(px))
+ elif py > bh:
+ y_distance = float(py - bh)
+ else:
+ y_distance = 0.0
+
+ if y_distance == 0 and x_distance == 0:
+ return 0.0
+ elif y_distance != 0 and x_distance == 0:
+ return y_distance
+ elif y_distance == 0 and x_distance != 0:
+ return x_distance
+ else:
+ x2 = 0 if x_distance > 0 else bw
+ y2 = 0 if y_distance > 0 else bh
+ return sqrt((px - x2)**2 + (py - y2)**2)
+
+class AntlerWindow(Gtk.Window, Clutter.Animatable, ProximityWindowBase):
+ __gtype_name__ = "AntlerWindow"
__gproperties__ = {
'animated-window-position' : (gobject.TYPE_PYOBJECT, 'Window position',
'Window position in X, Y coordinates',
@@ -52,7 +107,7 @@ class CaribouWindow(Gtk.Window, Clutter.Animatable, ProximityWindowBase):
max_alpha=max_alpha,
max_distance=max_distance)
- self.set_name("CaribouWindow")
+ self.set_name("AntlerWindow")
self._vbox = Gtk.VBox()
self.add(self._vbox)
@@ -64,11 +119,7 @@ class CaribouWindow(Gtk.Window, Clutter.Animatable, ProximityWindowBase):
self._cursor_location = Rectangle()
self._entry_location = Rectangle()
self._default_placement = default_placement or \
- CaribouWindowPlacement()
-
- conf_file_path = self._get_keyboard_conf()
- if conf_file_path:
- text_entry_mech.load_kb(conf_file_path)
+ AntlerWindowPlacement()
self.connect('show', self._on_window_show)
@@ -118,13 +169,12 @@ class CaribouWindow(Gtk.Window, Clutter.Animatable, ProximityWindowBase):
self.keyboard.destroy()
super(Gtk.Window, self).destroy()
-
- def set_cursor_location(self, cursor_location):
- self._cursor_location = cursor_location
+ def set_cursor_location(self, x, y, w, h):
+ self._cursor_location = Rectangle(x, y, w, h)
self._update_position()
- def set_entry_location(self, entry_location):
- self._entry_location = entry_location
+ def set_entry_location(self, x, y, w, h):
+ self._entry_location = Rectangle(x, y, w, h)
self._update_position()
def set_default_placement(self, default_placement):
@@ -182,49 +232,29 @@ class CaribouWindow(Gtk.Window, Clutter.Animatable, ProximityWindowBase):
def _calculate_axis(self, axis_placement, root_bbox):
bbox = root_bbox
- if axis_placement.stickto == CaribouWindowPlacement.CURSOR:
+ if axis_placement.stickto == AntlerWindowPlacement.CURSOR:
bbox = self._cursor_location
- elif axis_placement.stickto == CaribouWindowPlacement.ENTRY:
+ elif axis_placement.stickto == AntlerWindowPlacement.ENTRY:
bbox = self._entry_location
offset = axis_placement.get_offset(bbox.x, bbox.y)
- if axis_placement.align == CaribouWindowPlacement.END:
+ if axis_placement.align == AntlerWindowPlacement.END:
offset += axis_placement.get_length(bbox.width, bbox.height)
- if axis_placement.gravitate == CaribouWindowPlacement.INSIDE:
+ if axis_placement.gravitate == AntlerWindowPlacement.INSIDE:
offset -= axis_placement.get_length(
self.get_allocated_width(),
self.get_allocated_height())
- elif axis_placement.align == CaribouWindowPlacement.START:
- if axis_placement.gravitate == CaribouWindowPlacement.OUTSIDE:
+ elif axis_placement.align == AntlerWindowPlacement.START:
+ if axis_placement.gravitate == AntlerWindowPlacement.OUTSIDE:
offset -= axis_placement.get_length(
self.get_allocated_width(),
self.get_allocated_height())
- elif axis_placement.align == CaribouWindowPlacement.CENTER:
+ elif axis_placement.align == AntlerWindowPlacement.CENTER:
offset += axis_placement.get_length(bbox.width, bbox.height)/2
return offset
- def _get_keyboard_conf(self):
- layout = SettingsManager.layout.value
- conf_file_path = os.path.join(data_path, CARIBOU_LAYOUT_DIR, layout)
-
- if os.path.exists(conf_file_path):
- return conf_file_path
- else:
- json_path = '%s.json' % conf_file_path
-
- if os.path.exists(json_path):
- return json_path
-
- xml_path = '%s.xml' % conf_file_path
-
- if os.path.exists(xml_path):
- return xml_path
-
- raise Exception("Could not load keyboard %s" % conf_file_path)
-
-
def show_all(self):
Gtk.Window.show_all(self)
self.keyboard.show_all()
@@ -239,18 +269,18 @@ class CaribouWindow(Gtk.Window, Clutter.Animatable, ProximityWindowBase):
req = child.size_request()
self.resize(req.width + border, req.height + border)
-class CaribouWindowDocked(CaribouWindow):
- __gtype_name__ = "CaribouWindowDocked"
+class AntlerWindowDocked(AntlerWindow):
+ __gtype_name__ = "AntlerWindowDocked"
def __init__(self, text_entry_mech):
- placement = CaribouWindowPlacement(
- xalign=CaribouWindowPlacement.END,
- yalign=CaribouWindowPlacement.START,
- xstickto=CaribouWindowPlacement.SCREEN,
- ystickto=CaribouWindowPlacement.SCREEN,
- xgravitate=CaribouWindowPlacement.INSIDE)
+ placement = AntlerWindowPlacement(
+ xalign=AntlerWindowPlacement.END,
+ yalign=AntlerWindowPlacement.START,
+ xstickto=AntlerWindowPlacement.SCREEN,
+ ystickto=AntlerWindowPlacement.SCREEN,
+ xgravitate=AntlerWindowPlacement.INSIDE)
- CaribouWindow.__init__(self, text_entry_mech, placement)
+ AntlerWindow.__init__(self, text_entry_mech, placement)
self.connect('map-event', self.__onmapped)
@@ -268,32 +298,32 @@ class CaribouWindowDocked(CaribouWindow):
def hide(self):
animation = self._roll_out()
- animation.connect('completed', lambda x: CaribouWindow.hide(self))
+ animation.connect('completed', lambda x: AntlerWindow.hide(self))
-class CaribouWindowEntry(CaribouWindow):
- __gtype_name__ = "CaribouWindowEntry"
+class AntlerWindowEntry(AntlerWindow):
+ __gtype_name__ = "AntlerWindowEntry"
def __init__(self, text_entry_mech):
- placement = CaribouWindowPlacement(
- xalign=CaribouWindowPlacement.START,
- xstickto=CaribouWindowPlacement.ENTRY,
- ystickto=CaribouWindowPlacement.ENTRY,
- xgravitate=CaribouWindowPlacement.INSIDE,
- ygravitate=CaribouWindowPlacement.OUTSIDE)
+ placement = AntlerWindowPlacement(
+ xalign=AntlerWindowPlacement.START,
+ xstickto=AntlerWindowPlacement.ENTRY,
+ ystickto=AntlerWindowPlacement.ENTRY,
+ xgravitate=AntlerWindowPlacement.INSIDE,
+ ygravitate=AntlerWindowPlacement.OUTSIDE)
- CaribouWindow.__init__(self, text_entry_mech, placement)
+ AntlerWindow.__init__(self, text_entry_mech, placement)
def _calculate_axis(self, axis_placement, root_bbox):
- offset = CaribouWindow._calculate_axis(self, axis_placement, root_bbox)
+ offset = AntlerWindow._calculate_axis(self, axis_placement, root_bbox)
if axis_placement.axis == 'y':
if offset + self.get_allocated_height() > root_bbox.height + root_bbox.y:
- new_axis_placement = axis_placement.copy(align=CaribouWindowPlacement.START)
- offset = CaribouWindow._calculate_axis(self, new_axis_placement, root_bbox)
+ new_axis_placement = axis_placement.copy(align=AntlerWindowPlacement.START)
+ offset = AntlerWindow._calculate_axis(self, new_axis_placement, root_bbox)
return offset
-class CaribouWindowPlacement(object):
+class AntlerWindowPlacement(object):
START = 'start'
END = 'end'
CENTER = 'center'
@@ -354,7 +384,6 @@ class CaribouWindowPlacement(object):
ystickto or self.CURSOR,
ygravitate or self.OUTSIDE)
-
class Rectangle(object):
def __init__(self, x=0, y=0, width=0, height=0):
self.x = x
@@ -363,11 +392,11 @@ class Rectangle(object):
self.height = height
if __name__ == "__main__":
- import keyboard
+ import keyboard_view
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
- w = CaribouWindowDocked(keyboard.CaribouKeyboard())
+ w = AntlerWindowDocked(keyboard_view.AntlerKeyboardView())
w.show_all()
try:
diff --git a/caribou/common/Makefile.am b/caribou/common/Makefile.am
deleted file mode 100644
index 74805af..0000000
--- a/caribou/common/Makefile.am
+++ /dev/null
@@ -1,11 +0,0 @@
-caribou_commondir = $(pkgpythondir)/common/
-
-caribou_common_PYTHON = \
- __init__.py \
- const.py \
- settings_manager.py \
- settings.py \
- setting_types.py
-
-clean-local:
- rm -rf *.pyc *.pyo
diff --git a/caribou/common/__init__.py b/caribou/common/__init__.py
deleted file mode 100644
index 8d1c8b6..0000000
--- a/caribou/common/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/caribou/common/const.py b/caribou/common/const.py
deleted file mode 100644
index b3a13b7..0000000
--- a/caribou/common/const.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Caribou - text entry and UI navigation application
-#
-# Copyright (C) 2010 Warp Networks S.L.
-# * Contributor: David Pellicer <dpellicer@warp.es>
-#
-# This program 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 program 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 program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-from os.path import join
-from os.path import dirname
-
-from caribou import data_path
-
-# Application name
-APP_NAME = 'Caribou'
-APP_SLUG_NAME = 'caribou'
-
-# Paths
-DATA_DIR = data_path
-KEYBOARDS_DIR = join(DATA_DIR, 'keyboards')
-
-# Preferences
-CARIBOU_GCONF = '/org/gnome/caribou/osk'
-
-# Key types
-NORMAL_KEY_TYPE = 'normal'
-LAYOUT_SWITCHER_KEY_TYPE = 'layout_switcher'
-PREFERENCES_KEY_TYPE = 'preferences'
-DUMMY_KEY_TYPE = 'dummy'
-MASK_KEY_TYPE = 'mask'
diff --git a/caribou/common/settings.py b/caribou/common/settings.py
deleted file mode 100644
index a3d900d..0000000
--- a/caribou/common/settings.py
+++ /dev/null
@@ -1,179 +0,0 @@
-import os
-from setting_types import *
-from gettext import gettext as _
-import caribou.common.const as const
-import caribou.ui.i18n
-import xml.dom.minidom
-
-GSETTINGS_SCHEMA = "org.gnome.caribou"
-
-try:
- import json
-except ImportError:
- HAS_JSON = False
-else:
- HAS_JSON = True
-
-def fetch_keyboards():
- try:
- files = os.listdir(const.KEYBOARDS_DIR)
- except:
- files = []
- kbds = []
- for f in files:
- if (HAS_JSON and f.endswith('.json')) or f.endswith('.xml'):
- module = f.rsplit('.', 1)[0]
- # TODO: verify keyboard before adding it to the list
- kbds.append(module)
- return kbds
-
-settings = SettingsGroup("_top", "", [
- SettingsGroup("keyboard", _("Keyboard"), [
- SettingsGroup("general", _("General"), [
- StringSetting(
- "layout", _("Keyboard layout"), "qwerty",
- _("The layout Caribou should use."),
- _("The layout should be in the data directory of "
- "Caribou (usually /usr/share/caribou/keyboards) "
- "and should be a .xml or .json file."),
- allowed=[(a,a) for a in fetch_keyboards()])]),
- SettingsGroup("color", _("Color"), [
- BooleanSetting(
- "default_colors", _("Use system theme"), True,
- _("Use the default theme colors"),
- insensitive_when_true=["normal_color",
- "mouse_over_color"]),
- ColorSetting(
- "normal_color", _("Normal state"), "grey80",
- _("Color of the keys when there is no "
- "event on them")),
- ColorSetting(
- "mouse_over_color", _("Mouse over"), "yellow",
- _("Color of the keys when the mouse goes "
- "over the key"))]),
- SettingsGroup("fontandsize", _("Font and size"), [
- BooleanSetting(
- "default_font", _("Use system fonts"), True,
- _("Use the default system font for keyboard"),
- insensitive_when_true=["key_font"]),
- FontSetting("key_font", _("Key font"), "Sans 12",
- _("Custom font for keyboard"))
- ])
- ]),
- SettingsGroup("scanning", _("Scanning"), [
- BooleanSetting(
- "scan_enabled", _("Enable scanning"), False,
- _("Enable switch scanning"),
- insensitive_when_false=["scanning_general",
- "scanning_input",
- "scanning_color"]),
- SettingsGroup("scanning_general", _("General"), [
- StringSetting("scanning_type", _("Scanning mode"),
- "block",
- _("Scanning type, block or row"),
- allowed=[("block", _("Block")),
- ("row", _("Row"))]),
- FloatSetting("step_time", _("Step time"), 1.0,
- _("Time between key transitions"),
- min=0.1, max=60.0),
- BooleanSetting("reverse_scanning",
- _("Reverse scanning"), False,
- _("Scan in reverse order"))
- ]),
- SettingsGroup("scanning_input", _("Input"), [
- StringSetting("switch_type", _("Switch device"),
- "keyboard",
- _("Switch device, keyboard or mouse"),
- entry_type=ENTRY_RADIO,
- allowed=[("keyboard", _("Keyboard")),
- ("mouse", _("Mouse"))],
- children=[
- StringSetting("keyboard_key", _("Switch key"),
- "Shift_R",
- _(
- "Key to use with scanning mode"),
- allowed=[
- ("Shift_R", _("Right shift")),
- ("Shift_L", _("Left shift")),
- ("ISO_Level3_Shift", _("Alt Gr")),
- ("Num_Lock", _("Num lock"))]),
- StringSetting("mouse_button", _("Switch button"),
- "2",
- _(
- "Mouse button to use in the scanning "
- "mode"),
- allowed=[("1", _("Button 1")),
- ("2", _("Button 2")),
- ("3", _("Button 3"))])
- ]),
- ]),
- SettingsGroup("scanning_color", _("Color"), [
- ColorSetting("block_scanning_color", _("Block color"),
- "purple", _("Color of block scans")),
- ColorSetting("row_scanning_color", _("Row color"),
- "green", _("Color of row scans")),
- ColorSetting("button_scanning_color", _("Key color"),
- "cyan", _("Color of key scans")),
- ColorSetting("cancel_scanning_color",
- _("Cancel color"),
- "red", _("Color of cancel scan"))
- ])
- ])
- ])
-
-if __name__ == "__main__":
- from gi.repository import GLib
-
- class SchemasMaker:
- def create_schemas(self):
- doc = xml.dom.minidom.Document()
- schemafile = doc.createElement('schemalist')
- schema = doc.createElement('schema')
- schema.setAttribute("id", GSETTINGS_SCHEMA)
- schema.setAttribute("path", "/org/gnome/caribou/osk/")
- schemafile.appendChild(schema)
- self._create_schema(settings, doc, schema)
-
- self._pretty_xml(schemafile)
-
- def _attribs(self, e):
- if not e.attributes.items():
- return ""
- return ' ' + ' '.join(['%s="%s"' % (k,v) \
- for k,v in e.attributes.items()])
-
- def _pretty_xml(self, e, indent=0):
- if not e.childNodes or \
- (len(e.childNodes) == 1 and \
- e.firstChild.nodeType == e.TEXT_NODE):
- print '%s%s' % (' '*indent*2, e.toxml().strip())
- else:
- print '%s<%s%s>' % (' '*indent*2, e.tagName, self._attribs(e))
- for c in e.childNodes:
- self._pretty_xml(c, indent + 1)
- print '%s</%s>' % (' '*indent*2, e.tagName)
-
- def _append_children_element_value_pairs(self, doc, element, pairs):
- for e, t in pairs:
- el = doc.createElement(e)
- te = doc.createTextNode(str(t))
- el.appendChild(te)
- element.appendChild(el)
-
- def _create_schema(self, setting, doc, schemalist):
- if hasattr(setting, 'gsettings_key'):
- key = doc.createElement('key')
- key.setAttribute('name', setting.gsettings_key)
- key.setAttribute('type', setting.variant_type)
- schemalist.appendChild(key)
- self._append_children_element_value_pairs(
- doc, key, [('default',
- getattr(setting.gvariant, "print")(False)),
- ('_summary', setting.short_desc),
- ('_description', setting.long_desc)])
-
- for s in setting:
- self._create_schema(s, doc, schemalist)
-
- maker = SchemasMaker()
- maker.create_schemas()
diff --git a/caribou/daemon/Makefile.am b/caribou/daemon/Makefile.am
new file mode 100644
index 0000000..859c29e
--- /dev/null
+++ b/caribou/daemon/Makefile.am
@@ -0,0 +1,8 @@
+caribou_daemondir = $(pkgpythondir)/daemon/
+
+caribou_daemon_PYTHON = \
+ __init__.py \
+ main.py
+
+clean-local:
+ rm -rf *.pyc *.pyo
diff --git a/caribou/daemon/__init__.py b/caribou/daemon/__init__.py
new file mode 100644
index 0000000..fd9812d
--- /dev/null
+++ b/caribou/daemon/__init__.py
@@ -0,0 +1 @@
+from main import CaribouDaemon
diff --git a/caribou/daemon/main.py b/caribou/daemon/main.py
new file mode 100644
index 0000000..4f3def9
--- /dev/null
+++ b/caribou/daemon/main.py
@@ -0,0 +1,165 @@
+import pyatspi
+import dbus
+from gi.repository import Gio
+from string import Template
+
+from caribou.i18n import _
+from caribou import APP_NAME
+
+debug = False
+
+class CaribouDaemon:
+ def __init__(self, keyboard_name="Antler"):
+ if not self._get_a11y_enabled():
+ self._show_no_a11y_dialogs()
+ bus = dbus.SessionBus()
+ try:
+ dbus_obj = bus.get_object("org.gnome.Caribou.%s" % keyboard_name,
+ "/org/gnome/Caribou/%s" % keyboard_name)
+ except dbus.DBusException, e:
+ self._show_error_dialog(e.message)
+ self.keyboard_proxy = dbus.Interface(dbus_obj, "org.gnome.Caribou.Keyboard")
+ self._current_acc = None
+ self._register_event_listeners()
+
+ def _show_error_dialog(self, message):
+ from gi.repository import Gtk
+ msgdialog = Gtk.MessageDialog(None,
+ Gtk.DialogFlags.MODAL,
+ Gtk.MessageType.ERROR,
+ Gtk.ButtonsType.CLOSE,
+ _("Error starting %s") % APP_NAME)
+ msgdialog.format_secondary_text(message)
+ msgdialog.run()
+ quit()
+
+ def _show_no_a11y_dialogs(self):
+ from gi.repository import Gtk
+ msgdialog = Gtk.MessageDialog(None,
+ Gtk.DialogFlags.MODAL,
+ Gtk.MessageType.QUESTION,
+ Gtk.ButtonsType.YES_NO,
+ _("In order to use %s, accessibility needs "
+ "to be enabled. Do you want to enable "
+ "it now?") % APP_NAME)
+ resp = msgdialog.run()
+ if resp == Gtk.ResponseType.NO:
+ msgdialog.destroy()
+ quit()
+ if resp == Gtk.ResponseType.YES:
+ settings = Gio.Settings('org.gnome.desktop.interface')
+ atspi = settings.set_boolean("toolkit-accessibility", True)
+ msgdialog2 = Gtk.MessageDialog(msgdialog,
+ Gtk.DialogFlags.MODAL,
+ Gtk.MessageType.INFO,
+ Gtk.ButtonsType.OK,
+ _("Accessibility has been enabled. "
+ "Log out and back in again to use "
+ "%s." % APP_NAME))
+ msgdialog2.run()
+ msgdialog2.destroy()
+ msgdialog.destroy()
+ quit()
+
+
+ def _register_event_listeners(self):
+ pyatspi.Registry.registerEventListener(
+ self.on_focus, "object:state-changed:focused")
+ pyatspi.Registry.registerEventListener(self.on_focus, "focus")
+ pyatspi.Registry.registerEventListener(
+ self.on_text_caret_moved, "object:text-caret-moved")
+
+ def _deregister_event_listeners(self):
+ pyatspi.Registry.deregisterEventListener(
+ self.on_focus, "object:state-changed:focused")
+ pyatspi.Registry.deregisterEventListener(self.on_focus, "focus")
+ pyatspi.Registry.deregisterEventListener(
+ self.on_text_caret_moved, "object:text-caret-moved")
+
+ def _get_a11y_enabled(self):
+ try:
+ try:
+ settings = Gio.Settings('org.gnome.desktop.interface')
+ atspi = settings.get_boolean("toolkit-accessibility")
+ return atspi
+ except:
+ raise
+ from gi.repository import GConf
+ gconfc = GConf.Client.get_default()
+ atspi1 = gconfc.get_bool(
+ "/desktop/gnome/interface/accessibility")
+ atspi2 = gconfc.get_bool(
+ "/desktop/gnome/interface/accessibility2")
+ return atspi1 or atspi2
+ except:
+ raise
+ return False
+
+ def on_text_caret_moved(self, event):
+ if self._current_acc == event.source:
+ text = self._current_acc.queryText()
+ x, y, w, h = text.getCharacterExtents(text.caretOffset,
+ pyatspi.DESKTOP_COORDS)
+ if (x, y, w, h) == (0, 0, 0, 0):
+ component = self._current_acc.queryComponent()
+ bb = component.getExtents(pyatspi.DESKTOP_COORDS)
+ x, y, w, h = bb.x, bb.y, bb.width, bb.height
+
+ self.keyboard_proxy.SetCursorLocation(x, y, w, h)
+ if debug == True:
+ print "object:text-caret-moved in", event.host_application.name,
+ print event.detail1, event.source.description
+
+ def _set_entry_location(self, acc):
+ text = acc.queryText()
+ bx, by, bw, bh = text.getCharacterExtents(text.caretOffset,
+ pyatspi.DESKTOP_COORDS)
+
+ component = acc.queryComponent()
+ entry_bb = component.getExtents(pyatspi.DESKTOP_COORDS)
+
+ if (bx, by, bw, bh) == (0, 0, 0, 0):
+ bx, by, bw, bh = entry_bb.x, entry_bb.y, entry_bb.width, entry_bb.height
+
+ self.keyboard_proxy.SetCursorLocation(bx, by, bw, bh)
+
+ self.keyboard_proxy.SetEntryLocation(entry_bb.x, entry_bb.y,
+ entry_bb.width, entry_bb.height)
+
+ self.keyboard_proxy.Show()
+
+ def on_focus(self, event):
+ acc = event.source
+ source_role = acc.getRole()
+ if acc.getState().contains(pyatspi.STATE_EDITABLE) or \
+ source_role == pyatspi.ROLE_TERMINAL:
+ if source_role in (pyatspi.ROLE_TEXT,
+ pyatspi.ROLE_PARAGRAPH,
+ pyatspi.ROLE_PASSWORD_TEXT,
+ pyatspi.ROLE_TERMINAL,
+ pyatspi.ROLE_ENTRY):
+ if event.type.startswith("focus") or event.detail1 == 1:
+ self._set_entry_location(acc)
+ self._current_acc = event.source
+ if debug == True:
+ print "enter text widget in", event.host_application.name
+ elif event.detail1 == 0 and acc == self._current_acc:
+ self.keyboard_proxy.Hide()
+ self._current_acc = None
+ if debug == True:
+ print "leave text widget in", event.host_application.name
+ else:
+ if debug == True:
+ print _("WARNING - Caribou: unhandled editable widget:"), \
+ event.source
+
+ def clean_exit(self):
+ self.keyboard_proxy.Hide()
+ self._deregister_event_listeners()
+
+ def run(self):
+ try:
+ pyatspi.Registry.start()
+ except KeyboardInterrupt:
+ self.clean_exit()
+ pyatspi.Registry.stop()
diff --git a/caribou/ui/i18n.py.in b/caribou/i18n.py.in
index bf7ad0f..bf7ad0f 100644
--- a/caribou/ui/i18n.py.in
+++ b/caribou/i18n.py.in
diff --git a/caribou/settings/Makefile.am b/caribou/settings/Makefile.am
new file mode 100644
index 0000000..468adab
--- /dev/null
+++ b/caribou/settings/Makefile.am
@@ -0,0 +1,11 @@
+caribou_settingsdir = $(pkgpythondir)/settings/
+
+caribou_settings_PYTHON = \
+ __init__.py \
+ preferences_window.py \
+ settings_manager.py \
+ caribou_settings.py \
+ setting_types.py
+
+clean-local:
+ rm -rf *.pyc *.pyo
diff --git a/caribou/settings/__init__.py b/caribou/settings/__init__.py
new file mode 100644
index 0000000..0ec8b40
--- /dev/null
+++ b/caribou/settings/__init__.py
@@ -0,0 +1,5 @@
+GSETTINGS_SCHEMA = "org.gnome.caribou"
+
+from caribou_settings import CaribouSettings
+
+AllSettings = [CaribouSettings]
diff --git a/caribou/settings/caribou_settings.py b/caribou/settings/caribou_settings.py
new file mode 100644
index 0000000..638e1c4
--- /dev/null
+++ b/caribou/settings/caribou_settings.py
@@ -0,0 +1,64 @@
+from caribou.settings.setting_types import *
+from caribou.i18n import _
+
+CaribouSettings = SettingsTopGroup(
+ _("Caribou Preferences"), "/org/gnome/caribou/", "org.gnome.caribou",
+ [SettingsGroup("keyboard", _("Keyboard"), [
+ SettingsGroup("general", _("General"), [
+ StringSetting(
+ "keyboard_type", _("Keyboard Type"), "touch",
+ _("The keyboard geometery Caribou should use"),
+ _("The keyboard geometery determines the shape "
+ "and complexity of the keyboard, it could range from "
+ "a 'natural' look and feel good for composing simple "
+ "text, to a fullscale keyboard."),
+ allowed=[(('touch'), _('Touch'))])]),
+ ]),
+ SettingsGroup("scanning", _("Scanning"), [
+ BooleanSetting(
+ "scan_enabled", _("Enable scanning"), False,
+ _("Enable switch scanning"),
+ insensitive_when_false=["scanning_general",
+ "scanning_input"]),
+ SettingsGroup("scanning_general", _("General"), [
+ StringSetting("scanning_type", _("Scanning mode"),
+ "block",
+ _("Scanning type, block or row"),
+ allowed=[("block", _("Block")),
+ ("row", _("Row"))]),
+ FloatSetting("step_time", _("Step time"), 1.0,
+ _("Time between key transitions"),
+ min=0.1, max=60.0),
+ BooleanSetting("reverse_scanning",
+ _("Reverse scanning"), False,
+ _("Scan in reverse order"))
+ ]),
+ SettingsGroup("scanning_input", _("Input"), [
+ StringSetting("switch_type", _("Switch device"),
+ "keyboard",
+ _("Switch device, keyboard or mouse"),
+ entry_type=ENTRY_RADIO,
+ allowed=[("keyboard", _("Keyboard")),
+ ("mouse", _("Mouse"))],
+ children=[
+ StringSetting("keyboard_key", _("Switch key"),
+ "Shift_R",
+ _(
+ "Key to use with scanning mode"),
+ allowed=[
+ ("Shift_R", _("Right shift")),
+ ("Shift_L", _("Left shift")),
+ ("ISO_Level3_Shift", _("Alt Gr")),
+ ("Num_Lock", _("Num lock"))]),
+ StringSetting("mouse_button", _("Switch button"),
+ "2",
+ _(
+ "Mouse button to use in the scanning "
+ "mode"),
+ allowed=[("1", _("Button 1")),
+ ("2", _("Button 2")),
+ ("3", _("Button 3"))])
+ ]),
+ ]),
+ ])
+ ])
diff --git a/caribou/ui/preferences_window.py b/caribou/settings/preferences_window.py
index 0158ffb..58d1b4c 100644
--- a/caribou/ui/preferences_window.py
+++ b/caribou/settings/preferences_window.py
@@ -18,47 +18,24 @@
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-import caribou.common.const as const
-from caribou.common.setting_types import *
-from caribou.common.settings_manager import SettingsManager
+from caribou.settings.setting_types import *
-from gi.repository import GConf
import gobject
from gi.repository import Gdk
from gi.repository import Gtk
-from gi.repository import Pango
-import sys
-import virtkey
-import os
-import traceback
-from i18n import _
-try:
- import json
-except ImportError:
- HAS_JSON = False
-else:
- HAS_JSON = True
-import xml.etree.ElementTree as ET
-from xml.dom import minidom
-import gettext
-import i18n
-
-class PreferencesWindow(Gtk.Dialog):
- __gtype_name__ = "PreferencesWindow"
-
- def __init__(self):
- gobject.GObject.__init__(self)
- self.set_title(_("Caribou Preferences"))
- self.add_button(Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)
- self.set_border_width(6)
+class AbstractPreferencesUI:
+ def populate_settings(self, groups):
notebook = Gtk.Notebook()
- vbox = self.get_content_area()
- vbox.add(notebook)
- self._populate_settings(notebook, SettingsManager.groups)
+ self._populate_settings(notebook, groups)
+ if notebook.get_n_pages() == 1:
+ notebook.set_show_tabs(False)
+
+ return notebook
def _populate_settings(self, parent, setting, level=0):
if level == 0:
+ self.set_title(setting.label)
for s in setting:
vbox = Gtk.VBox()
parent.append_page(vbox, Gtk.Label(label=s.label))
@@ -248,11 +225,38 @@ class PreferencesWindow(Gtk.Dialog):
self._update_setting(setting, combo.get_active_id(),
handler_id)
+class PreferencesDialog(Gtk.Dialog, AbstractPreferencesUI):
+ __gtype_name__ = "PreferencesDialog"
+
+ def __init__(self, settings_manager):
+ gobject.GObject.__init__(self)
+ self.add_button(Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)
+ self.set_border_width(6)
+
+ notebook = self.populate_settings(settings_manager.groups)
+ vbox = self.get_content_area()
+ vbox.add(notebook)
+
+class PreferencesWindow(Gtk.Window, AbstractPreferencesUI):
+ __gtype_name__ = "PreferencesWindow"
+
+ def __init__(self, settings_manager):
+ gobject.GObject.__init__(self)
+ self.set_border_width(6)
+
+ notebook = self.populate_settings(settings_manager.groups)
+ self.add(notebook)
+
if __name__ == "__main__":
+ from caribou.settings.settings_manager import SettingsManager
+ from caribou.settings import CaribouSettings
+
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
- w = PreferencesWindow()
+
+ w = PreferencesDialog(CaribouSettings())
w.show_all()
+
try:
w.run()
except KeyboardInterrupt:
diff --git a/caribou/common/setting_types.py b/caribou/settings/setting_types.py
index 109bf1b..b0e374d 100644
--- a/caribou/common/setting_types.py
+++ b/caribou/settings/setting_types.py
@@ -53,6 +53,16 @@ class Setting(gobject.GObject):
class SettingsGroup(Setting):
pass
+class SettingsTopGroup(SettingsGroup):
+ def __init__(self, label, path, schema_id, children=[]):
+ SettingsGroup.__init__(self, "_top", label, children)
+ self.path = path
+ self.schema_id = schema_id
+
+ def __call__(self):
+ from caribou.settings.settings_manager import SettingsManager
+ return SettingsManager(self)
+
class ValueSetting(Setting):
variant_type = ''
entry_type=ENTRY_DEFAULT
diff --git a/caribou/common/settings_manager.py b/caribou/settings/settings_manager.py
index 66119f8..1368f3a 100644
--- a/caribou/common/settings_manager.py
+++ b/caribou/settings/settings_manager.py
@@ -1,10 +1,9 @@
import os
from gi.repository import Gio
-from setting_types import *
-from settings import settings, GSETTINGS_SCHEMA
-import const
+from caribou.settings.setting_types import *
+from caribou.settings import GSETTINGS_SCHEMA
-class _SettingsManager(object):
+class SettingsManager(object):
def __init__(self, settings):
self.groups = settings
self._gsettings = Gio.Settings(GSETTINGS_SCHEMA)
@@ -66,5 +65,3 @@ class _SettingsManager(object):
def __call__(self):
return self
-
-SettingsManager = _SettingsManager(settings)
diff --git a/caribou/ui/Makefile.am b/caribou/ui/Makefile.am
deleted file mode 100644
index fb24db4..0000000
--- a/caribou/ui/Makefile.am
+++ /dev/null
@@ -1,16 +0,0 @@
-caribou_uidir = $(pkgpythondir)/ui/
-
-caribou_ui_PYTHON = \
- __init__.py \
- i18n.py \
- keyboard.py \
- scan.py \
- main.py \
- opacity.py \
- preferences_window.py \
- window.py
-
-DISTCLEANFILES = i18n.py
-
-clean-local:
- rm -rf *.pyc *.pyo
diff --git a/caribou/ui/__init__.py b/caribou/ui/__init__.py
deleted file mode 100644
index 8b13789..0000000
--- a/caribou/ui/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/caribou/ui/keyboard.py b/caribou/ui/keyboard.py
deleted file mode 100644
index c390d49..0000000
--- a/caribou/ui/keyboard.py
+++ /dev/null
@@ -1,461 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Caribou - text entry and UI navigation application
-#
-# Copyright (C) 2009 Adaptive Technology Resource Centre
-# * Contributor: Ben Konrath <ben@bagu.org>
-# Copyright (C) 2009 Eitan Isaacson <eitan@monotonous.org>
-# Copyright (C) 2010 Igalia S.L.
-# * Contributor: Joaquim Rocha <jrocha@igalia.com>
-#
-# This program 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 program 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 program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-import caribou.common.const as const
-from caribou.common.settings_manager import SettingsManager
-from preferences_window import PreferencesWindow
-from gi.repository import GConf
-import gobject
-from gi.repository import Gdk
-from gi.repository import Gtk
-from gi.repository import Pango
-from gi.repository import Caribou
-import sys
-import os
-import traceback
-from caribou.ui.i18n import _
-from caribou.common.setting_types import *
-
-try:
- import json
-except ImportError:
- HAS_JSON = False
-else:
- HAS_JSON = True
-import xml.etree.ElementTree as ET
-from xml.dom import minidom
-import gettext
-import i18n
-
-class BaseKey(object):
- '''An abstract class the represents a key on the keyboard.
- Inheriting classes also need to inherit from Gtk.Button or any
- of it's subclasses.'''
-
- def __init__(self, label = '', value = '', key_type = 'normal',
- width = 1, fill = False):
- self.key_type = key_type
- self.value = value
- self.width = float(width)
- self.fill = False
- self.label = label or value
- if self.key_type == const.DUMMY_KEY_TYPE:
- self.set_relief(Gtk.ReliefStyle.NONE)
- self.set_sensitive(False)
- elif self.key_type == const.PREFERENCES_KEY_TYPE:
- image = Gtk.Image()
- image.set_from_stock(Gtk.STOCK_PREFERENCES,
- Gtk.IconSize.BUTTON)
- self.set_image(image)
- else:
- if label:
- label_markup = Gtk.Label()
- label_markup.set_markup(self.label)
- self.add(label_markup)
- else:
- self.set_label(self.label)
-
- ctx = self.get_style_context()
- ctx.add_class("caribou-keyboard-button")
-
- for name in ["default_font", "key_font"]:
- getattr(SettingsManager, name).connect("value-changed",
- self._key_font_changed)
-
- if not SettingsManager.default_font.value:
- self._key_font_changed(None, None)
-
- def _key_font_changed(self, setting, value):
- if SettingsManager.default_font.value:
- self.reset_font()
- else:
- self.set_font(SettingsManager.key_font.value)
-
- def scan_highlight_key(self):
- raise NotImplemented
-
- def scan_highlight_row(self):
- raise NotImplemented
-
- def scan_highlight_block(self):
- raise NotImplemented
-
- def scan_highlight_cancel(self):
- raise NotImplemented
-
- def scan_highlight_clear(self):
- raise NotImplemented
-
- def _on_image_key_mapped(self, key):
- key_width = key.get_allocated_height()
- icon_size = Gtk.IconSize.MENU
- image = Gtk.Image()
- for size in [Gtk.IconSize.MENU,
- Gtk.IconSize.SMALL_TOOLBAR,
- Gtk.IconSize.LARGE_TOOLBAR,
- Gtk.IconSize.BUTTON,
- Gtk.IconSize.DND,
- Gtk.IconSize.DIALOG]:
- pixbuf = image.render_icon_pixbuf(Gtk.STOCK_PREFERENCES, size)
- pixel_size = pixbuf.get_width()
- if pixel_size > key_width:
- break
- icon_size = size
- image.set_from_stock(Gtk.STOCK_PREFERENCES, icon_size)
- self.set_image(image)
-
- def set_font(self, font):
- raise NotImplemented
-
- def reset_font(self):
- raise NotImplemented
-
- def _get_value(self):
- return self._value
-
- def _set_value(self, value):
- if self.key_type in (const.NORMAL_KEY_TYPE, const.MASK_KEY_TYPE):
- if type(value) == str:
- value = value.decode('utf-8')
- if type(value) == unicode:
- if len(value) == 1:
- self._value = Gdk.unicode_to_keyval(ord(value))
- else:
- key_value = Gdk.keyval_from_name(value)
- if key_value:
- self._value = key_value
- else:
- self._value = value
-
- value = property(_get_value, _set_value)
-
-class Key(Gtk.Button, BaseKey):
- def __init__(self, label = '', value = '', key_type = 'normal',
- width = 1, fill = False):
- gobject.GObject.__init__(self)
- BaseKey.__init__(self, label, value, key_type, width, fill)
-
- def set_font(self, font):
- child = self.get_child()
- if isinstance(child, Gtk.Label):
- child.modify_font(Pango.font_description_from_string(font))
- if child is not None:
- child.queue_resize()
-
- def reset_font(self):
- label = self.get_child()
- if not isinstance(label, Gtk.Label):
- return
- label.modify_font(None)
-
- def _replace_scan_class_style(self, scan_class=None):
- ctx = self.get_style_context()
- for cls in ctx.list_classes():
- if cls.startswith('caribou-scan'):
- ctx.remove_class(cls)
- if scan_class:
- ctx.add_class(scan_class)
- self.queue_draw()
-
- def scan_highlight_key(self):
- self._replace_scan_class_style("caribou-scan-key")
-
- def scan_highlight_row(self):
- self._replace_scan_class_style("caribou-scan-row")
-
- def scan_highlight_block(self):
- self._replace_scan_class_style("caribou-scan-block")
-
- def scan_highlight_cancel(self):
- self._replace_scan_class_style("caribou-scan-cancel")
-
- def scan_highlight_clear(self):
- self._replace_scan_class_style()
-
-class ModifierKey(Gtk.ToggleButton, Key):
- pass
-
-class KeyboardLayout(Gtk.Table):
- KEY_SPAN = 4
- def __init__(self, name):
- gobject.GObject.__init__(self)
- self.layout_name = name
- self.rows = []
- self.set_homogeneous(True)
-
- def add_row(self, row):
- row_num = len(self.rows)
- self.rows.append(row)
- last_col = 0
- for i, key in enumerate(row):
- next_col = (last_col + (key.width * self.KEY_SPAN))
- self.attach(key, last_col, next_col,
- row_num * self.KEY_SPAN, (row_num + 1) * self.KEY_SPAN,
- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL,
- Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL,
- 0, 0)
- last_col = next_col
-
- def get_scan_rows(self):
- return [filter(lambda x: x.is_sensitive(), row) for row in self.rows]
-
- def get_scan_blocks(self, optimal_block_size=8):
- # TODO: smarter division using optimal block size.
- scan_rows = self.get_scan_rows()
- col_num = max([len(row) for row in scan_rows])
- blocks = []
-
- for row_index in xrange(len(scan_rows)):
- for col_index in xrange(max([len(row) for row in scan_rows])):
- try:
- key = scan_rows[row_index][col_index]
- except IndexError:
- continue
-
- try:
- group = blocks[row_index/2]
- except IndexError:
- group = []
- blocks.append(group)
-
- try:
- group[col_index/3].append(key)
- except IndexError:
- block = []
- block.append(key)
- group.append(block)
-
- return reduce(lambda a, b: a + b, blocks)
-
-
-
-class KbLayoutDeserializer(object):
- def __init__(self):
- pass
-
- def deserialize(self, kb_layout_file):
- kb_file = os.path.abspath(kb_layout_file)
- if not os.path.isfile(kb_file):
- return []
- kb_file_obj = open(kb_file)
- contents = kb_file_obj.read()
- kb_file_obj.close()
- basename, ext = os.path.splitext(kb_file)
- try:
- kb_layouts = self._deserialize_from_format(ext, contents)
- except Exception, e:
- traceback.print_exc()
- else:
- return kb_layouts
- return []
-
- def _deserialize_from_format(self, format, contents):
- if format == '.xml':
- return self._deserialize_from_xml(contents)
- if HAS_JSON and format == '.json':
- return self._deserialize_from_json(contents)
- return []
-
- def _deserialize_from_json(self, contents):
- contents_dict = json.loads(contents)
- layouts = self._create_kb_layout_from_dict(contents_dict)
- return layouts
-
- def _convert_xml_to_dict(self, element):
- if element.text and element.text.strip():
- return element.text
- attributes = element.attrib
- for child in element.getchildren():
- if attributes.get(child.tag):
- attributes[child.tag] += [self._convert_xml_to_dict(child)]
- else:
- attributes[child.tag] = [self._convert_xml_to_dict(child)]
- for key, value in attributes.items():
- if isinstance(value, list) and len(value) == 1:
- attributes[key] = value[0]
- return attributes
-
- def _deserialize_from_xml(self, xml_string):
- element = ET.fromstring(xml_string)
- layout_dict = self._convert_xml_to_dict(element)
- return self._create_kb_layout_from_dict(layout_dict)
-
- def _create_kb_layout_from_dict(self, dictionary):
- if not isinstance(dictionary, dict):
- return None
- layouts = self._get_dict_value_as_list(dictionary, 'layout')
- layouts_encoded = []
- for layout in layouts:
- name = layout.get('name')
- if not name:
- continue
- kb_layout = KeyboardLayout(name)
- rows_list = self._get_dict_value_as_list(layout, 'rows')
- for rows in rows_list:
- for row_encoded in self._get_rows_from_dict(rows):
- kb_layout.add_row(row_encoded)
- layouts_encoded.append(kb_layout)
- return layouts_encoded
-
- def _get_rows_from_dict(self, rows):
- rows_encoded = []
- row_list = self._get_dict_value_as_list(rows, 'row')
- for row in row_list:
- keys = self._get_dict_value_as_list(row, 'key')
- if keys:
- rows_encoded.append(self._get_keys_from_list(keys))
- return rows_encoded
-
- def _get_keys_from_list(self, keys_list):
- keys = []
- for key_vars in keys_list:
- vars = {}
- for key, value in key_vars.items():
- vars[str(key)] = value
- if vars.get('key_type', '') == const.MASK_KEY_TYPE:
- key = ModifierKey(**vars)
- else:
- key = Key(**vars)
- keys.append(key)
- return keys
-
- def _get_dict_value_as_list(self, dictionary, key):
- if isinstance(dictionary, list):
- return dictionary
- value = dictionary.get(key)
- if not value:
- return None
- if isinstance(value, list):
- return value
- return [value]
-
-class CaribouKeyboard(Gtk.Notebook):
- __gtype_name__ = "CaribouKeyboard"
-
- def __init__(self):
- gobject.GObject.__init__(self)
- self.set_show_tabs(False)
- self.vk = Caribou.VirtualKeyboard()
- self.key_size = 30
- self.current_page = 0
- self.depressed_mods = []
-
- self.row_height = -1
-
- def load_kb(self, kb_location):
- kb_deserializer = KbLayoutDeserializer()
- layouts = kb_deserializer.deserialize(kb_location)
- self._set_layouts(layouts)
-
- def _set_layouts(self, layout_list):
- self._clear()
- for layout in layout_list:
- self.append_page(layout, None)
- for row in layout.rows:
- for key in row:
- if key.key_type == const.LAYOUT_SWITCHER_KEY_TYPE:
- key.connect('clicked',
- self._pressed_layout_switcher_key)
- elif key.key_type == const.MASK_KEY_TYPE:
- key.connect('toggled',
- self._toggled_mask_key)
- elif key.key_type == const.PREFERENCES_KEY_TYPE:
- key.connect('clicked',
- self._pressed_preferences_key)
- else:
- key.connect('pressed',
- self._pressed_normal_key)
- key.connect('released',
- self._released_normal_key)
-
- def _clear(self):
- n_pages = self.get_n_pages()
- for i in range(n_pages):
- self.remove_page(i)
-
- def _pressed_normal_key(self, key):
- self.vk.keyval_press(key.value)
-
- def _released_normal_key(self, key):
- self.vk.keyval_release(key.value)
- while True:
- try:
- mod = self.depressed_mods.pop()
- except IndexError:
- break
- mod.set_active (False)
-
- def _pressed_layout_switcher_key(self, key):
- self._switch_to_layout(key.value)
-
- def _toggled_mask_key(self, key):
- if key.get_active():
- self.vk.keyval_press(key.value)
- self.depressed_mods.append(key)
- else:
- self.vk.keyval_release(key.value)
- try:
- mod = self.depressed_mods.remove(key)
- except ValueError:
- pass
-
- def show_all_(self):
- self.set_current_page(self.current_page)
- Gtk.Notebook.show_all(self)
-
- def _pressed_preferences_key(self, key):
- p = PreferencesWindow()
- p.show_all()
- p.run()
- p.destroy()
-
- def _switch_to_layout(self, name):
- n_pages = self.get_n_pages()
- for i in range(n_pages):
- if self.get_nth_page(i).layout_name == name:
- self.set_current_page(i)
- self.current_page = i
- break
-
- def get_current_layout(self):
- i = self.get_current_page()
- return self.get_nth_page(i)
-
- def get_layouts(self):
- return [self.get_nth_page(i) for i in xrange(self.get_n_pages())]
-
-if __name__ == "__main__":
- import signal
- signal.signal(signal.SIGINT, signal.SIG_DFL)
-
- w = Gtk.Window()
-
- kb = CaribouKeyboard()
- kb.load_kb('data/keyboards/qwerty.xml')
-
- w.add(kb)
-
- w.show_all()
-
- Gtk.main()
diff --git a/caribou/ui/main.py b/caribou/ui/main.py
deleted file mode 100644
index 7e861b8..0000000
--- a/caribou/ui/main.py
+++ /dev/null
@@ -1,275 +0,0 @@
-import pyatspi
-from gi.repository import Gtk
-from gi.repository import Gdk
-from gi.repository import Gio
-from string import Template
-
-from window import CaribouWindowEntry, Rectangle
-from keyboard import CaribouKeyboard
-from caribou.common.settings_manager import SettingsManager
-from caribou.ui.i18n import _
-import caribou.common.const as const
-from scan import ScanMaster
-
-debug = False
-
-CSS_TEMPLATE = """
-.caribou-keyboard-button {
-background-image: none;
-background-color: $normal_bg;
-}
-
-.caribou-keyboard-button:hover {
-background-image: none;
-background-color: $mouseover_bg;
-}
-"""
-
-SCAN_CSS_TEMPLATE = """
-.caribou-scan-key {
-background-image: none;
-background-color: $button_scan;
-}
-
-.caribou-scan-row {
-background-image: none;
-background-color: $row_scan;
-}
-
-.caribou-scan-block {
-background-image: none;
-background-color: $block_scan;
-}
-
-.caribou-scan-cancel {
-background-image: none;
-background-color: $cancel_scan;
-}
-"""
-
-class Caribou:
- def __init__(self,
- kb_factory=CaribouKeyboard,
- window_factory=CaribouWindowEntry):
- if not self._get_a11y_enabled():
- msgdialog = Gtk.MessageDialog(None,
- Gtk.DialogFlags.MODAL,
- Gtk.MessageType.QUESTION,
- Gtk.ButtonsType.YES_NO,
- _("In order to use %s, accessibility needs "
- "to be enabled. Do you want to enable "
- "it now?") % const.APP_NAME)
- resp = msgdialog.run()
- if resp == Gtk.ResponseType.NO:
- msgdialog.destroy()
- quit()
- if resp == Gtk.ResponseType.YES:
- settings = Gio.Settings('org.gnome.desktop.interface')
- atspi = settings.set_boolean("toolkit-accessibility", True)
- msgdialog2 = Gtk.MessageDialog(msgdialog,
- Gtk.DialogFlags.MODAL,
- Gtk.MessageType.INFO,
- Gtk.ButtonsType.OK,
- _("Accessibility has been enabled. "
- "Log out and back in again to use "
- "%s.") % const.APP_NAME)
- msgdialog2.run()
- msgdialog2.destroy()
- msgdialog.destroy()
- quit()
- self.__current_acc = None
- self.window_factory = window_factory
- self.kb_factory = kb_factory
- kb = kb_factory()
- self.window = window_factory(kb)
- self._register_event_listeners()
- SettingsManager.layout.connect("value-changed",
- self._on_layout_changed)
-
- # Scanning
- self.scan_master = ScanMaster(self.window, kb)
- SettingsManager.scan_enabled.connect("value-changed",
- self._on_scan_toggled)
- if SettingsManager.scan_enabled.value:
- self.scan_master.start()
-
- self._custom_css_provider = Gtk.CssProvider()
-
- for name in ["normal_color", "mouse_over_color", "default_colors"]:
- getattr(SettingsManager, name).connect("value-changed",
- self._colors_changed)
- self._colors_changed(None, None)
-
- self._scan_css_provider = Gtk.CssProvider()
- Gtk.StyleContext.add_provider_for_screen(
- Gdk.Screen.get_default(),
- self._scan_css_provider,
- Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
-
- for name in ["button_scanning_color",
- "row_scanning_color",
- "block_scanning_color",
- "cancel_scanning_color"]:
- getattr(SettingsManager, name).connect("value-changed",
- self._scan_colors_changed)
- self._scan_colors_changed(None, None)
-
- def _colors_changed(self, setting, value):
- if SettingsManager.default_colors.value:
- Gtk.StyleContext.remove_provider_for_screen(
- Gdk.Screen.get_default(),
- self._custom_css_provider)
- else:
- Gtk.StyleContext.add_provider_for_screen(
- Gdk.Screen.get_default(),
- self._custom_css_provider,
- Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
- self._custom_css_provider.load_from_data(
- Template(CSS_TEMPLATE).substitute(
- normal_bg=SettingsManager.normal_color.value,
- mouseover_bg=SettingsManager.mouse_over_color.value), -1)
-
- def _scan_colors_changed(self, setting, value):
- self._scan_css_provider.load_from_data(Template(SCAN_CSS_TEMPLATE).substitute(
- button_scan=SettingsManager.button_scanning_color.value,
- row_scan=SettingsManager.row_scanning_color.value,
- block_scan=SettingsManager.block_scanning_color.value,
- cancel_scan=SettingsManager.cancel_scanning_color.value), -1)
-
-
- def _register_event_listeners(self):
- pyatspi.Registry.registerEventListener(
- self.on_focus, "object:state-changed:focused")
- pyatspi.Registry.registerEventListener(self.on_focus, "focus")
- pyatspi.Registry.registerEventListener(
- self.on_text_caret_moved, "object:text-caret-moved")
-
- def _deregister_event_listeners(self):
- pyatspi.Registry.deregisterEventListener(
- self.on_focus, "object:state-changed:focused")
- pyatspi.Registry.deregisterEventListener(self.on_focus, "focus")
- pyatspi.Registry.deregisterEventListener(
- self.on_text_caret_moved, "object:text-caret-moved")
-
- def _on_scan_toggled(self, setting, val):
- if val:
- self.scan_master.start()
- else:
- self.scan_master.stop()
-
- def _on_layout_changed(self, setting, val):
- self._deregister_event_listeners()
- self.window.destroy()
- self._update_window()
- self._register_event_listeners()
-
- def _update_window(self):
- kb = self.kb_factory()
- self.scan_master.set_keyboard(kb)
- self.window = self.window_factory(kb)
-
- def _get_a11y_enabled(self):
- try:
- try:
- settings = Gio.Settings('org.gnome.desktop.interface')
- atspi = settings.get_boolean("toolkit-accessibility")
- print "->", atspi
- return atspi
- except:
- raise
- from gi.repository import GConf
- gconfc = GConf.Client.get_default()
- atspi1 = gconfc.get_bool(
- "/desktop/gnome/interface/accessibility")
- atspi2 = gconfc.get_bool(
- "/desktop/gnome/interface/accessibility2")
- return atspi1 or atspi2
- except:
- raise
- return False
-
- def on_text_caret_moved(self, event):
- if self.__current_acc == event.source:
- self.__set_location(event.source)
- if debug == True:
- print "object:text-caret-moved in", event.host_application.name,
- print event.detail1, event.source.description
-
- def __set_text_location(self, acc):
- text = acc.queryText()
- [x, y, width, height] = text.getCharacterExtents(text.caretOffset, pyatspi.DESKTOP_COORDS)
- self.window.set_cursor_location(Rectangle(x, y, width, height))
-
- component = acc.queryComponent()
- entry_bb = component.getExtents(pyatspi.DESKTOP_COORDS)
- self.window.set_entry_location(entry_bb)
- self.window.show_all()
-
- def __set_entry_location(self, acc):
- text = acc.queryText()
- cursor_bb = Rectangle(
- *text.getCharacterExtents(text.caretOffset,
- pyatspi.DESKTOP_COORDS))
-
- component = acc.queryComponent()
- entry_bb = component.getExtents(pyatspi.DESKTOP_COORDS)
-
- if cursor_bb == Rectangle(0, 0, 0, 0):
- cursor_bb = entry_bb
-
- self.window.set_cursor_location(cursor_bb)
- self.window.set_entry_location(entry_bb)
-
- self.window.show_all()
-
- def on_focus(self, event):
- acc = event.source
- source_role = acc.getRole()
- if acc.getState().contains(pyatspi.STATE_EDITABLE) or \
- source_role == pyatspi.ROLE_TERMINAL:
- if source_role in (pyatspi.ROLE_TEXT,
- pyatspi.ROLE_PARAGRAPH,
- pyatspi.ROLE_PASSWORD_TEXT,
- pyatspi.ROLE_TERMINAL):
- if event.type.startswith("focus") or event.detail1 == 1:
- self.__set_text_location(acc)
- self.__current_acc = event.source
- self.__set_location = self.__set_text_location
- if debug == True:
- print "enter text widget in", event.host_application.name
- elif event.detail1 == 0 and acc == self.__current_acc:
- self.window.hide()
- self.__current_acc = None
- self.__set_location = None
- if debug == True:
- print "leave text widget in", event.host_application.name
-
- elif source_role == pyatspi.ROLE_ENTRY:
- if event.type.startswith("focus") or event.detail1 == 1:
- self.__set_entry_location(acc)
- self.__current_acc = event.source
- self.__set_location = self.__set_entry_location
- if debug == True:
- print "enter entry widget in", event.host_application.name
- elif event.detail1 == 0:
- self.window.hide()
- self.__current_acc = None
- self.__set_location = None
- if debug == True:
- print "leave entry widget in", event.host_application.name
- else:
- if debug == True:
- print _("WARNING - Caribou: unhandled editable widget:"), event.source
-
- # Firefox does not report leave entry widget events.
- # This could be a way to get the entry widget leave events.
- #else:
- # if event.detail1 == 1:
- # self.window.hide()
- # print "--> LEAVE EDITABLE TEXT <--"
-
- def clean_exit(self):
- self.scan_master.stop()
- self._deregister_event_listeners()
-
-
diff --git a/caribou/ui/opacity.py b/caribou/ui/opacity.py
deleted file mode 100644
index be742d8..0000000
--- a/caribou/ui/opacity.py
+++ /dev/null
@@ -1,83 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Caribou - text entry and UI navigation application
-#
-# Copyright (C) 2009 Eitan Isaacson <eitan@monotonous.org>
-#
-# This program 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 program 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 program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-import glib
-from math import sqrt
-
-class ProximityWindowBase(object):
- def __init__(self, min_alpha=1.0, max_alpha=1.0, max_distance=100):
- if self.__class__ == ProximityWindowBase:
- raise TypeError, \
- "ProximityWindowBase is an abstract class, " \
- "must be subclassed with a Gtk.Window"
- self.connect('map-event', self.__onmapped)
- self.max_distance = max_distance
- if max_alpha < min_alpha:
- raise ValueError, "min_alpha can't be larger than max_alpha"
- self.min_alpha = min_alpha
- self.max_alpha = max_alpha
-
- def __onmapped(self, obj, event):
- if self.is_composited():
- self.set_opacity(self.max_alpha)
- if self.max_alpha != self.min_alpha:
- # Don't waste CPU if the max and min are equal.
- glib.timeout_add(80, self._proximity_check)
-
- def _proximity_check(self):
- px, py = self.get_pointer()
-
- ww = self.get_allocated_width()
- wh = self.get_allocated_height()
-
- distance = self._get_distance_to_bbox(px, py, ww, wh)
-
- opacity = (self.max_alpha - self.min_alpha) * \
- (1 - min(distance, self.max_distance)/self.max_distance)
- opacity += self.min_alpha
-
- self.set_opacity(opacity)
- return self.props.visible
-
- def _get_distance_to_bbox(self, px, py, bw, bh):
- if px < 0:
- x_distance = float(abs(px))
- elif px > bw:
- x_distance = float(px - bw)
- else:
- x_distance = 0.0
-
- if py < 0:
- y_distance = float(abs(px))
- elif py > bh:
- y_distance = float(py - bh)
- else:
- y_distance = 0.0
-
- if y_distance == 0 and x_distance == 0:
- return 0.0
- elif y_distance != 0 and x_distance == 0:
- return y_distance
- elif y_distance == 0 and x_distance != 0:
- return x_distance
- else:
- x2 = 0 if x_distance > 0 else bw
- y2 = 0 if y_distance > 0 else bh
- return sqrt((px - x2)**2 + (py - y2)**2)
diff --git a/caribou/ui/scan.py b/caribou/ui/scan.py
deleted file mode 100644
index 94aa8c2..0000000
--- a/caribou/ui/scan.py
+++ /dev/null
@@ -1,216 +0,0 @@
-import gobject
-import pyatspi
-from gi.repository import Gdk
-from gi.repository import Gtk
-import caribou.common.const as const
-from caribou.common.settings_manager import SettingsManager
-
-# Scan constants
-BUTTON = 'button'
-ROW = 'row'
-BLOCK = 'block'
-CANCEL = 'cancel'
-REVERSE = 'reverse'
-MOUSE_SWITCH_TYPE = 'mouse'
-KEYBOARD_SWITCH_TYPE = 'keyboard'
-KEYBOARD_KEY_LIST = {"Shift R" : "Shift_R",
- "Shift L" : "Shift_L",
- "Alt Gr" : "ISO_Level3_Shift",
- "Num Lock": "Num_Lock"}
-DEFAULT_KEYBOARD_KEY = 'Shift R'
-DEFAULT_MOUSE_BUTTON = '1'
-MIN_STEP_TIME = 50
-MAX_STEP_TIME = 5000
-TIME_SINGLE_INCREMENT = 1
-TIME_MULTI_INCREMENT = 10
-DEFAULT_STEP_TIME = 1000
-DEFAULT_SCANNING_TYPE = ROW
-DEFAULT_SWITCH_TYPE = KEYBOARD_SWITCH_TYPE
-
-class ScanMaster():
- def __init__(self, root_window, keyboard=None):
- self.root_window = root_window
- self._timer = 0
- self._scan_path = None
- self.started = False
-
- SettingsManager.step_time.connect("value-changed",
- self._on_step_time_changed)
- SettingsManager.scanning_type.connect("value-changed",
- self._on_scanning_type_changed)
- if keyboard:
- self.set_keyboard(keyboard)
-
- def start(self):
- if self.started: return
-
- if self._timer == 0:
- self._timer = gobject.timeout_add(
- int(SettingsManager.step_time.value*1000), self._scan)
-
- self._grab_mouse_events()
-
- pyatspi.Registry.registerKeystrokeListener(
- self._on_key_pressed, mask=0, kind=(pyatspi.KEY_PRESSED_EVENT,))
-
- def stop(self):
- if self.started: return
-
- self._ungrab_mouse_events()
-
- if self._last_block is not None:
- self._multi_map(lambda x: x.scan_highlight_clear(), self._last_block)
-
- if self._timer != 0:
- gobject.source_remove(self._timer)
- self._timer = 0
-
- pyatspi.Registry.deregisterKeystrokeListener(
- self._on_key_pressed, mask=0, kind=pyatspi.KEY_PRESSED_EVENT)
-
- def _on_scanning_type_changed(self, setting, val):
- layout = self.keyboard.get_current_layout()
- if SettingsManager.scanning_type.value == ROW:
- self._blocks = layout.get_scan_rows()
- else:
- self._blocks = layout.get_scan_blocks()
-
- def _on_step_time_changed(self, setting, val):
- if self._timer != 0:
- gobject.source_remove(self._timer)
- self._timer = gobject.timeout_add(int(1000*val), self._scan)
-
- def _on_layout_activated(self, keyboard, layout, num):
- if SettingsManager.scanning_type.value == ROW:
- self._blocks = layout.get_scan_rows()
- else:
- self._blocks = layout.get_scan_blocks()
- if SettingsManager.reverse_scanning.value:
- self._scan_path = [0]
- else:
- self._scan_path = [-1]
-
- def set_keyboard(self, keyboard):
- self._last_block = None
- keyboard.connect("switch-page", self._on_layout_activated)
- self.keyboard = keyboard
-
- def _multi_map(self, func, array):
- if isinstance(array, list):
- for item in array:
- self._multi_map(func, item)
- else:
- func(array)
-
- def _get_element_at_path(self, array, path):
- element = array
- for index in path:
- element = element[index]
- return element
-
- def _get_next_reverse_block(self):
- cancel = False
-
- if self._scan_path[-1] > 0:
- self._scan_path = self._scan_path[:-1] + [0]
-
- self._scan_path += [self._scan_path.pop() - 1]
-
- try:
- block = self._get_element_at_path(self._blocks,
- self._scan_path)
- except IndexError:
- if len(self._scan_path) == 1:
- block = self._blocks[-1]
- self._scan_path = [-1]
- else:
- block = self._get_element_at_path(
- self._blocks, self._scan_path[:-1])
- self._scan_path = self._scan_path[:-1] + [0]
- cancel = True
-
- return cancel, block
-
-
- def _get_next_block(self):
- cancel = False
- self._scan_path += [self._scan_path.pop() + 1]
- try:
- block = self._get_element_at_path(self._blocks,
- self._scan_path)
- except IndexError:
- if len(self._scan_path) == 1:
- block = self._blocks[0]
- self._scan_path = [0]
- else:
- block = self._get_element_at_path(
- self._blocks, self._scan_path[:-1])
- self._scan_path = self._scan_path[:-1] + [-1]
- cancel = True
-
- return cancel, block
-
- def _scan(self):
- if self._scan_path is None: return True
-
- if self._last_block is not None:
- self._multi_map(lambda x: x.scan_highlight_clear(), self._last_block)
-
- if SettingsManager.reverse_scanning.value:
- self._cancel, next_block = self._get_next_reverse_block()
- else:
- self._cancel, next_block = self._get_next_block()
-
- if self._cancel:
- self._multi_map(lambda x: x.scan_highlight_cancel(), next_block)
- elif isinstance(next_block, list):
- if SettingsManager.scanning_type.value == ROW:
- self._multi_map(lambda x: x.scan_highlight_row(), next_block)
- else:
- self._multi_map(lambda x: x.scan_highlight_block(), next_block)
- else:
- self._multi_map(lambda x: x.scan_highlight_key(), next_block)
-
- self._last_block = next_block
- return True
-
- def _do_switch(self):
- if self._cancel:
- assert(len(self._scan_path) > 1)
- self._scan_path.pop()
- elif isinstance(self._last_block, list):
- assert(len(self._last_block) > 0)
- if SettingsManager.reverse_scanning.value:
- self._scan_path.append(0)
- else:
- self._scan_path.append(-1)
- else:
- self._last_block.clicked()
-
- def _grab_mouse_events(self):
- Gdk.event_handler_set(self._mouse_handler, None)
-
- def _ungrab_mouse_events(self):
- Gdk.event_handler_set(Gtk.main_do_event, None)
-
- def _mouse_handler(self, event, user_data):
- if SettingsManager.switch_type.value != MOUSE_SWITCH_TYPE or \
- event.type not in (Gdk.EventType.BUTTON_PRESS,
- Gdk.EventType.ENTER_NOTIFY):
- Gtk.main_do_event(event)
- return
-
- if self.root_window.get_window().is_visible():
- if event.type == Gdk.EventType.BUTTON_PRESS and \
- str(event.button.button) == \
- SettingsManager.mouse_button.value:
- self._do_switch()
- elif event.type != Gdk.EventType.ENTER_NOTIFY:
- Gtk.main_do_event(event)
- else:
- Gtk.main_do_event(event)
-
- def _on_key_pressed(self, event):
- if SettingsManager.switch_type.value == KEYBOARD_SWITCH_TYPE and \
- SettingsManager.keyboard_key.value == event.event_string:
- self._do_switch()
diff --git a/configure.ac b/configure.ac
index 366da21..f8f5783 100644
--- a/configure.ac
+++ b/configure.ac
@@ -14,7 +14,6 @@ AM_MAINTAINER_MODE([enable])
# to configure or passing V=1 to make
AM_SILENT_RULES([yes])
-
AM_PATH_GLIB_2_0(2.27.5,,,gobject)
if test "$GLIB_LIBS" = ""; then
AC_MSG_ERROR(GLIB 2.27.5 or later is required to build libcaribou)
@@ -37,10 +36,16 @@ PKG_CHECK_MODULES(CARIBOU, [
AC_SUBST(CARIBOU_CFLAGS)
AC_SUBST(CARIBOU_LIBS)
+AM_PROG_VALAC([0.9.3])
+AC_SUBST(VALAC)
+AC_SUBST(VALAFLAGS)
+
PKG_CHECK_MODULES(LIBCARIBOU, [
gdk-3.0 >= $GDK_REQUIRED,
xtst,
- x11
+ x11,
+ libxklavier,
+ json-glib-1.0
])
AC_SUBST(LIBCARIBOU_CFLAGS)
AC_SUBST(LIBCARIBOU_LIBS)
@@ -67,12 +72,16 @@ AC_OUTPUT([
Makefile
po/Makefile.in
caribou/Makefile
-caribou/common/Makefile
-caribou/ui/i18n.py
-caribou/ui/Makefile
+caribou/i18n.py
+caribou/antler/Makefile
+caribou/settings/Makefile
+caribou/daemon/Makefile
bin/Makefile
bin/caribou
+bin/caribou-preferences
+bin/antler-keyboard
data/Makefile
-data/keyboards/Makefile
+data/layouts/Makefile
+data/layouts/touch/Makefile
libcaribou/Makefile
])
diff --git a/data/Makefile.am b/data/Makefile.am
index 581ca65..11e2611 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = keyboards
+SUBDIRS = layouts
@GSETTINGS_RULES@
@INTLTOOL_XML_NOMERGE_RULE@
@@ -13,12 +13,19 @@ autostartdir = $(sysconfdir)/xdg/autostart
autostart_in_files = caribou-autostart.desktop.in
autostart_DATA = $(autostart_in_files:.desktop.in=.desktop)
+servicefiledir = $(datadir)/dbus-1/services
+servicefile_in_files = org.gnome.Caribou.Antler.service.in
+servicefile_DATA = $(servicefile_in_files:.service.in=.service)
+
+org.gnome.Caribou.Antler.service: org.gnome.Caribou.Antler.service.in
+ $(AM_V_GEN)sed -e "s|[@]libexecdir[@]|$(libexecdir)|" $< > $@
+
@INTLTOOL_DESKTOP_RULE@
EXTRA_DIST = $(desktop_in_files) $(autostart_in_files)
-org.gnome.caribou.gschema.xml.in: $(top_srcdir)/caribou/common/settings.py
- PYTHONPATH=${PYTHONPATH}:$(top_srcdir) $(PYTHON) $< > $@
+org.gnome.caribou.gschema.xml.in: $(top_srcdir)/tools/make_schema.py
+ $< org.gnome.caribou
CLEANFILES = $(desktop_DATA) \
$(autostart_DATA) \
diff --git a/data/keyboards/Makefile.am b/data/keyboards/Makefile.am
deleted file mode 100644
index 64d947e..0000000
--- a/data/keyboards/Makefile.am
+++ /dev/null
@@ -1,10 +0,0 @@
-keyboardsdir = $(datadir)/caribou/keyboards/
-keyboards_DATA = \
- qwerty.xml \
- hebrew.xml \
- lexic_es.json \
- qwerty_en.json \
- qwerty_es.json
-
-
-EXTRA_DIST = $(keyboards_DATA)
diff --git a/data/keyboards/hebrew.xml b/data/keyboards/hebrew.xml
deleted file mode 100644
index 251ec81..0000000
--- a/data/keyboards/hebrew.xml
+++ /dev/null
@@ -1,272 +0,0 @@
-<keyboard>
- <layout>
- <name>lowercase</name>
- <rows>
- <row>
- <key key_type="preferences"/>
- <key key_type="dummy" width="1.25"/>
- <key value="ק"/>
- <key value="ר"/>
- <key value="א"/>
- <key value="ט"/>
- <key value="ו"/>
- <key value="ן"/>
- <key value="ם"/>
- <key value="פ"/>
- <key key_type="dummy" width="0.775"/>
- <key>
- <value>BackSpace</value>
- <label>&lt;big&gt;⌫&lt;/big&gt;</label>
- <width>1.5</width>
- </key>
- </row>
- <row>
- <key>
- <label>&lt;b&gt;&lt;sup&gt;←&lt;/sup&gt;&lt;sub&gt;→&lt;/sub&gt;&lt;/b&gt;"</label>
- <value>Tab</value>
- </key>
- <key value="ש"/>
- <key value="ד"/>
- <key value="ג"/>
- <key value="כ"/>
- <key value="ע"/>
- <key value="י"/>
- <key value="ח"/>
- <key value="ל"/>
- <key value="ך"/>
- <key value="ף"/>
- <key>
- <value>Return</value>
- <label>&lt;b&gt;↲&lt;/b&gt;</label>
- <width>1.5</width>
- </key>
- </row>
- <row>
- <key>
- <label>&lt;b&gt;↑&lt;/b&gt;</label>
- <key_type>layout_switcher</key_type>
- <value>uppercase</value>
- <width>1.5</width>
- </key>
- <key value="ז"/>
- <key value="ס"/>
- <key value="ב"/>
- <key value="ה"/>
- <key value="נ"/>
- <key value="מ"/>
- <key value="צ"/>
- <key value="ת"/>
- <key value="ץ"/>
- <key value=","/>
- <key value="."/>
- </row>
- <row>
- <key>
- <label>&lt;small&gt;&lt;i&gt;1%+&lt;/i&gt;&lt;/small&gt;</label>
- <key_type>layout_switcher</key_type>
- <value>special</value>
- <width>1.5</width>
- </key>
- <key>
- <label>&lt;small&gt;&lt;b&gt;Ctrl&lt;/b&gt;&lt;/small&gt;</label>
- <value>Control_L</value>
- <key_type>mask</key_type>
- <width>1.5</width>
- </key>
- <key>
- <label>&lt;small&gt;&lt;b&gt;Alt&lt;/b&gt;&lt;/small&gt;</label>
- <value>Alt_L</value>
- <key_type>mask</key_type>
- <width>1.5</width>
- </key>
- <key key_type="dummy" width="0.5"/>
- <key label="______" value=" " width="3"/>
- <key key_type="dummy" width="0.5"/>
- <key value="'"/>
- <key value="&quot;"/>
- <key value="!"/>
- <key value="?"/>
- </row>
- </rows>
- </layout>
-
- <layout>
- <name>uppercase</name>
- <rows>
- <row>
- <key key_type="preferences"/>
- <key value="Q"/>
- <key value="W"/>
- <key value="E"/>
- <key value="R"/>
- <key value="T"/>
- <key value="Y"/>
- <key value="U"/>
- <key value="I"/>
- <key value="O"/>
- <key value="P"/>
- <key>
- <value>BackSpace</value>
- <label>&lt;big&gt;⌫&lt;/big&gt;</label>
- <width>1.5</width>
- </key>
- </row>
- <row>
- <key>
- <label>&lt;b&gt;&lt;sup&gt;←&lt;/sup&gt;&lt;sub&gt;→&lt;/sub&gt;&lt;/b&gt;"</label>
- <value>Tab</value>
- </key>
- <key key_type="dummy" width="0.275"/>
- <key value="A"/>
- <key value="S"/>
- <key value="D"/>
- <key value="F"/>
- <key value="G"/>
- <key value="H"/>
- <key value="J"/>
- <key value="K"/>
- <key value="L"/>
- <key key_type="dummy" width="0.75"/>
- <key>
- <value>Return</value>
- <label>&lt;b&gt;↲&lt;/b&gt;</label>
- <width>1.5</width>
- </key>
- </row>
- <row>
- <key>
- <label>&lt;b&gt;↓&lt;/b&gt;</label>
- <key_type>layout_switcher</key_type>
- <value>lowercase</value>
- <width>1.5</width>
- </key>
- <key key_type="dummy" width="0.5"/>
- <key value="Z"/>
- <key value="X"/>
- <key value="C"/>
- <key value="V"/>
- <key value="B"/>
- <key value="N"/>
- <key value="M"/>
- <key key_type="dummy" width="0.5"/>
- <key value=","/>
- <key value="."/>
- <key value=";"/>
- </row>
- <row>
- <key>
- <label>&lt;small&gt;&lt;i&gt;1%+&lt;/i&gt;&lt;/small&gt;</label>
- <key_type>layout_switcher</key_type>
- <value>special</value>
- <width>1.5</width>
- </key>
- <key>
- <label>&lt;small&gt;&lt;b&gt;Ctrl&lt;/b&gt;&lt;/small&gt;</label>
- <value>Control_L</value>
- <key_type>mask</key_type>
- <width>1.5</width>
- </key>
- <key>
- <label>&lt;small&gt;&lt;b&gt;Alt&lt;/b&gt;&lt;/small&gt;</label>
- <value>Alt_L</value>
- <key_type>mask</key_type>
- <width>1.5</width>
- </key>
- <key key_type="dummy" width="0.5"/>
- <key label="______" value=" " width="3"/>
- <key key_type="dummy" width="0.5"/>
- <key value="'"/>
- <key value="&quot;"/>
- <key value="!"/>
- <key value="?"/>
- </row>
- </rows>
- </layout>
-
- <layout>
- <name>special</name>
- <rows>
- <row>
- <key key_type="preferences"/>
- <key value="1"/>
- <key value="2"/>
- <key value="3"/>
- <key value="4"/>
- <key value="5"/>
- <key value="6"/>
- <key value="7"/>
- <key value="8"/>
- <key value="9"/>
- <key value="0"/>
- <key>
- <value>BackSpace</value>
- <label>&lt;big&gt;⌫&lt;/big&gt;</label>
- <width>1.5</width>
- </key>
- </row>
- <row>
- <key key_type="dummy" width="0.25"/>
- <key key_type="dummy" width="0.25"/>
- <key value="@"/>
- <key value="#"/>
- <key value="$"/>
- <key value="%"/>
- <key value="&amp;"/>
- <key value="*"/>
- <key value="("/>
- <key value=")"/>
- <key value="-"/>
- <key value="+"/>
- <key key_type="dummy" width="0.25"/>
- <key>
- <value>Return</value>
- <label>&lt;b&gt;↲&lt;/b&gt;</label>
- <width>2</width>
- </key>
- </row>
- <row>
- <key key_type="dummy" width="0.25"/>
- <key value="&lt;"/>
- <key value="&gt;"/>
- <key value="€"/>
- <key value="£"/>
- <key value="{"/>
- <key value="}"/>
- <key value="["/>
- <key value="]"/>
- <key value="_" label="&lt;small&gt;_&lt;/small&gt;"/>
- <key value="="/>
- <key key_type="dummy" width="0.25"/>
- <key value="Up" label="&lt;b&gt;↑&lt;/b&gt;"/>
- <key value="\"/>
- </row>
- <row>
- <key>
- <label>&lt;small&gt;&lt;i&gt;abc&lt;/i&gt;&lt;/small&gt;</label>
- <key_type>layout_switcher</key_type>
- <value>lowercase</value>
- <width>1.5</width>
- </key>
- <key>
- <label>&lt;small&gt;&lt;b&gt;Ctrl&lt;/b&gt;&lt;/small&gt;</label>
- <value>Control_L</value>
- <key_type>mask</key_type>
- <width>1.5</width>
- </key>
- <key>
- <label>&lt;small&gt;&lt;b&gt;Alt&lt;/b&gt;&lt;/small&gt;</label>
- <value>Alt_L</value>
- <key_type>mask</key_type>
- <width>1.5</width>
- </key>
- <key key_type="dummy" width="0.5"/>
- <key label="______" value=" " width="3"/>
- <key key_type="dummy" width="0.5"/>
- <key value="|"/>
- <key value="Left" label="&lt;b&gt;←&lt;/b&gt;"/>
- <key value="Down" label="&lt;b&gt;↓&lt;/b&gt;"/>
- <key value="Right" label="&lt;b&gt;→&lt;/b&gt;"/>
- </row>
- </rows>
- </layout>
-</keyboard>
diff --git a/data/keyboards/lexic_es.json b/data/keyboards/lexic_es.json
deleted file mode 100644
index 1d72adc..0000000
--- a/data/keyboards/lexic_es.json
+++ /dev/null
@@ -1,300 +0,0 @@
-
-{"layout": [
- {"name": "lowercase",
- "rows": {"row": [{"key":
- [{"value" : "e",
- "width": 2},
- {"value": "s",
- "width": 2},
- {"value": "i",
- "width": 2},
- {"value": "u",
- "width": 2},
- {"value": "m",
- "width": 2},
- {"value": "y",
- "width": 2},
- {"value": "v",
- "width": 2},
- {"value": "f",
- "width": 2},
- {"value": "x",
- "width": 2},
- {"key_type": "preferences",
- "width": 2}
- ]
- },
- {"key":[{"value" : "a",
- "width": 2},
- {"value": "n",
- "width": 2},
- {"value": "l",
- "width": 2},
- {"value": "t",
- "width": 2},
- {"value": "p",
- "width": 2},
- {"value": "b",
- "width": 2},
- {"value": "g",
- "width": 2},
- {"value": "z",
- "width": 2},
- {"value": "w",
- "width": 2},
- {"label": "<i>1%+</i>",
- "key_type": "layout_switcher",
- "value": "special",
- "width": 2}
- ]
- },
- {"key":[{"value" : "o",
- "width": 2},
- {"value": "r",
- "width": 2},
- {"value": "d",
- "width": 2},
- {"value": "c",
- "width": 2},
- {"value": "q",
- "width": 2},
- {"value": "h",
- "width": 2},
- {"value": "j",
- "width": 2},
- {"value": "ñ",
- "width": 2},
- {"value": "k",
- "width": 2},
- {"label": "<b>Ctrl D</b>",
- "value": "Control_R",
- "width": 2}
- ]
- },
- {"key": [{"value": "uppercase",
- "label": "<b>⇧</b>",
- "key_type": "layout_switcher",
- "width": 3.33},
- {"value": "BackSpace",
- "label": "<big>⌫</big>",
- "width": 3.33},
- {"label": "____",
- "value": " ",
- "width": 3.33},
- {"value": "Return",
- "label": "<b>↲</b>",
- "width": 3.33},
- {"value": ",",
- "width": 3.33},
- {"value": ".",
- "width": 3.33}
- ]
- }
- ]
- }
- },
- {"name": "special",
- "rows": {"row": [{"key":
- [{"value": "7",
- "width": 2},
- {"value": "8",
- "width": 2},
- {"value": "9",
- "width": 2},
- {"value": ".",
- "width": 2},
- {"value": "*",
- "width": 2},
- {"value": "¿",
- "width": 2},
- {"value": "\\",
- "width": 2},
- {"value": ";",
- "width": 2},
- {"value": "\"",
- "width": 2},
- {"key_type": "preferences",
- "width": 2}
- ]
- },
- {"key": [{"value": "4",
- "width": 2},
- {"value": "5",
- "width": 2},
- {"value": "6",
- "width": 2},
- {"value": "+",
- "width": 2},
- {"value": "/",
- "width": 2},
- {"value": "?",
- "width": 2},
- {"value": "(",
- "width": 2},
- {"value": "€",
- "width": 2},
- {"value": "@",
- "width": 2},
- {"key_type": "layout_switcher",
- "value": "lowercase",
- "label": "abc",
- "width": 2}
- ]
- },
- {"key": [{"value": "1",
- "width": 2},
- {"value": "2",
- "width": 2},
- {"value": "3",
- "width": 2},
- {"value": "-",
- "width": 2},
- {"value": "Up",
- "label": "<b>↑</b>",
- "width": 2},
- {"value": "%",
- "width": 2},
- {"value": ")",
- "width": 2},
- {"value": "_",
- "width": 2},
- {"value": "#",
- "width": 2},
- {"key_type": "mask",
- "value": "Control_L",
- "label": "<b>Ctrl I</b>",
- "width": 2}
- ]
- },
- {"key": [{"value": "0",
- "width": 3},
- {"label": "<big>⌫</big>",
- "value": "BackSpace",
- "width": 3},
- {"label": "<b>←</b>",
- "width": 2,
- "value": "Left"},
- {"label": "<b>↓</b>",
- "width": 2,
- "value": "Down"},
- {"label": "<b>→</b>",
- "width": 2,
- "value": "Right"},
- {"value": ":",
- "width": 2},
- {"value": "'",
- "width": 2},
- {"value": "$",
- "width": 2},
- {"key_type": "mask",
- "label": "<b>Alt I</b>",
- "value": "Alt_L",
- "width": 2}
- ]
- }
- ]
-}
- },
- {"name": "uppercase",
- "rows": {"row": [{"key":[
- {"value" : "E",
- "width": 2},
- {"value": "S",
- "width": 2},
- {"value": "I",
- "width": 2},
- {"value": "U",
- "width": 2},
- {"value": "M",
- "width": 2},
- {"value": "Y",
- "width": 2},
- {"value": "V",
- "width": 2},
- {"value": "F",
- "width": 2},
- {"value": "X",
- "width": 2},
- {"key_type": "preferences",
- "width": 2}
- ]
- },
- {"key":[{"value" : "A",
- "width": 2},
- {"value": "N",
- "width": 2},
- {"value": "L",
- "width": 2},
- {"value": "T",
- "width": 2},
- {"value": "P",
- "width": 2},
- {"value": "B",
- "width": 2},
- {"value": "G",
- "width": 2},
- {"value": "Z",
- "width": 2},
- {"value": "W",
- "width": 2},
- {"label": "<i>1%+</i>",
- "key_type": "layout_switcher",
- "value": "special",
- "width": 2}
- ]
- },
- {"key":[{"value" : "O",
- "width": 2},
- {"value": "R",
- "width": 2},
- {"value": "D",
- "width": 2},
- {"value": "C",
- "width": 2},
- {"value": "Q",
- "width": 2},
- {"value": "H",
- "width": 2},
- {"value": "J",
- "width": 2},
- {"value": "Ñ",
- "width": 2},
- {"value": "K",
- "width": 2},
- {"label": "<b>Ctrl D</b>",
- "value": "Control_R",
- "width": 2}
- ]
- },
- {"key": [{"value": "lowercase",
- "label": "<b>⇩</b>",
- "key_type": "layout_switcher",
- "width": 3.33},
- {"value": "BackSpace",
- "label": "<big>⌫</big>",
- "width": 3.33},
- {"label": "____",
- "value": " ",
- "width": 3.33},
- {"value": "Return",
- "label": "<b>↲</b>",
- "width": 3.33},
- {"value": ",",
- "width": 3.33},
- {"value": ".",
- "width": 3.33}
- ]
- }
- ]
- }
- }
- ]
-}
-
-
-
-
-
-
-
-
diff --git a/data/keyboards/qwerty.xml b/data/keyboards/qwerty.xml
deleted file mode 100644
index af5bb6e..0000000
--- a/data/keyboards/qwerty.xml
+++ /dev/null
@@ -1,274 +0,0 @@
-<keyboard>
- <layout>
- <name>lowercase</name>
- <rows>
- <row>
- <key key_type="preferences"/>
- <key value="q"/>
- <key value="w"/>
- <key value="e"/>
- <key value="r"/>
- <key value="t"/>
- <key value="y"/>
- <key value="u"/>
- <key value="i"/>
- <key value="o"/>
- <key value="p"/>
- <key>
- <value>BackSpace</value>
- <label>&lt;big&gt;⌫&lt;/big&gt;</label>
- <width>1.5</width>
- </key>
- </row>
- <row>
- <key>
- <label>&lt;b&gt;&lt;sup&gt;←&lt;/sup&gt;&lt;sub&gt;→&lt;/sub&gt;&lt;/b&gt;"</label>
- <value>Tab</value>
- </key>
- <key key_type="dummy" width="0.25"/>
- <key value="a"/>
- <key value="s"/>
- <key value="d"/>
- <key value="f"/>
- <key value="g"/>
- <key value="h"/>
- <key value="j"/>
- <key value="k"/>
- <key value="l"/>
- <key key_type="dummy" width="0.25"/>
- <key>
- <value>Return</value>
- <label>&lt;b&gt;↲&lt;/b&gt;</label>
- <width>2</width>
- </key>
- </row>
- <row>
- <key>
- <label>&lt;b&gt;↑&lt;/b&gt;</label>
- <key_type>layout_switcher</key_type>
- <value>uppercase</value>
- <width>1.5</width>
- </key>
- <key key_type="dummy" width="0.5"/>
- <key value="z"/>
- <key value="x"/>
- <key value="c"/>
- <key value="v"/>
- <key value="b"/>
- <key value="n"/>
- <key value="m"/>
- <key key_type="dummy" width="0.5"/>
- <key value=","/>
- <key value="."/>
- <key value=";"/>
- </row>
- <row>
- <key>
- <label>&lt;small&gt;&lt;i&gt;1%+&lt;/i&gt;&lt;/small&gt;</label>
- <key_type>layout_switcher</key_type>
- <value>special</value>
- <width>1.5</width>
- </key>
- <key>
- <label>&lt;small&gt;&lt;b&gt;Ctrl&lt;/b&gt;&lt;/small&gt;</label>
- <value>Control_L</value>
- <key_type>mask</key_type>
- <width>1.5</width>
- </key>
- <key>
- <label>&lt;small&gt;&lt;b&gt;Alt&lt;/b&gt;&lt;/small&gt;</label>
- <value>Alt_L</value>
- <key_type>mask</key_type>
- <width>1.5</width>
- </key>
- <key key_type="dummy" width="0.5"/>
- <key label="______" value=" " width="3"/>
- <key key_type="dummy" width="0.5"/>
- <key value="'"/>
- <key value="&quot;"/>
- <key value="!"/>
- <key value="?"/>
- </row>
- </rows>
- </layout>
-
- <layout>
- <name>uppercase</name>
- <rows>
- <row>
- <key key_type="preferences"/>
- <key value="Q"/>
- <key value="W"/>
- <key value="E"/>
- <key value="R"/>
- <key value="T"/>
- <key value="Y"/>
- <key value="U"/>
- <key value="I"/>
- <key value="O"/>
- <key value="P"/>
- <key>
- <value>BackSpace</value>
- <label>&lt;big&gt;⌫&lt;/big&gt;</label>
- <width>1.5</width>
- </key>
- </row>
- <row>
- <key>
- <label>&lt;b&gt;&lt;sup&gt;←&lt;/sup&gt;&lt;sub&gt;→&lt;/sub&gt;&lt;/b&gt;"</label>
- <value>Tab</value>
- </key>
- <key key_type="dummy" width="0.25"/>
- <key value="A"/>
- <key value="S"/>
- <key value="D"/>
- <key value="F"/>
- <key value="G"/>
- <key value="H"/>
- <key value="J"/>
- <key value="K"/>
- <key value="L"/>
- <key key_type="dummy" width="0.25"/>
- <key>
- <value>Return</value>
- <label>&lt;b&gt;↲&lt;/b&gt;</label>
- <width>2</width>
- </key>
- </row>
- <row>
- <key>
- <label>&lt;b&gt;↓&lt;/b&gt;</label>
- <key_type>layout_switcher</key_type>
- <value>lowercase</value>
- <width>1.5</width>
- </key>
- <key key_type="dummy" width="0.5"/>
- <key value="Z"/>
- <key value="X"/>
- <key value="C"/>
- <key value="V"/>
- <key value="B"/>
- <key value="N"/>
- <key value="M"/>
- <key key_type="dummy" width="0.5"/>
- <key value=","/>
- <key value="."/>
- <key value=";"/>
- </row>
- <row>
- <key>
- <label>&lt;small&gt;&lt;i&gt;1%+&lt;/i&gt;&lt;/small&gt;</label>
- <key_type>layout_switcher</key_type>
- <value>special</value>
- <width>1.5</width>
- </key>
- <key>
- <label>&lt;small&gt;&lt;b&gt;Ctrl&lt;/b&gt;&lt;/small&gt;</label>
- <value>Control_L</value>
- <key_type>mask</key_type>
- <width>1.5</width>
- </key>
- <key>
- <label>&lt;small&gt;&lt;b&gt;Alt&lt;/b&gt;&lt;/small&gt;</label>
- <value>Alt_L</value>
- <key_type>mask</key_type>
- <width>1.5</width>
- </key>
- <key key_type="dummy" width="0.5"/>
- <key label="______" value=" " width="3"/>
- <key key_type="dummy" width="0.5"/>
- <key value="'"/>
- <key value="&quot;"/>
- <key value="!"/>
- <key value="?"/>
- </row>
- </rows>
- </layout>
-
- <layout>
- <name>special</name>
- <rows>
- <row>
- <key key_type="preferences"/>
- <key value="1"/>
- <key value="2"/>
- <key value="3"/>
- <key value="4"/>
- <key value="5"/>
- <key value="6"/>
- <key value="7"/>
- <key value="8"/>
- <key value="9"/>
- <key value="0"/>
- <key>
- <value>BackSpace</value>
- <label>&lt;big&gt;⌫&lt;/big&gt;</label>
- <width>1.5</width>
- </key>
- </row>
- <row>
- <key key_type="dummy" width="0.25"/>
- <key key_type="dummy" width="0.25"/>
- <key value="@"/>
- <key value="#"/>
- <key value="$"/>
- <key value="%"/>
- <key value="&amp;"/>
- <key value="*"/>
- <key value="("/>
- <key value=")"/>
- <key value="-"/>
- <key value="+"/>
- <key key_type="dummy" width="0.25"/>
- <key>
- <value>Return</value>
- <label>&lt;b&gt;↲&lt;/b&gt;</label>
- <width>2</width>
- </key>
- </row>
- <row>
- <key key_type="dummy" width="0.25"/>
- <key value="&lt;"/>
- <key value="&gt;"/>
- <key value="€"/>
- <key value="£"/>
- <key value="{"/>
- <key value="}"/>
- <key value="["/>
- <key value="]"/>
- <key value="_" label="&lt;small&gt;_&lt;/small&gt;"/>
- <key value="="/>
- <key key_type="dummy" width="0.25"/>
- <key value="Up" label="&lt;b&gt;↑&lt;/b&gt;"/>
- <key value="\"/>
- </row>
- <row>
- <key>
- <label>&lt;small&gt;&lt;i&gt;abc&lt;/i&gt;&lt;/small&gt;</label>
- <key_type>layout_switcher</key_type>
- <value>lowercase</value>
- <width>1.5</width>
- </key>
- <key>
- <label>&lt;small&gt;&lt;b&gt;Ctrl&lt;/b&gt;&lt;/small&gt;</label>
- <value>Control_L</value>
- <key_type>mask</key_type>
- <width>1.5</width>
- </key>
- <key>
- <label>&lt;small&gt;&lt;b&gt;Alt&lt;/b&gt;&lt;/small&gt;</label>
- <value>Alt_L</value>
- <key_type>mask</key_type>
- <width>1.5</width>
- </key>
- <key key_type="dummy" width="0.5"/>
- <key label="______" value=" " width="3"/>
- <key key_type="dummy" width="0.5"/>
- <key value="|"/>
- <key value="Left" label="&lt;b&gt;←&lt;/b&gt;"/>
- <key value="Down" label="&lt;b&gt;↓&lt;/b&gt;"/>
- <key value="Right" label="&lt;b&gt;→&lt;/b&gt;"/>
- </row>
- </rows>
- </layout>
-</keyboard>
diff --git a/data/keyboards/qwerty_en.json b/data/keyboards/qwerty_en.json
deleted file mode 100644
index 8864085..0000000
--- a/data/keyboards/qwerty_en.json
+++ /dev/null
@@ -1,261 +0,0 @@
-
-{"layout": [
- {"name": "lowercase",
- "rows": {"row": [{"key": [{"key_type": "preferences"},
- {"value": "q"},
- {"value": "w"},
- {"value": "e"},
- {"value": "r"},
- {"value": "t"},
- {"value": "y"},
- {"value": "u"},
- {"value": "i"},
- {"value": "o"},
- {"value": "p"},
- {"value": "BackSpace",
- "label": "<big>⌫</big>",
- "width": 1.5}
- ]
- },
- {"key": [{"label": "<b><sup>←</sup><sub>→</sub></b>",
- "value": "Tab"},
- {"key_type": "dummy",
- "width": 0.25},
- {"value": "a"},
- {"value": "s"},
- {"value": "d"},
- {"value": "f"},
- {"value": "g"},
- {"value": "h"},
- {"value": "j"},
- {"value": "k"},
- {"value": "l"},
- {"key_type": "dummy",
- "width": 0.25},
- {"value": "Return",
- "label": "<b>↲</b>",
- "width": 2}
- ]
- },
- {"key": [{"label": "<b>↑</b>",
- "key_type": "layout_switcher",
- "value": "uppercase",
- "width": 1.5},
- {"key_type": "dummy",
- "width": 0.5},
- {"value": "z"},
- {"value": "x"},
- {"value": "c"},
- {"value": "v"},
- {"value": "b"},
- {"value": "n"},
- {"value": "m"},
- {"key_type": "dummy",
- "width": 0.5},
- {"value": ","},
- {"value": "."},
- {"value": ";"}
- ]
- },
- {"key": [{"label": "<small><i>1%+</i></small>",
- "key_type": "layout_switcher",
- "value": "special",
- "width": 1.5},
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_L",
- "key_type": "mask",
- "width": 1.5},
- {"label": "<small><b>Alt</b></small>",
- "value": "Alt_L",
- "key_type": "mask",
- "width": 1.5},
- {"key_type": "dummy",
- "width": 0.5},
- {"label": "______",
- "value": " ",
- "width": 3},
- {"key_type": "dummy",
- "width": 0.5},
- {"value": "'"},
- {"value": "\""},
- {"value": "!"},
- {"value": "?"}
- ]
- }
- ]
- }
- },
- {"name": "uppercase",
- "rows": {"row": [{"key": [{"key_type": "preferences"},
- {"value": "Q"},
- {"value": "W"},
- {"value": "E"},
- {"value": "R"},
- {"value": "T"},
- {"value": "Y"},
- {"value": "U"},
- {"value": "I"},
- {"value": "O"},
- {"value": "P"},
- {"value": "BackSpace",
- "label": "<big>⌫</big>",
- "width": 1.5}
- ]
- },
- {"key": [{"label": "<b><sup>←</sup><sub>→</sub></b>",
- "value": "Tab"},
- {"key_type": "dummy",
- "width": 0.25},
- {"value": "A"},
- {"value": "S"},
- {"value": "D"},
- {"value": "F"},
- {"value": "G"},
- {"value": "G"},
- {"value": "H"},
- {"value": "J"},
- {"value": "K"},
- {"key_type": "dummy",
- "width": 0.25},
- {"value": "Return",
- "label": "<b>↲</b>",
- "width": 2}
- ]
- },
- {"key": [{"label": "<b>↓</b>",
- "key_type": "layout_switcher",
- "value": "lowercase",
- "width": 1.5},
- {"key_type": "dummy",
- "width": 0.5},
- {"value": "Z"},
- {"value": "X"},
- {"value": "C"},
- {"value": "V"},
- {"value": "B"},
- {"value": "N"},
- {"value": "M"},
- {"key_type": "dummy",
- "width": 0.5},
- {"value": ","},
- {"value": "."},
- {"value": ";"}
- ]
- },
- {"key": [{"label": "<small><i>1%+</i></small>",
- "key_type": "layout_switcher",
- "value": "special",
- "width": 1.5},
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_L",
- "key_type": "mask",
- "width": 1.5},
- {"label": "<small><b>Alt</b></small>",
- "value": "Alt_L",
- "key_type": "mask",
- "width": 1.5},
- {"key_type": "dummy",
- "width": 0.5},
- {"label": "______",
- "value": " ",
- "width": 3},
- {"key_type": "dummy",
- "width": 0.5},
- {"value": "'"},
- {"value": "\""},
- {"value": "!"},
- {"value": "?"}
- ]
- }
- ]
- }
- },
- {"name": "special",
- "rows": {"row": [{"key": [{"key_type": "preferences"},
- {"value": "1"},
- {"value": "2"},
- {"value": "3"},
- {"value": "4"},
- {"value": "5"},
- {"value": "6"},
- {"value": "7"},
- {"value": "8"},
- {"value": "9"},
- {"value": "0"},
- {"value": "BackSpace",
- "label": "<big>⌫</big>",
- "width": 1.5}
- ]
- },
- {"key": [{"key_type": "dummy",
- "width": 0.25},
- {"value": "@"},
- {"value": "#"},
- {"value": "$"},
- {"value": "%"},
- {"value": "&"},
- {"value": "*"},
- {"value": "("},
- {"value": ")"},
- {"value": "-"},
- {"value": "+"},
- {"key_type": "dummy",
- "width": 0.25},
- {"value": "Return",
- "label": "<b>↲</b>",
- "width": 2}
- ]
- },
- {"key": [{"key_type": "dummy",
- "width": 0.25},
- {"value": "<"},
- {"value": ">"},
- {"value": "€"},
- {"value": "£"},
- {"value": "{"},
- {"value": "}"},
- {"value": "["},
- {"value": "]"},
- {"label": "<small>_</small>",
- "value": "_"},
- {"value": "="},
- {"key_type": "dummy",
- "width": 0.25},
- {"label": "<b>↑</b>",
- "value": "Up"},
- {"value": "\\"}
- ]
- },
- {"key": [{"label": "<small><i>abc</i></small>",
- "key_type": "layout_switcher",
- "value": "lowercase",
- "width": 1.5},
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_L",
- "key_type": "mask",
- "width": 1.5},
- {"label": "<small><b>Alt</b></small>",
- "value": "Alt_L",
- "key_type": "mask",
- "width": 1.5},
- {"key_type": "dummy",
- "width": 0.5},
- {"label": "______",
- "value": " ",
- "width": 3},
- {"key_type": "dummy",
- "width": 0.5},
- {"value": "|"},
- {"label": "<b>←</b>",
- "value": "Left"},
- {"label": "<b>↓</b>",
- "value": "Down"},
- {"label": "<b>→</b>",
- "value": "Right"}
- ]
- }
- ]
- }
- }
- ]
-}
diff --git a/data/keyboards/qwerty_es.json b/data/keyboards/qwerty_es.json
deleted file mode 100644
index 4136d08..0000000
--- a/data/keyboards/qwerty_es.json
+++ /dev/null
@@ -1,1318 +0,0 @@
-{"layout":
-[
- {"name": "uppercase",
- "rows": {"row": [{"key":[
- {"value": "Escape", "label": "<small>Esc</small>", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.4},
- {"value": "F1",
- "width": 1.2},
- {"value": "F2",
- "width": 1.2},
- {"value": "F3",
- "width": 1.2},
- {"value": "F4",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "F5",
- "width": 1.2},
- {"value": "F6",
- "width": 1.2},
- {"value": "F7",
- "width": 1.2},
- {"value": "F8",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "F9",
- "width": 1.2},
- {"value": "F10",
- "width": 1.2},
- {"value": "F11",
- "width": 1.2},
- {"value": "F12",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.4},
- {"key_type": "preferences", "width": 1.2}
- ]
- },
- {"key": [
- {"value": "º", "width": 1.2},
- {"value": "1", "width": 1.2},
- {"value": "2", "width": 1.2},
- {"value": "3", "width": 1.2},
- {"value": "4", "width": 1.2},
- {"value": "5", "width": 1.2},
- {"value": "6", "width": 1.2},
- {"value": "7", "width": 1.2},
- {"value": "8", "width": 1.2},
- {"value": "9", "width": 1.2},
- {"value": "0", "width": 1.2},
- {"value": "'", "width": 1.2},
- {"value": "¡", "width": 1.2},
- {"value": "BackSpace",
- "label": "<big>⌫</big>",
- "width": 2.4}
- ]
- },
- {"key": [
- {"label": "<b><sup>←</sup><sub>→</sub></b>",
- "value": "Tab",
- "width": 1.8},
- {"value": "Q", "width": 1.2},
- {"value": "W", "width": 1.2},
- {"value": "E", "width": 1.2},
- {"value": "R", "width": 1.2},
- {"value": "T", "width": 1.2},
- {"value": "Y", "width": 1.2},
- {"value": "U", "width": 1.2},
- {"value": "I", "width": 1.2},
- {"value": "O", "width": 1.2},
- {"value": "P", "width": 1.2},
- {"value": "`", "width": 1.2},
- {"value": "+", "width": 1.2},
- {"value": "Return",
- "label": "<b>↲</b>",
- "width": 1.8}
- ]
- },
- {"key": [
- {"label": "<small>Bloq M</small>",
- "value": "lowercase",
- "key_type": "layout_switcher",
- "width": 2.6},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "A", "width": 1.2},
- {"value": "S", "width": 1.2},
- {"value": "D", "width": 1.2},
- {"value": "F", "width": 1.2},
- {"value": "G", "width": 1.2},
- {"value": "H", "width": 1.2},
- {"value": "J", "width": 1.2},
- {"value": "K", "width": 1.2},
- {"value": "L", "width": 1.2},
- {"value": "Ñ", "width": 1.2},
- {"value": "´", "width": 1.2},
- {"value": "Ç", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.8}
- ]
- },
- {"key": [
- {"label": "<b>↑</b>",
- "key_type": "layout_switcher",
- "value": "uppercase_shift",
- "width": 1.6},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "<",
- "label": "&lt;", "width": 1.2},
- {"value": "Z", "width": 1.2},
- {"value": "X", "width": 1.2},
- {"value": "C", "width": 1.2},
- {"value": "V", "width": 1.2},
- {"value": "B", "width": 1.2},
- {"value": "N", "width": 1.2},
- {"value": "M", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": ",", "width": 1.2},
- {"value": ".", "width": 1.2},
- {"value": "-", "width": 1.2},
- {"label": "<b>↑</b>",
- "key_type": "layout_switcher",
- "value": "uppercase_shift",
- "width": 2.8}
- ]
- },
- {"key":[
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_L",
- "key_type": "mask",
- "width": 1.8},
- {"label": "<small><b>Win</b></small>",
- "value": "Super_L",
- "key_type": "mask",
- "width": 1.6},
- {"label": "<small><b>Alt</b></small>",
- "value": "Alt_L",
- "key_type": "mask",
- "width": 1.6},
- {"key_type": "dummy",
- "width": 0.4},
- {"label": "______",
- "value": " ",
- "width": 7.4},
- {"key_type": "dummy",
- "width": 0.4},
- {"label": "<small><b>Alt Gr</b></small>",
- "value": "uppercase_alt",
- "key_type": "layout_switcher",
- "width": 1.6},
- {"label": "<small><b>Win</b></small>",
- "value": "Super_R",
- "key_type": "mask",
- "width": 1.6},
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_R",
- "width": 1.6}
- ]
- }
- ]
- }
- },
-
-
- {"name": "lowercase_shift",
- "rows": {"row": [{"key":[
- {"value": "Escape", "label": "<small>Esc</small>", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.4},
- {"value": "F1",
- "width": 1.2},
- {"value": "F2",
- "width": 1.2},
- {"value": "F3",
- "width": 1.2},
- {"value": "F4",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "F5",
- "width": 1.2},
- {"value": "F6",
- "width": 1.2},
- {"value": "F7",
- "width": 1.2},
- {"value": "F8",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "F9",
- "width": 1.2},
- {"value": "F10",
- "width": 1.2},
- {"value": "F11",
- "width": 1.2},
- {"value": "F12",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.4},
- {"key_type": "preferences", "width": 1.2}
- ]
- },
- {"key": [
- {"value": "º", "width": 1.2},
- {"value": "ª", "width": 1.2},
- {"value": "!", "width": 1.2},
- {"value": "\"", "width": 1.2},
- {"value": "·", "width": 1.2},
- {"value": "%", "width": 1.2},
- {"value": "&", "width": 1.2},
- {"value": "/", "width": 1.2},
- {"value": "(", "width": 1.2},
- {"value": ")", "width": 1.2},
- {"value": "=", "width": 1.2},
- {"value": "?", "width": 1.2},
- {"value": "¿", "width": 1.2},
- {"value": "BackSpace",
- "label": "<big>⌫</big>",
- "width": 2.4}
- ]
- },
- {"key": [
- {"label": "<b><sup>←</sup><sub>→</sub></b>",
- "value": "Tab",
- "width": 1.8},
- {"value": "Q", "width": 1.2},
- {"value": "W", "width": 1.2},
- {"value": "E", "width": 1.2},
- {"value": "R", "width": 1.2},
- {"value": "T", "width": 1.2},
- {"value": "Y", "width": 1.2},
- {"value": "U", "width": 1.2},
- {"value": "I", "width": 1.2},
- {"value": "O", "width": 1.2},
- {"value": "P", "width": 1.2},
- {"value": "^", "width": 1.2},
- {"value": "*", "width": 1.2},
- {"value": "Return",
- "label": "<b>↲</b>",
- "width": 1.8}
- ]
- },
- {"key":[
- {"label": "<small>Bloq M</small>",
- "value": "uppercase_shift",
- "key_type": "layout_switcher",
- "width": 2.6},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "A", "width": 1.2},
- {"value": "S", "width": 1.2},
- {"value": "D", "width": 1.2},
- {"value": "F", "width": 1.2},
- {"value": "G", "width": 1.2},
- {"value": "H", "width": 1.2},
- {"value": "J", "width": 1.2},
- {"value": "K", "width": 1.2},
- {"value": "L", "width": 1.2},
- {"value": "Ñ", "width": 1.2},
- {"value": "¨", "width": 1.2},
- {"value": "Ç", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.8}
- ]
- },
- {"key":[
- {"label": "<b>↑</b>",
- "key_type": "layout_switcher",
- "value": "lowercase",
- "width": 1.6},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": ">",
- "label": "&gt;", "width": 1.2},
- {"value": "Z", "width": 1.2},
- {"value": "X", "width": 1.2},
- {"value": "C", "width": 1.2},
- {"value": "V", "width": 1.2},
- {"value": "B", "width": 1.2},
- {"value": "N", "width": 1.2},
- {"value": "M", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": ";", "width": 1.2},
- {"value": ":", "width": 1.2},
- {"value": "_", "width": 1.2},
- {"label": "<b>↑</b>",
- "key_type": "layout_switcher",
- "value": "lowercase",
- "width": 2.8}
- ]
- },
- {"key":[
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_L",
- "key_type": "mask",
- "width": 1.8},
- {"label": "<small><b>Win</b></small>",
- "value": "Super_L",
- "key_type": "mask",
- "width": 1.6},
- {"label": "<small><b>Alt</b></small>",
- "value": "Alt_L",
- "key_type": "mask",
- "width": 1.6},
- {"key_type": "dummy",
- "width": 0.4},
- {"label": "______",
- "value": " ",
- "width": 7.4},
- {"key_type": "dummy",
- "width": 0.4},
- {"label": "<small><b>Alt Gr</b></small>",
- "value": "lowercase_alt_shift",
- "key_type": "layout_switcher",
- "width": 1.6},
- {"label": "<small><b>Win</b></small>",
- "value": "Super_R",
- "key_type": "mask",
- "width": 1.6},
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_R",
- "width": 1.6}
- ]
- }
- ]
- }
- },
- {"name": "uppercase_shift",
- "rows": {"row": [{"key": [
- {"value": "Escape", "label": "<small>Esc</small>", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.4},
- {"value": "F1",
- "width": 1.2},
- {"value": "F2",
- "width": 1.2},
- {"value": "F3",
- "width": 1.2},
- {"value": "F4",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "F5",
- "width": 1.2},
- {"value": "F6",
- "width": 1.2},
- {"value": "F7",
- "width": 1.2},
- {"value": "F8",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "F9",
- "width": 1.2},
- {"value": "F10",
- "width": 1.2},
- {"value": "F11",
- "width": 1.2},
- {"value": "F12",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.4},
- {"key_type": "preferences", "width": 1.2}
- ]
- },
- {"key":[
- {"value": "º", "width": 1.2},
- {"value": "ª", "width": 1.2},
- {"value": "!", "width": 1.2},
- {"value": "\"", "width": 1.2},
- {"value": "·", "width": 1.2},
- {"value": "%", "width": 1.2},
- {"value": "&", "width": 1.2},
- {"value": "/", "width": 1.2},
- {"value": "(", "width": 1.2},
- {"value": ")", "width": 1.2},
- {"value": "=", "width": 1.2},
- {"value": "?", "width": 1.2},
- {"value": "¿", "width": 1.2},
- {"value": "BackSpace",
- "label": "<big>⌫</big>",
- "width": 2.4}
- ]
- },
- {"key":[
- {"label": "<b><sup>←</sup><sub>→</sub></b>",
- "value": "Tab",
- "width": 1.8},
- {"value": "q", "width": 1.2},
- {"value": "w", "width": 1.2},
- {"value": "e", "width": 1.2},
- {"value": "r", "width": 1.2},
- {"value": "t", "width": 1.2},
- {"value": "y", "width": 1.2},
- {"value": "u", "width": 1.2},
- {"value": "i", "width": 1.2},
- {"value": "o", "width": 1.2},
- {"value": "p", "width": 1.2},
- {"value": "^", "width": 1.2},
- {"value": "*", "width": 1.2},
- {"value": "Return",
- "label": "<b>↲</b>",
- "width": 1.8}
- ]
- },
- {"key": [
- {"label": "<small>Bloq M</small>",
- "value": "lowercase_shift",
- "key_type": "layout_switcher",
- "width": 2.6},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "a", "width": 1.2},
- {"value": "s", "width": 1.2},
- {"value": "d", "width": 1.2},
- {"value": "f", "width": 1.2},
- {"value": "g", "width": 1.2},
- {"value": "h", "width": 1.2},
- {"value": "j", "width": 1.2},
- {"value": "k", "width": 1.2},
- {"value": "l", "width": 1.2},
- {"value": "ñ", "width": 1.2},
- {"value": "¨", "width": 1.2},
- {"value": "Ç", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.8}
- ]
- },
- {"key":[
- {"label": "<b>↑</b>",
- "key_type": "layout_switcher",
- "value": "uppercase",
- "width": 1.6},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": ">",
- "label": "&gt;", "width": 1.2},
- {"value": "z", "width": 1.2},
- {"value": "x", "width": 1.2},
- {"value": "c", "width": 1.2},
- {"value": "v", "width": 1.2},
- {"value": "b", "width": 1.2},
- {"value": "n", "width": 1.2},
- {"value": "m", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": ";", "width": 1.2},
- {"value": ":", "width": 1.2},
- {"value": "_", "width": 1.2},
- {"label": "<b>↑</b>",
- "key_type": "layout_switcher",
- "value": "uppercase",
- "width": 2.8}
- ]
- },
- {"key":[
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_L",
- "key_type": "mask",
- "width": 1.8},
- {"label": "<small><b>Win</b></small>",
- "value": "Super_L",
- "key_type": "mask",
- "width": 1.6},
- {"label": "<small><b>Alt</b></small>",
- "value": "Alt_L",
- "key_type": "mask",
- "width": 1.6},
- {"key_type": "dummy",
- "width": 0.4},
- {"label": "______",
- "value": " ",
- "width": 7.4},
- {"key_type": "dummy",
- "width": 0.4},
- {"label": "<small><b>Alt Gr</b></small>",
- "value": "uppercase_alt_shift",
- "key_type": "layout_switcher",
- "width": 1.6},
- {"label": "<small><b>Win</b></small>",
- "value": "Super_R",
- "key_type": "mask",
- "width": 1.6},
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_R",
- "width": 1.6}
- ]
- }
- ]
- }
- },
- {"name": "uppercase_alt",
- "rows": {"row": [{"key":[
- {"value": "Escape", "label": "<small>Esc</small>", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.4},
- {"value": "F1",
- "width": 1.2},
- {"value": "F2",
- "width": 1.2},
- {"value": "F3",
- "width": 1.2},
- {"value": "F4",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "F5",
- "width": 1.2},
- {"value": "F6",
- "width": 1.2},
- {"value": "F7",
- "width": 1.2},
- {"value": "F8",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "F9",
- "width": 1.2},
- {"value": "F10",
- "width": 1.2},
- {"value": "F11",
- "width": 1.2},
- {"value": "F12",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.4},
- {"key_type": "preferences", "width": 1.2}
- ]
- },
- {"key": [
- {"value": "\\", "width": 1.2},
- {"value": "|", "width": 1.2},
- {"value": "@", "width": 1.2},
- {"value": "#", "width": 1.2},
- {"value": "~", "width": 1.2},
- {"value": "½", "width": 1.2},
- {"value": "¬", "width": 1.2},
- {"value": "{", "width": 1.2},
- {"value": "[", "width": 1.2},
- {"value": "]", "width": 1.2},
- {"value": "}", "width": 1.2},
- {"value": "\\", "width": 1.2},
- {"value": "¡", "width": 1.2},
- {"value": "BackSpace",
- "label": "<big>⌫</big>",
- "width": 2.4}
- ]
- },
- {"key":[
- {"label": "<b><sup>←</sup><sub>→</sub></b>",
- "value": "Tab",
- "width": 1.8},
- {"value": "@", "width": 1.2},
- {"value": "Ł", "width": 1.2},
- {"value": "€", "width": 1.2},
- {"value": "¶", "width": 1.2},
- {"value": "Ŧ", "width": 1.2},
- {"value": "←", "width": 1.2},
- {"value": "↓", "width": 1.2},
- {"value": "→", "width": 1.2},
- {"value": "Ø", "width": 1.2},
- {"value": "Þ", "width": 1.2},
- {"value": "[", "width": 1.2},
- {"value": "]", "width": 1.2},
- {"value": "Return",
- "label": "<b>↲</b>",
- "width": 1.8}
- ]
- },
- {"key":[
- {"label": "<small>Bloq M</small>",
- "value": "lowercase_alt",
- "key_type": "layout_switcher",
- "width": 2.6},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "Æ", "width": 1.2},
- {"value": "ß", "width": 1.2},
- {"value": "Ð", "width": 1.2},
- {"value": "Đ", "width": 1.2},
- {"value": "Ŋ", "width": 1.2},
- {"value": "Ħ", "width": 1.2},
- {"value": "J", "width": 1.2},
- {"value": "ĸ", "width": 1.2},
- {"value": "Ł", "width": 1.2},
- {"value": "~", "width": 1.2},
- {"value": "{", "width": 1.2},
- {"value": "}", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.8}
- ]
- },
- {"key":[
- {"label": "<b>↑</b>",
- "key_type": "layout_switcher",
- "value": "uppercase_alt_shift",
- "width": 1.6},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "|",
- "label": "|", "width": 1.2},
- {"value": "«", "width": 1.2},
- {"value": "»", "width": 1.2},
- {"value": "¢", "width": 1.2},
- {"value": "“", "width": 1.2},
- {"value": "”", "width": 1.2},
- {"value": "N", "width": 1.2},
- {"value": "M", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": ",", "width": 1.2},
- {"value": ".", "width": 1.2},
- {"value": "-", "width": 1.2},
- {"label": "<b>↑</b>",
- "key_type": "layout_switcher",
- "value": "uppercase_alt_shift",
- "width": 2.8}
- ]
- },
- {"key":[
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_L",
- "key_type": "mask",
- "width": 1.8},
- {"label": "<small><b>Win</b></small>",
- "value": "Super_L",
- "key_type": "mask",
- "width": 1.6},
- {"label": "<small><b>Alt</b></small>",
- "value": "Alt_L",
- "key_type": "mask",
- "width": 1.6},
- {"key_type": "dummy",
- "width": 0.4},
- {"label": "______",
- "value": " ",
- "width": 7.4},
- {"key_type": "dummy",
- "width": 0.4},
- {"label": "<small><b>Alt Gr</b></small>",
- "value": "uppercase",
- "key_type": "layout_switcher",
- "width": 1.6},
- {"label": "<small><b>Win</b></small>",
- "value": "Super_R",
- "key_type": "mask",
- "width": 1.6},
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_R",
- "width": 1.6}
- ]
- }
- ]
- }
- },
-{"name": "lowercase_alt_shift",
- "rows": {"row": [{"key": [
- {"value": "Escape", "label": "<small>Esc</small>", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.4},
- {"value": "F1",
- "width": 1.2},
- {"value": "F2",
- "width": 1.2},
- {"value": "F3",
- "width": 1.2},
- {"value": "F4",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "F5",
- "width": 1.2},
- {"value": "F6",
- "width": 1.2},
- {"value": "F7",
- "width": 1.2},
- {"value": "F8",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "F9",
- "width": 1.2},
- {"value": "F10",
- "width": 1.2},
- {"value": "F11",
- "width": 1.2},
- {"value": "F12",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.4},
- {"key_type": "preferences", "width": 1.2}
- ]
- },
- {"key":[
- {"value": "\\", "width": 1.2},
- {"value": "¡", "width": 1.2},
- {"value": "⅛", "width": 1.2},
- {"value": "£", "width": 1.2},
- {"value": "$", "width": 1.2},
- {"value": "⅜", "width": 1.2},
- {"value": "⅝", "width": 1.2},
- {"value": "⅞", "width": 1.2},
- {"value": "™", "width": 1.2},
- {"value": "±", "width": 1.2},
- {"value": "°", "width": 1.2},
- {"value": "¿", "width": 1.2},
- {"value": "~", "width": 1.2},
- {"value": "BackSpace",
- "label": "<big>⌫</big>",
- "width": 2.4}
- ]
- },
- {"key":[
- {"label": "<b><sup>←</sup><sub>→</sub></b>",
- "value": "Tab",
- "width": 1.8},
- {"value": "@", "width": 1.2},
- {"value": "Ł", "width": 1.2},
- {"value": "€", "width": 1.2},
- {"value": "¶", "width": 1.2},
- {"value": "Ŧ", "width": 1.2},
- {"value": "←", "width": 1.2},
- {"value": "↓", "width": 1.2},
- {"value": "→", "width": 1.2},
- {"value": "Ø", "width": 1.2},
- {"value": "Þ", "width": 1.2},
- {"value": "[", "width": 1.2},
- {"value": "]", "width": 1.2},
- {"value": "Return",
- "label": "<b>↲</b>",
- "width": 1.8}
- ]
- },
- {"key":[
- {"label": "<small>Bloq M</small>",
- "value": "uppercase_alt_shift",
- "key_type": "layout_switcher",
- "width": 2.6},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "Æ", "width": 1.2},
- {"value": "ß", "width": 1.2},
- {"value": "Ð", "width": 1.2},
- {"value": "Đ", "width": 1.2},
- {"value": "Ŋ", "width": 1.2},
- {"value": "Ħ", "width": 1.2},
- {"value": "J", "width": 1.2},
- {"value": "ĸ", "width": 1.2},
- {"value": "Ł", "width": 1.2},
- {"value": "~", "width": 1.2},
- {"value": "{", "width": 1.2},
- {"value": "}", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.8}
- ]
- },
- {"key":[
- {"label": "<b>↑</b>",
- "key_type": "layout_switcher",
- "value": "lowercase_alt",
- "width": 1.6},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "|",
- "label": "|", "width": 1.2},
- {"value": "«", "width": 1.2},
- {"value": "»", "width": 1.2},
- {"value": "¢", "width": 1.2},
- {"value": "“", "width": 1.2},
- {"value": "”", "width": 1.2},
- {"value": "N", "width": 1.2},
- {"value": "M", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": ",", "width": 1.2},
- {"value": ".", "width": 1.2},
- {"value": "-", "width": 1.2},
- {"label": "<b>↑</b>",
- "key_type": "layout_switcher",
- "value": "lowercase_alt",
- "width": 2.8}
- ]
- },
- {"key":[
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_L",
- "key_type": "mask",
- "width": 1.8},
- {"label": "<small><b>Win</b></small>",
- "value": "Super_L",
- "key_type": "mask",
- "width": 1.6},
- {"label": "<small><b>Alt</b></small>",
- "value": "Alt_L",
- "key_type": "mask",
- "width": 1.6},
- {"key_type": "dummy",
- "width": 0.4},
- {"label": "______",
- "value": " ",
- "width": 7.4},
- {"key_type": "dummy",
- "width": 0.4},
- {"label": "<small><b>Alt Gr</b></small>",
- "value": "lowercase_shift",
- "key_type": "layout_switcher",
- "width": 1.6},
- {"label": "<small><b>Win</b></small>",
- "value": "Super_R",
- "key_type": "mask",
- "width": 1.6},
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_R",
- "width": 1.6}
- ]
- }
- ]
- }
- },
- {"name": "lowercase_alt",
- "rows": {"row": [{"key":[
- {"value": "Escape", "label": "<small>Esc</small>"},
- {"key_type": "dummy",
- "width": 0.4},
- {"value": "F1",
- "width": 1.2},
- {"value": "F2",
- "width": 1.2},
- {"value": "F3",
- "width": 1.2},
- {"value": "F4",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "F5",
- "width": 1.2},
- {"value": "F6",
- "width": 1.2},
- {"value": "F7",
- "width": 1.2},
- {"value": "F8",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "F9",
- "width": 1.2},
- {"value": "F10",
- "width": 1.2},
- {"value": "F11",
- "width": 1.2},
- {"value": "F12",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.4},
- {"key_type": "preferences"}
- ]
- },
- {"key":[
- {"value": "\\", "width": 1.2},
- {"value": "|", "width": 1.2},
- {"value": "@", "width": 1.2},
- {"value": "#", "width": 1.2},
- {"value": "~", "width": 1.2},
- {"value": "½", "width": 1.2},
- {"value": "¬", "width": 1.2},
- {"value": "{", "width": 1.2},
- {"value": "[", "width": 1.2},
- {"value": "[", "width": 1.2},
- {"value": "}", "width": 1.2},
- {"value": "\\", "width": 1.2},
- {"value": "~", "width": 1.2},
- {"value": "BackSpace",
- "label": "<big>⌫</big>",
- "width": 2.4}
- ]
- },
- {"key":[
- {"label": "<b><sup>←</sup><sub>→</sub></b>",
- "value": "Tab",
- "width": 1.8},
- {"value": "@", "width": 1.2},
- {"value": "ł", "width": 1.2},
- {"value": "€", "width": 1.2},
- {"value": "¶", "width": 1.2},
- {"value": "ŧ", "width": 1.2},
- {"value": "←", "width": 1.2},
- {"value": "↓", "width": 1.2},
- {"value": "→", "width": 1.2},
- {"value": "ø", "width": 1.2},
- {"value": "þ", "width": 1.2},
- {"value": "[", "width": 1.2},
- {"value": "]", "width": 1.2},
- {"value": "Return",
- "label": "<b>↲</b>",
- "width": 1.8}
- ]
- },
- {"key":[
- {"label": "<small>Bloq M</small>",
- "value": "uppercase_alt",
- "key_type": "layout_switcher",
- "width": 2.6},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "æ", "width": 1.2},
- {"value": "ß", "width": 1.2},
- {"value": "ð", "width": 1.2},
- {"value": "đ", "width": 1.2},
- {"value": "ŋ", "width": 1.2},
- {"value": "ħ", "width": 1.2},
- {"value": "j", "width": 1.2},
- {"value": "ĸ", "width": 1.2},
- {"value": "ł", "width": 1.2},
- {"value": "~", "width": 1.2},
- {"value": "{", "width": 1.2},
- {"value": "}", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.8}
- ]
- },
- {"key":[
- {"label": "<b>↑</b>",
- "key_type": "layout_switcher",
- "value": "lowercase_alt_shift",
- "width": 1.6},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "|",
- "label": "&lt;", "width": 1.2},
- {"value": "«", "width": 1.2},
- {"value": "»", "width": 1.2},
- {"value": "¢", "width": 1.2},
- {"value": "“", "width": 1.2},
- {"value": "”", "width": 1.2},
- {"value": "n", "width": 1.2},
- {"value": "µ", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "─", "width": 1.2},
- {"value": "·", "width": 1.2},
- {"value": "-", "width": 1.2},
- {"label": "<b>↑</b>",
- "key_type": "layout_switcher",
- "value": "lowercase_alt_shift",
- "width": 2.8}
- ]
- },
- {"key":[
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_L",
- "key_type": "mask",
- "width": 1.8},
- {"label": "<small><b>Win</b></small>",
- "value": "Super_L",
- "key_type": "mask",
- "width": 1.6},
- {"label": "<small><b>Alt</b></small>",
- "value": "Alt_L",
- "key_type": "mask",
- "width": 1.6},
- {"key_type": "dummy",
- "width": 0.4},
- {"label": "______",
- "value": " ",
- "width": 7.4},
- {"key_type": "dummy",
- "width": 0.4},
- {"label": "<small><b>Alt Gr</b></small>",
- "value": "lowercase",
- "key_type": "layout_switcher",
- "width": 1.6},
- {"label": "<small><b>Win</b></small>",
- "value": "Super_R",
- "key_type": "mask",
- "width": 1.6},
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_R",
- "width": 1.6}
- ]
- }
- ]
- }
- },
-{"name": "uppercase_alt_shift",
- "rows": {"row": [{"key":[
- {"value": "Escape", "label": "<small>Esc</small>", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.4},
- {"value": "F1",
- "width": 1.2},
- {"value": "F2",
- "width": 1.2},
- {"value": "F3",
- "width": 1.2},
- {"value": "F4",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "F5",
- "width": 1.2},
- {"value": "F6",
- "width": 1.2},
- {"value": "F7",
- "width": 1.2},
- {"value": "F8",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "F9",
- "width": 1.2},
- {"value": "F10",
- "width": 1.2},
- {"value": "F11",
- "width": 1.2},
- {"value": "F12",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.4},
- {"key_type": "preferences", "width": 1.2}
- ]
- },
- {"key":[
- {"value": "\\", "width": 1.2},
- {"value": "¡", "width": 1.2},
- {"value": "⅛", "width": 1.2},
- {"value": "£", "width": 1.2},
- {"value": "$", "width": 1.2},
- {"value": "⅜", "width": 1.2},
- {"value": "⅝", "width": 1.2},
- {"value": "⅞", "width": 1.2},
- {"value": "™", "width": 1.2},
- {"value": "±", "width": 1.2},
- {"value": "°", "width": 1.2},
- {"value": "¿", "width": 1.2},
- {"value": "~", "width": 1.2},
- {"value": "BackSpace",
- "label": "<big>⌫</big>",
- "width": 2.4}
- ]
- },
- {"key":[
- {"label": "<b><sup>←</sup><sub>→</sub></b>",
- "value": "Tab",
- "width": 1.8},
- {"value": "@", "width": 1.2},
- {"value": "ł", "width": 1.2},
- {"value": "€", "width": 1.2},
- {"value": "¶", "width": 1.2},
- {"value": "ŧ", "width": 1.2},
- {"value": "←", "width": 1.2},
- {"value": "↓", "width": 1.2},
- {"value": "→", "width": 1.2},
- {"value": "ø", "width": 1.2},
- {"value": "þ", "width": 1.2},
- {"value": "[", "width": 1.2},
- {"value": "]", "width": 1.2},
- {"value": "Return",
- "label": "<b>↲</b>",
- "width": 1.8}
- ]
- },
- {"key":[
- {"label": "<small>Bloq M</small>",
- "value": "lowercase_alt_shift",
- "key_type": "layout_switcher",
- "width": 2.6},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "æ", "width": 1.2},
- {"value": "ß", "width": 1.2},
- {"value": "ð", "width": 1.2},
- {"value": "đ", "width": 1.2},
- {"value": "ŋ", "width": 1.2},
- {"value": "ħ", "width": 1.2},
- {"value": "j", "width": 1.2},
- {"value": "ĸ", "width": 1.2},
- {"value": "ł", "width": 1.2},
- {"value": "~", "width": 1.2},
- {"value": "{", "width": 1.2},
- {"value": "}", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.8}
- ]
- },
- {"key":[
- {"label": "<b>↑</b>",
- "key_type": "layout_switcher",
- "value": "uppercase_alt",
- "width": 1.6},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "|",
- "label": "&lt;", "width": 1.2},
- {"value": "«", "width": 1.2},
- {"value": "»", "width": 1.2},
- {"value": "¢", "width": 1.2},
- {"value": "“", "width": 1.2},
- {"value": "”", "width": 1.2},
- {"value": "n", "width": 1.2},
- {"value": "µ", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "─", "width": 1.2},
- {"value": "·", "width": 1.2},
- {"value": "-", "width": 1.2},
- {"label": "<b>↑</b>",
- "key_type": "layout_switcher",
- "value": "uppercase_alt",
- "width": 2.8}
- ]
- },
- {"key":[
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_L",
- "key_type": "mask",
- "width": 1.8},
- {"label": "<small><b>Win</b></small>",
- "value": "Super_L",
- "key_type": "mask",
- "width": 1.6},
- {"label": "<small><b>Alt</b></small>",
- "value": "Alt_L",
- "key_type": "mask",
- "width": 1.6},
- {"key_type": "dummy",
- "width": 0.4},
- {"label": "______",
- "value": " ",
- "width": 7.4},
- {"key_type": "dummy",
- "width": 0.4},
- {"label": "<small><b>Alt Gr</b></small>",
- "value": "uppercase_shift",
- "key_type": "layout_switcher",
- "width": 1.6},
- {"label": "<small><b>Win</b></small>",
- "value": "Super_R",
- "key_type": "mask",
- "width": 1.6},
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_R",
- "width": 1.6}
- ]
- }
- ]
- }
- },
- {"name": "lowercase",
- "rows": {"row": [{"key":[
- {"value": "Escape", "label": "<small>Esc</small>", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.4},
- {"value": "F1",
- "width": 1.2},
- {"value": "F2",
- "width": 1.2},
- {"value": "F3",
- "width": 1.2},
- {"value": "F4",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "F5",
- "width": 1.2},
- {"value": "F6",
- "width": 1.2},
- {"value": "F7",
- "width": 1.2},
- {"value": "F8",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "F9",
- "width": 1.2},
- {"value": "F10",
- "width": 1.2},
- {"value": "F11",
- "width": 1.2},
- {"value": "F12",
- "width": 1.2},
- {"key_type": "dummy",
- "width": 0.4},
- {"key_type": "preferences", "width": 1.2}
- ]
- },
- {"key":[
- {"value": "º", "width": 1.2},
- {"value": "1", "width": 1.2},
- {"value": "2", "width": 1.2},
- {"value": "3", "width": 1.2},
- {"value": "4", "width": 1.2},
- {"value": "5", "width": 1.2},
- {"value": "6", "width": 1.2},
- {"value": "7", "width": 1.2},
- {"value": "8", "width": 1.2},
- {"value": "9", "width": 1.2},
- {"value": "0", "width": 1.2},
- {"value": "'", "width": 1.2},
- {"value": "¡", "width": 1.2},
- {"value": "BackSpace",
- "label": "<big>⌫</big>",
- "width": 2.4}
- ]
- },
- {"key":[
- {"label": "<b><sup>←</sup><sub>→</sub></b>",
- "value": "Tab",
- "width": 1.8},
- {"value": "q", "width": 1.2},
- {"value": "w", "width": 1.2},
- {"value": "e", "width": 1.2},
- {"value": "r", "width": 1.2},
- {"value": "t", "width": 1.2},
- {"value": "y", "width": 1.2},
- {"value": "u", "width": 1.2},
- {"value": "i", "width": 1.2},
- {"value": "o", "width": 1.2},
- {"value": "p", "width": 1.2},
- {"value": "`", "width": 1.2},
- {"value": "+", "width": 1.2},
- {"value": "Return",
- "label": "<b>↲</b>",
- "width": 1.8}
- ]
- },
- {"key":[
- {"label": "<small>Bloq M</small>",
- "value": "uppercase",
- "key_type": "layout_switcher",
- "width": 2.6},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "a", "width": 1.2},
- {"value": "s", "width": 1.2},
- {"value": "d", "width": 1.2},
- {"value": "f", "width": 1.2},
- {"value": "g", "width": 1.2},
- {"value": "h", "width": 1.2},
- {"value": "j", "width": 1.2},
- {"value": "k", "width": 1.2},
- {"value": "l", "width": 1.2},
- {"value": "ñ", "width": 1.2},
- {"value": "´", "width": 1.2},
- {"value": "ç", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.8}
- ]
- },
- {"key":[
- {"label": "<b>↑</b>",
- "key_type": "layout_switcher",
- "value": "lowercase_shift",
- "width": 1.6},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": "<",
- "label": "&lt;", "width": 1.2},
- {"value": "z", "width": 1.2},
- {"value": "x", "width": 1.2},
- {"value": "c", "width": 1.2},
- {"value": "v", "width": 1.2},
- {"value": "b", "width": 1.2},
- {"value": "n", "width": 1.2},
- {"value": "m", "width": 1.2},
- {"key_type": "dummy",
- "width": 0.2},
- {"value": ",", "width": 1.2},
- {"value": ".", "width": 1.2},
- {"value": "-", "width": 1.2},
- {"label": "<b>↑</b>",
- "key_type": "layout_switcher",
- "value": "lowercase_shift",
- "width": 2.8}
- ]
- },
- {"key":[
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_L",
- "key_type": "mask",
- "width": 1.8},
- {"label": "<small><b>Win</b></small>",
- "value": "Super_L",
- "key_type": "mask",
- "width": 1.6},
- {"label": "<small><b>Alt</b></small>",
- "value": "Alt_L",
- "key_type": "mask",
- "width": 1.6},
- {"key_type": "dummy",
- "width": 0.4},
- {"label": "______",
- "value": " ",
- "width": 7.4},
- {"key_type": "dummy",
- "width": 0.4},
- {"label": "<small><b>Alt Gr</b></small>",
- "value": "lowercase_alt",
- "key_type": "layout_switcher",
- "width": 1.6},
- {"label": "<small><b>Win</b></small>",
- "value": "Super_R",
- "key_type": "mask",
- "width": 1.6},
- {"label": "<small><b>Ctrl</b></small>",
- "value": "Control_R",
- "width": 1.6}
- ]
- }
- ]
- }
- }
-]
- }
diff --git a/data/keyboards/qwerty_ja.xml b/data/keyboards/qwerty_ja.xml
deleted file mode 100644
index 6515f15..0000000
--- a/data/keyboards/qwerty_ja.xml
+++ /dev/null
@@ -1,782 +0,0 @@
-<keyboard>
- <layout>
- <name>lowercase</name>
- <rows>
- <row>
- <key>
- <value>Escape</value>
- <label>&lt;small&gt;Esc&lt;/small&gt;</label>
- <width>1.2</width>
- </key>
- <key key_type="dummy" width="0.4"/>
- <key value="F1" width="1.2"/>
- <key value="F2" width="1.2"/>
- <key value="F3" width="1.2"/>
- <key value="F4" width="1.2"/>
- <key key_type="dummy" width="0.2"/>
- <key value="F5" width="1.2"/>
- <key value="F6" width="1.2"/>
- <key value="F7" width="1.2"/>
- <key value="F8" width="1.2"/>
- <key key_type="dummy" width="0.2"/>
- <key value="F9" width="1.2"/>
- <key value="F10" width="1.2"/>
- <key value="F11" width="1.2"/>
- <key value="F12" width="1.2"/>
- <key key_type="dummy" width="0.4"/>
- <key key_type="preferences" width="1.2"/>
- <key key_type="dummy" width="0.2" />
- <key value="Print" label="&lt;small&gt;PSc&lt;/small&gt;" width="1.2" />
- <key value="Scroll_Lock" label="&lt;small&gt;SLk&lt;/small&gt;" width="1.2" />
- <key value="Pause" label="&lt;small&gt;Pus&lt;/small&gt;" width="1.2" />
- </row>
- <row>
- <key value="Zenkaku_Hankaku" label="&lt;small&gt;半/全&lt;/small&gt;" width="1.2"/>
- <key>
- <value>1</value>
- <label>&lt;sup&gt;1&lt;/sup&gt; &lt;sub&gt;ぬ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>2</value>
- <label>&lt;sup&gt;2&lt;/sup&gt; &lt;sub&gt;ふ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>3</value>
- <label>&lt;sup&gt;3&lt;/sup&gt; &lt;sub&gt;あ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>4</value>
- <label>&lt;sup&gt;4&lt;/sup&gt; &lt;sub&gt;う&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>5</value>
- <label>&lt;sup&gt;5&lt;/sup&gt; &lt;sub&gt;え&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>6</value>
- <label>&lt;sup&gt;6&lt;/sup&gt; &lt;sub&gt;お&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>7</value>
- <label>&lt;sup&gt;7&lt;/sup&gt; &lt;sub&gt;や&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>8</value>
- <label>&lt;sup&gt;8&lt;/sup&gt; &lt;sub&gt;ゆ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>9</value>
- <label>&lt;sup&gt;9&lt;/sup&gt; &lt;sub&gt;よ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>0</value>
- <label>&lt;sup&gt;0&lt;/sup&gt; &lt;sub&gt;わ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>-</value>
- <label>&lt;sup&gt;-&lt;/sup&gt; &lt;sub&gt;ほ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>^</value>
- <label>&lt;sup&gt;^&lt;/sup&gt; &lt;sub&gt;へ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>\</value>
- <label>&lt;sup&gt;\&lt;/sup&gt; &lt;sub&gt;ー&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>BackSpace</value>
- <label>&lt;big&gt;⌫&lt;/big&gt;</label>
- <width>1.2</width>
- </key>
- <key key_type="dummy" width="0.2" />
- <key value="Insert" label="&lt;small&gt;Ins&lt;/small&gt;" width="1.2" />
- <key value="Home" label="&lt;small&gt;Hom&lt;/small&gt;" width="1.2" />
- <key value="Prior" label="&lt;small&gt;PUp&lt;/small&gt;" width="1.2" />
- </row>
- <row>
- <key>
- <value>Tab</value>
- <label>&lt;b&gt;&lt;sup&gt;←&lt;/sup&gt;&lt;sub&gt;→&lt;/sub&gt;&lt;/b&gt;</label>
- <width>1.8</width>
- </key>
- <key>
- <value>q</value>
- <label>&lt;sup&gt;q&lt;/sup&gt; &lt;sub&gt;た&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>w</value>
- <label>&lt;sup&gt;w&lt;/sup&gt; &lt;sub&gt;て&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>e</value>
- <label>&lt;sup&gt;e&lt;/sup&gt; &lt;sub&gt;い&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>r</value>
- <label>&lt;sup&gt;r&lt;/sup&gt; &lt;sub&gt;す&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>t</value>
- <label>&lt;sup&gt;t&lt;/sup&gt; &lt;sub&gt;か&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>y</value>
- <label>&lt;sup&gt;y&lt;/sup&gt; &lt;sub&gt;ん&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>u</value>
- <label>&lt;sup&gt;u&lt;/sup&gt; &lt;sub&gt;な&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>i</value>
- <label>&lt;sup&gt;i&lt;/sup&gt; &lt;sub&gt;に&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>o</value>
- <label>&lt;sup&gt;o&lt;/sup&gt; &lt;sub&gt;ら&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>p</value>
- <label>&lt;sup&gt;p&lt;/sup&gt; &lt;sub&gt;せ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>@</value>
- <label>&lt;sup&gt;@&lt;/sup&gt; &lt;sub&gt;゛&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>[</value>
- <label>&lt;sup&gt;[&lt;/sup&gt; &lt;sub&gt;゜&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>Return</value>
- <label>&lt;b&gt;↲&lt;/b&gt;</label>
- <width>1.8</width>
- </key>
- <key key_type="dummy" width="0.2" />
- <key value="Delete" label="&lt;small&gt;Del&lt;/small&gt;" width="1.2" />
- <key value="End" label="&lt;small&gt;End&lt;/small&gt;" width="1.2" />
- <key value="Next" label="&lt;small&gt;PDn&lt;/small&gt;" width="1.2" />
- </row>
- <row>
- <key>
- <value>lock</value>
- <label>&lt;small&gt;&lt;b&gt;Caps&lt;/b&gt;&lt;/small&gt;</label>
- <key_type>mask</key_type>
- <width>2.1</width>
- </key>
- <key>
- <value>a</value>
- <label>&lt;sup&gt;a&lt;/sup&gt; &lt;sub&gt;ち&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>s</value>
- <label>&lt;sup&gt;s&lt;/sup&gt; &lt;sub&gt;と&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>d</value>
- <label>&lt;sup&gt;d&lt;/sup&gt; &lt;sub&gt;し&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>f</value>
- <label>&lt;sup&gt;f&lt;/sup&gt; &lt;sub&gt;は&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>g</value>
- <label>&lt;sup&gt;g&lt;/sup&gt; &lt;sub&gt;き&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>h</value>
- <label>&lt;sup&gt;h&lt;/sup&gt; &lt;sub&gt;く&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>j</value>
- <label>&lt;sup&gt;j&lt;/sup&gt; &lt;sub&gt;ま&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>k</value>
- <label>&lt;sup&gt;k&lt;/sup&gt; &lt;sub&gt;の&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>l</value>
- <label>&lt;sup&gt;l&lt;/sup&gt; &lt;sub&gt;り&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>;</value>
- <label>&lt;sup&gt;;&lt;/sup&gt; &lt;sub&gt;れ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>:</value>
- <label>&lt;sup&gt;:&lt;/sup&gt; &lt;sub&gt;け&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>]</value>
- <label>&lt;sup&gt;]&lt;/sup&gt; &lt;sub&gt;む&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key key_type="dummy" width="1.5"/>
- <key key_type="dummy" width="3.8" />
- </row>
- <row>
- <key>
- <value>uppercase</value>
- <key_type>layout_switcher</key_type>
- <label>&lt;b&gt;↑&lt;/b&gt;Shift</label>
- <width>2.7</width>
- </key>
- <key>
- <value>z</value>
- <label>&lt;sup&gt;z&lt;/sup&gt; &lt;sub&gt;つ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>x</value>
- <label>&lt;sup&gt;x&lt;/sup&gt; &lt;sub&gt;さ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>c</value>
- <label>&lt;sup&gt;c&lt;/sup&gt; &lt;sub&gt;そ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>v</value>
- <label>&lt;sup&gt;v&lt;/sup&gt; &lt;sub&gt;ひ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>b</value>
- <label>&lt;sup&gt;b&lt;/sup&gt; &lt;sub&gt;こ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>n</value>
- <label>&lt;sup&gt;n&lt;/sup&gt; &lt;sub&gt;み&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>m</value>
- <label>&lt;sup&gt;m&lt;/sup&gt; &lt;sub&gt;も&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>,</value>
- <label>&lt;sup&gt;,&lt;/sup&gt; &lt;sub&gt;ね&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>.</value>
- <label>&lt;sup&gt;.&lt;/sup&gt; &lt;sub&gt;る&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>/</value>
- <label>&lt;sup&gt;/&lt;/sup&gt; &lt;sub&gt;め&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>\</value>
- <label>&lt;sup&gt;\&lt;/sup&gt; &lt;sub&gt;ろ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>uppercase</value>
- <key_type>layout_switcher</key_type>
- <label>&lt;b&gt;↑&lt;/b&gt;Shift</label>
- <width>2.1</width>
- </key>
- <key key_type="dummy" width="0.2" />
- <key key_type="dummy" width="1.2"/>
- <key value="Up" label="&lt;b&gt;↑&lt;/b&gt;" width="1.2" />
- <key key_type="dummy" width="1.2"/>
- </row>
- <row>
- <key>
- <value>Control_L</value>
- <label>&lt;small&gt;&lt;b&gt;Ctrl&lt;/b&gt;&lt;/small&gt;</label>
- <key_type>mask</key_type>
- <width>1.8</width>
- </key>
- <key>
- <value>Super_L</value>
- <label>&lt;small&gt;&lt;b&gt;Win&lt;/b&gt;&lt;/small&gt;</label>
- <width>1.5</width>
- </key>
- <key>
- <value>Alt_L</value>
- <label>&lt;small&gt;&lt;b&gt;Alt&lt;/b&gt;&lt;/small&gt;</label>
- <key_type>mask</key_type>
- <width>1.5</width>
- </key>
- <key>
- <value>Muhenkan</value>
- <label>&lt;small&gt;無変換&lt;/small&gt;</label>
- <width>1.8</width>
- </key>
- <key value=" " label="______" width="3.0"/>
- <key>
- <value>Henkan_Mode</value>
- <label>&lt;small&gt;変換&lt;/small&gt;</label>
- <width>1.8</width>
- </key>
- <key>
- <value>Hiragana_Katakana</value>
- <label>&lt;small&gt;かな&lt;/small&gt;</label>
- <width>1.5</width>
- </key>
- <key>
- <value>Alt_L</value>
- <label>&lt;small&gt;&lt;b&gt;Alt&lt;/b&gt;&lt;/small&gt;</label>
- <key_type>mask</key_type>
- <width>1.2</width>
- </key>
- <key>
- <value>Super_R</value>
- <label>&lt;small&gt;&lt;b&gt;Win&lt;/b&gt;&lt;/small&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>Menu</value>
- <label>&lt;small&gt;Menu&lt;/small&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>Control_L</value>
- <label>&lt;small&gt;&lt;b&gt;Ctrl&lt;/b&gt;&lt;/small&gt;</label>
- <key_type>mask</key_type>
- <width>1.5</width>
- </key>
- <key key_type="dummy" width="0.2" />
- <key value="Left" label="&lt;b&gt;←&lt;/b&gt;" width="1.2" />
- <key value="Down" label="&lt;b&gt;↓&lt;/b&gt;" width="1.2" />
- <key value="Right" label="&lt;b&gt;→&lt;/b&gt;" width="1.2" />
- </row>
- </rows>
- </layout>
- <layout>
- <name>uppercase</name>
- <rows>
- <row>
- <key>
- <value>Escape</value>
- <label>&lt;small&gt;Esc&lt;/small&gt;</label>
- <width>1.2</width>
- </key>
- <key key_type="dummy" width="0.4"/>
- <key value="F1" width="1.2"/>
- <key value="F2" width="1.2"/>
- <key value="F3" width="1.2"/>
- <key value="F4" width="1.2"/>
- <key key_type="dummy" width="0.2"/>
- <key value="F5" width="1.2"/>
- <key value="F6" width="1.2"/>
- <key value="F7" width="1.2"/>
- <key value="F8" width="1.2"/>
- <key key_type="dummy" width="0.2"/>
- <key value="F9" width="1.2"/>
- <key value="F10" width="1.2"/>
- <key value="F11" width="1.2"/>
- <key value="F12" width="1.2"/>
- <key key_type="dummy" width="0.4"/>
- <key key_type="preferences" width="1.2"/>
- <key key_type="dummy" width="0.2" />
- <key value="Print" label="&lt;small&gt;PSc&lt;/small&gt;" width="1.2" />
- <key value="Scroll_Lock" label="&lt;small&gt;SLk&lt;/small&gt;" width="1.2" />
- <key value="Pause" label="&lt;small&gt;Pus&lt;/small&gt;" width="1.2" />
- </row>
- <row>
- <key value="Zenkaku_Hankaku" label="&lt;small&gt;半/全&lt;/small&gt;" width="1.2"/>
- <key>
- <value>!</value>
- <label>&lt;sup&gt;!&lt;/sup&gt; &lt;sub&gt;ぬ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>"</value>
- <label>&lt;sup&gt;"&lt;/sup&gt; &lt;sub&gt;ふ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>#</value>
- <label>&lt;sup&gt;#&lt;/sup&gt; &lt;sub&gt;ぁ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>$</value>
- <label>&lt;sup&gt;$&lt;/sup&gt; &lt;sub&gt;ぅ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>%</value>
- <label>&lt;sup&gt;%&lt;/sup&gt; &lt;sub&gt;ぇ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>&amp;</value>
- <label>&lt;sup&gt;&amp;amp;&lt;/sup&gt; &lt;sub&gt;ぉ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>'</value>
- <label>&lt;sup&gt;'&lt;/sup&gt; &lt;sub&gt;ゃ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>(</value>
- <label>&lt;sup&gt;(&lt;/sup&gt; &lt;sub&gt;ゅ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>)</value>
- <label>&lt;sup&gt;)&lt;/sup&gt; &lt;sub&gt;ょ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>~</value>
- <label>&lt;sup&gt; &lt;/sup&gt; &lt;sub&gt;を&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>=</value>
- <label>&lt;sup&gt;=&lt;/sup&gt; &lt;sub&gt;ほ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>~</value>
- <label>&lt;sup&gt;~&lt;/sup&gt; &lt;sub&gt; &lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>|</value>
- <label>&lt;sup&gt;|&lt;/sup&gt; &lt;sub&gt; &lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>BackSpace</value>
- <label>&lt;big&gt;⌫&lt;/big&gt;</label>
- <width>1.2</width>
- </key>
- <key key_type="dummy" width="0.2" />
- <key value="Insert" label="&lt;small&gt;Ins&lt;/small&gt;" width="1.2" />
- <key value="Home" label="&lt;small&gt;Hom&lt;/small&gt;" width="1.2" />
- <key value="Prior" label="&lt;small&gt;PUp&lt;/small&gt;" width="1.2" />
- </row>
- <row>
- <key>
- <value>Tab</value>
- <label>&lt;b&gt;&lt;sup&gt;←&lt;/sup&gt;&lt;sub&gt;→&lt;/sub&gt;&lt;/b&gt;</label>
- <width>1.8</width>
- </key>
- <key>
- <value>Q</value>
- <label>&lt;sup&gt;Q&lt;/sup&gt; &lt;sub&gt;た&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>W</value>
- <label>&lt;sup&gt;W&lt;/sup&gt; &lt;sub&gt;て&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>E</value>
- <label>&lt;sup&gt;E&lt;/sup&gt; &lt;sub&gt;ぃ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>R</value>
- <label>&lt;sup&gt;R&lt;/sup&gt; &lt;sub&gt;す&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>T</value>
- <label>&lt;sup&gt;T&lt;/sup&gt; &lt;sub&gt;か&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>Y</value>
- <label>&lt;sup&gt;Y&lt;/sup&gt; &lt;sub&gt;ん&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>U</value>
- <label>&lt;sup&gt;U&lt;/sup&gt; &lt;sub&gt;な&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>I</value>
- <label>&lt;sup&gt;I&lt;/sup&gt; &lt;sub&gt;に&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>O</value>
- <label>&lt;sup&gt;O&lt;/sup&gt; &lt;sub&gt;ら&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>P</value>
- <label>&lt;sup&gt;P&lt;/sup&gt; &lt;sub&gt;せ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>`</value>
- <label>&lt;sup&gt;`&lt;/sup&gt; &lt;sub&gt;゛&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>{</value>
- <label>&lt;sup&gt;{&lt;/sup&gt; &lt;sub&gt;「&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>Return</value>
- <label>&lt;b&gt;↲&lt;/b&gt;</label>
- <width>1.8</width>
- </key>
- <key key_type="dummy" width="0.2" />
- <key value="Delete" label="&lt;small&gt;Del&lt;/small&gt;" width="1.2" />
- <key value="End" label="&lt;small&gt;End&lt;/small&gt;" width="1.2" />
- <key value="Next" label="&lt;small&gt;PDn&lt;/small&gt;" width="1.2" />
- </row>
- <row>
- <key>
- <value>lock</value>
- <label>&lt;small&gt;&lt;b&gt;Caps&lt;/b&gt;&lt;/small&gt;</label>
- <key_type>mask</key_type>
- <width>2.1</width>
- </key>
- <key>
- <value>A</value>
- <label>&lt;sup&gt;A&lt;/sup&gt; &lt;sub&gt;ち&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>S</value>
- <label>&lt;sup&gt;S&lt;/sup&gt; &lt;sub&gt;と&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>D</value>
- <label>&lt;sup&gt;D&lt;/sup&gt; &lt;sub&gt;し&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>F</value>
- <label>&lt;sup&gt;F&lt;/sup&gt; &lt;sub&gt;は&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>G</value>
- <label>&lt;sup&gt;G&lt;/sup&gt; &lt;sub&gt;き&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>H</value>
- <label>&lt;sup&gt;H&lt;/sup&gt; &lt;sub&gt;く&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>J</value>
- <label>&lt;sup&gt;J&lt;/sup&gt; &lt;sub&gt;ま&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>K</value>
- <label>&lt;sup&gt;K&lt;/sup&gt; &lt;sub&gt;の&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>L</value>
- <label>&lt;sup&gt;L&lt;/sup&gt; &lt;sub&gt;り&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>+</value>
- <label>&lt;sup&gt;+&lt;/sup&gt; &lt;sub&gt;れ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>*</value>
- <label>&lt;sup&gt;*&lt;/sup&gt; &lt;sub&gt; &lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>}</value>
- <label>&lt;sup&gt;}&lt;/sup&gt; &lt;sub&gt;」&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key key_type="dummy" width="1.5"/>
- <key key_type="dummy" width="3.8" />
- </row>
- <row>
- <key>
- <value>lowercase</value>
- <label>&lt;b&gt;↓&lt;/b&gt;Shift</label>
- <key_type>layout_switcher</key_type>
- <width>2.7</width>
- </key>
- <key>
- <value>Z</value>
- <label>&lt;sup&gt;Z&lt;/sup&gt; &lt;sub&gt;っ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>X</value>
- <label>&lt;sup&gt;X&lt;/sup&gt; &lt;sub&gt;さ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>C</value>
- <label>&lt;sup&gt;C&lt;/sup&gt; &lt;sub&gt;そ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>V</value>
- <label>&lt;sup&gt;V&lt;/sup&gt; &lt;sub&gt;ひ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>B</value>
- <label>&lt;sup&gt;B&lt;/sup&gt; &lt;sub&gt;こ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>N</value>
- <label>&lt;sup&gt;N&lt;/sup&gt; &lt;sub&gt;み&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>M</value>
- <label>&lt;sup&gt;M&lt;/sup&gt; &lt;sub&gt;も&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>&lt;</value>
- <label>&lt;sup&gt;&amp;lt;&lt;/sup&gt; &lt;sub&gt;、&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>&gt;</value>
- <label>&lt;sup&gt;&amp;gt;&lt;/sup&gt; &lt;sub&gt;。&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>?</value>
- <label>&lt;sup&gt;?&lt;/sup&gt; &lt;sub&gt;・&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>_</value>
- <label>&lt;sup&gt;_&lt;/sup&gt; &lt;sub&gt;ろ&lt;/sub&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>lowercase</value>
- <label>&lt;b&gt;↓&lt;/b&gt;Shift</label>
- <key_type>layout_switcher</key_type>
- <width>2.1</width>
- </key>
- <key key_type="dummy" width="0.2" />
- <key key_type="dummy" width="1.2"/>
- <key value="Up" label="&lt;b&gt;↑&lt;/b&gt;" width="1.2" />
- <key key_type="dummy" width="1.2"/>
- </row>
- <row>
- <key>
- <value>Control_L</value>
- <label>&lt;small&gt;&lt;b&gt;Ctrl&lt;/b&gt;&lt;/small&gt;</label>
- <key_type>mask</key_type>
- <width>1.8</width>
- </key>
- <key>
- <value>Super_L</value>
- <label>&lt;small&gt;&lt;b&gt;Win&lt;/b&gt;&lt;/small&gt;</label>
- <width>1.5</width>
- </key>
- <key>
- <value>Alt_L</value>
- <label>&lt;small&gt;&lt;b&gt;Alt&lt;/b&gt;&lt;/small&gt;</label>
- <key_type>mask</key_type>
- <width>1.5</width>
- </key>
- <key>
- <value>Muhenkan</value>
- <label>&lt;small&gt;無変換&lt;/small&gt;</label>
- <width>1.8</width>
- </key>
- <key value=" " label="______" width="3"/>
- <key>
- <value>Henkan_Mode</value>
- <label>&lt;small&gt;変換&lt;/small&gt;</label>
- <width>1.8</width>
- </key>
- <key>
- <value>Hiragana_Katakana</value>
- <label>&lt;small&gt;かな&lt;/small&gt;</label>
- <width>1.5</width>
- </key>
- <key>
- <value>Alt_L</value>
- <label>&lt;small&gt;&lt;b&gt;Alt&lt;/b&gt;&lt;/small&gt;</label>
- <key_type>mask</key_type>
- <width>1.2</width>
- </key>
- <key>
- <value>Super_R</value>
- <label>&lt;small&gt;&lt;b&gt;Win&lt;/b&gt;&lt;/small&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>Menu</value>
- <label>&lt;small&gt;Menu&lt;/small&gt;</label>
- <width>1.2</width>
- </key>
- <key>
- <value>Control_L</value>
- <label>&lt;small&gt;&lt;b&gt;Ctrl&lt;/b&gt;&lt;/small&gt;</label>
- <key_type>mask</key_type>
- <width>1.5</width>
- </key>
- <key key_type="dummy" width="0.2" />
- <key value="Left" label="&lt;b&gt;←&lt;/b&gt;" width="1.2" />
- <key value="Down" label="&lt;b&gt;↓&lt;/b&gt;" width="1.2" />
- <key value="Right" label="&lt;b&gt;→&lt;/b&gt;" width="1.2" />
- </row>
- </rows>
- </layout>
-</keyboard>
diff --git a/data/layouts/Makefile.am b/data/layouts/Makefile.am
new file mode 100644
index 0000000..9d82efe
--- /dev/null
+++ b/data/layouts/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = touch
diff --git a/data/layouts/touch/Makefile.am b/data/layouts/touch/Makefile.am
new file mode 100644
index 0000000..f18d728
--- /dev/null
+++ b/data/layouts/touch/Makefile.am
@@ -0,0 +1,8 @@
+touchlayoutsdir = $(datadir)/caribou/layouts/touch
+
+touchlayouts_DATA = \
+ ara.json \
+ il.json \
+ us.json
+
+EXTRA_DIST = $(touchlayouts_DATA)
diff --git a/data/layouts/touch/ara.json b/data/layouts/touch/ara.json
new file mode 100644
index 0000000..e757ee9
--- /dev/null
+++ b/data/layouts/touch/ara.json
@@ -0,0 +1,122 @@
+{
+ "level1" : {
+ "mode" : "default",
+ "rows" : [
+ [{"name" : "Arabic_dad"},
+ {"name" : "Arabic_sad"},
+ {"name" : "Arabic_qaf"},
+ {"name" : "Arabic_feh"},
+ {"name" : "Arabic_ghain"},
+ {"name" : "Arabic_ain"},
+ {"name" : "Arabic_ha"},
+ {"name" : "Arabic_khah"},
+ {"name" : "Arabic_hah"},
+ {"name" : "Arabic_jeem"},
+ {"name" : "BackSpace"}],
+ [{"name" : "Arabic_sheen", "margin_left" : 0.5},
+ {"name" : "Arabic_seen"},
+ {"name" : "Arabic_yeh"},
+ {"name" : "Arabic_beh"},
+ {"name" : "Arabic_lam"},
+ {"name" : "Arabic_alef"},
+ {"name" : "Arabic_teh"},
+ {"name" : "Arabic_noon"},
+ {"name" : "Arabic_meem"},
+ {"name" : "Arabic_kaf"}],
+ [{"name" : "Arabic_zah"},
+ {"name" : "Arabic_tah"},
+ {"name" : "Arabic_thal"},
+ {"name" : "Arabic_dal"},
+ {"name" : "Arabic_zain"},
+ {"name" : "Arabic_ra"},
+ {"name" : "Arabic_waw"},
+ {"name" : "Arabic_tehmarbuta"},
+ {"name" : "Arabic_theh"},
+ {"name" : "Return", "width" : 2.0}],
+ [{"name" : "Caribou_Symbols", "width" : 2.0, "toggle" : "symbols1"},
+ {"name" : "Arabic_fathatan"},
+ {"name" : "space", "width" : 5.0},
+ {"name" : "Caribou_Prefs", "margin_left" : 2.0}]
+ ]
+ },
+ "symbols1" : {
+ "mode" : "locked",
+ "rows" : [
+ [{"name" : "Arabic_1"},
+ {"name" : "Arabic_2"},
+ {"name" : "Arabic_3"},
+ {"name" : "Arabic_4"},
+ {"name" : "Arabic_5"},
+ {"name" : "Arabic_6"},
+ {"name" : "Arabic_7"},
+ {"name" : "Arabic_8"},
+ {"name" : "Arabic_9"},
+ {"name" : "Arabic_0"},
+ {"name" : "BackSpace"}],
+ [{"name" : "minus", "margin_left" : 0.5},
+ {"name" : "slash"},
+ {"name" : "colon"},
+ {"name" : "Arabic_semicolon"},
+ {"name" : "parenleft"},
+ {"name" : "parenright"},
+ {"name" : "dollar"},
+ {"name" : "ampersand"},
+ {"name" : "at"},
+ {"name" : "Return", "width" : 1.5}],
+ [{"name" : "Caribou_Symbols_More", "width" : 2.0, "toggle" : "symbols2"},
+ {"name" : "period"},
+ {"name" : "Arabic_comma"},
+ {"name" : "Arabic_question_mark"},
+ {"name" : "slash"},
+ {"name" : "exclam"},
+ {"name" : "apostrophe"},
+ {"name" : "quotedbl"},
+ {"name" : "bar"},
+ {"name" : "numbersign"}],
+ [{"name" : "Caribou_Alpha", "width" : 2.0, "toggle" : "default"},
+ {"name" : "Caribou_Emoticons"},
+ {"name" : "space", "width" : 5.0},
+ {"name" : "Caribou_Prefs", "margin_left" : 2.0}]
+ ]
+ },
+ "symbols2" : {
+ "mode" : "locked",
+ "rows" : [
+ [{"name" : "Arabic_percent"},
+ {"name" : "bracketleft"},
+ {"name" : "bracketright"},
+ {"name" : "braceleft"},
+ {"name" : "braceright"},
+ {"name" : "backslash"},
+ {"name" : "plus"},
+ {"name" : "equal"},
+ {"name" : "grave"},
+ {"name" : "underscore"},
+ {"name" : "BackSpace"}],
+ [{"name" : "less", "margin_left" : 0.5},
+ {"name" : "greater"},
+ {"name" : "asterisk"},
+ {"name" : "semicolon"},
+ {"name" : "parenleft"},
+ {"name" : "parenright"},
+ {"name" : "dollar"},
+ {"name" : "ampersand"},
+ {"name" : "at"},
+ {"name" : "Return", "width" : 1.5}],
+ [{"name" : "Caribou_Symbols", "width" : 2.0, "toggle" : "symbols1"},
+ {"name" : "period"},
+ {"name" : "comma"},
+ {"name" : "question"},
+ {"name" : "slash"},
+ {"name" : "exclam"},
+ {"name" : "apostrophe"},
+ {"name" : "quotedbl"},
+ {"name" : "bar"},
+ {"name" : "numbersign"}],
+ [{"name" : "Caribou_Alpha", "width" : 2.0, "toggle" : "default"},
+ {"name" : "Caribou_Emoticons"},
+ {"name" : "space", "width" : 5.0},
+ {"name" : "Caribou_Prefs", "margin_left" : 2.0}]
+ ]
+ }
+}
diff --git a/data/layouts/touch/il.json b/data/layouts/touch/il.json
new file mode 100644
index 0000000..b0939ed
--- /dev/null
+++ b/data/layouts/touch/il.json
@@ -0,0 +1,122 @@
+{
+ "level1" : {
+ "mode" : "default",
+ "rows" : [
+ [{"name" : "period"},
+ {"name" : "comma"},
+ {"name" : "hebrew_qoph"},
+ {"name" : "hebrew_resh"},
+ {"name" : "hebrew_aleph"},
+ {"name" : "hebrew_tet"},
+ {"name" : "hebrew_waw"},
+ {"name" : "hebrew_finalnun"},
+ {"name" : "hebrew_finalmem"},
+ {"name" : "hebrew_pe"},
+ {"name" : "BackSpace"}],
+ [{"name" : "hebrew_shin", "margin_left" : 0.5},
+ {"name" : "hebrew_dalet"},
+ {"name" : "hebrew_gimel"},
+ {"name" : "hebrew_kaph"},
+ {"name" : "hebrew_ayin"},
+ {"name" : "hebrew_yod"},
+ {"name" : "hebrew_chet"},
+ {"name" : "hebrew_lamed"},
+ {"name" : "hebrew_finalkaph"},
+ {"name" : "hebrew_finalpe"}],
+ [{"name" : "hebrew_zain"},
+ {"name" : "hebrew_samech"},
+ {"name" : "hebrew_bet"},
+ {"name" : "hebrew_he"},
+ {"name" : "hebrew_nun"},
+ {"name" : "hebrew_mem"},
+ {"name" : "hebrew_zade"},
+ {"name" : "hebrew_taw"},
+ {"name" : "hebrew_finalzade"},
+ {"name" : "Return", "width" : 2.0}],
+ [{"name" : "Caribou_Symbols", "width" : 2.0, "toggle" : "symbols1"},
+ {"name" : "Caribou_Emoticons"},
+ {"name" : "space", "width" : 5.0},
+ {"name" : "Caribou_Prefs", "margin_left" : 2.0}]
+ ]
+ },
+ "symbols1" : {
+ "mode" : "locked",
+ "rows" : [
+ [{"name" : "1"},
+ {"name" : "2"},
+ {"name" : "3"},
+ {"name" : "4"},
+ {"name" : "5"},
+ {"name" : "6"},
+ {"name" : "7"},
+ {"name" : "8"},
+ {"name" : "9"},
+ {"name" : "0"},
+ {"name" : "BackSpace"}],
+ [{"name" : "minus", "margin_left" : 0.5},
+ {"name" : "slash"},
+ {"name" : "colon"},
+ {"name" : "semicolon"},
+ {"name" : "parenleft"},
+ {"name" : "parenright"},
+ {"name" : "dollar"},
+ {"name" : "ampersand"},
+ {"name" : "at"},
+ {"name" : "Return", "width" : 1.5}],
+ [{"name" : "Caribou_Symbols_More", "width" : 2.0, "toggle" : "symbols2"},
+ {"name" : "period"},
+ {"name" : "comma"},
+ {"name" : "question"},
+ {"name" : "slash"},
+ {"name" : "exclam"},
+ {"name" : "apostrophe"},
+ {"name" : "quotedbl"},
+ {"name" : "bar"},
+ {"name" : "numbersign"}],
+ [{"name" : "Caribou_Alpha", "width" : 2.0, "toggle" : "default"},
+ {"name" : "Caribou_Emoticons"},
+ {"name" : "space", "width" : 5.0},
+ {"name" : "Caribou_Prefs", "margin_left" : 2.0}]
+ ]
+ },
+ "symbols2" : {
+ "mode" : "locked",
+ "rows" : [
+ [{"name" : "percent"},
+ {"name" : "bracketleft"},
+ {"name" : "bracketright"},
+ {"name" : "braceleft"},
+ {"name" : "braceright"},
+ {"name" : "backslash"},
+ {"name" : "plus"},
+ {"name" : "equal"},
+ {"name" : "grave"},
+ {"name" : "underscore"},
+ {"name" : "BackSpace"}],
+ [{"name" : "less", "margin_left" : 0.5},
+ {"name" : "greater"},
+ {"name" : "asterisk"},
+ {"name" : "semicolon"},
+ {"name" : "parenleft"},
+ {"name" : "parenright"},
+ {"name" : "dollar"},
+ {"name" : "ampersand"},
+ {"name" : "at"},
+ {"name" : "Return", "width" : 1.5}],
+ [{"name" : "Caribou_Symbols", "width" : 2.0, "toggle" : "symbols1"},
+ {"name" : "period"},
+ {"name" : "comma"},
+ {"name" : "question"},
+ {"name" : "slash"},
+ {"name" : "exclam"},
+ {"name" : "apostrophe"},
+ {"name" : "quotedbl"},
+ {"name" : "bar"},
+ {"name" : "numbersign"}],
+ [{"name" : "Caribou_Alpha", "width" : 2.0, "toggle" : "default"},
+ {"name" : "Caribou_Emoticons"},
+ {"name" : "space", "width" : 5.0},
+ {"name" : "Caribou_Prefs", "margin_left" : 2.0}]
+ ]
+ }
+}
diff --git a/data/layouts/touch/us.json b/data/layouts/touch/us.json
new file mode 100644
index 0000000..20fcf04
--- /dev/null
+++ b/data/layouts/touch/us.json
@@ -0,0 +1,212 @@
+{
+ "level1" : {
+ "mode" : "default",
+ "rows" : [
+ [{"name" : "q"},
+ {"name" : "w"},
+ {"name" : "e", "extended_names" : ["egrave",
+ "eacute",
+ "ecircumflex",
+ "ediaeresis",
+ "emacron"]},
+ {"name" : "r"},
+ {"name" : "t"},
+ {"name" : "y"},
+ {"name" : "u", "extended_names" : ["ugrave",
+ "uacute",
+ "ucircumflex",
+ "udiaeresis",
+ "umacron"]},
+ {"name" : "i", "extended_names" : ["igrave",
+ "iacute",
+ "icircumflex",
+ "idiaeresis",
+ "imacron"]},
+ {"name" : "o", "extended_names" : ["ograve",
+ "oacute",
+ "ocircumflex",
+ "odiaeresis",
+ "omacron"]},
+ {"name" : "p"},
+ {"name" : "BackSpace"}],
+ [{"name" : "a", "extended_names" : ["agrave",
+ "aacute",
+ "acircumflex",
+ "adiaeresis",
+ "aring",
+ "atilde",
+ "ae",
+ "amacron"],
+ "margin_left" : 0.5},
+ {"name" : "s"},
+ {"name" : "d"},
+ {"name" : "f"},
+ {"name" : "g"},
+ {"name" : "h"},
+ {"name" : "j"},
+ {"name" : "k"},
+ {"name" : "l"},
+ {"name" : "Return", "width" : 1.5}],
+ [{"name" : "Caribou_ShiftUp", "toggle" : "level2"},
+ {"name" : "z"},
+ {"name" : "x"},
+ {"name" : "c", "extended_names" : ["ccedilla"]},
+ {"name" : "v"},
+ {"name" : "b"},
+ {"name" : "n"},
+ {"name" : "m"},
+ {"name" : "comma"},
+ {"name" : "period"},
+ {"name" : "question"}],
+ [{"name" : "Caribou_Symbols", "width" : 2.0, "toggle" : "symbols1"},
+ {"name" : "Caribou_Emoticons"},
+ {"name" : "space", "width" : 5.0},
+ {"name" : "Caribou_Prefs", "margin_left" : 2.0}]
+ ]
+ },
+ "level2" : {
+ "mode" : "latched",
+ "rows" : [
+ [{"name" : "Q"},
+ {"name" : "W"},
+ {"name" : "E", "extended_names" : ["Egrave",
+ "Eacute",
+ "Ecircumflex",
+ "Ediaeresis",
+ "Emacron"]},
+ {"name" : "R"},
+ {"name" : "T"},
+ {"name" : "Y"},
+ {"name" : "U", "extended_names" : ["Ugrave",
+ "Uacute",
+ "Ucircumflex",
+ "Udiaeresis",
+ "Umacron"]},
+ {"name" : "I", "extended_names" : ["Igrave",
+ "Iacute",
+ "Icircumflex",
+ "Idiaeresis",
+ "Imacron"]},
+ {"name" : "O", "extended_names" : ["Ograve",
+ "Oacute",
+ "Ocircumflex",
+ "Odiaeresis",
+ "Omacron"]},
+ {"name" : "P"},
+ {"name" : "BackSpace"}],
+ [{"name" : "A", "extended_names" : ["Agrave",
+ "Aacute",
+ "Acircumflex",
+ "Adiaeresis",
+ "Aring",
+ "Atilde",
+ "Ae",
+ "Amacron"],
+ "margin_left" : 0.5},
+ {"name" : "S"},
+ {"name" : "D"},
+ {"name" : "F"},
+ {"name" : "G"},
+ {"name" : "H"},
+ {"name" : "J"},
+ {"name" : "K"},
+ {"name" : "L"},
+ {"name" : "Return", "width" : 1.5}],
+ [{"name" : "Caribou_ShiftDown", "toggle" : "level1"},
+ {"name" : "Z"},
+ {"name" : "X"},
+ {"name" : "C", "extended_names" : ["Ccedilla"]},
+ {"name" : "V"},
+ {"name" : "B"},
+ {"name" : "N"},
+ {"name" : "M"},
+ {"name" : "comma"},
+ {"name" : "period"},
+ {"name" : "question"}],
+ [{"name" : "Caribou_Symbols", "width" : 2.0, "toggle" : "default"},
+ {"name" : "Caribou_Emoticons"},
+ {"name" : "space", "width" : 5.0},
+ {"name" : "Caribou_Prefs", "margin_left" : 2.0}]
+ ]
+ },
+ "symbols1" : {
+ "mode" : "locked",
+ "rows" : [
+ [{"name" : "1"},
+ {"name" : "2"},
+ {"name" : "3"},
+ {"name" : "4"},
+ {"name" : "5"},
+ {"name" : "6"},
+ {"name" : "7"},
+ {"name" : "8"},
+ {"name" : "9"},
+ {"name" : "0"},
+ {"name" : "BackSpace"}],
+ [{"name" : "minus", "margin_left" : 0.5},
+ {"name" : "slash"},
+ {"name" : "colon"},
+ {"name" : "semicolon"},
+ {"name" : "parenleft"},
+ {"name" : "parenright"},
+ {"name" : "dollar"},
+ {"name" : "ampersand"},
+ {"name" : "at"},
+ {"name" : "Return", "width" : 1.5}],
+ [{"name" : "Caribou_Symbols_More", "width" : 2.0, "toggle" : "symbols2"},
+ {"name" : "period"},
+ {"name" : "comma"},
+ {"name" : "question", "extended_names" : ["questiondown"]},
+ {"name" : "slash"},
+ {"name" : "exclam", "extended_names" : ["exclamdown"]},
+ {"name" : "apostrophe"},
+ {"name" : "quotedbl"},
+ {"name" : "bar"},
+ {"name" : "numbersign"}],
+ [{"name" : "Caribou_Alpha", "width" : 2.0, "toggle" : "default"},
+ {"name" : "Caribou_Emoticons"},
+ {"name" : "space", "width" : 5.0},
+ {"name" : "Caribou_Prefs", "margin_left" : 2.0}]
+ ]
+ },
+ "symbols2" : {
+ "mode" : "locked",
+ "rows" : [
+ [{"name" : "percent"},
+ {"name" : "bracketleft"},
+ {"name" : "bracketright"},
+ {"name" : "braceleft"},
+ {"name" : "braceright"},
+ {"name" : "backslash"},
+ {"name" : "plus"},
+ {"name" : "equal"},
+ {"name" : "grave"},
+ {"name" : "underscore"},
+ {"name" : "BackSpace"}],
+ [{"name" : "less", "margin_left" : 0.5},
+ {"name" : "greater"},
+ {"name" : "asterisk"},
+ {"name" : "semicolon"},
+ {"name" : "parenleft"},
+ {"name" : "parenright"},
+ {"name" : "dollar"},
+ {"name" : "ampersand"},
+ {"name" : "at"},
+ {"name" : "Return", "width" : 1.5}],
+ [{"name" : "Caribou_Symbols", "width" : 2.0, "toggle" : "symbols1"},
+ {"name" : "period"},
+ {"name" : "comma"},
+ {"name" : "question"},
+ {"name" : "slash"},
+ {"name" : "exclam"},
+ {"name" : "apostrophe"},
+ {"name" : "quotedbl"},
+ {"name" : "bar"},
+ {"name" : "numbersign"}],
+ [{"name" : "Caribou_Alpha", "width" : 2.0, "toggle" : "default"},
+ {"name" : "Caribou_Emoticons"},
+ {"name" : "space", "width" : 5.0},
+ {"name" : "Caribou_Prefs", "margin_left" : 2.0}]
+ ]
+ }
+}
diff --git a/data/org.gnome.Caribou.Antler.service.in b/data/org.gnome.Caribou.Antler.service.in
new file mode 100644
index 0000000..fd85a4e
--- /dev/null
+++ b/data/org.gnome.Caribou.Antler.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.gnome.Caribou.Antler
+Exec=@libexecdir@/antler-keyboard
diff --git a/libcaribou/Makefile.am b/libcaribou/Makefile.am
index c7f7a0a..9e157e9 100644
--- a/libcaribou/Makefile.am
+++ b/libcaribou/Makefile.am
@@ -1,93 +1,73 @@
-INCLUDES = \
- -DG_LOG_DOMAIN=\"libcaribou\" \
- -I$(top_srcdir) \
- $(LIBCARIBOU_CFLAGS)
-
-
-MARSHAL_GENERATED = caribou-marshal.c caribou-marshal.h
-MKENUMS_GENERATED = caribou-enum-types.c caribou-enum-types.h
-
-caribou-marshal.h: caribou-marshal.list
- $(AM_V_GEN) ( $(GLIB_GENMARSHAL) --prefix=caribou_marshal $(srcdir)/caribou-marshal.list --header > caribou-marshal.tmp \
- && mv caribou-marshal.tmp caribou-marshal.h ) \
- || ( rm -f caribou-marshal.tmp && exit 1 )
-
-caribou-marshal.c: caribou-marshal.h
- $(AM_V_GEN) ( (echo '#include "caribou-marshal.h"'; $(GLIB_GENMARSHAL) --prefix=caribou_marshal $(srcdir)/caribou-marshal.list --body) > caribou-marshal.tmp \
- && mv caribou-marshal.tmp caribou-marshal.c ) \
- || ( rm -f caribou-marshal.tmp && exit 1 )
-
-caribou-enum-types.h: $(caribou_headers)
- $(AM_V_GEN) ( cd $(srcdir) && $(GLIB_MKENUMS) --template caribou-enum-types.h.tmpl \
- $(caribou_headers) ) > caribou-enum-types.h.tmp \
- && mv caribou-enum-types.h.tmp caribou-enum-types.h \
- || rm -f caribou-enum-type.h.tmp
+lib_LTLIBRARIES = libcaribou.la
-caribou-enum-types.c: $(libcaribouinclude_HEADERS)
- $(AM_V_GEN) ( cd $(srcdir) && $(GLIB_MKENUMS) --template caribou-enum-types.c.tmpl \
- $(caribou_headers) ) > caribou-enum-types.c.tmp \
- && mv caribou-enum-types.c.tmp caribou-enum-types.c \
- || rm -f caribou-enum-type.c.tmp
+INCLUDES = \
+ -DG_LOG_DOMAIN=\"caribou\" \
+ -I$(top_srcdir) \
+ $(LIBCARIBOU_CFLAGS)
-BUILT_SOURCES = $(MARSHAL_GENERATED) $(MKENUMS_GENERATED)
+libcaribou_la_VALAFLAGS = \
+ -H caribou.h --vapi caribou-1.0.vapi \
+ -h caribou-internals.h \
+ --vapidir=. \
+ --pkg x11 --pkg json-glib-1.0 --pkg gdk-3.0 --pkg gio-2.0 \
+ --pkg libxklavier --pkg external-libs --pkg gdk-x11-3.0 \
+ --internal-vapi caribou-internals-1.0.vapi \
+ --library caribou-1.0 --gir _Caribou-1.0.gir \
+ $(VALAFLAGS)
-CLEANFILES = $(MARSHAL_GENERATED) $(MKENUMS_GENERATED)
+libcaribou_la_CPPFLAGS = \
+ $(INCLUDES)
libcaribouincludedir = $(includedir)/libcaribou
-caribou_headers = \
- caribou.h \
- caribou-virtual-keyboard.h
-
-libcaribouinclude_HEADERS = \
- $(caribou_headers) \
- caribou-enum-types.h
+caribouinclude_headers = \
+ caribou.h
-lib_LTLIBRARIES = libcaribou.la
+libcaribouinclude_HEADERS = \
+ $(caribou_headers)
libcaribou_la_LIBADD = \
$(LIBCARIBOU_LIBS)
-libcaribou_la_SOURCES = \
- $(BUILT_SOURCES) \
- caribou-virtual-keyboard.c
+libcaribou_la_SOURCES = \
+ xadapter.vala \
+ keyboard-model.vala \
+ keyboard-service.vala \
+ group-model.vala \
+ level-model.vala \
+ row-model.vala \
+ key-model.vala \
+ util.vala \
+ json-deserializer.vala
+
+EXTRA_DIST = \
+ external-libs.vapi \
+ libxklavier.vapi
#
# Introspection support
#
-include $(INTROSPECTION_MAKEFILE)
-INTROSPECTION_GIRS =
-INTROSPECTION_SCANNER_ARGS = --add-include-path=.
-INTROSPECTION_COMPILER_ARGS = --includedir=.
if HAVE_INTROSPECTION
+girdir = $(datadir)/gir-1.0
+gir_DATA = Caribou-1.0.gir
-gi_caribou_files = \
- $(filter-out caribou.h caribou-enum-types.% caribou-marshal.h,\
- $(caribou_headers) $(filter-out %.h, $(libcaribou_la_SOURCES)))
-# gi_built_caribou_files = caribou-enum-types.h
-
-Caribou-1.0.gir: libcaribou.la
-Caribou_1_0_gir_INCLUDES = Gdk-3.0
-Caribou_1_0_gir_CFLAGS = $(INCLUDES)
-Caribou_1_0_gir_LIBS = libcaribou.la
-Caribou_1_0_gir_EXPORT_PACKAGES = libcaribou
-Caribou_1_0_gir_SCANNERFLAGS = --c-include "libcaribou/caribou.h"
-Caribou_1_0_gir_FILES = \
- $(addprefix $(srcdir)/, $(gi_caribou_files)) \
- $(foreach f,$(gi_built_caribou_files), \
- $(if $(shell test -f $(addprefix $(srcdir)/,$(f)) && echo yes), \
- $(addprefix $(srcdir)/,$(f)), \
- $(f)))
-
-INTROSPECTION_GIRS += Caribou-1.0.gir
+typelibdir = $(libdir)/girepository-1.0
+typelib_DATA = Caribou-1.0.typelib
-girdir = $(datadir)/gir-1.0
-gir_DATA = $(INTROSPECTION_GIRS)
+Caribou-1.0.gir: _Caribou-1.0.gir
+ $(top_srcdir)/tools/fix_gir.py $< > $@
-typelibsdir = $(libdir)/girepository-1.0
-typelibs_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
+Caribou-1.0.typelib: Caribou-1.0.gir
+ @INTROSPECTION_COMPILER@ --shared-library=libcaribou -o $@ $^
+endif
-CLEANFILES += $(gir_DATA) $(typelibs_DATA)
+Caribou-1.0.gir caribou-internals-1.0.vapi caribou-1.0.vapi: libcaribou.la
-endif \ No newline at end of file
+CLEANFILES = \
+ caribou-1.0.vapi \
+ caribou-internals-1.0.vapi \
+ Caribou-1.0.typelib \
+ Caribou-1.0.gir \
+ _Caribou-1.0.gir \
+ *.[ch] \ No newline at end of file
diff --git a/libcaribou/caribou-enum-types.h.tmpl b/libcaribou/caribou-enum-types.h.tmpl
deleted file mode 100644
index e69de29..0000000
--- a/libcaribou/caribou-enum-types.h.tmpl
+++ /dev/null
diff --git a/libcaribou/caribou-marshal.list b/libcaribou/caribou-marshal.list
deleted file mode 100644
index fa33740..0000000
--- a/libcaribou/caribou-marshal.list
+++ /dev/null
@@ -1 +0,0 @@
-NONE:NONE
diff --git a/libcaribou/caribou-virtual-keyboard.c b/libcaribou/caribou-virtual-keyboard.c
deleted file mode 100644
index 50846f8..0000000
--- a/libcaribou/caribou-virtual-keyboard.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2011, Eitan Isaacson <eitan@monotonous.org>
- */
-
-#include "caribou-virtual-keyboard.h"
-#include "caribou-marshal.h"
-#include <X11/Xlib.h>
-#include <X11/extensions/XTest.h>
-#include <gdk/gdk.h>
-#include <gdk/gdkx.h>
-#include <X11/XKBlib.h>
-
-struct _CaribouVirtualKeyboardPrivate {
- GdkDisplay *display;
-};
-
-G_DEFINE_TYPE (CaribouVirtualKeyboard, caribou_virtual_keyboard, G_TYPE_OBJECT)
-
-enum {
- PLACEHOLDER,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-static void
-dispose (GObject *object)
-{
- CaribouVirtualKeyboard *self = CARIBOU_VIRTUAL_KEYBOARD (object);
-
- G_OBJECT_CLASS (caribou_virtual_keyboard_parent_class)->dispose (object);
-}
-
-static void
-caribou_virtual_keyboard_init (CaribouVirtualKeyboard *self)
-{
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), CARIBOU_TYPE_VIRTUAL_KEYBOARD,
- CaribouVirtualKeyboardPrivate);
-
- self->priv->display = gdk_display_get_default ();
-}
-
-static void
-caribou_virtual_keyboard_class_init (CaribouVirtualKeyboardClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (CaribouVirtualKeyboardPrivate));
-
- /* virtual method override */
- object_class->dispose = dispose;
-
- /* signals */
- signals[PLACEHOLDER] =
- g_signal_new ("placeholder",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL, NULL,
- caribou_marshal_NONE__NONE,
- G_TYPE_NONE, 0);
-}
-
-/**
- * caribou_virtual_keyboard_new:
- *
- * Create a new #CaribouVirtualKeyboard.
- *
- * Returns: A new #CaribouVirtualKeyboard.
- */
-CaribouVirtualKeyboard *
-caribou_virtual_keyboard_new ()
-{
- return g_object_new (CARIBOU_TYPE_VIRTUAL_KEYBOARD, NULL);
-}
-
-static Display *
-_get_xdisplay (CaribouVirtualKeyboard *self)
-{
- g_return_if_fail (self != NULL);
-
- return GDK_DISPLAY_XDISPLAY (self->priv->display);
-}
-
-static KeyCode
-keycode_for_keyval (guint keyval,
- guint *modmask)
-{
- GdkKeymap *km = gdk_keymap_get_default ();
- GdkKeymapKey *kmk;
- gint len;
- KeyCode keycode;
-
- g_return_val_if_fail (modmask != NULL, 0);
-
- if (gdk_keymap_get_entries_for_keyval (km, keyval, &kmk, &len)) {
- keycode = kmk[0].keycode;
- *modmask = (kmk[0].level == 1) ? GDK_SHIFT_MASK : 0;
- g_free (kmk);
- }
-
- return keycode;
-}
-
-/**
- * caribou_virtual_keyboard_mod_latch:
- * @mask: the modifier mask
- *
- * Simulate a keyboard modifier key press
- */
-void
-caribou_virtual_keyboard_mod_latch (CaribouVirtualKeyboard *self,
- int mask)
-{
- Bool b;
- b = XkbLatchModifiers(_get_xdisplay (self), XkbUseCoreKbd, mask, mask);
- g_print ("latching %d %d\n", mask, b);
- gdk_display_sync (self->priv->display);
-}
-
-/**
- * caribou_virtual_keyboard_mod_unlatch:
- * @mask: the modifier mask
- *
- * Simulate a keyboard modifier key release
- */
-void
-caribou_virtual_keyboard_mod_unlatch (CaribouVirtualKeyboard *self,
- int mask)
-{
- g_print ("unlatching %d\n", mask);
- XkbLatchModifiers(_get_xdisplay (self), XkbUseCoreKbd, mask, 0);
- gdk_display_sync (self->priv->display);
-}
-
-/**
- * caribou_virtual_keyboard_keyval_press:
- * @keyval: the keyval to simulate
- *
- * Simulate a keyboard key press with a given keyval.
- */
-void
-caribou_virtual_keyboard_keyval_press (CaribouVirtualKeyboard *self,
- guint keyval)
-{
- guint mask;
- KeyCode keycode = keycode_for_keyval (keyval, &mask);
-
- if (mask != 0)
- caribou_virtual_keyboard_mod_latch (self, mask);
-
- XTestFakeKeyEvent(_get_xdisplay (self), keycode, TRUE, CurrentTime);
- gdk_display_sync (self->priv->display);
-}
-
-/**
- * caribou_virtual_keyboard_keyval_release:
- * @keyval: the keyval to simulate
- *
- * Simulate a keyboard key press with a given keyval.
- */
-void
-caribou_virtual_keyboard_keyval_release (CaribouVirtualKeyboard *self,
- guint keyval)
-{
- guint mask;
- KeyCode keycode = keycode_for_keyval (keyval, &mask);
-
- XTestFakeKeyEvent(_get_xdisplay (self), keycode, FALSE, CurrentTime);
-
- if (mask != 0)
- caribou_virtual_keyboard_mod_unlatch (self, mask);
-
- gdk_display_sync (self->priv->display);
-}
diff --git a/libcaribou/caribou-virtual-keyboard.h b/libcaribou/caribou-virtual-keyboard.h
deleted file mode 100644
index 01e7499..0000000
--- a/libcaribou/caribou-virtual-keyboard.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011, Eitan Isaacson <eitan@monotonous.org>
- */
-
-#ifndef CARIBOU_VIRTUAL_KEYBOARD_H
-#define CARIBOU_VIRTUAL_KEYBOARD_H
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-#define CARIBOU_TYPE_VIRTUAL_KEYBOARD (caribou_virtual_keyboard_get_type ())
-#define CARIBOU_VIRTUAL_KEYBOARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CARIBOU_TYPE_VIRTUAL_KEYBOARD, CaribouVirtualKeyboard))
-#define CARIBOU_VIRTUAL_KEYBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CARIBOU_TYPE_VIRTUAL_KEYBOARD, CaribouVirtualKeyboardClass))
-#define CARIBOU_IS_VIRTUAL_KEYBOARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CARIBOU_TYPE_VIRTUAL_KEYBOARD))
-#define CARIBOU_IS_VIRTUAL_KEYBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), CARIBOU_TYPE_VIRTUAL_KEYBOARD))
-#define CARIBOU_VIRTUAL_KEYBOARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CARIBOU_TYPE_VIRTUAL_KEYBOARD, CaribouVirtualKeyboardClass))
-
-typedef struct _CaribouVirtualKeyboard CaribouVirtualKeyboard;
-typedef struct _CaribouVirtualKeyboardClass CaribouVirtualKeyboardClass;
-typedef struct _CaribouVirtualKeyboardPrivate CaribouVirtualKeyboardPrivate;
-
-struct _CaribouVirtualKeyboard {
- GObject parent;
-
- CaribouVirtualKeyboardPrivate *priv;
-};
-
-struct _CaribouVirtualKeyboardClass {
- GObjectClass parent_class;
-
-};
-
-GType caribou_virtual_keyboard_get_type (void);
-
-CaribouVirtualKeyboard *caribou_virtual_keyboard_new ();
-
-void caribou_virtual_keyboard_keyval_press (CaribouVirtualKeyboard *self,
- guint keyval);
-
-void caribou_virtual_keyboard_keyval_release (CaribouVirtualKeyboard *self,
- guint keyval);
-
-void caribou_virtual_keyboard_mod_latch (CaribouVirtualKeyboard *self,
- int mask);
-
-void caribou_virtual_keyboard_mod_unlatch (CaribouVirtualKeyboard *self,
- int mask);
-
-G_END_DECLS
-
-#endif /* CARIBOU_VIRTUAL_KEYBOARD_H */
diff --git a/libcaribou/caribou.h b/libcaribou/caribou.h
deleted file mode 100644
index 66b4c9f..0000000
--- a/libcaribou/caribou.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2011, Eitan Isaacson <eitan@monotonous.org>
- */
-
-#ifndef CARIBOU_H
-#define CARIBOU_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <libcaribou/caribou-virtual-keyboard.h>
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* CARIBOU_H */
diff --git a/libcaribou/external-libs.vapi b/libcaribou/external-libs.vapi
new file mode 100644
index 0000000..6a87d33
--- /dev/null
+++ b/libcaribou/external-libs.vapi
@@ -0,0 +1,234 @@
+using X;
+
+[CCode (cprefix = "", lower_case_cprefix = "",
+ cheader_filename = "X11/extensions/XTest.h")]
+namespace XTest {
+ [CCode (cname = "XTestFakeKeyEvent")]
+ public int fake_key_event (Display dpy, uchar keycode, bool key_press,
+ ulong delay);
+}
+
+[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "X11/Xlib.h")]
+namespace X {
+ [CCode (cname = "XKeycodeToKeysym")]
+ public int keycode_to_keysym (Display dpy, uchar keycode, int index);
+
+}
+
+[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "X11/XKBlib.h")]
+namespace Xkb {
+
+ [CCode (cname = "XkbGetKeyboard")]
+ public Desc get_keyboard (X.Display dpy, uint which, uint device_spec);
+
+ [CCode (cname = "XkbSetMap")]
+ public void set_map (X.Display dpy, uint which, Desc xkb);
+
+ [CCode (cname = "XkbFreeKeyboard")]
+ public void free_keyboard (Desc xkb, uint which, bool free_all);
+
+ [CCode (cname = "XkbGetState")]
+ public void get_state (X.Display dpy, uint device_spec, out State state);
+
+ [CCode (cname = "XkbSelectEvents")]
+ public void select_events (X.Display dpy, uint device_spec, ulong bits_to_change,
+ ulong values_for_bits);
+
+ [CCode (cname = "XkbLatchModifiers")]
+ public void latch_modifiers (X.Display dpy, uint device_spec, uint affect,
+ uint values);
+
+ [Compact]
+ [CCode (cname = "XkbAnyEvent", free_function = "")]
+ public struct AnyEvent {
+ int xkb_type;
+ }
+
+ [Compact]
+ [CCode (cname = "XkbStateNotifyEvent", free_function = "")]
+ public struct StateNotifyEvent {
+ uint changed;
+ int group;
+ uint mods;
+ }
+
+ [Compact]
+ [CCode (cname = "XkbEvent", free_function = "")]
+ public struct Event {
+ int type;
+ AnyEvent any;
+ StateNotifyEvent state;
+ }
+
+ [Compact]
+ [CCode (cname = "XkbStateRec", free_function = "")]
+ public struct State {
+ uchar group;
+ uchar locked_group;
+ ushort base_group;
+ ushort latched_group;
+ uchar mods;
+ uchar base_mods;
+ uchar latched_mods;
+ uchar locked_mods;
+ uchar compat_state;
+ uchar grab_mods;
+ uchar compat_grab_mods;
+ uchar lookup_mods;
+ uchar compat_lookup_mods;
+ ushort ptr_buttons;
+ }
+
+ [Compact]
+ [CCode (cname = "XkbDescRec", free_function = "")]
+ public class Desc {
+ public X.Display dpy;
+ public ushort flags;
+ public ushort device_spec;
+ public char min_key_code;
+ public char max_key_code;
+ public Controls ctrls;
+ public ServerMap server;
+ public ClientMap map;
+ public Indicator indicators;
+ public Names names;
+ public CompatMap compat;
+ public Geometry geom;
+ }
+
+ [Compact]
+ [CCode (cname = "XkbControlsRec", free_function = "")]
+ public class Controls {
+ }
+
+ [Compact]
+ [CCode (cname = "XkbServerMapRec", free_function = "")]
+ public class ServerMap {
+ }
+
+ [Compact]
+ [CCode (cname = "XkbKeyTypeRec", free_function = "")]
+ public struct KeyType {
+ }
+
+ [CCode (cname = "XkbSymMapRec", free_function = "")]
+ public struct SymMap {
+ uchar kt_index[4];
+ uchar group_info;
+ uchar width;
+ ushort offset;
+ }
+
+ [Compact]
+ [CCode (cname = "XkbClientMapRec", free_function = "")]
+ public class ClientMap {
+ public uchar size_types;
+ public uchar num_types;
+ public KeyType[] types;
+
+ public ushort size_syms;
+ public ushort num_syms;
+ public uint[] syms;
+ public SymMap[] key_sym_map;
+
+ public uchar[] modmap;
+ }
+
+ [Compact]
+ [CCode (cname = "XkbIndicatorRec", free_function = "")]
+ public class Indicator {
+ }
+
+ [Compact]
+ [CCode (cname = "XkbNamesRec", free_function = "")]
+ public class Names {
+ }
+
+ [Compact]
+ [CCode (cname = "XkbCompatMapRec", free_function = "")]
+ public class CompatMap {
+ }
+
+ [Compact]
+ [CCode (cname = "XkbGeometryRec", free_function = "")]
+ public class Geometry {
+ }
+
+ [CCode (cname = "XkbUseCoreKbd")]
+ public int UseCoreKbd;
+ [CCode (cname = "XkbUseCorePtr")]
+ public int UseCorePtr;
+ [CCode (cname = "XkbDfltXIClass")]
+ public int DfltXIClass;
+ [CCode (cname = "XkbDfltXIId")]
+ public int DfltXIId;
+ [CCode (cname = "XkbAllXIClasses")]
+ public int AllXIClasses;
+ [CCode (cname = "XkbAllXIIds")]
+ public int AllXIIds;
+ [CCode (cname = "XkbXINone")]
+ public int XINone;
+
+ [CCode (cname = "XkbGBN_TypesMask")]
+ public int GBN_TypesMask;
+ [CCode (cname = "XkbGBN_CompatMapMask")]
+ public int GBN_CompatMapMask;
+ [CCode (cname = "XkbGBN_ClientSymbolsMask")]
+ public int GBN_ClientSymbolsMask;
+ [CCode (cname = "XkbGBN_ServerSymbolsMask")]
+ public int GBN_ServerSymbolsMask;
+ [CCode (cname = "XkbGBN_SymbolsMask")]
+ public int GBN_SymbolsMask;
+ [CCode (cname = "XkbGBN_IndicatorMapMask")]
+ public int GBN_IndicatorMapMask;
+ [CCode (cname = "XkbGBN_KeyNamesMask")]
+ public int GBN_KeyNamesMask;
+ [CCode (cname = "XkbGBN_GeometryMask")]
+ public int GBN_GeometryMask;
+ [CCode (cname = "XkbGBN_OtherNamesMask")]
+ public int GBN_OtherNamesMask;
+ [CCode (cname = "XkbGBN_AllComponentsMask")]
+ public int GBN_AllComponentsMask;
+
+ [CCode (cname = "XkbOneLevelIndex")]
+ public int OneLevelIndex;
+
+ [CCode (cname = "XkbNewKeyboardNotifyMask")]
+ public int NewKeyboardNotifyMask;
+ [CCode (cname = "XkbMapNotifyMask")]
+ public int MapNotifyMask;
+ [CCode (cname = "XkbStateNotifyMask")]
+ public int StateNotifyMask;
+ [CCode (cname = "XkbControlsNotifyMask")]
+ public int ControlsNotifyMask;
+ [CCode (cname = "XkbIndicatorStateNotifyMask")]
+ public int IndicatorStateNotifyMask;
+ [CCode (cname = "XkbIndicatorMapNotifyMask")]
+ public int IndicatorMapNotifyMask;
+ [CCode (cname = "XkbNamesNotifyMask")]
+ public int NamesNotifyMask;
+ [CCode (cname = "XkbCompatMapNotifyMask")]
+ public int CompatMapNotifyMask;
+ [CCode (cname = "XkbBellNotifyMask")]
+ public int BellNotifyMask;
+ [CCode (cname = "XkbActionMessageMask")]
+ public int ActionMessageMask;
+ [CCode (cname = "XkbAccessXNotifyMask")]
+ public int AccessXNotifyMask;
+ [CCode (cname = "XkbExtensionDeviceNotifyMask")]
+ public int ExtensionDeviceNotifyMask;
+ [CCode (cname = "XkbAllEventsMask")]
+ public int AllEventsMask;
+
+ [CCode (cname = "XkbStateNotify")]
+ public int StateNotify;
+
+ [CCode (cname = "XkbGroupStateMask")]
+ public int GroupStateMask;
+
+ [CCode (cname = "XkbModifierStateMask")]
+ public int ModifierStateMask;
+
+ [CCode (cname = "XkbAllMapComponentsMask")]
+ public int AllMapComponentsMask;
+} \ No newline at end of file
diff --git a/libcaribou/group-model.vala b/libcaribou/group-model.vala
new file mode 100644
index 0000000..564dbd8
--- /dev/null
+++ b/libcaribou/group-model.vala
@@ -0,0 +1,50 @@
+using GLib;
+
+namespace Caribou {
+ public class GroupModel : GLib.Object {
+ public string active_level { get; private set; }
+
+ public string group;
+ public string variant;
+ private string default_level;
+ private HashTable<string, LevelModel> levels;
+
+ public GroupModel (string group, string variant) {
+ this.group = group;
+ this.variant = variant;
+ levels = new HashTable<string, LevelModel> (str_hash, str_equal);
+ active_level = default_level;
+ }
+
+ public static string create_group_name (string group, string variant) {
+ if (variant != "")
+ return @"$(group)_$(variant)";
+ else
+ return group;
+ }
+
+ public void add_level (string lname, LevelModel level) {
+ levels.insert (lname, level);
+ level.level_toggled.connect(on_level_toggled);
+ if (level.mode == "default") {
+ default_level = lname;
+ active_level = lname;
+ }
+ }
+
+ public string[] get_levels () {
+ return Util.list_to_array (levels.get_keys ());
+ }
+
+ public LevelModel get_level (string level_name) {
+ return levels.lookup(level_name);
+ }
+
+ private void on_level_toggled (string new_level) {
+ if (new_level == "default")
+ active_level = default_level;
+ else
+ active_level = new_level;
+ }
+ }
+} \ No newline at end of file
diff --git a/libcaribou/json-deserializer.vala b/libcaribou/json-deserializer.vala
new file mode 100644
index 0000000..e136042
--- /dev/null
+++ b/libcaribou/json-deserializer.vala
@@ -0,0 +1,126 @@
+namespace Caribou {
+
+ private class JsonDeserializer : Object {
+
+ public static bool get_layout_file_inner (string data_dir,
+ string group,
+ string variant,
+ out File fp) {
+ string[] files = {@"$(group)_$(variant).json", @"$(group).json"};
+
+ foreach (string fn in files) {
+ string layout_fn = GLib.Path.build_filename (data_dir, fn);
+ fp = GLib.File.new_for_path (layout_fn);
+ if (fp.query_exists ())
+ return true;
+ }
+
+ return false;
+ }
+
+ public static GLib.File get_layout_file (string group,
+ string variant) throws IOError {
+ Settings caribou_settings = new Settings ("org.gnome.caribou");
+ string kb_type = caribou_settings.get_string("keyboard-type");
+
+ List<string> dirs = new List<string> ();
+ string custom_dir = Environment.get_variable("CARIBOU_LAYOUTS_DIR");
+
+ if (custom_dir != null)
+ dirs.append (Path.build_filename (custom_dir, "layouts", kb_type));
+
+ dirs.append (Path.build_filename (Environment.get_user_data_dir (),
+ "caribou", "layouts", kb_type));
+
+ foreach (string data_dir in Environment.get_system_data_dirs ()) {
+ dirs.append (Path.build_filename (
+ data_dir, "caribou", "layouts", kb_type));
+ }
+
+ foreach (string data_dir in dirs) {
+ File fp;
+ if (get_layout_file_inner (data_dir, group, variant, out fp))
+ return fp;
+ }
+
+ throw new IOError.NOT_FOUND (
+ "Could not find layout file for %s %s", group, variant); }
+
+ public static void load_group (GroupModel group) {
+ Json.Parser parser = new Json.Parser ();
+
+ try {
+ GLib.File f = get_layout_file (group.group, group.variant);
+ parser.load_from_stream (f.read (), (Cancellable) null);
+ create_levels_from_json (group, parser.get_root ());
+ } catch (GLib.Error e) {
+ stdout.printf ("Failed to load JSON: %s\n", e.message);
+ return;
+ }
+ }
+
+ public static void create_levels_from_json (GroupModel group,
+ Json.Node root) {
+ Json.Object obj = root.get_object ();
+
+ if (root.get_node_type () != Json.NodeType.OBJECT)
+ return;
+
+ foreach (string levelname in obj.get_members ()) {
+ unowned Json.Object json_level = obj.get_object_member (levelname);
+ string mode = "";
+
+ if (json_level.has_member ("mode"))
+ mode = json_level.get_string_member ("mode");
+
+ Json.Array json_rows = json_level.get_array_member ("rows");
+ LevelModel level = new LevelModel(mode, json_rows.get_length ());
+
+ group.add_level(levelname, level);
+
+ load_rows (level, json_rows);
+ }
+ }
+
+ public static void load_rows (LevelModel level, Json.Array json_rows) {
+ uint i,j;
+
+ for (i=0;i<level.n_rows;i++) {
+ Json.Array json_keys = json_rows.get_array_element (i);
+ uint nkeys = json_keys.get_length ();
+ for (j=0;j<nkeys;j++) {
+ Json.Object json_key = json_keys.get_object_element (j);
+ level.add_key (i, load_key (json_key));
+ }
+ }
+
+ }
+
+ public static KeyModel load_key (Json.Object json_key) {
+ KeyModel key = new KeyModel (json_key.get_string_member ("name"));
+
+ if (json_key.has_member ("toggle"))
+ key.toggle = json_key.get_string_member ("toggle");
+
+ if (json_key.has_member ("margin_left"))
+ key.margin_left = json_key.get_double_member ("margin_left");
+
+ if (json_key.has_member ("width"))
+ key.width = json_key.get_double_member ("width");
+
+ if (json_key.has_member ("extended_names")) {
+ Json.Array json_keys = json_key.get_array_member ("extended_names");
+ uint nkeys = json_keys.get_length ();
+ uint i;
+
+ key.add_subkey(key.name);
+
+ for (i=0;i<nkeys;i++)
+ key.add_subkey(json_keys.get_string_element (i));
+ }
+
+ return key;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/libcaribou/key-model.vala b/libcaribou/key-model.vala
new file mode 100644
index 0000000..90f3625
--- /dev/null
+++ b/libcaribou/key-model.vala
@@ -0,0 +1,71 @@
+using GLib;
+
+namespace Caribou {
+ public class KeyModel : GLib.Object {
+ public double margin_left { get; set; default = 0.0; }
+ public double width { get; set; default = 1.0; }
+ public string toggle { get; set; default = ""; }
+
+ public bool show_subkeys { get; private set; default = false; }
+ public string name { get; private set; }
+ public uint keyval { get; private set; }
+
+ private uint hold_tid;
+ private XAdapter xadapter;
+ private List<KeyModel> _extended_keys;
+
+ public signal void key_pressed ();
+ public signal void key_released ();
+ public signal void key_clicked ();
+ public signal void key_hold_end ();
+ public signal void key_hold ();
+
+ public KeyModel (string name) {
+ this.name = name;
+ xadapter = XAdapter.get_default();
+ keyval = Gdk.keyval_from_name (name);
+ }
+
+ public void add_subkey (string name) {
+ KeyModel key = new KeyModel (name);
+ key.key_clicked.connect(on_subkey_clicked);
+ _extended_keys.append (key);
+ }
+
+ private void on_subkey_clicked () {
+ show_subkeys = false;
+ }
+
+ public void press () {
+ hold_tid = GLib.Timeout.add(1000, on_key_held);
+ key_pressed();
+ }
+
+ public void release () {
+ key_released();
+ if (hold_tid != 0) {
+ GLib.Source.remove (hold_tid);
+ hold_tid = 0;
+ key_clicked();
+ if (keyval != 0) {
+ xadapter.keyval_press(keyval);
+ xadapter.keyval_release(keyval);
+ }
+ } else {
+ key_hold_end ();
+ }
+ }
+
+ private bool on_key_held () {
+ hold_tid = 0;
+ if (_extended_keys.length () != 0)
+ show_subkeys = true;
+ key_hold ();
+ return false;
+ }
+
+ public unowned List<KeyModel> get_extended_keys () {
+ return _extended_keys;
+ }
+ }
+} \ No newline at end of file
diff --git a/libcaribou/keyboard-model.vala b/libcaribou/keyboard-model.vala
new file mode 100644
index 0000000..b9d96f4
--- /dev/null
+++ b/libcaribou/keyboard-model.vala
@@ -0,0 +1,49 @@
+using Bus;
+
+namespace Caribou {
+ public class KeyboardModel : Object {
+ public string active_group { get; private set; default = ""; }
+
+ XAdapter xadapter;
+ HashTable<string, GroupModel> groups;
+
+ construct {
+ uint grpid;
+ string group, variant;
+ string[] grps, variants;
+ int i;
+
+ groups = new HashTable<string, GroupModel> (str_hash, str_equal);
+
+ xadapter = XAdapter.get_default ();
+ xadapter.group_changed.connect (on_group_changed);
+
+ grpid = xadapter.get_current_group (out group, out variant);
+ on_group_changed (grpid, group, variant);
+
+ xadapter.get_groups (out grps, out variants);
+
+ for (i=0;i<grps.length;i++)
+ populate_group (grps[i], variants[i]);
+ }
+
+ private void populate_group (string group, string variant) {
+ GroupModel grp = new GroupModel (group, variant);
+ groups.insert (GroupModel.create_group_name (group, variant), grp);
+ JsonDeserializer.load_group (grp);
+ }
+
+ public string[] get_groups () {
+ return Util.list_to_array (groups.get_keys ());
+ }
+
+ public GroupModel get_group (string group_name) {
+ return groups.lookup(group_name);
+ }
+
+ private void on_group_changed (uint grpid, string group, string variant) {
+ active_group = group;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/libcaribou/keyboard-service.vala b/libcaribou/keyboard-service.vala
new file mode 100644
index 0000000..ee0035f
--- /dev/null
+++ b/libcaribou/keyboard-service.vala
@@ -0,0 +1,35 @@
+namespace Caribou {
+ [DBus(name = "org.gnome.Caribou.Keyboard")]
+ public abstract class KeyboardService : Object {
+ public string name { get; private set; default = "CaribouKeyboard"; }
+
+ public abstract void set_cursor_location(int x, int y, int w, int h);
+ public abstract void set_entry_location(int x, int y, int w, int h);
+ public abstract void show();
+ public abstract void hide();
+
+ protected void register_keyboard (string name) {
+ this.name = name;
+ string dbus_name = @"org.gnome.Caribou.$name";
+ Bus.own_name (BusType.SESSION, dbus_name, BusNameOwnerFlags.NONE,
+ on_bus_aquired, on_name_aquired, on_name_lost);
+ }
+
+ private void on_name_aquired (DBusConnection conn, string name) {
+ }
+
+ private void on_name_lost (DBusConnection conn, string name) {
+ stderr.printf ("Could not aquire %s\n", name);
+ }
+
+ private void on_bus_aquired (DBusConnection conn) {
+ try {
+ string path = @"/org/gnome/Caribou/$name";
+ conn.register_object (path, this);
+ } catch (IOError e) {
+ stderr.printf ("Could not register service: %s\n", e.message);
+ }
+ }
+
+ }
+} \ No newline at end of file
diff --git a/libcaribou/level-model.vala b/libcaribou/level-model.vala
new file mode 100644
index 0000000..14e8ea8
--- /dev/null
+++ b/libcaribou/level-model.vala
@@ -0,0 +1,41 @@
+using GLib;
+
+namespace Caribou {
+ public class LevelModel : GLib.Object {
+ public signal void level_toggled (string new_level);
+
+ public string mode { get; private set; default = ""; }
+ public int n_rows {
+ get {
+ return _rows.length;
+ }
+ }
+
+ private RowModel[] _rows;
+
+ public LevelModel (string mode, uint nrows) {
+ uint i;
+ this.mode = mode;
+ _rows = new RowModel[nrows];
+ for (i=0;i<nrows;i++)
+ _rows[i] = new RowModel ();
+ }
+
+ public void add_key (uint rownum, KeyModel key) {
+ key.key_clicked.connect (on_key_clicked);
+ _rows[rownum].add_key (key);
+ }
+
+ public RowModel[] get_rows () {
+ return _rows;
+ }
+
+ private void on_key_clicked (KeyModel key) {
+ if (key.toggle != "")
+ level_toggled (key.toggle);
+ else
+ level_toggled ("default");
+ }
+
+ }
+} \ No newline at end of file
diff --git a/libcaribou/libxklavier.vapi b/libcaribou/libxklavier.vapi
new file mode 100644
index 0000000..7d31572
--- /dev/null
+++ b/libcaribou/libxklavier.vapi
@@ -0,0 +1,182 @@
+/* libxklavier.vapi generated by vapigen, do not modify. */
+
+[CCode (cprefix = "Xkl", lower_case_cprefix = "xkl_")]
+namespace Xkl {
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public class ConfigItem : GLib.Object {
+ [CCode (array_length = false)]
+ public weak char[] description;
+ [CCode (array_length = false)]
+ public weak char[] name;
+ [CCode (array_length = false)]
+ public weak char[] short_description;
+ [CCode (has_construct_function = false)]
+ public ConfigItem ();
+ }
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public class ConfigRec : GLib.Object {
+ public string[] layouts;
+ public weak string model;
+ public string[] options;
+ public string[] variants;
+ [CCode (has_construct_function = false)]
+ public ConfigRec ();
+ public bool activate (Xkl.Engine engine);
+ public bool equals (Xkl.ConfigRec data2);
+ public bool get_from_backup (Xkl.Engine engine);
+ public bool get_from_root_window_property (X.Atom rules_atom_name, string rules_file_out, Xkl.Engine engine);
+ public bool get_from_server (Xkl.Engine engine);
+ public void reset ();
+ public bool set_to_root_window_property (X.Atom rules_atom_name, string rules_file, Xkl.Engine engine);
+ public static bool write_to_file (Xkl.Engine engine, string file_name, Xkl.ConfigRec data, bool binary);
+ }
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public class ConfigRegistry : GLib.Object {
+ [CCode (has_construct_function = false)]
+ protected ConfigRegistry ();
+ public bool find_layout (Xkl.ConfigItem item);
+ public bool find_model (Xkl.ConfigItem item);
+ public bool find_option (string option_group_name, Xkl.ConfigItem item);
+ public bool find_option_group (Xkl.ConfigItem item);
+ public bool find_variant (string layout_name, Xkl.ConfigItem item);
+ public void foreach_country (Xkl.ConfigItemProcessFunc func, void* data);
+ public void foreach_country_variant (string country_code, Xkl.TwoConfigItemsProcessFunc func, void* data);
+ public void foreach_language (Xkl.ConfigItemProcessFunc func, void* data);
+ public void foreach_language_variant (string language_code, Xkl.TwoConfigItemsProcessFunc func, void* data);
+ public void foreach_layout (Xkl.ConfigItemProcessFunc func, void* data);
+ public void foreach_layout_variant (string layout_name, Xkl.ConfigItemProcessFunc func, void* data);
+ public void foreach_model (Xkl.ConfigItemProcessFunc func, void* data);
+ public void foreach_option (string option_group_name, Xkl.ConfigItemProcessFunc func, void* data);
+ public void foreach_option_group (Xkl.ConfigItemProcessFunc func, void* data);
+ public static unowned Xkl.ConfigRegistry get_instance (Xkl.Engine engine);
+ public bool load (bool if_extras_needed);
+ public void search_by_pattern (string pattern, Xkl.TwoConfigItemsProcessFunc func, void* data);
+ [NoAccessorMethod]
+ public Xkl.Engine engine { owned get; construct; }
+ }
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public class Engine : GLib.Object {
+ [CCode (has_construct_function = false)]
+ protected Engine ();
+ public static void INT__LONG_LONG (GLib.Closure closure, GLib.Value return_value, uint n_param_values, GLib.Value param_values, void* invocation_hint, void* marshal_data);
+ public static void VOID__FLAGS_INT_BOOLEAN (GLib.Closure closure, GLib.Value return_value, uint n_param_values, GLib.Value param_values, void* invocation_hint, void* marshal_data);
+ public void allow_one_switch_to_secondary_group ();
+ public bool backup_names_prop ();
+ [NoWrapper]
+ public virtual void config_notify ();
+ public void delete_state (X.Window win);
+ public int filter_events (X.Event evt);
+ public unowned string get_backend_name ();
+ public unowned Xkl.State get_current_state ();
+ public X.Window get_current_window ();
+ public int get_current_window_group ();
+ public int get_default_group ();
+ public uint get_features ();
+ public unowned string get_groups_names ();
+ public bool get_indicators_handling ();
+ public unowned string get_indicators_names ();
+ public static unowned Xkl.Engine get_instance (X.Display display);
+ public uint get_max_num_groups ();
+ public int get_next_group ();
+ public uint get_num_groups ();
+ public int get_prev_group ();
+ public uint get_secondary_groups_mask ();
+ public bool get_state (X.Window win, Xkl.State state_out);
+ public unowned string get_window_title (X.Window win);
+ public bool grab_key (int keycode, uint modifiers);
+ public bool is_group_per_toplevel_window ();
+ public bool is_window_from_same_toplevel_window (X.Window win1, X.Window win2);
+ public bool is_window_transparent (X.Window win);
+ public void lock_group (int group);
+ public int pause_listen ();
+ public int resume_listen ();
+ public void save_state (X.Window win, Xkl.State state);
+ public void set_default_group (int group);
+ public void set_group_per_toplevel_window (bool is_global);
+ public void set_indicators_handling (bool whether_handle);
+ public void set_secondary_groups_mask (uint mask);
+ public void set_window_transparent (X.Window win, bool transparent);
+ public int start_listen (uint flags);
+ [NoWrapper]
+ public virtual void state_notify (Xkl.EngineStateChange change_type, int group, bool restore);
+ public int stop_listen (uint flags);
+ public bool ungrab_key (int keycode, uint modifiers);
+ [NoAccessorMethod]
+ public string backendName { owned get; }
+ public uint default_group { get; }
+ [NoAccessorMethod]
+ public void* display { get; construct; }
+ public Xkl.EngineFeatures features { get; }
+ public bool indicators_handling { get; }
+ public uint max_num_groups { get; }
+ public uint num_groups { get; }
+ public uint secondary_groups_mask { get; }
+ public virtual signal void X_config_changed ();
+ public virtual signal void X_new_device ();
+ public virtual signal void X_state_changed (int p0, int p1, bool p2);
+ public virtual signal int new_toplevel_window (long p0, long p1);
+ }
+ [Compact]
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public class State {
+ public int32 group;
+ public uint32 indicators;
+ }
+ [CCode (cprefix = "XKLF_", cheader_filename = "libxklavier/xklavier.h")]
+ [Flags]
+ public enum EngineFeatures {
+ CAN_TOGGLE_INDICATORS,
+ CAN_OUTPUT_CONFIG_AS_ASCII,
+ CAN_OUTPUT_CONFIG_AS_BINARY,
+ MULTIPLE_LAYOUTS_SUPPORTED,
+ REQUIRES_MANUAL_LAYOUT_MANAGEMENT,
+ DEVICE_DISCOVERY
+ }
+ [CCode (cprefix = "XKLL_", cheader_filename = "libxklavier/xklavier.h")]
+ public enum EngineListenModes {
+ MANAGE_WINDOW_STATES,
+ TRACK_KEYBOARD_STATE,
+ MANAGE_LAYOUTS
+ }
+ [CCode (cprefix = "", cheader_filename = "libxklavier/xklavier.h")]
+ public enum EngineStateChange {
+ GROUP_CHANGED,
+ INDICATORS_CHANGED
+ }
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public delegate void ConfigItemProcessFunc (Xkl.ConfigRegistry config, Xkl.ConfigItem item);
+ [CCode (cheader_filename = "libxklavier/xklavier.h", has_target = false)]
+ public delegate void LogAppender (char[] file, char[] function, int level, char[] format, void* args);
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public delegate void TwoConfigItemsProcessFunc (Xkl.ConfigRegistry config, Xkl.ConfigItem item, Xkl.ConfigItem subitem);
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public const int MAX_CI_DESC_LENGTH;
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public const int MAX_CI_NAME_LENGTH;
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public const int MAX_CI_SHORT_DESC_LENGTH;
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public const string XCI_PROP_ALLOW_MULTIPLE_SELECTION;
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public const string XCI_PROP_COUNTRY_LIST;
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public const string XCI_PROP_EXTRA_ITEM;
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public const string XCI_PROP_LANGUAGE_LIST;
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public const string XCI_PROP_VENDOR;
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public static void default_log_appender (char[] file, char[] function, int level, char[] format, void* args);
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public static unowned string get_country_name (string code);
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public static unowned string get_language_name (string code);
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public static unowned string get_last_error ();
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public static bool restore_names_prop (Xkl.Engine engine);
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public static void set_debug_level (int level);
+ [CCode (cheader_filename = "libxklavier/xklavier.h")]
+ public static void set_log_appender (Xkl.LogAppender fun);
+}
diff --git a/libcaribou/row-model.vala b/libcaribou/row-model.vala
new file mode 100644
index 0000000..de4456c
--- /dev/null
+++ b/libcaribou/row-model.vala
@@ -0,0 +1,22 @@
+namespace Caribou {
+ public class RowModel : GLib.Object {
+
+ List<KeyModel> keys;
+
+ public RowModel () {
+ keys = new List<KeyModel> ();
+ }
+
+ public void add_key (KeyModel key) {
+ keys.append (key);
+ }
+
+ public KeyModel get_key (uint index) {
+ return keys.nth (index).data;
+ }
+
+ public unowned List<weak KeyModel> get_keys () {
+ return keys;
+ }
+ }
+}
diff --git a/libcaribou/util.vala b/libcaribou/util.vala
new file mode 100644
index 0000000..c4625ae
--- /dev/null
+++ b/libcaribou/util.vala
@@ -0,0 +1,13 @@
+namespace Caribou {
+ class Util {
+ public static string[] list_to_array (List<string> list) {
+ string[] rv = new string[list.length()];
+ int i = 0;
+ foreach (string v in list) {
+ rv[i] = v;
+ i++;
+ }
+ return rv;
+ }
+ }
+} \ No newline at end of file
diff --git a/libcaribou/xadapter.vala b/libcaribou/xadapter.vala
new file mode 100644
index 0000000..d240f08
--- /dev/null
+++ b/libcaribou/xadapter.vala
@@ -0,0 +1,213 @@
+using Xkl;
+using Gdk;
+using Xkb;
+using XTest;
+using X;
+
+namespace Caribou {
+ public class XAdapter : Object {
+
+ /* Signals */
+ public signal void modifiers_changed (uint modifiers);
+ public signal void group_changed (uint gid, string group, string variant);
+
+ /* Private properties */
+ private static XAdapter instance;
+ X.Display xdisplay;
+ Xkb.Desc xkbdesc;
+ Xkl.Engine xkl_engine;
+ uint reserved_keysym;
+ uchar reserved_keycode;
+ uchar modifiers;
+ uchar group;
+
+ construct {
+ Xkb.State state;
+
+ this.xdisplay = new X.Display ();
+ this.xkbdesc = Xkb.get_keyboard (this.xdisplay,
+ Xkb.GBN_AllComponentsMask,
+ Xkb.UseCoreKbd);
+ this.xkl_engine = Xkl.Engine.get_instance (this.xdisplay);
+
+ Xkb.get_state (this.xdisplay, Xkb.UseCoreKbd, out state);
+
+ this.group = state.group;
+ this.modifiers = state.mods;
+
+ this.reserved_keycode = 0;
+
+ Xkb.select_events (
+ this.xdisplay, Xkb.UseCoreKbd,
+ Xkb.StateNotifyMask | Xkb.AccessXNotifyMask,
+ Xkb.StateNotifyMask | Xkb.AccessXNotifyMask);
+
+ ((Gdk.Window) null).add_filter (x_event_filter); // Did I blow your mind?
+ }
+
+ ~XAdapter () {
+ Xkb.free_keyboard(this.xkbdesc, Xkb.GBN_AllComponentsMask, true);
+ }
+
+ public static XAdapter get_default() {
+ if (instance == null)
+ instance = new XAdapter ();
+ return instance;
+ }
+
+ private Gdk.FilterReturn x_event_filter (Gdk.XEvent xevent, Gdk.Event event) {
+ void* pointer = &xevent;
+ Xkb.Event *xev = (Xkb.Event *) pointer;
+
+ if (xev.any.xkb_type == Xkb.StateNotify) {
+ Xkb.StateNotifyEvent *sevent = &xev.state;
+ if ((sevent.changed & Xkb.GroupStateMask) != 0) {
+ Xkl.ConfigRec config_rec = new Xkl.ConfigRec ();
+ config_rec.get_from_server (this.xkl_engine);
+ group_changed (sevent.group, config_rec.layouts[sevent.group],
+ config_rec.variants[sevent.group]);
+ this.group = (uchar) sevent.group;
+ } else if ((sevent.changed & Xkb.ModifierStateMask) != 0) {
+ this.modifiers = (uchar) sevent.mods;
+ }
+ }
+
+ return Gdk.FilterReturn.CONTINUE;
+ }
+
+ private uchar get_reserved_keycode () {
+ uchar i;
+ unowned Xkb.Desc xkbdesc = this.xkbdesc;
+
+ for (i = xkbdesc.max_key_code; i >= xkbdesc.min_key_code; --i) {
+ if (xkbdesc.map.key_sym_map[i].kt_index[0] == Xkb.OneLevelIndex) {
+ if (X.keycode_to_keysym (this.xdisplay, i, 0) != 0) {
+ Gdk.error_trap_push ();
+ this.xdisplay.grab_key (i, 0,
+ Gdk.x11_get_default_root_xwindow (), true,
+ X.GrabMode.Sync, X.GrabMode.Sync);
+ this.xdisplay.flush ();
+ this.xdisplay.ungrab_key (
+ i, 0, Gdk.x11_get_default_root_xwindow ());
+ if (Gdk.error_trap_pop () == 0)
+ return i;
+ }
+ }
+ }
+
+ return (uchar) this.xdisplay.keysym_to_keycode (0x0023); // XK_numbersign
+ }
+
+ private void replace_keycode (uint keysym) {
+ if (this.reserved_keycode == 0) {
+ this.reserved_keycode = get_reserved_keycode ();
+ this.reserved_keysym = X.keycode_to_keysym (this.xdisplay,
+ this.reserved_keycode, 0);
+ }
+
+ this.xdisplay.flush ();
+ uint offset = this.xkbdesc.map.key_sym_map[this.reserved_keycode].offset;
+
+ this.xkbdesc.map.syms[offset] = keysym;
+
+ Xkb.set_map (this.xdisplay, Xkb.AllMapComponentsMask, this.xkbdesc);
+ /**
+ * FIXME: the use of XkbChangeMap, and the reuse of the priv->xkb_desc
+ * structure, would be far preferable. HOWEVER it does not seem to work
+ * using XFree 4.3.
+ **/
+
+ this.xdisplay.flush ();
+
+ if (keysym != this.reserved_keysym)
+ GLib.Timeout.add (500, reset_reserved);
+ }
+
+ private bool reset_reserved () {
+ replace_keycode (this.reserved_keysym);
+ return false;
+ }
+
+ private uchar keycode_for_keyval (uint keyval, out uint modmask) {
+ Gdk.Keymap kmap= Gdk.Keymap.get_default ();
+ Gdk.KeymapKey[] kmk;
+ uchar keycode = 0;
+
+ if (kmap.get_entries_for_keyval (keyval, out kmk)) {
+ Gdk.KeymapKey best_match = kmk[0];
+ foreach (KeymapKey km in kmk)
+ if (km.group == this.group)
+ best_match = km;
+
+ keycode = (uchar) best_match.keycode;
+ modmask = (best_match.level == 1) ? Gdk.ModifierType.SHIFT_MASK : 0;
+ } else {
+ replace_keycode (keyval);
+ keycode = this.reserved_keycode;
+ }
+
+ return keycode;
+ }
+
+ public void keyval_press (uint keyval) {
+ uint mask;
+ uchar keycode = keycode_for_keyval (keyval, out mask);
+
+ if (mask != 0)
+ mod_latch (mask);
+
+ XTest.fake_key_event (this.xdisplay, keycode, true, X.CURRENT_TIME);
+ this.xdisplay.flush ();
+ }
+
+ public void keyval_release (uint keyval) {
+ uchar keycode = keycode_for_keyval (keyval, null);
+
+ XTest.fake_key_event (this.xdisplay, keycode, false, X.CURRENT_TIME);
+ this.xdisplay.flush ();
+ }
+
+ public void mod_latch (uint mask) {
+ Xkb.latch_modifiers (this.xdisplay, Xkb.UseCoreKbd, mask, mask);
+ this.xdisplay.flush ();
+ }
+
+ public void mod_unlatch (uint mask) {
+ Xkb.latch_modifiers (this.xdisplay, Xkb.UseCoreKbd, mask, 0);
+ this.xdisplay.flush ();
+ }
+
+ public uint get_current_group (out string group_name,
+ out string variant_name) {
+ Xkl.ConfigRec config_rec = new Xkl.ConfigRec ();
+ config_rec.get_from_server (this.xkl_engine);
+ group_name = config_rec.layouts[this.group];
+ variant_name = config_rec.variants[this.group];
+
+ return this.group;
+ }
+
+ public void get_groups (out string[] group_names,
+ out string[] variant_names) {
+ int i;
+ Xkl.ConfigRec config_rec = new Xkl.ConfigRec ();
+ config_rec.get_from_server (this.xkl_engine);
+
+ for (i=0; i<4; i++)
+ if (config_rec.layouts[i] == null)
+ break;
+
+ group_names = new string[i];
+ variant_names = new string[i];
+
+ for (; i>=0; i--) {
+ group_names[i] = config_rec.layouts[i];
+ variant_names[i] = config_rec.variants[i];
+ }
+ }
+
+ public void me () {
+ stdout.printf("%p\n", this.xkl_engine);
+ }
+ }
+}
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0a869dd..5f44bd0 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,5 +1,4 @@
[encoding: UTF-8]
-caribou/ui/main.py
-caribou/ui/keyboard.py
-caribou/common/settings.py
-caribou/ui/preferences_window.py
+caribou/settings/caribou_settings.py
+caribou/__init__.py
+caribou/daemon/main.py
diff --git a/tools/fix_gir.py b/tools/fix_gir.py
new file mode 100755
index 0000000..31190e3
--- /dev/null
+++ b/tools/fix_gir.py
@@ -0,0 +1,63 @@
+#!/usr/bin/python
+
+from xml.dom import minidom
+
+def purge_white_space_and_fix_namespace(node, indent=0):
+ if getattr(node, "tagName", None) == "namespace":
+ name = node.getAttribute("name")
+ node.setAttribute("name", name.lstrip('_'))
+ for child in [c for c in node.childNodes]:
+ if child.nodeType == node.TEXT_NODE or \
+ getattr(child, "tagName", None) == "annotation":
+ node.removeChild(child)
+ continue
+ purge_white_space_and_fix_namespace(child, indent+1)
+
+def find_ancestor(node, name):
+ if getattr(node, "tagName") == name:
+ return node
+ parent = getattr(node, "parentNode", None)
+ if not parent:
+ return None
+ return find_ancestor(parent, name)
+
+def fix_vfuncs(dom):
+ for f in dom.getElementsByTagName("callback"):
+ record = find_ancestor(f, "record")
+ if not record:
+ continue
+
+ name = record.getAttribute("name")
+ cname = record.getAttribute("c:type")
+
+ assert(name.endswith("Class"))
+ assert(cname.endswith("Class"))
+
+ params = (f.getElementsByTagName("parameters") or [None])[0]
+
+ if not params:
+ params = dom.createElement("parameters")
+ f.insertBefore(params, f.firstChild)
+
+ param = dom.createElement("parameter")
+ param.setAttribute("name", "self")
+ param.setAttribute("transfer-ownership", "none")
+ ptype = dom.createElement("type")
+ ptype.setAttribute("name", name[:-5])
+ ptype.setAttribute("c:type", cname[:-5])
+ param.appendChild(ptype)
+ params.insertBefore(param, params.firstChild)
+
+if __name__ == "__main__":
+ import sys
+
+ if len(sys.argv) != 2:
+ print "supply a gir file"
+ sys.exit(1)
+
+ dom = minidom.parse(sys.argv[-1])
+
+ purge_white_space_and_fix_namespace(dom)
+ fix_vfuncs(dom)
+
+ print dom.toprettyxml(indent=" ", newl="\n")
diff --git a/tools/make_schema.py b/tools/make_schema.py
new file mode 100755
index 0000000..c9ee361
--- /dev/null
+++ b/tools/make_schema.py
@@ -0,0 +1,84 @@
+#!/usr/bin/python
+
+from gi.repository import GLib
+import xml.dom.minidom
+
+import os,sys
+sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+from caribou.settings import caribou_settings
+
+class SchemasMaker:
+ def __init__(self, settings):
+ self.settings = settings
+
+ def create_schemas(self):
+ doc = xml.dom.minidom.Document()
+ schemafile = doc.createElement('schemalist')
+ schema = doc.createElement('schema')
+ schema.setAttribute("id", self.settings.schema_id)
+ schemafile.appendChild(schema)
+ self._create_schema(self.settings, doc, schema)
+
+ fp = open("%s.gschema.xml.in" % self.settings.schema_id, 'w')
+ self._pretty_xml(fp, schemafile)
+ fp.close()
+
+ def _attribs(self, e):
+ if not e.attributes.items():
+ return ""
+ return ' ' + ' '.join(['%s="%s"' % (k,v) \
+ for k,v in e.attributes.items()])
+
+ def _pretty_xml(self, fp, e, indent=0):
+ if not e.childNodes or \
+ (len(e.childNodes) == 1 and \
+ e.firstChild.nodeType == e.TEXT_NODE):
+ fp.write('%s%s\n' % (' '*indent*2, e.toxml().strip()))
+ else:
+ fp.write('%s<%s%s>\n' % (' '*indent*2, e.tagName, self._attribs(e)))
+ for c in e.childNodes:
+ self._pretty_xml(fp, c, indent + 1)
+ fp.write('%s</%s>\n' % (' '*indent*2, e.tagName))
+
+ def _append_children_element_value_pairs(self, doc, element, pairs):
+ for e, t in pairs:
+ el = doc.createElement(e)
+ te = doc.createTextNode(str(t))
+ el.appendChild(te)
+ element.appendChild(el)
+
+ def _create_schema(self, setting, doc, schemalist):
+ if hasattr(setting, 'path'):
+ schemalist.setAttribute("path", setting.path)
+ if hasattr(setting, 'gsettings_key'):
+ key = doc.createElement('key')
+ key.setAttribute('name', setting.gsettings_key)
+ key.setAttribute('type', setting.variant_type)
+ schemalist.appendChild(key)
+ self._append_children_element_value_pairs(
+ doc, key, [('default',
+ getattr(setting.gvariant, "print")(False)),
+ ('_summary', setting.short_desc),
+ ('_description', setting.long_desc)])
+
+ for s in setting:
+ self._create_schema(s, doc, schemalist)
+
+if __name__ == "__main__":
+ from caribou.settings import AllSettings
+
+ if (len(sys.argv) != 2):
+ print "usage: %s <schema id>" % sys.argv[0]
+ sys.exit(1)
+
+ avail_settings = dict([(s.schema_id, s) for s in AllSettings])
+
+ try:
+ settings = avail_settings[sys.argv[-1]]
+ except KeyError:
+ print "Schema '%s' not available", sys.argv[-1]
+ sys.exit(1)
+
+ maker = SchemasMaker(settings)
+ maker.create_schemas()