From 1788b7a040fcb6074ab2bbf322e2385be5661b28 Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Tue, 14 Dec 2010 15:54:07 -0800 Subject: Transitioned to introspection GTK3. Things that are not working yet: - GConf notification. Not critical, will get it working when we move to GSettings. - Scanning. The module needs a lot of work anyway, will probably be doing alot of cleanup with transition. - Proximity opacity. This has been a hidden feature anyway. - Animation. Ditto, it's been hidden. Need to expose those two settings in the UI. --- bin/caribou.in | 6 +- caribou/common/setting_types.py | 38 +++++-- caribou/common/settings.py | 2 +- caribou/common/settings_manager.py | 25 +++-- caribou/ui/animation.py | 26 +++-- caribou/ui/keyboard.py | 223 +++++++++++++++---------------------- caribou/ui/main.py | 48 ++++---- caribou/ui/opacity.py | 4 +- caribou/ui/preferences_window.py | 99 +++++++++------- caribou/ui/scan.py | 27 ++--- caribou/ui/window.py | 115 +++++++++++-------- 11 files changed, 322 insertions(+), 291 deletions(-) diff --git a/bin/caribou.in b/bin/caribou.in index 9e8e0ae..1c2235c 100644 --- a/bin/caribou.in +++ b/bin/caribou.in @@ -27,7 +27,7 @@ from optparse import OptionParser import gettext import sys -import gtk +from gi.repository import Gtk import os # We can't rely on prefix if we're installed by relocated RPM. Instead, we @@ -67,6 +67,6 @@ if __name__ == "__main__": main.debug = options.debug caribou = main.Caribou() - caribou.window.hide_all() + caribou.window.hide() - gtk.main() + Gtk.main() diff --git a/caribou/common/setting_types.py b/caribou/common/setting_types.py index 17faa61..5b8aa95 100644 --- a/caribou/common/setting_types.py +++ b/caribou/common/setting_types.py @@ -1,4 +1,5 @@ import gobject +from gi.repository import GConf GCONF_DIR="/apps/caribou/osk/" @@ -36,7 +37,6 @@ class Setting(gobject.GObject): self._sensitive = sensitive self.emit('sensitivity-changed', sensitive) - def __len__(self): return len(self.children) @@ -56,7 +56,7 @@ class SettingsGroup(Setting): pass class ValueSetting(Setting): - gconf_type = '' + gconf_type = GConf.ValueType.INVALID entry_type=ENTRY_DEFAULT def __init__(self, name, label, default, short_desc="", long_desc="", allowed=[], entry_type=ENTRY_DEFAULT, sensitive=None, @@ -80,7 +80,7 @@ class ValueSetting(Setting): @value.setter def value(self, val): - _val = self.convert_value(val) + _val = self.convert_value(self._from_gconf_value(val)) if self.allowed and _val not in [a for a, b in self.allowed]: raise ValueError, "'%s' not a valid value" % _val self._value = _val @@ -98,8 +98,32 @@ class ValueSetting(Setting): def gconf_default(self): return self.default + def set_gconf_value(self, val): + if val.type == GConf.ValueType.BOOL: + return val.set_bool(self.value) + if val.type == GConf.ValueType.FLOAT: + return val.set_float(self.value) + if val.type == GConf.ValueType.INT: + return val.set_int(self.value) + if val.type == GConf.ValueType.STRING: + return val.set_string(self.value) + + def _from_gconf_value(self, val): + if not isinstance(val, GConf.Value): + return val + if val.type == GConf.ValueType.BOOL: + return val.get_bool() + if val.type == GConf.ValueType.FLOAT: + return val.get_float() + if val.type == GConf.ValueType.INT: + return val.get_int() + if val.type == GConf.ValueType.STRING: + return val.get_string() + + return val.to_string() + class BooleanSetting(ValueSetting): - gconf_type = 'boolean' + gconf_type = GConf.ValueType.BOOL entry_type = ENTRY_CHECKBOX def convert_value(self, val): # Almost anything could be a boolean. @@ -110,7 +134,7 @@ class BooleanSetting(ValueSetting): str(self.default).lower() class IntegerSetting(ValueSetting): - gconf_type = 'int' + gconf_type = GConf.ValueType.INT entry_type = ENTRY_SPIN def __init__(self, *args, **kwargs): self.min = kwargs.pop('min', gobject.G_MININT) @@ -121,7 +145,7 @@ class IntegerSetting(ValueSetting): return int(val) class FloatSetting(ValueSetting): - gconf_type = 'float' + gconf_type = GConf.ValueType.FLOAT entry_type = ENTRY_SPIN def __init__(self, *args, **kwargs): self.min = kwargs.pop('min', gobject.G_MINFLOAT) @@ -132,7 +156,7 @@ class FloatSetting(ValueSetting): return float(val) class StringSetting(ValueSetting): - gconf_type = 'string' + gconf_type = GConf.ValueType.STRING def convert_value(self, val): return str(val) diff --git a/caribou/common/settings.py b/caribou/common/settings.py index 179974a..09a23a9 100644 --- a/caribou/common/settings.py +++ b/caribou/common/settings.py @@ -166,7 +166,7 @@ if __name__ == "__main__": doc, schema, [('key', '/schemas' + setting.gconf_key), ('applyto', setting.gconf_key), ('owner', 'caribou'), - ('type', setting.gconf_type), + ('type', setting.gconf_type.value_nick), ('default', setting.gconf_default)]) locale = doc.createElement('locale') locale.setAttribute('name', 'C') diff --git a/caribou/common/settings_manager.py b/caribou/common/settings_manager.py index 256ef76..92b5137 100644 --- a/caribou/common/settings_manager.py +++ b/caribou/common/settings_manager.py @@ -1,5 +1,5 @@ import os -import gconf +from gi.repository import GConf from setting_types import * from settings import settings import const @@ -7,9 +7,9 @@ import const class _SettingsManager(object): def __init__(self, settings): self.groups = settings - self.gconf_client = gconf.client_get_default() + self.gconf_client = GConf.Client.get_default() self.gconf_client.add_dir(const.CARIBOU_GCONF, - gconf.CLIENT_PRELOAD_NONE) + GConf.ClientPreloadType.PRELOAD_NONE) self._settings_map = {} self._map_settings(self.groups) @@ -35,18 +35,20 @@ class _SettingsManager(object): if isinstance(setting, SettingsGroup): continue try: - setting.value = self.gconf_client.get_value(setting.gconf_key) + setting.value = self.gconf_client.get(setting.gconf_key) except ValueError: - self.gconf_client.set_value(setting.gconf_key, setting.value) + val = GConf.Value.new(setting.gconf_type) + setting.set_gconf_value(val) + self.gconf_client.set(setting.gconf_key, val) self._change_dependant_sensitivity(setting) handler_id = setting.connect('value-changed', self._on_value_changed) - self.gconf_client.notify_add(setting.gconf_key, - self._gconf_setting_changed_cb, - (setting, handler_id)) + #self.gconf_client.notify_add(setting.gconf_key, + # self._gconf_setting_changed_cb, + # (setting, handler_id)) def _change_dependant_sensitivity(self, setting): for name in setting.insensitive_when_false: @@ -59,8 +61,11 @@ class _SettingsManager(object): child.sensitive = i == index def _on_value_changed(self, setting, value): - if value != self.gconf_client.get_value(setting.gconf_key): - self.gconf_client.set_value(setting.gconf_key, value) + if value != self.gconf_client.get(setting.gconf_key): + print setting.gconf_type + val = GConf.Value.new(setting.gconf_type) + setting.set_gconf_value(val) + self.gconf_client.set(setting.gconf_key, val) self._change_dependant_sensitivity(setting) def _gconf_setting_changed_cb(self, client, connection_id, entry, data): diff --git a/caribou/ui/animation.py b/caribou/ui/animation.py index 44a9dfd..c382929 100644 --- a/caribou/ui/animation.py +++ b/caribou/ui/animation.py @@ -18,16 +18,16 @@ # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -import clutter +from gi.repository import Clutter class AnimatedWindowBase(object): - def __init__(self, ease=clutter.EASE_IN_QUAD): + def __init__(self, ease=Clutter.AnimationMode.EASE_IN_QUAD): if self.__class__ == AnimatedWindowBase: raise TypeError, \ "AnimatedWindowBase is an abstract class, " \ - "must be subclassed with a gtk.Window" + "must be subclassed with a Gtk.Window" - self._actor = clutter.Rectangle() + self._actor = Clutter.Rectangle() self.ease = ease def _on_new_frame(self, timeline, timing): @@ -37,25 +37,27 @@ class AnimatedWindowBase(object): def animated_move(self, x, y): orig_x, orig_y = self.get_position() self._actor.set_position(orig_x, orig_y) - self._actor.set_size(self.allocation.width, self.allocation.height) - animation = self._actor.animate( - self.ease, 250, "x", x, "y", y) + #allocation = self.get_allocation() + #print allocation.width, allocation.height + #self._actor.set_size(self.allocation.width, self.allocation.height) + animation = self._actor.animatev(self.ease, 250, ["x", "y"]) timeline = animation.get_timeline() timeline.connect('new-frame', self._on_new_frame) return animation if __name__ == "__main__": - import gtk - class AnimatedWindow(gtk.Window, AnimatedWindowBase): + import gobject + from gi.repository import Gtk + class AnimatedWindow(Gtk.Window, AnimatedWindowBase): def __init__(self): - gtk.Window.__init__(self) + gobject.GObject.__init__(self) AnimatedWindowBase.__init__(self) aw = AnimatedWindow() aw.show_all() aw.move(100, 100) - aw.animated_move(200, 200) - gtk.main() + #aw.animated_move(200, 200) + Gtk.main() diff --git a/caribou/ui/keyboard.py b/caribou/ui/keyboard.py index b3098d3..b6ca509 100644 --- a/caribou/ui/keyboard.py +++ b/caribou/ui/keyboard.py @@ -24,12 +24,12 @@ import caribou.common.const as const from caribou.common.settings_manager import SettingsManager -import scan from preferences_window import PreferencesWindow -import gconf +from gi.repository import GConf import gobject -import gtk -import pango +from gi.repository import Gdk +from gi.repository import Gtk +from gi.repository import Pango import sys import virtkey import os @@ -48,23 +48,23 @@ from xml.dom import minidom import gettext import i18n -KEY_MASKS = {'shift': gtk.gdk.SHIFT_MASK, - 'lock': gtk.gdk.LOCK_MASK, - 'control': gtk.gdk.CONTROL_MASK, - 'mod1': gtk.gdk.MOD1_MASK, - 'mod2': gtk.gdk.MOD2_MASK, - 'mod3': gtk.gdk.MOD3_MASK, - 'mod4': gtk.gdk.MOD4_MASK, - 'mod5': gtk.gdk.MOD5_MASK, - 'button1': gtk.gdk.BUTTON1_MASK, - 'button2': gtk.gdk.BUTTON2_MASK, - 'button3': gtk.gdk.BUTTON3_MASK, - 'button4': gtk.gdk.BUTTON4_MASK, - 'button5': gtk.gdk.BUTTON5_MASK} +KEY_MASKS = {'shift': Gdk.ModifierType.SHIFT_MASK, + 'lock': Gdk.ModifierType.LOCK_MASK, + 'control': Gdk.ModifierType.CONTROL_MASK, + 'mod1': Gdk.ModifierType.MOD1_MASK, + 'mod2': Gdk.ModifierType.MOD2_MASK, + 'mod3': Gdk.ModifierType.MOD3_MASK, + 'mod4': Gdk.ModifierType.MOD4_MASK, + 'mod5': Gdk.ModifierType.MOD5_MASK, + 'button1': Gdk.ModifierType.BUTTON1_MASK, + 'button2': Gdk.ModifierType.BUTTON2_MASK, + 'button3': Gdk.ModifierType.BUTTON3_MASK, + 'button4': Gdk.ModifierType.BUTTON4_MASK, + 'button5': Gdk.ModifierType.BUTTON5_MASK} class BaseKey(object): '''An abstract class the represents a key on the keyboard. - Inheriting classes also need to inherit from gtk.Button or any + Inheriting classes also need to inherit from Gtk.Button or any of it's subclasses.''' def __init__(self, label = '', value = '', key_type = 'normal', @@ -75,70 +75,45 @@ class BaseKey(object): self.fill = False self.label = label or value if self.key_type == const.DUMMY_KEY_TYPE: - self.set_relief(gtk.RELIEF_NONE) + 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.ICON_SIZE_BUTTON) + 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 = Gtk.Label() label_markup.set_markup(self.label) self.add(label_markup) else: self.set_label(self.label) - - self.connect('size-allocate', self._on_size_allocate) - - def _on_size_allocate(self, widget, allocation): - widget.set_property('width-request', allocation.height * self.width) - + def set_font(self, font): - label = self.get_child() - if not isinstance(label, gtk.Label): - return - rcstyle = label.get_modifier_style() - rcstyle.font_desc = pango.FontDescription(font) - - label.modify_style(rcstyle) - label.queue_resize() + raise NotImplemented def reset_font(self): - label = self.get_child() - if not isinstance(label, gtk.Label): - return - rcstyle = label.get_modifier_style() - rcstyle.font_desc = None - label.modify_style(rcstyle) - label.queue_resize() + raise NotImplemented def set_color(self, normal_color, mouse_over_color): - rcstyle = self.get_modifier_style() - - rcstyle.bg[gtk.STATE_NORMAL] = gtk.gdk.Color(normal_color) - rcstyle.bg[gtk.STATE_PRELIGHT] = gtk.gdk.Color(mouse_over_color) - - self.modify_style(rcstyle) + raise NotImplemented def reset_color(self): - rcstyle = self.get_modifier_style() - rcstyle.bg[gtk.STATE_NORMAL] = None - rcstyle.bg[gtk.STATE_PRELIGHT] = None - self.modify_style(rcstyle) + raise NotImplemented def _get_value(self): return self._value def _set_value(self, value): if self.key_type == const.NORMAL_KEY_TYPE: - if type(value) == str or type(value) == unicode: + if type(value) == str: value = value.decode('utf-8') + if type(value) == unicode: if len(value) == 1: - self._value = gtk.gdk.unicode_to_keyval(ord(value)) + self._value = Gdk.unicode_to_keyval(ord(value)) else: - key_value = gtk.gdk.keyval_from_name(value) + key_value = Gdk.keyval_from_name(value) if key_value: self._value = key_value elif self.key_type == const.MASK_KEY_TYPE: @@ -151,38 +126,59 @@ class BaseKey(object): value = property(_get_value, _set_value) -class Key(gtk.Button, BaseKey): +class Key(Gtk.Button, BaseKey): def __init__(self, label = '', value = '', key_type = 'normal', width = 1, fill = False): - gtk.Button.__init__(self) + gobject.GObject.__init__(self) BaseKey.__init__(self, label, value, key_type, width, fill) -class ModifierKey(gtk.ToggleButton, BaseKey): - def __init__(self, label = '', value = '', key_type = 'normal', - width = 1, fill = False): - gtk.ToggleButton.__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 set_color(self, normal_color, mouse_over_color): + self.modify_bg(Gtk.StateType.NORMAL, Gdk.color_parse(normal_color)[1]) + self.modify_bg(Gtk.StateType.PRELIGHT, + Gdk.color_parse(mouse_over_color)[1]) + + def reset_color(self): + self.modify_bg(Gtk.StateType.NORMAL, None) + self.modify_bg(Gtk.StateType.PRELIGHT, None) + +class ModifierKey(Gtk.ToggleButton, Key): + pass -class KeyboardLayout(gtk.Alignment): +class KeyboardLayout(Gtk.Table): + KEY_SPAN = 4 def __init__(self, name): - super(KeyboardLayout, self).__init__(0, 0, 0, 0) + gobject.GObject.__init__(self) self.layout_name = name self.rows = [] - self.vbox = gtk.VBox() - self.vbox.set_homogeneous(True) - self.add(self.vbox) + self.set_homogeneous(True) def add_row(self, row): + row_num = len(self.rows) self.rows.append(row) - alignment = gtk.Alignment(0.5, 0.5, 1, 1) - hbox = gtk.HBox() - for key in row: - hbox.pack_start(key, expand = True, fill = key.fill) - alignment.add(hbox) - self.vbox.pack_start(alignment) + 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 class KbLayoutDeserializer(object): - def __init__(self): pass @@ -282,11 +278,11 @@ class KbLayoutDeserializer(object): return value return [value] -class CaribouKeyboard(gtk.Notebook): +class CaribouKeyboard(Gtk.Notebook): __gtype_name__ = "CaribouKeyboard" def __init__(self): - gtk.Notebook.__init__(self) + gobject.GObject.__init__(self) self.set_show_tabs(False) self.vk = virtkey.virtkey() self.key_size = 30 @@ -302,50 +298,18 @@ class CaribouKeyboard(gtk.Notebook): getattr(SettingsManager, name).connect("value-changed", self._key_font_changed) - self.scan_enabled = SettingsManager.scan_enabled - - self.scan_enabled.connect("value-changed", - self._scan_enabled) - - self.scan_service = None - - self.connect('size-allocate', self._on_size_allocate) - self.row_height = -1 - def reset_row_height(self): - for i in xrange(self.get_n_pages()): - layout = self.get_nth_page(i) - for row in layout.vbox.get_children(): - row.set_property('height-request', -1) - self.row_height = -1 - - def _on_size_allocate(self, notebook, allocation): - if self.row_height > 0: - return - - for i in xrange(self.get_n_pages()): - layout = self.get_nth_page(i) - rows = layout.vbox.get_children() - height = rows[0].allocation.height - self.row_height = max(self.row_height, height) - for i in xrange(self.get_n_pages()): - layout = self.get_nth_page(i) - for row in layout.vbox.get_children(): - row.set_property('height-request', self.row_height) - - def load_kb(self, kb_location): kb_deserializer = KbLayoutDeserializer() 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() for layout in layout_list: - self.append_page(layout) + self.append_page(layout, None) for row in layout.rows: for key in row: if key.key_type == const.LAYOUT_SWITCHER_KEY_TYPE: @@ -361,14 +325,10 @@ class CaribouKeyboard(gtk.Notebook): key.connect('clicked', self._pressed_normal_key) - def _scan_enabled(self, setting, val): - self._enable_scanning() - def _colors_changed(self, setting, val): self._update_key_style() def _key_font_changed(self, setting, val): - self.reset_row_height() self._update_key_style() def _update_key_style(self): @@ -416,9 +376,7 @@ class CaribouKeyboard(gtk.Notebook): def show_all(self): self.set_current_page(self.current_page) - gtk.Notebook.show_all(self) - #if self.scan_enabled.value: - # self.scan_service.start() + Gtk.Notebook.show_all(self) def _pressed_preferences_key(self, key): p = PreferencesWindow() @@ -426,19 +384,10 @@ class CaribouKeyboard(gtk.Notebook): p.run() p.destroy() - def _enable_scanning(self): - if self.scan_enabled.value and self.scan_service is None: - current_layout = self.get_nth_page(self.current_page) - self.scan_service = scan.ScanService( - current_layout.rows, - self.get_parent().get_parent()) - def destroy(self): - if self.scan_enabled.value: - self.scan_service.destroy() for id in self._gconf_connections: self.client.notify_remove(id) - super(gtk.Notebook, self).destroy() + super(Gtk.Notebook, self).destroy() def _switch_to_layout(self, name): n_pages = self.get_n_pages() @@ -446,7 +395,19 @@ 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.value: - self.scan_service.change_keyboard( - self.get_nth_page(i).rows) break + +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 index e5dcee2..49058a2 100644 --- a/caribou/ui/main.py +++ b/caribou/ui/main.py @@ -1,10 +1,10 @@ -import gtk.gdk as gdk import pyatspi -import gconf -import gtk +from gi.repository import GConf +from gi.repository import Gtk +from gi.repository import Gdk import signal -from window import CaribouWindowEntry +from window import CaribouWindowEntry, Rectangle from keyboard import CaribouKeyboard from caribou.ui.i18n import _ import caribou.common.const as const @@ -21,10 +21,10 @@ class Caribou: self.window_factory = window_factory self.kb_factory = kb_factory self.window = window_factory(kb_factory()) - self.client = gconf.client_get_default() + self.client = GConf.Client.get_default() self._register_event_listeners() - self.client.notify_add(const.CARIBOU_GCONF + "/layout", - self._on_layout_changed) + #self.client.notify_add(const.CARIBOU_GCONF + "/layout", + # self._on_layout_changed) signal.signal(signal.SIGINT, self.signal_handler) def _register_event_listeners(self): @@ -34,7 +34,7 @@ class Caribou: pyatspi.Registry.registerEventListener( self.on_text_caret_moved, "object:text-caret-moved") pyatspi.Registry.registerKeystrokeListener( - self.on_key_down, mask=None, kind=(pyatspi.KEY_PRESSED_EVENT,)) + self.on_key_down, mask=0, kind=(pyatspi.KEY_PRESSED_EVENT,)) def _deregister_event_listeners(self): pyatspi.Registry.deregisterEventListener( @@ -43,7 +43,7 @@ class Caribou: pyatspi.Registry.deregisterEventListener( self.on_text_caret_moved, "object:text-caret-moved") pyatspi.Registry.deregisterKeystrokeListener( - self.on_key_down, mask=None, kind=pyatspi.KEY_PRESSED_EVENT) + self.on_key_down, mask=0, kind=pyatspi.KEY_PRESSED_EVENT) def _on_layout_changed(self, client, connection_id, entry, args): self._deregister_event_listeners() @@ -56,7 +56,7 @@ class Caribou: def _get_a11y_enabled(self): try: - gconfc = gconf.client_get_default() + 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 @@ -73,7 +73,7 @@ class Caribou: 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(gdk.Rectangle(x, y, width, height)) + self.window.set_cursor_location(Rectangle(x, y, width, height)) component = acc.queryComponent() entry_bb = component.getExtents(pyatspi.DESKTOP_COORDS) @@ -82,14 +82,14 @@ class Caribou: def __set_entry_location(self, acc): text = acc.queryText() - cursor_bb = gdk.Rectangle( + cursor_bb = Rectangle( *text.getCharacterExtents(text.caretOffset, pyatspi.DESKTOP_COORDS)) component = acc.queryComponent() entry_bb = component.getExtents(pyatspi.DESKTOP_COORDS) - if cursor_bb == gdk.Rectangle(0, 0, 0, 0): + if cursor_bb == Rectangle(0, 0, 0, 0): cursor_bb = entry_bb self.window.set_cursor_location(cursor_bb) @@ -99,11 +99,13 @@ class Caribou: def on_focus(self, event): acc = event.source - if pyatspi.STATE_EDITABLE in acc.getState().getStates() or event.source_role == pyatspi.ROLE_TERMINAL: - if event.source_role in (pyatspi.ROLE_TEXT, - pyatspi.ROLE_PARAGRAPH, - pyatspi.ROLE_PASSWORD_TEXT, - pyatspi.ROLE_TERMINAL): + source_role = acc.getRole() + if pyatspi.STATE_EDITABLE in acc.getState().getStates() 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 @@ -111,13 +113,13 @@ class Caribou: if debug == True: print "enter text widget in", event.host_application.name elif event.detail1 == 0 and acc == self.__current_acc: - self.window.hide_all() + self.window.hide() self.__current_acc = None self.__set_location = None if debug == True: print "leave text widget in", event.host_application.name - elif event.source_role == pyatspi.ROLE_ENTRY: + 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 @@ -125,7 +127,7 @@ class Caribou: if debug == True: print "enter entry widget in", event.host_application.name elif event.detail1 == 0: - self.window.hide_all() + self.window.hide() self.__current_acc = None self.__set_location = None if debug == True: @@ -138,7 +140,7 @@ class Caribou: # This could be a way to get the entry widget leave events. #else: # if event.detail1 == 1: - # self.window.hide_all() + # self.window.hide() # print "--> LEAVE EDITABLE TEXT <--" def on_key_down(self, event): @@ -180,6 +182,6 @@ class Caribou: result = pyatspi.Registry.deregisterKeystrokeListener(self.on_key_down, mask=None, kind=pyatspi.KEY_PRESSED_EVENT) if debug == True: print "deregisterKeystrokeListener" - gtk.main_quit() + Gtk.main_quit() diff --git a/caribou/ui/opacity.py b/caribou/ui/opacity.py index bab14d5..7214aa4 100644 --- a/caribou/ui/opacity.py +++ b/caribou/ui/opacity.py @@ -18,7 +18,7 @@ # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -import gtk, glib +import glib from math import sqrt class ProximityWindowBase(object): @@ -26,7 +26,7 @@ class ProximityWindowBase(object): if self.__class__ == ProximityWindowBase: raise TypeError, \ "ProximityWindowBase is an abstract class, " \ - "must be subclassed with a gtk.Window" + "must be subclassed with a Gtk.Window" self.connect('map-event', self.__onmapped) self.max_distance = max_distance if max_alpha < min_alpha: diff --git a/caribou/ui/preferences_window.py b/caribou/ui/preferences_window.py index c11cbf8..0158ffb 100644 --- a/caribou/ui/preferences_window.py +++ b/caribou/ui/preferences_window.py @@ -20,12 +20,13 @@ import caribou.common.const as const from caribou.common.setting_types import * +from caribou.common.settings_manager import SettingsManager -import scan -import gconf +from gi.repository import GConf import gobject -import gtk -import pango +from gi.repository import Gdk +from gi.repository import Gtk +from gi.repository import Pango import sys import virtkey import os @@ -41,25 +42,26 @@ import xml.etree.ElementTree as ET from xml.dom import minidom import gettext import i18n -from caribou.common.settings_manager import SettingsManager -class PreferencesWindow(gtk.Dialog): +class PreferencesWindow(Gtk.Dialog): __gtype_name__ = "PreferencesWindow" def __init__(self): - gtk.Dialog.__init__(self, _("Caribou Preferences"), - buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)) + gobject.GObject.__init__(self) + self.set_title(_("Caribou Preferences")) + self.add_button(Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE) self.set_border_width(6) - notebook = gtk.Notebook() - self.vbox.add(notebook) + notebook = Gtk.Notebook() + vbox = self.get_content_area() + vbox.add(notebook) self._populate_settings(notebook, SettingsManager.groups) def _populate_settings(self, parent, setting, level=0): if level == 0: for s in setting: - vbox = gtk.VBox() - parent.append_page(vbox, gtk.Label(s.label)) + vbox = Gtk.VBox() + parent.append_page(vbox, Gtk.Label(label=s.label)) self._populate_settings(vbox, s, 1) else: parent.set_border_width(6) @@ -68,7 +70,7 @@ class PreferencesWindow(gtk.Dialog): for s in setting: if not isinstance(s, SettingsGroup): if table is None: - table = gtk.Table(1, 2) + table = Gtk.Table.new(1, 2, False) table.set_row_spacings(3) table.set_col_spacings(3) parent.pack_start(table, False, False, 0) @@ -76,12 +78,12 @@ class PreferencesWindow(gtk.Dialog): row += 1 else: table = None - frame = gtk.Frame() - frame.set_shadow_type(gtk.SHADOW_NONE) - label = gtk.Label() + frame = Gtk.Frame() + frame.set_shadow_type(Gtk.ShadowType.NONE) + label = Gtk.Label() label.set_markup('%s' % s.label) frame.set_label_widget(label) - vbox = gtk.VBox() + vbox = Gtk.VBox() frame.add(vbox) parent.pack_start(frame, False, False, 0) self._sensitivity_changed_cb(s, s.sensitive, frame, None) @@ -91,36 +93,35 @@ class PreferencesWindow(gtk.Dialog): self._populate_settings(vbox, s, level + 1) def _create_widget(self, table, row, setting, xpadding=0): - print 'create', setting.name control = None label = None value_changed_cb = None control_changed_cb = None control_changed_signal = None if isinstance(setting, BooleanSetting): - control = gtk.CheckButton(setting.label) + control = Gtk.CheckButton.new_with_label(setting.label) control.set_active(setting.value) value_changed_cb = lambda s, v, w: w.set_active(v) control_changed_cb = self._checkbutton_toggled_cb control_changed_signal = 'toggled' else: - label = gtk.Label("%s:" % setting.label) + label = Gtk.Label(label="%s:" % setting.label) label.set_alignment(0.0, 0.5) if setting.entry_type == ENTRY_COLOR: - control = gtk.ColorButton( - gtk.gdk.color_parse(setting.value)) + control = Gtk.ColorButton.new_with_color( + Gdk.color_parse(setting.value)[1]) value_changed_cb = \ - lambda s, v, w: w.set_color(gtk.gdk.color_parse(v)) + lambda s, v, w: w.set_color(Gdk.color_parse(v)) control_changed_cb = self._colorbutton_changed_cb control_changed_signal = 'color-set' elif setting.entry_type == ENTRY_FONT: - control = gtk.FontButton(setting.value) + control = Gtk.FontButton.new_with_font(setting.value) value_changed_cb = lambda s, v, w: w.set_font_name(v) control_changed_cb = self._fontbutton_changed_cb control_changed_signal = 'font-set' elif setting.entry_type == ENTRY_SPIN: - control = gtk.SpinButton() + control = Gtk.SpinButton() if isinstance(setting.value, float): control.set_digits(2) control.set_increments(0.01, 0.1) @@ -136,15 +137,16 @@ class PreferencesWindow(gtk.Dialog): "If a radio entry has children, they must be equal " \ "in quantity to the allowed values." label = None - control = gtk.Table( - len(setting.allowed) + len(setting.children), 2) + control = Gtk.Table.new( + len(setting.allowed) + len(setting.children), 2, False) control.set_row_spacings(3) control.set_col_spacings(3) radios = [] for string, localized in setting.allowed: - radios.append(gtk.RadioButton(None, localized)) + radios.append(Gtk.RadioButton.new_with_label( + [], localized)) for radio in radios[1:]: - radio.set_group(radios[0]) + radio.join_group(radios[0]) hid = setting.connect( 'value-changed', @@ -157,7 +159,11 @@ class PreferencesWindow(gtk.Dialog): for i, radio in enumerate(radios): radio.connect('toggled', self._radio_changed_cb, setting, radios, hid) - control.attach(radio, 0, 2, r, r + 1) + control.attach( + radio, 0, 2, r, r + 1, + Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, + Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, + 0, 0) r += 1 if setting.children: self._create_widget(control, r, @@ -165,27 +171,34 @@ class PreferencesWindow(gtk.Dialog): r += 1 elif setting.entry_type == ENTRY_COMBO or setting.allowed: - control = gtk.combo_box_new_text() + control = Gtk.ComboBoxText.new() for option in setting.allowed: - control.append_text(option[1]) - control.set_active( - [a for a, b in setting.allowed].index(setting.value)) - value_changed_cb = lambda s, v, w: w.set_active( - [a for a, b in s.allowed].index(v)) + control.append(option[0], option[1]) + control.set_active_id(setting.value) + value_changed_cb = lambda s, v, w: w.set_active_id(v) control_changed_cb = self._combo_changed_cb control_changed_signal = 'changed' else: - control = gtk.Entry() + control = Gtk.Entry() control.set_text(setting.value) value_changed_cb = lambda s, v, w: w.set_text(v) control_changed_cb = self._string_changed_cb control_changed_signal = 'insert-at-cursor' if label is not None: - table.attach(label, 0, 1, row, row + 1, xpadding=xpadding) - table.attach(control, 1, 2, row, row + 1) + table.attach(label, 0, 1, row, row + 1, + Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, + Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, + xpadding, 0) + table.attach(control, 1, 2, row, row + 1, + Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, + Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, + 0, 0) else: - table.attach(control, 0, 2, row, row + 1, xpadding=xpadding) + table.attach(control, 0, 2, row, row + 1, + Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, + Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, + xpadding, 0) self._sensitivity_changed_cb(setting, setting.sensitive, control, label) @@ -232,15 +245,15 @@ class PreferencesWindow(gtk.Dialog): self._update_setting(setting, entry.get_text(), handler_id) def _combo_changed_cb(self, combo, setting, handler_id): - self._update_setting(setting, setting.allowed[combo.get_active()][0], + self._update_setting(setting, combo.get_active_id(), handler_id) if __name__ == "__main__": import signal signal.signal(signal.SIGINT, signal.SIG_DFL) - w = PreferencesWindow_() + w = PreferencesWindow() w.show_all() try: w.run() except KeyboardInterrupt: - gtk.main_quit() + Gtk.main_quit() diff --git a/caribou/ui/scan.py b/caribou/ui/scan.py index 992f1d9..f845903 100644 --- a/caribou/ui/scan.py +++ b/caribou/ui/scan.py @@ -1,6 +1,7 @@ import gobject import pyatspi -import gtk +from gi.repository import Gdk +from gi.repository import Gtk import caribou.common.const as const from caribou.common.settings_manager import SettingsManager @@ -203,23 +204,23 @@ class ScanService(): def _grab_mouse_events(self): - gtk.gdk.event_handler_set(self._mouse_handler) + Gdk.event_handler_set(self._mouse_handler) def _ungrab_mouse_events(self): - gtk.gdk.event_handler_set(gtk.main_do_event) + 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 \ + if event.type == Gdk.EventType.BUTTON_PRESS and \ str(event.button) == self.switch_key.value: self._handle_press() - elif event.type == gtk.gdk.BUTTON_RELEASE and \ + elif event.type == Gdk.BUTTON_RELEASE and \ str(event.button) == self.switch_key.value: self._handle_release() - elif not event.type == gtk.gdk.ENTER_NOTIFY: - gtk.main_do_event(event) + elif not event.type == Gdk.ENTER_NOTIFY: + Gtk.main_do_event(event) else: - gtk.main_do_event(event) + Gtk.main_do_event(event) def _scan_block(self): if self.is_stop: @@ -237,18 +238,18 @@ class ScanService(): self.index_i = 0 self.selected_block = [] - width = self.root_window.size_request()[0] - height = self.root_window.size_request()[1] + #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, + block_window = (root_x + offset_w, root_y + offset_h, width/3, height/2) - empty_r = gtk.gdk.Rectangle() + empty_r = () try: for row in self.keyboard: line = [] @@ -257,7 +258,7 @@ class ScanService(): 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_r = (abs_b_x, abs_b_y, button.size_request()[0], button.size_request()[1]) diff --git a/caribou/ui/window.py b/caribou/ui/window.py index 0ed5c90..78b2c61 100644 --- a/caribou/ui/window.py +++ b/caribou/ui/window.py @@ -22,34 +22,35 @@ import animation from caribou import data_path -import gconf -import gtk -import gtk.gdk as gdk +from gi.repository import GConf +from gi.repository import Gtk +from gi.repository import Gdk import opacity import os import sys +import gobject CARIBOU_GCONF_LAYOUT_KEY = '/apps/caribou/osk/layout' CARIBOU_LAYOUT_DIR = 'keyboards' -class CaribouWindow(gtk.Window): +class CaribouWindow(Gtk.Window): __gtype_name__ = "CaribouWindow" - def __init__(self, text_entry_mech, default_placement=None, min_alpha=1.0, max_alpha=1.0, max_distance=100): - super(CaribouWindow, self).__init__(gtk.WINDOW_POPUP) + gobject.GObject.__init__(self, type=Gtk.WindowType.POPUP) + self.set_name("CaribouWindow") - self._vbox = gtk.VBox() + self._vbox = Gtk.VBox() self.add(self._vbox) self.keyboard = text_entry_mech - self._vbox.pack_start(text_entry_mech) + self._vbox.pack_start(text_entry_mech, True, True, 0) self.connect("size-allocate", lambda w, a: self._update_position()) - self._gconf_client = gconf.client_get_default() + self._gconf_client = GConf.Client.get_default() - self._cursor_location = gdk.Rectangle() - self._entry_location = gdk.Rectangle() + self._cursor_location = Rectangle() + self._entry_location = Rectangle() self._default_placement = default_placement or \ CaribouWindowPlacement() @@ -61,7 +62,7 @@ class CaribouWindow(gtk.Window): def destroy(self): self.keyboard.destroy() - super(gtk.Window, self).destroy() + super(Gtk.Window, self).destroy() def set_cursor_location(self, cursor_location): @@ -77,12 +78,12 @@ class CaribouWindow(gtk.Window): self._update_position() def _get_root_bbox(self): - root_window = gdk.get_default_root_window() - args = root_window.get_position() + root_window.get_size() + root_window = Gdk.get_default_root_window() + args = root_window.get_geometry() - root_bbox = gdk.Rectangle(*args) + root_bbox = Rectangle(*args) - current_screen = gtk.gdk.screen_get_default().get_number() + current_screen = Gdk.Screen.get_default().get_number() for panel in self._gconf_client.all_dirs('/apps/panel/toplevels'): orientation = self._gconf_client.get_string(panel+'/orientation') size = self._gconf_client.get_int(panel+'/size') @@ -114,9 +115,9 @@ class CaribouWindow(gtk.Window): def _update_position(self): x, y = self._calculate_position() root_bbox = self._get_root_bbox() - proposed_position = \ - gdk.Rectangle(x, y, self.allocation.width, self.allocation.height) - + proposed_position = Rectangle(x, y, self.get_allocated_width(), + self.get_allocated_height()) + x += self._default_placement.x.adjust_to_bounds(root_bbox, proposed_position) y += self._default_placement.y.adjust_to_bounds(root_bbox, proposed_position) self.move(x, y) @@ -129,17 +130,21 @@ class CaribouWindow(gtk.Window): elif axis_placement.stickto == CaribouWindowPlacement.ENTRY: bbox = self._entry_location - offset = axis_placement.get_offset(bbox) + offset = axis_placement.get_offset(bbox.x, bbox.y) if axis_placement.align == CaribouWindowPlacement.END: - offset += axis_placement.get_length(bbox) + offset += axis_placement.get_length(bbox.width, bbox.height) if axis_placement.gravitate == CaribouWindowPlacement.INSIDE: - offset -= axis_placement.get_length(self.allocation) + 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: - offset -= axis_placement.get_length(self.allocation) + offset -= axis_placement.get_length( + self.get_allocated_width(), + self.get_allocated_height()) elif axis_placement.align == CaribouWindowPlacement.CENTER: - offset += axis_placement.get_length(bbox)/2 + offset += axis_placement.get_length(bbox.width, bbox.height)/2 return offset @@ -163,18 +168,18 @@ class CaribouWindow(gtk.Window): def show_all(self): - gtk.Window.show_all(self) + Gtk.Window.show_all(self) self.keyboard.show_all() - def hide_all(self): - self.keyboard.hide_all() - gtk.Window.hide_all(self) + def hide(self): + self.keyboard.hide() + Gtk.Window.hide(self) def _on_window_show(self, window): child = self.get_child() border = self.get_border_width() - w, h = child.size_request() - self.resize(w + border, h + border) + req = child.size_request() + self.resize(req.width + border, req.height + border) class CaribouWindowDocked(CaribouWindow, animation.AnimatedWindowBase, @@ -202,15 +207,11 @@ class CaribouWindowDocked(CaribouWindow, def _roll_in(self): x, y = self.get_position() self.move(x + self.allocation.width, y) - return self.animated_move(x, y) + #return self.animated_move(x, y) def _roll_out(self): x, y = self.get_position() - return self.animated_move(x + self.allocation.width, y) - - def hide_all(self): - animation = self._roll_out() - animation.connect('completed', lambda x: CaribouWindow.hide_all(self)) + #return self.animated_move(x + self.allocation.width, y) def hide(self): animation = self._roll_out() @@ -233,9 +234,8 @@ class CaribouWindowEntry(CaribouWindow): def _calculate_axis(self, axis_placement, root_bbox): offset = CaribouWindow._calculate_axis(self, axis_placement, root_bbox) - if axis_placement.axis == 'y': - if offset + self.allocation.height > root_bbox.height + root_bbox.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) @@ -266,17 +266,20 @@ class CaribouWindowPlacement(object): stickto or self.stickto, gravitate or self.gravitate) - def get_offset(self, bbox): - return bbox.x if self.axis == 'x' else bbox.y + def get_offset(self, x, y): + return x if self.axis == 'x' else y - def get_length(self, bbox): - return bbox.width if self.axis == 'x' else bbox.height + def get_length(self, width, height): + return width if self.axis == 'x' else height def adjust_to_bounds(self, root_bbox, child_bbox): - child_vector_start = self.get_offset(child_bbox) - child_vector_end = self.get_length(child_bbox) + child_vector_start - root_vector_start = self.get_offset(root_bbox) - root_vector_end = self.get_length(root_bbox) + root_vector_start + child_vector_start = self.get_offset(child_bbox.x, child_bbox.y) + child_vector_end = \ + self.get_length(child_bbox.width, child_bbox.height) + \ + child_vector_start + root_vector_start = self.get_offset(root_bbox.x, root_bbox.y) + root_vector_end = self.get_length( + root_bbox.width, root_bbox.height) + root_vector_start if root_vector_end < child_vector_end: return root_vector_end - child_vector_end @@ -299,3 +302,23 @@ 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 + self.y = y + self.width = width + self.height = height + +if __name__ == "__main__": + import keyboard + import signal + signal.signal(signal.SIGINT, signal.SIG_DFL) + + w = CaribouWindowDocked(keyboard.CaribouKeyboard) + w.show_all() + + try: + Gtk.main() + except KeyboardInterrupt: + Gtk.main_quit() -- cgit v1.2.1 From c3c4d70a64132ba3ed29d6fd7337de4fb4fe77cd Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Tue, 4 Jan 2011 13:36:18 -0800 Subject: Fixed opacity.py for introspection. --- caribou/ui/opacity.py | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/caribou/ui/opacity.py b/caribou/ui/opacity.py index 7214aa4..be742d8 100644 --- a/caribou/ui/opacity.py +++ b/caribou/ui/opacity.py @@ -42,9 +42,12 @@ class ProximityWindowBase(object): glib.timeout_add(80, self._proximity_check) def _proximity_check(self): - x, y = self.get_pointer() - - distance = self._get_distance_to_bbox(x, y, self.allocation) + 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) @@ -53,28 +56,28 @@ class ProximityWindowBase(object): self.set_opacity(opacity) return self.props.visible - def _get_distance_to_bbox(self, x, y, bbox): - if x < bbox.x: - x_distance = bbox.x - x - elif x > bbox.width + bbox.x: - x_distance = bbox.width + bbox.x - x + 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 + x_distance = 0.0 - if y < bbox.y: - y_distance = bbox.y - y - elif y > bbox.height + bbox.y: - y_distance = bbox.height + bbox.y - y + if py < 0: + y_distance = float(abs(px)) + elif py > bh: + y_distance = float(py - bh) else: - y_distance = 0 + y_distance = 0.0 if y_distance == 0 and x_distance == 0: return 0.0 elif y_distance != 0 and x_distance == 0: - return abs(float(y_distance)) + return y_distance elif y_distance == 0 and x_distance != 0: - return abs(float(x_distance)) + return x_distance else: - x2 = bbox.x if x_distance > 0 else bbox.x + bbox.width - y2 = bbox.y if y_distance > 0 else bbox.y + bbox.height - return sqrt((x - x2)**2 + (y - y2)**2) + x2 = 0 if x_distance > 0 else bw + y2 = 0 if y_distance > 0 else bh + return sqrt((px - x2)**2 + (py - y2)**2) -- cgit v1.2.1 From 4e16b91b6ea151cbf487dd7f775afedfbbc905e6 Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Wed, 5 Jan 2011 16:26:26 -0800 Subject: Fixed animation to use Clutter GI properly. Moved to main window class. --- caribou/ui/Makefile.am | 1 - caribou/ui/animation.py | 63 ---------------------------------------------- caribou/ui/window.py | 67 ++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 58 insertions(+), 73 deletions(-) delete mode 100644 caribou/ui/animation.py diff --git a/caribou/ui/Makefile.am b/caribou/ui/Makefile.am index 8813480..fb24db4 100644 --- a/caribou/ui/Makefile.am +++ b/caribou/ui/Makefile.am @@ -2,7 +2,6 @@ caribou_uidir = $(pkgpythondir)/ui/ caribou_ui_PYTHON = \ __init__.py \ - animation.py \ i18n.py \ keyboard.py \ scan.py \ diff --git a/caribou/ui/animation.py b/caribou/ui/animation.py deleted file mode 100644 index c382929..0000000 --- a/caribou/ui/animation.py +++ /dev/null @@ -1,63 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Caribou - text entry and UI navigation application -# -# Copyright (C) 2009 Eitan Isaacson -# -# 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 gi.repository import Clutter - -class AnimatedWindowBase(object): - def __init__(self, ease=Clutter.AnimationMode.EASE_IN_QUAD): - if self.__class__ == AnimatedWindowBase: - raise TypeError, \ - "AnimatedWindowBase is an abstract class, " \ - "must be subclassed with a Gtk.Window" - - self._actor = Clutter.Rectangle() - self.ease = ease - - def _on_new_frame(self, timeline, timing): - x, y = self._actor.get_position() - self.move(int(x), int(y)) - - def animated_move(self, x, y): - orig_x, orig_y = self.get_position() - self._actor.set_position(orig_x, orig_y) - #allocation = self.get_allocation() - #print allocation.width, allocation.height - #self._actor.set_size(self.allocation.width, self.allocation.height) - animation = self._actor.animatev(self.ease, 250, ["x", "y"]) - timeline = animation.get_timeline() - timeline.connect('new-frame', self._on_new_frame) - - return animation - -if __name__ == "__main__": - import gobject - from gi.repository import Gtk - class AnimatedWindow(Gtk.Window, AnimatedWindowBase): - def __init__(self): - gobject.GObject.__init__(self) - AnimatedWindowBase.__init__(self) - - aw = AnimatedWindow() - aw.show_all() - aw.move(100, 100) - #aw.animated_move(200, 200) - Gtk.main() - - diff --git a/caribou/ui/window.py b/caribou/ui/window.py index 78b2c61..995889e 100644 --- a/caribou/ui/window.py +++ b/caribou/ui/window.py @@ -20,11 +20,11 @@ # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -import animation from caribou import data_path from gi.repository import GConf from gi.repository import Gtk from gi.repository import Gdk +from gi.repository import Clutter import opacity import os import sys @@ -33,10 +33,19 @@ import gobject CARIBOU_GCONF_LAYOUT_KEY = '/apps/caribou/osk/layout' CARIBOU_LAYOUT_DIR = 'keyboards' -class CaribouWindow(Gtk.Window): +Clutter.init("caribou") + +class CaribouWindow(Gtk.Window, Clutter.Animatable): __gtype_name__ = "CaribouWindow" + __gproperties__ = { + 'animated-window-position' : (gobject.TYPE_PYOBJECT, 'Window position', + 'Window position in X, Y coordinates', + gobject.PARAM_READWRITE) + } + def __init__(self, text_entry_mech, default_placement=None, - min_alpha=1.0, max_alpha=1.0, max_distance=100): + min_alpha=1.0, max_alpha=1.0, max_distance=100, + animation_mode=Clutter.AnimationMode.EASE_IN_QUAD): gobject.GObject.__init__(self, type=Gtk.WindowType.POPUP) self.set_name("CaribouWindow") @@ -60,6 +69,48 @@ class CaribouWindow(Gtk.Window): self.connect('show', self._on_window_show) + # animation + self.animation_mode = animation_mode + self._stage = Clutter.Stage.get_default() + self._animation = None + + def do_get_property(self, property): + if property.name == "animated-window-position": + return self.get_position() + else: + raise AttributeError, 'unknown property %s' % property.name + + def do_set_property(self, property, value): + if property.name == "animated-window-position": + if value is not None: + x, y = value + self.move(x, y) + else: + raise AttributeError, 'unknown property %s' % property.name + + def do_animate_property(self, animation, prop_name, initial_value, + final_value, progress, gvalue): + if prop_name != "animated-window-position": return False + + ix, iy = initial_value + fx, fy = final_value + dx = int((fx - ix) * progress) + dy = int((fy - iy) * progress) + new_value = (ix + dx, iy + dy) + self.move(*new_value) + return True + + def animated_move(self, x, y): + self._animation = Clutter.Animation(object=self, + mode=self.animation_mode, + duration=250) + self._animation.bind("animated-window-position", (x, y)) + + timeline = self._animation.get_timeline() + timeline.start() + + return self._animation + def destroy(self): self.keyboard.destroy() super(Gtk.Window, self).destroy() @@ -182,7 +233,6 @@ class CaribouWindow(Gtk.Window): self.resize(req.width + border, req.height + border) class CaribouWindowDocked(CaribouWindow, - animation.AnimatedWindowBase, opacity.ProximityWindowBase): __gtype_name__ = "CaribouWindowDocked" @@ -195,7 +245,6 @@ class CaribouWindowDocked(CaribouWindow, xgravitate=CaribouWindowPlacement.INSIDE) CaribouWindow.__init__(self, text_entry_mech, placement) - animation.AnimatedWindowBase.__init__(self) opacity.ProximityWindowBase.__init__( self, min_alpha=0.5, max_alpha=0.8) @@ -206,12 +255,12 @@ class CaribouWindowDocked(CaribouWindow, def _roll_in(self): x, y = self.get_position() - self.move(x + self.allocation.width, y) - #return self.animated_move(x, y) + self.move(x + self.get_allocated_width(), y) + return self.animated_move(x, y) def _roll_out(self): x, y = self.get_position() - #return self.animated_move(x + self.allocation.width, y) + return self.animated_move(x + self.get_allocated_width(), y) def hide(self): animation = self._roll_out() @@ -315,7 +364,7 @@ if __name__ == "__main__": import signal signal.signal(signal.SIGINT, signal.SIG_DFL) - w = CaribouWindowDocked(keyboard.CaribouKeyboard) + w = CaribouWindowDocked(keyboard.CaribouKeyboard()) w.show_all() try: -- cgit v1.2.1 From 42650f8d9f0bcb72b6b0680d6e3486f0c2d58da8 Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Wed, 5 Jan 2011 17:02:46 -0800 Subject: Moved proximity base class to caribou window base class. --- caribou/ui/window.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/caribou/ui/window.py b/caribou/ui/window.py index 995889e..5e45d13 100644 --- a/caribou/ui/window.py +++ b/caribou/ui/window.py @@ -25,7 +25,7 @@ from gi.repository import GConf from gi.repository import Gtk from gi.repository import Gdk from gi.repository import Clutter -import opacity +from opacity import ProximityWindowBase import os import sys import gobject @@ -35,7 +35,7 @@ CARIBOU_LAYOUT_DIR = 'keyboards' Clutter.init("caribou") -class CaribouWindow(Gtk.Window, Clutter.Animatable): +class CaribouWindow(Gtk.Window, Clutter.Animatable, ProximityWindowBase): __gtype_name__ = "CaribouWindow" __gproperties__ = { 'animated-window-position' : (gobject.TYPE_PYOBJECT, 'Window position', @@ -47,6 +47,10 @@ class CaribouWindow(Gtk.Window, Clutter.Animatable): min_alpha=1.0, max_alpha=1.0, max_distance=100, animation_mode=Clutter.AnimationMode.EASE_IN_QUAD): gobject.GObject.__init__(self, type=Gtk.WindowType.POPUP) + ProximityWindowBase.__init__(self, + min_alpha=min_alpha, + max_alpha=max_alpha, + max_distance=max_distance) self.set_name("CaribouWindow") @@ -232,8 +236,7 @@ class CaribouWindow(Gtk.Window, Clutter.Animatable): req = child.size_request() self.resize(req.width + border, req.height + border) -class CaribouWindowDocked(CaribouWindow, - opacity.ProximityWindowBase): +class CaribouWindowDocked(CaribouWindow): __gtype_name__ = "CaribouWindowDocked" def __init__(self, text_entry_mech): @@ -245,8 +248,6 @@ class CaribouWindowDocked(CaribouWindow, xgravitate=CaribouWindowPlacement.INSIDE) CaribouWindow.__init__(self, text_entry_mech, placement) - opacity.ProximityWindowBase.__init__( - self, min_alpha=0.5, max_alpha=0.8) self.connect('map-event', self.__onmapped) @@ -277,8 +278,7 @@ class CaribouWindowEntry(CaribouWindow): xgravitate=CaribouWindowPlacement.INSIDE, ygravitate=CaribouWindowPlacement.OUTSIDE) - CaribouWindow.__init__(self, text_entry_mech, placement, min_alpha=0.075, - max_alpha=0.8) + CaribouWindow.__init__(self, text_entry_mech, placement) def _calculate_axis(self, axis_placement, root_bbox): -- cgit v1.2.1 From 7c7bcb7ace2d54b1289301000f60a7112ee6e737 Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Fri, 7 Jan 2011 01:17:18 -0800 Subject: Got most of scanning working. Yay. --- bin/caribou.in | 15 +- caribou/common/settings_manager.py | 2 +- caribou/ui/keyboard.py | 56 +++- caribou/ui/main.py | 77 ++---- caribou/ui/scan.py | 515 ++++++++++--------------------------- caribou/ui/window.py | 7 +- 6 files changed, 226 insertions(+), 446 deletions(-) diff --git a/bin/caribou.in b/bin/caribou.in index 1c2235c..35ef584 100644 --- a/bin/caribou.in +++ b/bin/caribou.in @@ -27,7 +27,7 @@ from optparse import OptionParser import gettext import sys -from gi.repository import Gtk +import pyatspi import os # We can't rely on prefix if we're installed by relocated RPM. Instead, we @@ -55,8 +55,12 @@ 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", @@ -69,4 +73,9 @@ if __name__ == "__main__": caribou = main.Caribou() caribou.window.hide() - Gtk.main() + try: + pyatspi.Registry.start() + except KeyboardInterrupt: + caribou.clean_exit() + pyatspi.Registry.stop() + diff --git a/caribou/common/settings_manager.py b/caribou/common/settings_manager.py index 92b5137..37d178b 100644 --- a/caribou/common/settings_manager.py +++ b/caribou/common/settings_manager.py @@ -19,7 +19,7 @@ class _SettingsManager(object): try: return self._settings_map[name] except KeyError: - raise AttributeError + raise AttributeError, "no setting named '%s'" % name def _map_settings(self, setting): if self._settings_map.has_key(setting.name): diff --git a/caribou/ui/keyboard.py b/caribou/ui/keyboard.py index b6ca509..38bdfc3 100644 --- a/caribou/ui/keyboard.py +++ b/caribou/ui/keyboard.py @@ -145,10 +145,11 @@ class Key(Gtk.Button, BaseKey): return label.modify_font(None) - def set_color(self, normal_color, mouse_over_color): + def set_color(self, normal_color, mouse_over_color=None): self.modify_bg(Gtk.StateType.NORMAL, Gdk.color_parse(normal_color)[1]) - self.modify_bg(Gtk.StateType.PRELIGHT, - Gdk.color_parse(mouse_over_color)[1]) + if mouse_over_color: + self.modify_bg(Gtk.StateType.PRELIGHT, + Gdk.color_parse(mouse_over_color)[1]) def reset_color(self): self.modify_bg(Gtk.StateType.NORMAL, None) @@ -177,6 +178,39 @@ class KeyboardLayout(Gtk.Table): 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): @@ -307,7 +341,7 @@ class CaribouKeyboard(Gtk.Notebook): self._update_key_style() def _set_layouts(self, layout_list): - self._clear() + self._clear() for layout in layout_list: self.append_page(layout, None) for row in layout.rows: @@ -374,7 +408,7 @@ class CaribouKeyboard(Gtk.Notebook): self.current_mask |= key.value self.vk.latch_mod(self.current_mask) - def show_all(self): + def show_all_(self): self.set_current_page(self.current_page) Gtk.Notebook.show_all(self) @@ -384,11 +418,6 @@ class CaribouKeyboard(Gtk.Notebook): p.run() p.destroy() - def destroy(self): - for id in self._gconf_connections: - self.client.notify_remove(id) - super(Gtk.Notebook, self).destroy() - def _switch_to_layout(self, name): n_pages = self.get_n_pages() for i in range(n_pages): @@ -397,6 +426,13 @@ class CaribouKeyboard(Gtk.Notebook): 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) diff --git a/caribou/ui/main.py b/caribou/ui/main.py index 49058a2..5175bb0 100644 --- a/caribou/ui/main.py +++ b/caribou/ui/main.py @@ -2,12 +2,13 @@ import pyatspi from gi.repository import GConf from gi.repository import Gtk from gi.repository import Gdk -import signal 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 @@ -20,12 +21,19 @@ class Caribou: self.__current_acc = None self.window_factory = window_factory self.kb_factory = kb_factory - self.window = window_factory(kb_factory()) + kb = kb_factory() + self.window = window_factory(kb) self.client = GConf.Client.get_default() self._register_event_listeners() - #self.client.notify_add(const.CARIBOU_GCONF + "/layout", - # self._on_layout_changed) - signal.signal(signal.SIGINT, self.signal_handler) + 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() def _register_event_listeners(self): pyatspi.Registry.registerEventListener( @@ -33,8 +41,6 @@ class Caribou: pyatspi.Registry.registerEventListener(self.on_focus, "focus") pyatspi.Registry.registerEventListener( self.on_text_caret_moved, "object:text-caret-moved") - pyatspi.Registry.registerKeystrokeListener( - self.on_key_down, mask=0, kind=(pyatspi.KEY_PRESSED_EVENT,)) def _deregister_event_listeners(self): pyatspi.Registry.deregisterEventListener( @@ -42,17 +48,23 @@ class Caribou: pyatspi.Registry.deregisterEventListener(self.on_focus, "focus") pyatspi.Registry.deregisterEventListener( self.on_text_caret_moved, "object:text-caret-moved") - pyatspi.Registry.deregisterKeystrokeListener( - self.on_key_down, mask=0, kind=pyatspi.KEY_PRESSED_EVENT) - def _on_layout_changed(self, client, connection_id, entry, args): + 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): - self.window = self.window_factory(self.kb_factory()) + kb = self.kb_factory() + self.scan_master.set_keyboard(kb) + self.window = self.window_factory(kb) def _get_a11y_enabled(self): try: @@ -134,7 +146,7 @@ class Caribou: print "leave entry widget in", event.host_application.name else: if debug == True: - print _("WARNING - Caribou: unhandled editable widget:"), event.source + 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. @@ -143,45 +155,8 @@ class Caribou: # self.window.hide() # print "--> LEAVE EDITABLE TEXT <--" - def on_key_down(self, event): - # key binding for controlling the row column scanning - if event.event_string == "Shift_R": - # TODO: implement keyboard scanning - pass - elif event.event_string == "Control_R": - self.clean_exit() - - def signal_handler(self,signal,frame): - # Clean exit pressing Control + C - self.clean_exit() - def clean_exit(self): - if debug == True: - print "quitting ..." - result = pyatspi.Registry.deregisterEventListener(self.on_text_caret_moved, "object:text-caret-moved") - if debug == True: - print "deregisterEventListener - object:text-caret-moved ...", - if result == False: - print "OK" - else: - print "FAIL" - result = pyatspi.Registry.deregisterEventListener(self.on_focus, "object:state-changed:focused") - if debug == True: - print "deregisterEventListener - object:state-changed:focused ...", - if result == False: - print "OK" - else: - print "FAIL" - result = pyatspi.Registry.deregisterEventListener(self.on_focus, "focus") - if debug == True: - print "deregisterEventListener - focus ...", - if result == False: - print "OK" - else: - print "FAIL" - result = pyatspi.Registry.deregisterKeystrokeListener(self.on_key_down, mask=None, kind=pyatspi.KEY_PRESSED_EVENT) - if debug == True: - print "deregisterKeystrokeListener" - Gtk.main_quit() + self.scan_master.stop() + self._deregister_event_listeners() diff --git a/caribou/ui/scan.py b/caribou/ui/scan.py index f845903..55feabf 100644 --- a/caribou/ui/scan.py +++ b/caribou/ui/scan.py @@ -5,7 +5,7 @@ from gi.repository import Gtk import caribou.common.const as const from caribou.common.settings_manager import SettingsManager -# Scan constans +# Scan constants BUTTON = 'button' ROW = 'row' BLOCK = 'block' @@ -27,400 +27,159 @@ DEFAULT_STEP_TIME = 1000 DEFAULT_SCANNING_TYPE = ROW DEFAULT_SWITCH_TYPE = KEYBOARD_SWITCH_TYPE -class ScanService(): - def __init__(self, keyboard, root_window): - self.keyboard = keyboard +class ScanMaster(): + def __init__(self, root_window, keyboard=None): 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 = [] - - # Settings we are interested in. - for name in ["step_time", "reverse_scanning", "scanning_type"]: - getattr(SettingsManager, name).connect("value-changed", - self._on_switch_changed) - - for name in ["switch_type", "mouse_button", "keyboard_key"]: - getattr(SettingsManager, name).connect("value-changed", - self._on_switch_changed) - - for name in ["default_colors", "normal_color", "mouse_over_color", - "row_scanning_color", "button_scanning_color", - "cancel_scanning_color", "block_scanning_color"]: - getattr(SettingsManager, name).connect("value-changed", - self._on_color_changed) - - SettingsManager.scan_enabled.connect("value-changed", - self._on_scan_toggled) - - self._configure_scanning() - self._set_colors() - self._configure_switch() - - def destroy(self): - self.stop() - self.clean() - self._deregister_events() - - - def _configure_switch(self): - self.switch_type = SettingsManager.switch_type.value - if self.switch_type == MOUSE_SWITCH_TYPE: - self.switch_key = SettingsManager.mouse_button.value - elif self.switch_type == KEYBOARD_SWITCH_TYPE: - self.switch_key = SettingsManager.keyboard_key + self._timer = 0 + self._scan_path = None + self.started = False - 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, settings, val): - self._deregister_events() - self._configure_switch() - - def _on_scan_toggled(self, settings, val): - if val: - self.start() - else: - self.stop() + 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 _on_color_changed(self, settings, val): - self._set_colors() + def start(self): + if self.started: return - def _on_scanning_type_changed(self, settings, val): - self._configure_scanning() + if self._timer == 0: + self._timer = gobject.timeout_add( + int(SettingsManager.step_time.value*1000), self._scan) - def _configure_scanning(self): - if not self.is_stop: - self._stop() - self.scanning_type = SettingsManager.scanning_type.value - self.reverse = SettingsManager.reverse_scanning.value - self.step_time = SettingsManager.step_time.value + self._grab_mouse_events() + + pyatspi.Registry.registerKeystrokeListener( + self._on_key_pressed, mask=0, kind=(pyatspi.KEY_PRESSED_EVENT,)) - if self.scanning_type == BLOCK: - self.selected_block = [] - else: - self.selected_block = self.keyboard - self.scanning = self.scanning_type - - def _set_colors(self): - self.default_colors = SettingsManager.default_colors.value - self.normal_color = SettingsManager.normal_color.value - self.mouse_over_color = SettingsManager.mouse_over_color.value - self.row_scanning_color = SettingsManager.row_scanning_color.value - self.button_scanning_color = \ - SettingsManager.button_scanning_color.value - self.cancel_scanning_color = \ - SettingsManager.cancel_scanning_color.value - self.block_scanning_color = SettingsManager.block_scanning_color.value - - # public start - def start(self, scanning=None): - self.scanning = scanning or self.scanning_type - self.clean() - if self.root_window and \ - self.switch_type == MOUSE_SWITCH_TYPE: - self._grab_mouse_events() - - if not self.reverse: - self.reset(self.scanning) - - # public stop def stop(self): - if self.switch_type == MOUSE_SWITCH_TYPE: - self._ungrab_mouse_events() - self.clean() - self._stop() - - #private start - def _start(self, scanning=ROW): - if self.is_stop == True and self.timerid == None: - self.is_stop = False - self.button_index = -1 - self.row_index = -1 - if scanning == ROW: - self.selected_row = [] - self.timerid = gobject.timeout_add( - int(1000*self.step_time), self._scan_row) - elif scanning == BUTTON: - self.selected_button = None - self.timerid = gobject.timeout_add( - int(1000*self.step_time), self._scan_button) - elif scanning == BLOCK: - self.selected_block = [] - self.selected_row = [] - self.clean() - self.index_i = 2 - self.index_j = 1 - self.timerid = gobject.timeout_add( - int(1000*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=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 == ROW: - self.selected_block = keyboard + if self.started: return + self._ungrab_mouse_events() - def _grab_mouse_events(self): - Gdk.event_handler_set(self._mouse_handler) + if self._last_block is not None: + self._multi_map(lambda x: x.reset_color(), self._last_block) - def _ungrab_mouse_events(self): - Gdk.event_handler_set(Gtk.main_do_event) + if self._timer != 0: + gobject.source_remove(self._timer) + self._timer = 0 - def _mouse_handler(self, event): - if self.root_window.window.is_visible(): - if event.type == Gdk.EventType.BUTTON_PRESS and \ - str(event.button) == self.switch_key.value: - self._handle_press() - elif event.type == Gdk.BUTTON_RELEASE and \ - str(event.button) == self.switch_key.value: - self._handle_release() - elif not event.type == Gdk.ENTER_NOTIFY: - Gtk.main_do_event(event) - else: - Gtk.main_do_event(event) + pyatspi.Registry.deregisterKeystrokeListener( + self._on_key_pressed, mask=0, kind=pyatspi.KEY_PRESSED_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 + 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.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 = (root_x + offset_w, - root_y + offset_h, - width/3, - height/2) - empty_r = () - 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 = (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 + 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.select_row(self.selected_row, - self.scanning_type == 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 == CANCEL: - self.scanning = BUTTON - self.selected_button = None - self.select_row(self.selected_row, True, self.row_scanning_color) - return True + self._blocks = layout.get_scan_blocks() + 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: - 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 = 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 = 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() + func(array) + + def _get_element_at_path(self, array, path): + element = array + for index in path: + element = element[index] + return element + + 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.reset_color(), + self._last_block) + + self._cancel, next_block = self._get_next_block() + + color = SettingsManager.button_scanning_color.value + + if self._cancel: + color = SettingsManager.cancel_scanning_color.value + elif isinstance(next_block, list): + if SettingsManager.scanning_type.value == ROW: + color = SettingsManager.row_scanning_color.value + else: + color = SettingsManager.block_scanning_color.value + + self._multi_map(lambda x: x.set_color(color, None), 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) + self._scan_path.append(-1) else: - button.set_color(self.normal_color, - self.mouse_over_color) + self._last_block.clicked() - def _on_key_pressed(self, event): - if event.event_string == "Escape": - SettingsManager.scan_enabled.value = False - elif self.switch_type == KEYBOARD_SWITCH_TYPE and \ - self.switch_key.value == event.event_string: - self._handle_press() - - def _on_key_released(self, event): - if self.switch_type == KEYBOARD_SWITCH_TYPE and \ - self.switch_key.value == 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 == ROW and \ - len(self.selected_row) > 0: - self.scanning = BUTTON - elif self.scanning == BLOCK and \ - len(self.selected_block) > 0: - self.scanning = ROW - elif self.scanning == 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 == CANCEL: - self.clean() - self.scanning = self.scanning_type - self._stop() + 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: - if not self.is_stop: - if self.scanning == ROW and \ - len(self.selected_row) > 0: - self.scanning = BUTTON - self.reset(BUTTON) - - elif self.scanning == BLOCK and \ - len(self.selected_block) > 0: - self.scanning = ROW - self.reset(ROW) - elif self.scanning == BUTTON and \ - self.selected_button: - self.selected_button.clicked() - self.scanning = 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 == CANCEL: - self.scanning = self.scanning_type - self.clean() - self.reset(self.scanning_type) - - + 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/caribou/ui/window.py b/caribou/ui/window.py index 5e45d13..d6739f1 100644 --- a/caribou/ui/window.py +++ b/caribou/ui/window.py @@ -21,11 +21,13 @@ # 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 GConf from gi.repository import Gtk from gi.repository import Gdk from gi.repository import Clutter -from opacity import ProximityWindowBase import os import sys import gobject @@ -204,8 +206,7 @@ class CaribouWindow(Gtk.Window, Clutter.Animatable, ProximityWindowBase): return offset def _get_keyboard_conf(self): - layout = self._gconf_client.get_string(CARIBOU_GCONF_LAYOUT_KEY) \ - or "qwerty" + layout = SettingsManager.layout.value conf_file_path = os.path.join(data_path, CARIBOU_LAYOUT_DIR, layout) if os.path.exists(conf_file_path): -- cgit v1.2.1 From c4d19a21c388241e6cfa7a2fd00bf87c70ce6fc4 Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Fri, 7 Jan 2011 12:45:08 -0800 Subject: Made reverse scanning work. --- caribou/ui/scan.py | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/caribou/ui/scan.py b/caribou/ui/scan.py index 55feabf..e774c46 100644 --- a/caribou/ui/scan.py +++ b/caribou/ui/scan.py @@ -85,7 +85,10 @@ class ScanMaster(): self._blocks = layout.get_scan_rows() else: self._blocks = layout.get_scan_blocks() - self._scan_path = [-1] + if SettingsManager.reverse_scanning.value: + self._scan_path = [0] + else: + self._scan_path = [-1] def set_keyboard(self, keyboard): self._last_block = None @@ -105,6 +108,30 @@ class ScanMaster(): 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] @@ -130,7 +157,10 @@ class ScanMaster(): self._multi_map(lambda x: x.reset_color(), self._last_block) - self._cancel, next_block = self._get_next_block() + if SettingsManager.reverse_scanning.value: + self._cancel, next_block = self._get_next_reverse_block() + else: + self._cancel, next_block = self._get_next_block() color = SettingsManager.button_scanning_color.value @@ -152,7 +182,10 @@ class ScanMaster(): self._scan_path.pop() elif isinstance(self._last_block, list): assert(len(self._last_block) > 0) - self._scan_path.append(-1) + if SettingsManager.reverse_scanning.value: + self._scan_path.append(0) + else: + self._scan_path.append(-1) else: self._last_block.clicked() -- cgit v1.2.1 From adbbcf2c98bd6634d86c95fe18591255d807fabc Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Fri, 7 Jan 2011 13:16:48 -0800 Subject: Use correct colors in scan. --- caribou/ui/keyboard.py | 96 ++++++++++++++++++++++++++++++-------------------- caribou/ui/scan.py | 4 +-- 2 files changed, 59 insertions(+), 41 deletions(-) diff --git a/caribou/ui/keyboard.py b/caribou/ui/keyboard.py index 38bdfc3..2dc924b 100644 --- a/caribou/ui/keyboard.py +++ b/caribou/ui/keyboard.py @@ -89,7 +89,63 @@ class BaseKey(object): self.add(label_markup) else: self.set_label(self.label) - + + for name in ["normal_color", "mouse_over_color", "default_colors"]: + getattr(SettingsManager, name).connect("value-changed", + self._colors_changed) + + 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) + + if not SettingsManager.default_colors.value: + self._colors_changed(None, None) + + def _colors_changed(self, setting, value): + if SettingsManager.default_colors.value: + self._normal_color = None + self._mouse_over_color = None + self.reset_color() + else: + self._normal_color = SettingsManager.normal_color.value + self._mouse_over_color = SettingsManager.mouse_over_color.value + self.set_color(self._normal_color, self._mouse_over_color) + + 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(self, color): + if color is None: + self._colors_changed(None, None) + else: + self.set_color(color) + + def _on_image_key_mapped(self, key): + print + 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() + print size, pixel_size, key_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 @@ -323,22 +379,12 @@ class CaribouKeyboard(Gtk.Notebook): self.current_mask = 0 self.current_page = 0 - # Settings we care about. - for name in ["normal_color", "mouse_over_color", "default_colors"]: - getattr(SettingsManager, name).connect("value-changed", - self._colors_changed) - - for name in ["default_font", "key_font"]: - getattr(SettingsManager, name).connect("value-changed", - self._key_font_changed) - self.row_height = -1 def load_kb(self, kb_location): kb_deserializer = KbLayoutDeserializer() layouts = kb_deserializer.deserialize(kb_location) self._set_layouts(layouts) - self._update_key_style() def _set_layouts(self, layout_list): self._clear() @@ -359,34 +405,6 @@ class CaribouKeyboard(Gtk.Notebook): key.connect('clicked', self._pressed_normal_key) - def _colors_changed(self, setting, val): - self._update_key_style() - - def _key_font_changed(self, setting, val): - self._update_key_style() - - def _update_key_style(self): - default_colors = SettingsManager.default_colors.value - normal_color = SettingsManager.normal_color.value - mouse_over_color = SettingsManager.mouse_over_color.value - default_font = SettingsManager.default_font.value - key_font = SettingsManager.key_font.value - - n_pages = self.get_n_pages() - for i in range(n_pages): - layout = self.get_nth_page(i) - for row in layout.rows: - for button in row: - if default_colors: - button.reset_color() - else: - button.set_color(normal_color, - mouse_over_color) - if default_font: - button.reset_font() - else: - button.set_font(key_font) - def _clear(self): n_pages = self.get_n_pages() for i in range(n_pages): diff --git a/caribou/ui/scan.py b/caribou/ui/scan.py index e774c46..16680fb 100644 --- a/caribou/ui/scan.py +++ b/caribou/ui/scan.py @@ -154,7 +154,7 @@ class ScanMaster(): if self._scan_path is None: return True if self._last_block is not None: - self._multi_map(lambda x: x.reset_color(), + self._multi_map(lambda x: x.scan_highlight(None), self._last_block) if SettingsManager.reverse_scanning.value: @@ -172,7 +172,7 @@ class ScanMaster(): else: color = SettingsManager.block_scanning_color.value - self._multi_map(lambda x: x.set_color(color, None), next_block) + self._multi_map(lambda x: x.scan_highlight(color), next_block) self._last_block = next_block return True -- cgit v1.2.1 From 1bba04c5cb81906f8fe578c53797ea2c6ea1a66d Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Fri, 7 Jan 2011 18:43:46 -0800 Subject: Update configure prerequisites. --- configure.ac | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 19dae9f..110a14a 100644 --- a/configure.ac +++ b/configure.ac @@ -20,12 +20,12 @@ AC_PATH_PROG(GCONFTOOL, gconftool-2) AM_GCONF_SOURCE_2 dnl == Library dependencies == -PYGTK_REQUIRED=2.16 -PYCLUTTER_REQUIRED=1.0 +GTK_REQUIRED=2.91.8 +CLUTTER_REQUIRED=1.5.11 PKG_CHECK_MODULES(CARIBOU, [ - pygtk-2.0 >= $PYGTK_REQUIRED, - pyclutter-1.0 >= $PYCLUTTER_REQUIRED]) + gtk+-3.0 >= $GTK_REQUIRED, + clutter-1.0 >= $CLUTTER_REQUIRED]) AC_SUBST(CARIBOU_CFLAGS) AC_SUBST(CARIBOU_LIBS) -- cgit v1.2.1