#!/usr/bin/env python
import gobject
import gtk
+import pango
+import dbus
+import ibus
from ibus import keysyms
from ibus import interface
def __init__ (self, dbusconn, object_path):
interface.IEngine.__init__ (self, dbusconn, object_path)
self._dbusconn = dbusconn
+ self._preedit_string = ""
# methods for dbus rpc
def ProcessKeyEvent (self, keyval, is_press, state):
+ # ignore key release events
if not is_press:
return False
- if keyval < 128 and (state & keysyms.CONTROL_MASK | keysyms.MOD1_MASK | keysyms.SHIFT_MASK) == 0:
- self.CommitString (chr(keyval))
- print "commit %s" % chr(keyval)
- return True
- return False
+
+ if self._preedit_string:
+ if keyval == keysyms.Return:
+ self.CommitString (self._preedit_string)
+ self._preedit_string = ""
+ self._update_preedit ()
+ return True
+ elif keyval == keysyms.BackSpace:
+ self._preedit_string = self._preedit_string[:-1]
+ self._update_preedit ()
+ return True
+
+ # ignore hotkeys or key > 128
+ if keyval >= 128 or (state & (keysyms.CONTROL_MASK | keysyms.MOD1_MASK)) != 0:
+ return False
+
+ self._preedit_string += chr (keyval)
+ self._update_preedit ()
+
+ return True
+
+ def _update_preedit (self):
+ preedit_len = len (self._preedit_string)
+ attrs = ibus.AttrList ()
+ attrs.append (ibus.AttributeUnderline (pango.UNDERLINE_SINGLE, 0, preedit_len))
+ self.PreeditChanged (self._preedit_string, attrs.to_dbus_value (), dbus.Int32 (preedit_len))
+ self.AuxStringChanged (self._preedit_string, attrs.to_dbus_value ())
def FocusIn (self):
print "FocusIn"
}
dbus_message_iter_recurse (&iter, &sub_iter);
if (dbus_message_iter_get_arg_type (&sub_iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type (&sub_iter) != DBUS_TYPE_UINT32 ) {
+ dbus_message_iter_get_element_type (&sub_iter) != DBUS_TYPE_INT32 ) {
g_warning ("The secode argument of PreeditChanged signal must be a Struct Array");
return;
}
}
switch (values[0]) {
- case 1: /* Decoration */
- attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE);
+ case 1: /* Underline */
+ attr = pango_attr_underline_new (values[1]);
attr->start_index = values[2];
attr->end_index = values[3];
pango_attr_list_insert (attrs, attr);
type = dbus_message_iter_get_arg_type (&iter);
if (type != DBUS_TYPE_INT32) {
- g_warning ("The third argument of PreeditChanged signal must be an Int32");
+ g_warning ("The third argument of PreeditChanged signal must be an Int32 %c", type);
pango_attr_list_unref (attrs);
return;
}
self._end_index = end_index
def to_dbus_value (self):
- values = [dbus.UInt32 (self._type),
- dbus.UInt32 (self._value),
- dbus.UInt32 (self._start_index),
- dbus.UInt32 (self._end_index)]
+ values = [dbus.Int32 (self._type),
+ dbus.Int32 (self._value),
+ dbus.Int32 (self._start_index),
+ dbus.Int32 (self._end_index)]
return dbus.Array (values)
def from_dbus_value (self, value):
if not isinstance (value, dbus.Array):
raise dbus.Exception ("Attribute must be dbus.Array (uuuu)")
- if len (value) != 4 or not all (map (lambda x: isinstance (x, dbus.UInt32), value)):
+ if len (value) != 4 or not all (map (lambda x: isinstance (x, dbus.Int32), value)):
raise dbus.Exception ("Attribute must be dbus.Array (uuuu)")
self._type = value[0]
class PangoAttrList (pango.AttrList):
def __init__ (self, attrs):
pango.AttrList.__init__ (self)
+ if attrs == None:
+ return
for attr in attrs:
pango_attr = None
- if attr._type == ATTR_TYPE_FOREGROUND:
+ if attr._type == ibus.ATTR_TYPE_FOREGROUND:
r = (attr._value & 0x00ff0000) >> 8
g = (attr._value & 0x0000ff00)
b = (attr._value & 0x000000ff) << 8
pango_attr = pango.AttrForeground (r, g, b,
attr._start_index, attr._end_index)
- elif attr._type == ATTR_TYPE_BACKGROUND:
+ elif attr._type == ibus.ATTR_TYPE_BACKGROUND:
r = (attr._value & 0x00ff0000) >> 8
g = (attr._value & 0x0000ff00)
b = (attr._value & 0x000000ff) << 8
pango_attr = pango.AttrBackground (r, g, b,
attr._start_index, attr._end_index)
- elif attr._type == ATTR_TYPE_UNDERLINE:
- pango_attr = pango.AttrUnderline (
- attr._value,
+ elif attr._type == ibus.ATTR_TYPE_UNDERLINE:
+ pango_attr = pango.AttrUnderline (attr._value,
attr._start_index, attr._end_index)
if pango_attr != None:
self.insert (pango_attr)
@signal (signature="ubu")
def ForwardKeyEvent (self, keyval, is_press, state): pass
- @signal (signature="svu")
+ @signal (signature="saaii")
def PreeditChanged (self, text, attrs, cursor_pos): pass
# below signals are optional. The engine could create and maintain panel by self.
dbus.service.method (dbus_interface = IBUS_PANE_IFACE, \
async_callbacks = ("reply_cb", "error_cb"), \
**args)
+ @method (in_signature="iiii")
+ def SetCursorLocation (self, x, y, w, h): pass
+
@method (in_signature="svu")
def SetPreeditString (self, text, attrs, cursor_pos): pass
def set_cursor_location (self, x, y, w, h, dbusconn):
client = self._lookup_client (dbusconn)
client.set_cursor_location (x, y, w, h)
+ self._panel.set_cursor_location (x, y, w, h)
def _filter_hotkeys (self, client, keyval, is_press, state):
if is_press and keyval == keysyms.space \
def _aux_string_changed_cb (self, client, text, attrs):
assert self._focused_client == client
- self._pabel.set_aux_string (text, attrs)
+ self._panel.set_aux_string (text, attrs)
def _update_lookup_table_cb (self, client, lookup_table):
assert self._focused_client == client
- self._pabel.update_lookup_table (lookup_table)
+ self._panel.update_lookup_table (lookup_table)
def _show_lookup_table_cb (self, client, lookup_table):
assert self._focused_client == client
- self._pabel.show_candidate_window ()
+ self._panel.show_candidate_window ()
def _hide_lookup_table_cb (self, client, lookup_table):
assert self._focused_client == client
- self._pabel.hide_candidate_window ()
+ self._panel.hide_candidate_window ()
##########################################################
# methods for im engines
"preedit-changed" : (
gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
- (gobject.TYPE_STRING, gobject.TYPE_PYOBJECT, gobject.TYPE_UINT)),
+ (gobject.TYPE_STRING, gobject.TYPE_PYOBJECT, gobject.TYPE_INT)),
"aux-string-changed" : (
gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
self.commit_string (text)
def _preedit_changed_cb (self, engine, text, attrs, cursor_pos):
- self.preedit_changed (self, text, attrs, cursor_pos)
+ self.preedit_changed (text, attrs, cursor_pos)
def _aux_string_changed_cb (self, engine, text, attrs):
self._aux_string = text
"preedit-changed" : (
gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
- (gobject.TYPE_STRING, gobject.TYPE_PYOBJECT, gobject.TYPE_UINT)),
+ (gobject.TYPE_STRING, gobject.TYPE_PYOBJECT, gobject.TYPE_INT)),
"aux-string-changed" : (
gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
self.emit ("forward-key-event", args[0], bool (arg[1]), arg[2])
return True
elif message.is_signal (ibus.IBUS_ENGINE_IFACE, "PreeditChanged"):
+ args = message.get_args_list ()
self.emit ("preedit-changed", args[0], args[1], args[2])
return True
elif message.is_signal (ibus.IBUS_ENGINE_IFACE, "AuxStringChanged"):
+ args = message.get_args_list ()
self.emit ("aux-string-changed", args[0], args[1])
return True
elif message.is_signal (ibus.IBUS_ENGINE_IFACE, "UpdateLookupTable"):
args = message.get_args_list ()
- lookup_table = ibus.lookup_table_from_dbus_value (args[0])
- self.emit ("update-lookup-table", lookup_table)
+ self.emit ("update-lookup-table", args[0])
return True
elif message.is_signal (ibus.IBUS_ENGINE_IFACE, "ShowLookupTable"):
- args = message.get_args_list ()
self.emit ("show-lookup-table")
return True
elif message.is_signal (ibus.IBUS_ENGINE_IFACE, "HideLookupTable"):
- args = message.get_args_list ()
self.emit ("hide-lookup-table")
return True
else:
self._engine.ProcessKeyEvent (keyval, is_press, state,
reply_handler = reply_cb,
error_handler = error_cb)
-
+
def set_cursor_location (self, x, y, w, h):
self._engine.SetCursorLocation (x, y, w, h)
self._ibusconn.connect ("destroy", self._ibusconn_destroy_cb)
self._ibusconn.connect ("dbus-signal", self._dbus_signal_cb)
+ def set_cursor_location (self, x, y, w, h):
+ self._panel.SetCursorLocation (x, y, w, h)
+
def set_preedit_string (self, text, attrs, cursor_pos):
self._panel.SetPreeditString (text, attrs, cursor_pos)
PYTHON = env PYTHONPATH=../ python
+all: test-panel
+
test-candidatewindow:
$(PYTHON) ./candidatewindow.py
import gtk.gdk as gdk
import gobject
import pango
+from ibus.gtk import PangoAttrList
class HSeparator (gtk.HBox):
def __init__ (self):
self._preedit_label.hide ()
def set_aux_string (self, text, attrs):
+ attrs = PangoAttrList (attrs)
self._aux_string = text
self._aux_label.set_text (text)
if attrs == None:
self._aux_attrs = attrs
self._aux_label.set_attributes (attrs)
- def set_preedit_string (self, text, attrs):
+ def set_preedit_string (self, text, attrs, cursor_pos):
+ attrs = PangoAttrList (attrs)
self._preedit_string = text
self._preedit_label.set_text (text)
if attrs == None:
def set_lookup_table (self, lookup_table):
self._lookup_table = lookup_table
candidates = self._lookup_table.get_canidates_in_current_page ()
+ candidates = map (lambda x: (x[0], PangoAttrList (x[1])), candidates)
+ self._candidate_area.set_candidates (candidates)
def set_orientation (self, orientation):
if self._orientation == orientation:
self._candidate_panel.connect ("size-request", self._size_request_cb)
self.add (self._candidate_panel)
self.move (100, 100)
+ self.show_all ()
- def set_preedit_string (self, text, attrs):
- self._candidate_panel.set_preedit_string (text, attrs)
+ def set_preedit_string (self, text, attrs, cursor_pos):
+ self._candidate_panel.set_preedit_string (text, attrs, cursor_pos)
def show_preedit_string (self, text, attrs):
self._candidate_panel.show_preedit_string ()
self._candidate_panel.set_aux_string (text, attrs)
def set_lookup_table (self, lookup_table):
- self._candidate_pabel.set_lookup_table (lookup_table)
+ self._candidate_panel.set_lookup_table (lookup_table)
def _size_request_cb (self, widget, size):
self.resize (1, 1)
def main ():
# gtk.settings_get_default ().props.gtk_theme_name = "/home/phuang/.themes/aud-Default/gtk-2.0/gtkrc"
- gtk.rc_parse ("./themes/default/gtkrc")
+ # gtk.rc_parse ("./themes/default/gtkrc")
PanelApplication ().run ()
if __name__ == "__main__":
import gtk
import gtk.gdk as gdk
import gobject
+import ibus
from ibus import interface
-from image import Image
-from handle import Handle
-
-class PanelBar (gtk.Toolbar):
- def __init__ (self):
- gtk.Toolbar.__init__ (self)
- self.set_property ("icon-size", gtk.ICON_SIZE_MENU)
- # self.set_orientation (gtk.ORIENTATION_VERTICAL)
- self._create_items ()
+from languagebar import LanguageBarWindow
+from candidatewindow import CandidateWindow
+
+class Panel (gobject.GObject):
+ def __init__ (self, proxy):
+ gobject.GObject.__init__ (self)
+ self._proxy = proxy
+ self._language_bar = LanguageBarWindow ()
+ self._candidate_panel = CandidateWindow ()
+
+ def set_cursor_location (self, x, y, w, h):
+ self._candidate_panel.move (x + w, y + h)
- def insert (self, toolitem, pos):
- gtk.Toolbar.insert (self, toolitem, pos)
- self.check_resize ()
-
- def _add_items (self):
- btn = gtk.ToolButton (gtk.STOCK_NEW)
- btn.connect ("clicked", lambda x: self._add_items ())
- self.insert (btn, -1)
- self.insert (gtk.ToolButton (gtk.STOCK_APPLY), -1)
- self.insert (gtk.SeparatorToolItem (), -1)
- self.show_all ()
-
- def _create_items (self):
- handle = Handle ()
- item = gtk.ToolItem ()
- item.add (handle)
- self.insert (item, -1)
-
- self._add_items ()
-
- def do_realize (self):
- gtk.Toolbar.do_realize (self)
- self.check_resize ()
+ def set_preedit_string (self, text, attrs, cursor_pos):
+ self._candidate_panel.set_preedit_string (text, attrs, cursor_pos)
+
+ def show_preedit_string (self):
+ self._candidate_panel.show_preedit_string ()
+
+ def hide_preedit_string (self):
+ self._candidate_panel.hide_preedit_string ()
+
+ def set_aux_string (self, text, attrs):
+ self._candidate_panel.set_aux_string (text, attrs)
+
+ def show_aux_string (self):
+ self._candidate_panel.show_aux_string ()
+
+ def hide_aux_string (self):
+ self._candidate_panel.hide_aux_string ()
- def do_check_resize (self):
- width = 0
- for item in self:
- w, h = item.size_request ()
- width += w
- self.set_size_request (width + 2, -1)
-
-gobject.type_register (PanelBar, "IBusToolbar")
-
-class PanelWindow (gtk.Window):
- def __init__ (self):
- gtk.Window.__init__ (self, gtk.WINDOW_POPUP)
- self._panel_bar = PanelBar ()
- self._panel_bar.connect ("size-request", self._size_request_cb)
- self.add (self._panel_bar)
- self.show_all ()
-
- def _size_request_cb (self, widget, size):
- self.resize (size.width, size.height)
-
- def do_size_allocate (self, allocation):
- gtk.Window.do_size_allocate (self, allocation)
- root = gdk.get_default_root_window ()
- workarea = root.property_get ("_NET_WORKAREA")[2]
- x, y = workarea[2] - allocation.width - 40, workarea[1] + workarea[3] - allocation.height
- self.move (x, y)
-
- def do_destroy (self):
- gtk.main_quit ()
- gtk.Window.do_destroy (self)
-
-gobject.type_register (PanelWindow, "IBusPanelWindow")
+ def update_lookup_table (self, lookup_table):
+ self._candidate_panel.set_lookup_table (lookup_table)
+
+ def show_candidate_window (self):
+ self._candidate_panel.show ()
+
+ def hide_candidate_window (self):
+ self._candidate_panel.hide ()
+
+ def show_language_bar (self):
+ selk._language_bar.show ()
+
+ def hide_language_bar (self):
+ selk._language_bar.hide ()
class PanelProxy (interface.IPanel):
def __init__ (self, dbusconn, object_path):
interface.IPanel.__init__ (self, dbusconn, object_path)
self._dbusconn = dbusconn
- self._panel = PanelWindow ()
+ self._panel = Panel (self)
+
+ def SetCursorLocation (self, x, y, w, h):
+ self._panel.set_cursor_location (x, y, w, h)
+
+ def SetPreeditString (self, text, attrs, cursor_pos):
+ attrs = ibus.attr_list_from_dbus_value (attrs)
+ self._panel.set_preedit_string (text, atrrs, cursor_pos)
+
+ def ShowPreeditString (self):
+ self._panel.show_preedit_string ()
+
+ def HidePreeditString (self):
+ self._panel.hide_preedit_string ()
+
+ def SetAuxString (self, text, attrs):
+ attrs = ibus.attr_list_from_dbus_value (attrs)
+ self._panel.set_aux_string (text, attrs)
+
+ def ShowAuxString (self):
+ self._panel.show_aux_string ()
+
+ def HideAuxString (self):
+ self._panel.hide_aux_string ()
+
+ def UpdateLookupTable (self, lookup_table):
+ self._panel.update_lookup_table ()
+
+ def ShowCandidateWindow (self):
+ self._panel.show_candidate_window ()
+
+ def HideCandidateWindow (self):
+ self._panel.hide_candidate_window ()
+
+ def ShowLanguageBar (self):
+ self._panel.show_language_bar ()
+
+ def HideLanguageBar (self):
+ self._panel.hide_language_bar ()
def Destroy (self):
- self._panel.destroy ()
+ self._pabel.destroy ()