From c35d19ab7d43328c33e9b1916f8508df944c2fc3 Mon Sep 17 00:00:00 2001 From: David Pellicer Date: Tue, 7 Dec 2010 09:19:56 -0800 Subject: Added scanning support. --- caribou/common/const.py | 22 +++ caribou/ui/Makefile.am | 1 + caribou/ui/__init__.py | 2 +- caribou/ui/keyboard.py | 241 +++++++++++++++++++++++++- caribou/ui/main.py | 7 +- caribou/ui/scan.py | 438 ++++++++++++++++++++++++++++++++++++++++++++++++ caribou/ui/window.py | 6 + data/caribou-prefs.ui | 309 +++++++++++++++++++++++++++++++++- 8 files changed, 1020 insertions(+), 6 deletions(-) create mode 100644 caribou/ui/scan.py diff --git a/caribou/common/const.py b/caribou/common/const.py index 202bc16..ecb61da 100644 --- a/caribou/common/const.py +++ b/caribou/common/const.py @@ -56,3 +56,25 @@ KEY_MASKS = {'shift': gtk.gdk.SHIFT_MASK, 'button3': gtk.gdk.BUTTON3_MASK, 'button4': gtk.gdk.BUTTON4_MASK, 'button5': gtk.gdk.BUTTON5_MASK} + +# Scan constans +BUTTON = 'button' +ROW = '1' +BLOCK = '0' +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 diff --git a/caribou/ui/Makefile.am b/caribou/ui/Makefile.am index f4a352d..27046b4 100644 --- a/caribou/ui/Makefile.am +++ b/caribou/ui/Makefile.am @@ -5,6 +5,7 @@ caribou_ui_PYTHON = \ animation.py \ i18n.py \ keyboard.py \ + scan.py \ main.py \ opacity.py \ window.py diff --git a/caribou/ui/__init__.py b/caribou/ui/__init__.py index 8d1c8b6..8b13789 100644 --- a/caribou/ui/__init__.py +++ b/caribou/ui/__init__.py @@ -1 +1 @@ - + diff --git a/caribou/ui/keyboard.py b/caribou/ui/keyboard.py index ace93b0..e395af8 100644 --- a/caribou/ui/keyboard.py +++ b/caribou/ui/keyboard.py @@ -23,6 +23,7 @@ # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import caribou.common.const as const +import caribou.ui.scan as scan import gconf import gobject import gtk @@ -31,6 +32,7 @@ import sys import virtkey import os import traceback +from caribou.ui.i18n import _ try: import json except ImportError: @@ -119,6 +121,150 @@ class KeyboardPreferences: self._on_default_font_toggled, client, key_font_button) + reverse_scanning_checkbox = builder.get_object( + "reverse_scanning_checkbox") + + reverse_scanning = client.get_bool(const.CARIBOU_GCONF + + "/reverse_scanning") + if reverse_scanning is None: + reverse_scanning is False + reverse_scanning_checkbox.set_active(reverse_scanning) + reverse_scanning_checkbox.connect('toggled', + self._on_reverse_scanning_toggled, + client) + + block_scanning_color_button = builder.get_object("block_scanning_color_button") + block_scanning_color_string = client.get_string(const.CARIBOU_GCONF + + "/block_scanning_color") or "purple" + block_scanning_color = gtk.gdk.Color(block_scanning_color_string) + block_scanning_color_button.set_color(block_scanning_color) + block_scanning_color_button.connect("color-set", + self._on_block_scanning_color_set, + client) + + row_scanning_color_button = builder.get_object("row_scanning_color_button") + row_scanning_color_string = client.get_string(const.CARIBOU_GCONF + + "/row_scanning_color") or "blue" + row_scanning_color = gtk.gdk.Color(row_scanning_color_string) + row_scanning_color_button.set_color(row_scanning_color) + row_scanning_color_button.connect("color-set", + self._on_row_scanning_color_set, + client) + + button_scanning_color_button = builder.get_object("button_scanning_color_button") + button_scanning_color_string = client.get_string(const.CARIBOU_GCONF + + "/button_scanning_color") or "green" + button_scanning_color = gtk.gdk.Color(button_scanning_color_string) + button_scanning_color_button.set_color(button_scanning_color) + button_scanning_color_button.connect("color-set", + self._on_button_scanning_color_set, + client) + + cancel_scanning_color_button = builder.get_object( + "cancel_scanning_color_button") + cancel_scanning_color_string = client.get_string(const.CARIBOU_GCONF + + "/cancel_scanning_color") or "red" + cancel_scanning_color = gtk.gdk.Color(cancel_scanning_color_string) + cancel_scanning_color_button.set_color(cancel_scanning_color) + cancel_scanning_color_button.connect("color-set", + self._on_cancel_scanning_color_set, + client) + scanning_type_combo = builder.get_object("scanning_type_combo") + scanning_type_combo.connect("changed", + self._on_scanning_type_combo_changed, + client) + types = [_("block"), _("row")] + for type in types: + scanning_type_combo.append_text(type) + type = client.get_string(const.CARIBOU_GCONF + "/scanning_type") + try: + scanning_type_combo.set_active(int(type)) + except: + scanning_type_combo.set_active(0) + + + mouse_button_combo = builder.get_object("mouse_button_combo") + mouse_button_combo.connect("changed", + self._on_mouse_button_combo_changed, + client) + mouse_buttons = [_("Left"), _("Center"), _("Right")] + for button in mouse_buttons: + mouse_button_combo.append_text(button) + button = client.get_string(const.CARIBOU_GCONF + "/mouse_button") + try: + mouse_button_combo.set_active(int(button)-1) + except: + mouse_button_combo.set_active(0) + + + keyboard_key_combo = builder.get_object("keyboard_key_combo") + keyboard_keys = const.KEYBOARD_KEY_LIST.keys() + keyboard_values = const.KEYBOARD_KEY_LIST.values() + for key in keyboard_keys: + keyboard_key_combo.append_text(key) + key = client.get_string(const.CARIBOU_GCONF + "/keyboard_key") + try: + keyboard_key_combo.set_active(keyboard_values.index(key)) + except: + keyboard_key_combo.set_active(0) + + keyboard_key_combo.connect("changed", + self._on_keyboard_key_combo_changed, + client) + + mouse_switch_radio = builder.get_object("mouse_switch_radio") + keyboard_switch_radio = builder.get_object("keyboard_switch_radio") + mouse_switch_radio.connect("toggled", self._on_switch_radio_toggled, + client, mouse_button_combo, + keyboard_key_combo) + + switch_type = client.get_string(const.CARIBOU_GCONF + "/switch_type") + if switch_type == const.KEYBOARD_SWITCH_TYPE: + keyboard_switch_radio.set_active(True) + else: + mouse_switch_radio.set_active(True) + + step_time_spin = builder.get_object("step_time_spin") + step_time_spin.set_value(client.get_int(const.CARIBOU_GCONF + + "/step_time")) + step_time_spin.connect("value_changed", + self._on_step_time_spin_changed, client) + + scan_enabled_checkbox = builder.get_object("scan_enabled_checkbox") + scan_enabled = client.get_bool(const.CARIBOU_GCONF + "/scan_enabled") + if scan_enabled is None: + scan_enabled is False + + scan_enabled_checkbox.set_active(scan_enabled) + + self._on_scan_enabled_toggled(scan_enabled_checkbox, + client, reverse_scanning_checkbox, + row_scanning_color_button, + button_scanning_color_button, + block_scanning_color_button, + cancel_scanning_color_button, + mouse_switch_radio, + keyboard_switch_radio, + mouse_button_combo, + keyboard_key_combo, + scanning_type_combo, + step_time_spin) + + scan_enabled_checkbox.connect('toggled', + self._on_scan_enabled_toggled, client, + reverse_scanning_checkbox, + row_scanning_color_button, + block_scanning_color_button, + button_scanning_color_button, + cancel_scanning_color_button, + mouse_switch_radio, + keyboard_switch_radio, + mouse_button_combo, + keyboard_key_combo, + scanning_type_combo, + step_time_spin) + + kbds = self._fetch_keyboards() for kbddef in kbds: layout_combo.append_text(kbddef) @@ -149,6 +295,36 @@ class KeyboardPreferences: normal_color_button.set_sensitive(not use_defaults) mouse_over_color_button.set_sensitive(not use_defaults) + def _on_scan_enabled_toggled(self, scan_enabled_checkbox, + gconf_client, *args): + scan_enabled = scan_enabled_checkbox.get_active() + gconf_client.set_bool(const.CARIBOU_GCONF + "/scan_enabled", scan_enabled) + for arg in args: + arg.set_sensitive(scan_enabled) + + def _on_reverse_scanning_toggled(self, reverse_scanning_checkbox, + gconf_client): + reverse_scanning = reverse_scanning_checkbox.get_active() + gconf_client.set_bool(const.CARIBOU_GCONF + "/reverse_scanning", + reverse_scanning) + def _on_switch_radio_toggled(self, mouse_switch_radio, + gconf_client, mouse_button_combo, + keyboard_key_combo): + mouse_switch = mouse_switch_radio.get_active() + if mouse_switch: + gconf_client.set_string(const.CARIBOU_GCONF + "/switch_type", + const.MOUSE_SWITCH_TYPE) + else: + gconf_client.set_string(const.CARIBOU_GCONF + "/switch_type", + const.KEYBOARD_SWITCH_TYPE) + mouse_button_combo.set_sensitive(mouse_switch) + keyboard_key_combo.set_sensitive(not mouse_switch) + + def _on_step_time_spin_changed(self, step_time_spin, gconf_client): + gconf_client.set_int(const.CARIBOU_GCONF + "/step_time", + step_time_spin.get_value_as_int()) + + def destroy(self, widget, data = None): self.window.destroy() @@ -167,13 +343,46 @@ class KeyboardPreferences: def _on_layout_changed(self, combobox, client): kbdname = combobox.get_active_text() - if kbdname: + actual_layout = client.get_string("/apps/caribou/osk/layout") + if kbdname and kbdname != actual_layout: client.set_string("/apps/caribou/osk/layout", kbdname) + def _on_scanning_type_combo_changed(self, scanning_type_combo, gconf_client): + value = str(scanning_type_combo.get_active()) + if value: + gconf_client.set_string(const.CARIBOU_GCONF + "/scanning_type", value) + + def _on_mouse_button_combo_changed(self, mouse_button_combo, client): + value = mouse_button_combo.get_active() + 1 + if value: + client.set_string(const.CARIBOU_GCONF + "/mouse_button", str(value)) + + def _on_keyboard_key_combo_changed(self, keyboard_key_combo, client): + value = keyboard_key_combo.get_active_text() + if value: + client.set_string(const.CARIBOU_GCONF + "/keyboard_key", + const.KEYBOARD_KEY_LIST[value]) + def _on_normal_state_color_set(self, colorbutton, client): color = colorbutton.get_color().to_string() client.set_string(const.CARIBOU_GCONF + "/normal_color", color) + def _on_block_scanning_color_set(self, colorbutton, client): + color = colorbutton.get_color().to_string() + client.set_string(const.CARIBOU_GCONF + "/block_scanning_color", color) + + def _on_row_scanning_color_set(self, colorbutton, client): + color = colorbutton.get_color().to_string() + client.set_string(const.CARIBOU_GCONF + "/row_scanning_color", color) + + def _on_button_scanning_color_set(self, colorbutton, client): + color = colorbutton.get_color().to_string() + client.set_string(const.CARIBOU_GCONF + "/button_scanning_color", color) + + def _on_cancel_scanning_color_set(self, colorbutton, client): + color = colorbutton.get_color().to_string() + client.set_string(const.CARIBOU_GCONF + "/cancel_scanning_color", color) + def _on_mouse_over_color_set(self, colorbutton, client): color = colorbutton.get_color().to_string() client.set_string(const.CARIBOU_GCONF + "/mouse_over_color", color) @@ -433,10 +642,14 @@ class CaribouKeyboard(gtk.Notebook): self._gconf_connections.append(self.client.notify_add( const.CARIBOU_GCONF + "/key_font", self._key_font_changed)) + self._gconf_connections.append(self.client.notify_add( + const.CARIBOU_GCONF + "/scan_enabled", + self._scan_enabled)) self.connect('size-allocate', self._on_size_allocate) self.row_height = -1 + self.scan_enabled = False self.keyboard_preferences = KeyboardPreferences() def reset_row_height(self): @@ -466,6 +679,7 @@ class CaribouKeyboard(gtk.Notebook): layouts = kb_deserializer.deserialize(kb_location) self._set_layouts(layouts) self._update_key_style() + self._enable_scanning() def _set_layouts(self, layout_list): self._clear() @@ -486,6 +700,9 @@ class CaribouKeyboard(gtk.Notebook): key.connect('clicked', self._pressed_normal_key) + def _scan_enabled(self, client, connection_id, entry, args): + self._enable_scanning() + def _colors_changed(self, client, connection_id, entry, args): self._update_key_style() @@ -543,6 +760,8 @@ class CaribouKeyboard(gtk.Notebook): def show_all(self): self.set_current_page(self.current_page) gtk.Notebook.show_all(self) + if self.scan_enabled: + self.scan_service.start() def is_preferences_open(self): if self.keyboard_preferences.window.window and \ @@ -554,7 +773,24 @@ class CaribouKeyboard(gtk.Notebook): def _pressed_preferences_key(self, key): self.keyboard_preferences.window.show_all() + def _enable_scanning(self): + enable = self.client.get_bool(const.CARIBOU_GCONF + '/scan_enabled') + if enable: + current_layout = self.get_nth_page(self.current_page) + if current_layout and not self.scan_enabled: + self.scan_service = scan.Scan_service(current_layout.rows, + self.get_parent().get_parent()) + self.scan_enabled = True + elif self.scan_enabled: + self.scan_service.destroy() + self.scan_service = None + self.scan_enabled = False + else: + self.scan_enabled = False + def destroy(self): + if self.scan_enabled: + self.scan_service.destroy() for id in self._gconf_connections: self.client.notify_remove(id) super(gtk.Notebook, self).destroy() @@ -565,4 +801,7 @@ class CaribouKeyboard(gtk.Notebook): if self.get_nth_page(i).layout_name == name: self.set_current_page(i) self.current_page = i + if self.scan_enabled: + self.scan_service.change_keyboard( + self.get_nth_page(i).rows) break diff --git a/caribou/ui/main.py b/caribou/ui/main.py index 0f99398..013cabf 100644 --- a/caribou/ui/main.py +++ b/caribou/ui/main.py @@ -131,9 +131,10 @@ class Caribou: if debug == True: print "leave entry widget in", event.host_application.name else: - print _("WARNING - Caribou: unhandled editable widget:"), event.source + if debug == True: + print _("WARNING - Caribou: unhandled editable widget:"), event.source - # Firefox does report leave entry widget events. + # 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: @@ -180,3 +181,5 @@ class Caribou: if debug == True: print "deregisterKeystrokeListener" gtk.main_quit() + + diff --git a/caribou/ui/scan.py b/caribou/ui/scan.py new file mode 100644 index 0000000..0964af1 --- /dev/null +++ b/caribou/ui/scan.py @@ -0,0 +1,438 @@ +import gobject +import pyatspi +import gtk +import caribou.common.const as const +import gconf + +class Scan_service(): + def __init__(self, keyboard, root_window): + self.keyboard = keyboard + self.root_window = root_window + self.selected_row = None + self.selected_button = None + self.button_index = 0 + self.row_index = 0 + self.index_i = 0 + self.index_j = 0 + self.is_stop = True + self.timerid = None + self.reverse = False + self.selected_block = [] + self.client = gconf.client_get_default() + self._gconf_connections = [] + self._gconf_connections.append(self.client.notify_add( + const.CARIBOU_GCONF + "/scanning_type", + self._on_scanning_type_changed)) + self._gconf_connections.append(self.client.notify_add( + const.CARIBOU_GCONF + "/step_time", + self._on_scanning_type_changed)) + self._gconf_connections.append(self.client.notify_add( + const.CARIBOU_GCONF + "/reverse_scanning", + self._on_scanning_type_changed)) + self._gconf_connections.append(self.client.notify_add( + const.CARIBOU_GCONF + "/switch_type", + self._on_switch_changed)) + self._gconf_connections.append(self.client.notify_add( + const.CARIBOU_GCONF + "/mouse_button", + self._on_switch_changed)) + self._gconf_connections.append(self.client.notify_add( + const.CARIBOU_GCONF + "/keyboard_key", + self._on_switch_changed)) + + self._gconf_connections.append(self.client.notify_add( + const.CARIBOU_GCONF + "/default_colors", + self._on_color_changed)) + self._gconf_connections.append(self.client.notify_add( + const.CARIBOU_GCONF + "/normal_color", + self._on_color_changed)) + self._gconf_connections.append(self.client.notify_add( + const.CARIBOU_GCONF + "/mouse_over_color", + self._on_color_changed)) + self._gconf_connections.append(self.client.notify_add( + const.CARIBOU_GCONF + "/row_scanning_color", + self._on_color_changed)) + self._gconf_connections.append(self.client.notify_add( + const.CARIBOU_GCONF + "/button_scanning_color", + self._on_color_changed)) + self._gconf_connections.append(self.client.notify_add( + const.CARIBOU_GCONF + "/cancel_scanning_color", + self._on_color_changed)) + self._gconf_connections.append(self.client.notify_add( + const.CARIBOU_GCONF + "/block_scanning_color", + self._on_color_changed)) + self._configure_scanning() + self._set_colors() + self._configure_switch() + + def destroy(self): + self.stop() + self.clean() + self._deregister_events() + for id in self._gconf_connections: + self.client.notify_remove(id) + + + + def _configure_switch(self): + self.switch_type = self.client.get_string(const.CARIBOU_GCONF + + "/switch_type") or "mouse" + if self.switch_type == const.MOUSE_SWITCH_TYPE: + self.switch_key = self.client.get_string(const.CARIBOU_GCONF + + "/mouse_button") or "2" + elif self.switch_type == const.KEYBOARD_SWITCH_TYPE: + self.switch_key = self.client.get_string(const.CARIBOU_GCONF + + "/keyboard_key") or "Shift_L" + try: + pyatspi.Registry.registerKeystrokeListener(self._on_key_pressed, + mask=None, kind=(pyatspi.KEY_PRESSED_EVENT,)) + pyatspi.Registry.registerKeystrokeListener(self._on_key_released, + mask=None, kind=(pyatspi.KEY_RELEASED_EVENT,)) + except: + print "Error while registering keyboard events in scan.py" + + def _deregister_events(self): + try: + pyatspi.Registry.deregisterKeystrokeListener(self._on_key_pressed, + mask=None, kind=(pyatspi.KEY_PRESSED_EVENT,)) + pyatspi.Registry.deregisterKeystrokeListener( + self._on_key_released, + mask=None, kind=(pyatspi.KEY_RELEASED_EVENT,)) + except: + print "Error while deregistering keyboard events in scan.py" + + def _on_switch_changed(self, client, connection_id, entry, args): + self._deregister_events() + self._configure_switch() + + def _on_color_changed(self, client, connection_id, entry, args): + self._set_colors() + + def _on_scanning_type_changed(self, client, connection_id, entry, args): + self._configure_scanning() + + def _configure_scanning(self): + if not self.is_stop: + self._stop() + self.scanning_type = self.client.get_string(const.CARIBOU_GCONF + + "/scanning_type") or "0" + self.reverse = self.client.get_bool(const.CARIBOU_GCONF + + "/reverse_scanning") or False + self.step_time = self.client.get_int(const.CARIBOU_GCONF + + "/step_time") or 1000 + if self.scanning_type == const.BLOCK: + self.selected_block = [] + else: + self.selected_block = self.keyboard + self.scanning = self.scanning_type + + def _set_colors(self): + self.default_colors = self.client.get_bool( + const.CARIBOU_GCONF + "/default_colors") \ + or True + self.normal_color = self.client.get_string( + const.CARIBOU_GCONF + "/normal_color") \ + or "gray80" + self.mouse_over_color = self.client.get_string( + const.CARIBOU_GCONF + "/mouse_over_color") \ + or "yellow" + + self.row_scanning_color = self.client.get_string( + const.CARIBOU_GCONF + "/row_scanning_color") \ + or "green" + self.button_scanning_color = self.client.get_string( + const.CARIBOU_GCONF + "/button_scanning_color") \ + or "cyan" + self.cancel_scanning_color = self.client.get_string( + const.CARIBOU_GCONF + "/cancel_scanning_color") \ + or "red" + self.block_scanning_color = self.client.get_string( + const.CARIBOU_GCONF + "/block_scanning_color") \ + or "purple" + + + # public start + def start(self, scanning=None): + self.scanning = scanning or self.scanning_type + self.clean() + if self.root_window and \ + self.switch_type == const.MOUSE_SWITCH_TYPE: + self._grab_mouse_events() + + if not self.reverse: + self.reset(self.scanning) + + # public stop + def stop(self): + if self.switch_type == const.MOUSE_SWITCH_TYPE: + self._ungrab_mouse_events() + self.clean() + self._stop() + + #private start + def _start(self, scanning=const.ROW): + if self.is_stop == True and self.timerid == None: + self.is_stop = False + self.button_index = -1 + self.row_index = -1 + if scanning == const.ROW: + self.selected_row = [] + self.timerid = gobject.timeout_add(self.step_time, self._scan_row) + elif scanning == const.BUTTON: + self.selected_button = None + self.timerid = gobject.timeout_add(self.step_time, self._scan_button) + elif scanning == const.BLOCK: + self.selected_block = [] + self.selected_row = [] + self.clean() + self.index_i = 2 + self.index_j = 1 + self.timerid = gobject.timeout_add(self.step_time, self._scan_block) + + # private stop + def _stop(self): + self.is_stop = True + if self.timerid: + gobject.source_remove(self.timerid) + self.timerid = None + + def reset(self, scanning=const.ROW): + self._stop() + self._start(scanning) + + def clean(self): + for row in self.keyboard: + for button in row: + self.select_button(button, False) + + + def change_keyboard(self, keyboard): + if not self.is_stop: + self._stop() + self.keyboard = keyboard + self.scanning = self.scanning_type + self.start(self.scanning_type) + if self.scanning == const.ROW: + self.selected_block = keyboard + + + def _grab_mouse_events(self): + gtk.gdk.event_handler_set(self._mouse_handler) + + def _ungrab_mouse_events(self): + gtk.gdk.event_handler_set(gtk.main_do_event) + + def _mouse_handler(self, event): + if self.root_window.window.is_visible(): + if event.type == gtk.gdk.BUTTON_PRESS and \ + str(event.button) == self.switch_key: + self._handle_press() + elif event.type == gtk.gdk.BUTTON_RELEASE and \ + str(event.button) == self.switch_key: + self._handle_release() + elif not event.type == gtk.gdk.ENTER_NOTIFY: + gtk.main_do_event(event) + else: + gtk.main_do_event(event) + + def _scan_block(self): + if self.is_stop: + return False + # Clean the previous block + self.select_block(self.selected_block, False) + # Update indexes, three horizontal blocks, and two vertical + if self.index_j < 2: + self.index_j += 1 + elif self.index_i < 1: + self.index_i += 1 + self.index_j = 0 + else: + self.index_j = 0 + self.index_i = 0 + + self.selected_block = [] + width = self.root_window.size_request()[0] + height = self.root_window.size_request()[1] + root_x = self.root_window.get_position()[0] + root_y = self.root_window.get_position()[1] + offset_w = self.index_j*(width/3) + offset_h = self.index_i*(height/2) + + block_window = gtk.gdk.Rectangle(root_x + offset_w, + root_y + offset_h, + width/3, + height/2) + empty_r = gtk.gdk.Rectangle() + try: + for row in self.keyboard: + line = [] + for button in row: + abs_b_x = button.get_allocation()[0] + \ + button.window.get_position()[0] + abs_b_y = button.get_allocation()[1] + \ + button.window.get_position()[1] + abs_b_r = gtk.gdk.Rectangle(abs_b_x, + abs_b_y, + button.size_request()[0], + button.size_request()[1]) + + # If button rectangle is inside the block: + intersect = block_window.intersect(abs_b_r) + # If the intersected rectangle != empty + if intersect != empty_r: + # If the witdth of intersection is bigger than half + # of button width and height, we append button to line + if (intersect.width > (abs_b_r.width / 2)) and \ + (intersect.height > (abs_b_r.height / 2)): + line.append(button) + + + if len(line) > 0: + self.selected_block.append(line) + + except Exception as e: + self.is_stop = True + return False + + self.select_block(self.selected_block, True, + self.block_scanning_color) + return True + + + + def _scan_row(self): + if self.is_stop: + return False + + else: + self.select_row(self.selected_row, + self.scanning_type == const.BLOCK, + self.block_scanning_color) + self.row_index += 1 + if self.row_index >= len(self.selected_block): + self.row_index = 0 + self.selected_row = self.selected_block[self.row_index] + self.select_row(self.selected_row, True, self.row_scanning_color) + return True + + def _scan_button(self): + if self.scanning == const.CANCEL: + self.scanning = const.BUTTON + self.selected_button = None + self.select_row(self.selected_row, True, self.row_scanning_color) + return True + else: + if self.selected_button and self.selected_button in self.selected_row: + self.select_button(self.selected_button, True, self.row_scanning_color) + + if self.is_stop: + return False + + self.button_index += 1 + if self.button_index >= len(self.selected_row): + self.select_row(self.selected_row, True, self.cancel_scanning_color) + self.button_index = -1 + self.scanning = const.CANCEL + return True + + self.selected_button = self.selected_row[self.button_index] + while self.selected_button.key_type == const.DUMMY_KEY_TYPE: + self.button_index += 1 + if self.button_index >= len(self.selected_row): + self.select_row(self.selected_row, True, self.cancel_scanning_color) + self.button_index = -1 + self.scanning = const.CANCEL + return True + + self.selected_button = self.selected_row[self.button_index] + self.select_button(self.selected_button, True, self.button_scanning_color) + return True + + def select_block(self, block, state, color=None): + for row in block: + self.select_row(row, state, color) + + def select_row(self, row, state, color=None): + for button in row: + self.select_button(button, state, color) + + def select_button(self, button, state, color=None): + if state: + button.set_color(color, self.mouse_over_color) + elif self.default_colors: + button.reset_color() + else: + button.set_color(self.normal_color, self.mouse_over_color) + + + def _on_key_pressed(self, event): + if event.event_string == "Escape": + self.stop() + elif self.switch_type == const.KEYBOARD_SWITCH_TYPE and \ + self.switch_key == event.event_string: + self._handle_press() + + def _on_key_released(self, event): + if self.switch_type == const.KEYBOARD_SWITCH_TYPE and \ + self.switch_key == event.event_string: + self._handle_release() + elif event.event_string != "Escape": + self._stop() + self.start() + + def _handle_press(self): + if self.reverse: + self._start(self.scanning) + + def _handle_release(self): + if self.reverse: + if not self.is_stop: + if self.scanning == const.ROW and \ + len(self.selected_row) > 0: + self.scanning = const.BUTTON + elif self.scanning == const.BLOCK and \ + len(self.selected_block) > 0: + self.scanning = const.ROW + elif self.scanning == const.BUTTON and \ + self.selected_button: + self.clean() + if self.selected_button.key_type == const.PREFERENCES_KEY_TYPE: + self.stop() + self.selected_button.clicked() + self.selected_button = None + self.scanning = self.scanning_type + self.reset() + + elif self.scanning == const.CANCEL: + self.clean() + self.scanning = self.scanning_type + self._stop() + + else: + if not self.is_stop: + if self.scanning == const.ROW and \ + len(self.selected_row) > 0: + self.scanning = const.BUTTON + self.reset(const.BUTTON) + + elif self.scanning == const.BLOCK and \ + len(self.selected_block) > 0: + self.scanning = const.ROW + self.reset(const.ROW) + elif self.scanning == const.BUTTON and \ + self.selected_button: + self.selected_button.clicked() + self.scanning = const.ROW + if self.selected_button.key_type \ + == const.PREFERENCES_KEY_TYPE: + self.selected_button = None + self.stop() + else: + self.selected_button = None + self.scanning = self.scanning_type + + elif self.scanning == const.CANCEL: + self.scanning = self.scanning_type + self.clean() + self.reset(self.scanning_type) + + diff --git a/caribou/ui/window.py b/caribou/ui/window.py index 08d3e2f..0ed5c90 100644 --- a/caribou/ui/window.py +++ b/caribou/ui/window.py @@ -59,6 +59,11 @@ class CaribouWindow(gtk.Window): self.connect('show', self._on_window_show) + def destroy(self): + self.keyboard.destroy() + super(gtk.Window, self).destroy() + + def set_cursor_location(self, cursor_location): self._cursor_location = cursor_location self._update_position() @@ -225,6 +230,7 @@ class CaribouWindowEntry(CaribouWindow): CaribouWindow.__init__(self, text_entry_mech, placement, min_alpha=0.075, max_alpha=0.8) + def _calculate_axis(self, axis_placement, root_bbox): offset = CaribouWindow._calculate_axis(self, axis_placement, root_bbox) diff --git a/data/caribou-prefs.ui b/data/caribou-prefs.ui index 97fcec0..bdc75e9 100644 --- a/data/caribou-prefs.ui +++ b/data/caribou-prefs.ui @@ -322,10 +322,290 @@ - + + True + + + True + 10 + 2 + + + _Scan enabled + True + True + False + True + True + + + 2 + + + + + Re_verse scanning + True + True + False + True + True + + + 2 + 1 + 2 + + + + + True + 0.05000000074505806 + Ste_p time: + True + + + 9 + 10 + + + + + True + True + + adjustment1 + + + 1 + 2 + 9 + 10 + + + + + _Keyboard switch + True + True + False + True + True + mouse_switch_radio + + + 8 + 9 + + + + + True + liststore4 + + + + 0 + + + + + 1 + 2 + 8 + 9 + + + + + True + liststore3 + + + + 0 + + + + + 1 + 2 + 7 + 8 + + + + + _Mouse switch + True + True + False + True + True + True + + + 7 + 8 + + + + + True + liststore2 + + + + 0 + + + + + 1 + 2 + 6 + 7 + + + + + True + 0.05000000074505806 + Scanning _type: + True + + + 6 + 7 + + + + + True + True + True + #000000000000 + + + 1 + 2 + 5 + 6 + + + + + True + 0.05000000074505806 + _Cancel color: + True + + + 5 + 6 + + + + + True + True + True + #000000000000 + + + 1 + 2 + 4 + 5 + + + + + True + 0.05000000074505806 + _Button color: + True + + + 4 + 5 + + + + + True + True + True + #000000000000 + + + 1 + 2 + 3 + 4 + + + + + True + 0.05000000074505806 + _Row color: + True + start + + + 3 + 4 + GTK_FILL + + + + + True + 0.05000000074505806 + B_lock color: + True + start + + + 2 + 3 + GTK_FILL + + + + + True + True + True + #000000000000 + + + 1 + 2 + 2 + 3 + + + + + 0 + + + + + 3 + - + + True + Scanning + + + 3 + False + @@ -368,4 +648,29 @@ button_close + + + + + + + + + + + + + + + + + + + + 1000 + 100 + 10000 + 10 + 100 + -- cgit v1.2.1