summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEitan Isaacson <eitan@monotonous.org>2010-12-14 15:54:07 -0800
committerEitan Isaacson <eitan@monotonous.org>2011-01-07 13:34:34 -0800
commit1788b7a040fcb6074ab2bbf322e2385be5661b28 (patch)
tree90ede3d28dfec6b0621044272b40f8bd5711922c
parent0b5e10eed67e5aa0734735ea19c11a611b486624 (diff)
downloadcaribou-1788b7a040fcb6074ab2bbf322e2385be5661b28.tar.gz
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.
-rw-r--r--bin/caribou.in6
-rw-r--r--caribou/common/setting_types.py38
-rw-r--r--caribou/common/settings.py2
-rw-r--r--caribou/common/settings_manager.py25
-rw-r--r--caribou/ui/animation.py26
-rw-r--r--caribou/ui/keyboard.py223
-rw-r--r--caribou/ui/main.py48
-rw-r--r--caribou/ui/opacity.py4
-rw-r--r--caribou/ui/preferences_window.py99
-rw-r--r--caribou/ui/scan.py27
-rw-r--r--caribou/ui/window.py115
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('<b>%s</b>' % 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()