diff options
author | Eitan Isaacson <eitan@monotonous.org> | 2011-04-27 20:32:35 -0700 |
---|---|---|
committer | Eitan Isaacson <eitan@monotonous.org> | 2011-05-02 10:18:49 -0700 |
commit | 6294dab42aec83a4e9edd314544903a67152b7fb (patch) | |
tree | e44d70f016e22510032935816be3d58014bb847c /libcaribou | |
parent | 1242c1ea37f30109609c041de3572f5b900a2a3b (diff) | |
download | caribou-6294dab42aec83a4e9edd314544903a67152b7fb.tar.gz |
libcaribou: Implemented CaribouKeyboardModel.
Diffstat (limited to 'libcaribou')
-rw-r--r-- | libcaribou/Makefile.am | 13 | ||||
-rw-r--r-- | libcaribou/group-model.vala | 50 | ||||
-rw-r--r-- | libcaribou/json-deserializer.vala | 126 | ||||
-rw-r--r-- | libcaribou/key-model.vala | 71 | ||||
-rw-r--r-- | libcaribou/keyboard-model.vala | 49 | ||||
-rw-r--r-- | libcaribou/keyboard-service.vala | 35 | ||||
-rw-r--r-- | libcaribou/level-model.vala | 41 | ||||
-rw-r--r-- | libcaribou/row-model.vala | 22 | ||||
-rw-r--r-- | libcaribou/util.vala | 13 |
9 files changed, 418 insertions, 2 deletions
diff --git a/libcaribou/Makefile.am b/libcaribou/Makefile.am index ca2b6b7..90cc34b 100644 --- a/libcaribou/Makefile.am +++ b/libcaribou/Makefile.am @@ -9,7 +9,8 @@ libcaribou_la_VALAFLAGS = \ -H caribou.h --vapi caribou-1.0.vapi \ -h caribou-internals.h \ --vapidir=. \ - --pkg x11 --pkg libxklavier --pkg external-libs --pkg gdk-3.0 --pkg gdk-x11-3.0 \ + --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) @@ -29,7 +30,15 @@ libcaribou_la_LIBADD = \ $(LIBCARIBOU_LIBS) libcaribou_la_SOURCES = \ - xadapter.vala + 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 \ 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/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 |