namespace Caribou { /** * Object providing access to keyboard in scanning mode. */ public class Scanner : Object { public bool bind_settings { get; construct; default=true; } private ScanGrouping _scan_grouping; public int scan_grouping { get { return (int) _scan_grouping; } set construct { _scan_grouping = (ScanGrouping) value; if (root_group != null) root_group.scan_grouping = _scan_grouping; reset (); } } private bool _scan_enabled; public bool scan_enabled { get { return _scan_enabled; } set construct { _scan_enabled = value; if (_scan_enabled) enable (); else disable (); } } private double _step_time; public double step_time { get { return _step_time; } set construct { _step_time = value; if (scan_tid != 0) { GLib.Source.remove (scan_tid); scan_tid = GLib.Timeout.add ((int) (_step_time*1000), scan); } } } private string _switch_device; public string switch_device { get { return _switch_device; } set construct { _switch_device = value; configure_switch (); } } private string _keyboard_key; public string keyboard_key { get { return _keyboard_key; } set construct { _keyboard_key = value; configure_switch (); } } private int _mouse_button; public int mouse_button { get { return _mouse_button; } set construct { _mouse_button = value; configure_switch (); } } public int scan_cycles { get; set construct; default=1; } public bool autorestart { get; set construct; default=false; } public bool inverse_scanning { get; set construct; default=false; } private delegate void UnconfigureSwitchFunc(); private UnconfigureSwitchFunc unconfigure_switch_func; private uint scan_tid; private KeyboardModel keyboard; private IScannableGroup root_group; private bool started; construct { /* defaults */ _scan_grouping = ScanGrouping.SUBGROUPS; _step_time = 1.0; _switch_device = "keyboard"; if (bind_settings) do_bind_settings (); } private void do_bind_settings () { Settings caribou_settings = new Settings ("org.gnome.caribou"); string[] settings = {"scan-grouping", "step-time", "scan-cycles", "autorestart", "inverse-scanning", "switch-device", "keyboard-key", "mouse-button", "scan-enabled"}; foreach (string setting in settings) { caribou_settings.bind (setting, this, setting, SettingsBindFlags.GET); } } private bool select () { IScannableItem? item = root_group.child_select (); if (item is IScannableGroup) { step (); return true; } else { reset (); return false; } } private void switch_pressed (uint code, bool pressed) { if (pressed) { if (!started) { step (); start (); return; } stop (); if (inverse_scanning) { step (); start (); } else { if (select () || autorestart) start (); } } } public void set_keyboard (KeyboardModel keyboard) { GroupModel group = keyboard.get_group(keyboard.active_group); this.keyboard = keyboard; this.keyboard.notify["active-group"].connect(on_group_changed); set_active_level (group.get_level (group.active_level)); foreach (string group_name in keyboard.get_groups()) { group = keyboard.get_group(group_name); group.notify["active-level"].connect(on_level_changed); } } private void on_level_changed (Object obj, ParamSpec prop) { GroupModel group = (GroupModel) obj; set_active_level (group.get_level (group.active_level)); } private void on_group_changed (Object obj, ParamSpec prop) { GroupModel group = keyboard.get_group(keyboard.active_group); set_active_level (group.get_level (group.active_level)); } private void set_active_level (LevelModel level) { root_group = (IScannableGroup) level; root_group.scan_grouping = _scan_grouping; } public void reset () { if (root_group != null) root_group.scan_reset (); } private void enable () { configure_switch (); } private void disable () { unconfigure_switch (); } private void start () { if (started || root_group == null) return; started = true; scan_tid = GLib.Timeout.add((int) (_step_time*1000), scan); } private void stop () { if (!started) return; started = false; if (scan_tid != 0) GLib.Source.remove (scan_tid); scan_tid = 0; } private IScannableItem? step () { IScannableItem item = root_group.child_step (scan_cycles); if (item == null) { reset (); } return item; } private bool scan () { if (inverse_scanning) select (); else return (step () != null); return true; } private void unconfigure_switch () { if (unconfigure_switch_func != null) unconfigure_switch_func (); unconfigure_switch_func = null; } private void configure_switch () { if (!scan_enabled) return; unconfigure_switch (); DisplayAdapter xadapter = DisplayAdapter.get_default(); if (switch_device == "keyboard" && keyboard_key != null) { uint keyval = Gdk.keyval_from_name (keyboard_key); xadapter.register_key_func (keyval, switch_pressed); unconfigure_switch_func = () => { xadapter.register_key_func (keyval, null); }; } else if (switch_device == "mouse" && mouse_button != 0) { xadapter.register_button_func (mouse_button, switch_pressed); unconfigure_switch_func = () => { xadapter.register_key_func (mouse_button, null); }; } } } }