}
#define DEFINE_FUNCTION(Name, name) \
- void bus_engine_proxy_##name (BusEngineProxy *engine) \
+ void \
+ bus_engine_proxy_##name (BusEngineProxy *engine) \
{ \
g_assert (BUS_IS_ENGINE_PROXY (engine)); \
ibus_proxy_call ((IBusProxy *) engine, \
#undef DEFINE_FUNCTION
+void
+bus_engine_proxy_candidate_clicked (BusEngineProxy *engine,
+ guint index,
+ guint button,
+ guint state)
+{
+ g_assert (BUS_IS_ENGINE_PROXY (engine));
+
+ ibus_proxy_call ((IBusProxy *) engine,
+ "CandidateClicked",
+ G_TYPE_UINT, &index,
+ G_TYPE_UINT, &button,
+ G_TYPE_UINT, &state,
+ G_TYPE_INVALID);
+}
IBusEngineDesc *
bus_engine_proxy_get_desc (BusEngineProxy *engine)
void bus_engine_proxy_page_down (BusEngineProxy *engine);
void bus_engine_proxy_cursor_up (BusEngineProxy *engine);
void bus_engine_proxy_cursor_down (BusEngineProxy *engine);
+void bus_engine_proxy_candidate_clicked (BusEngineProxy *engine,
+ guint index,
+ guint button,
+ guint state);
void bus_engine_proxy_enable (BusEngineProxy *engine);
void bus_engine_proxy_disable (BusEngineProxy *engine);
void bus_engine_proxy_property_activate (BusEngineProxy *engine,
}
}
-void
-bus_input_context_page_up (BusInputContext *context)
-{
- g_assert (BUS_IS_INPUT_CONTEXT (context));
-
- BusInputContextPrivate *priv;
- priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context);
-
- if (priv->engine) {
- bus_engine_proxy_page_up (priv->engine);
- }
-}
-
-void
-bus_input_context_page_down (BusInputContext *context)
-{
- g_assert (BUS_IS_INPUT_CONTEXT (context));
-
- BusInputContextPrivate *priv;
- priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context);
-
- if (priv->engine) {
- bus_engine_proxy_page_down (priv->engine);
- }
-}
-
-void
-bus_input_context_cursor_up (BusInputContext *context)
-{
- g_assert (BUS_IS_INPUT_CONTEXT (context));
-
- BusInputContextPrivate *priv;
- priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context);
-
- if (priv->engine) {
- bus_engine_proxy_cursor_up (priv->engine);
- }
-}
+#define DEFINE_FUNC(name) \
+ void \
+ bus_input_context_##name (BusInputContext *context) \
+ { \
+ g_assert (BUS_IS_INPUT_CONTEXT (context)); \
+ \
+ BusInputContextPrivate *priv; \
+ priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); \
+ \
+ if (priv->engine) { \
+ bus_engine_proxy_##name (priv->engine); \
+ } \
+ }
+
+DEFINE_FUNC(page_up)
+DEFINE_FUNC(page_down)
+DEFINE_FUNC(cursor_up)
+DEFINE_FUNC(cursor_down)
+
+#undef DEFINE_FUNC
void
-bus_input_context_cursor_down (BusInputContext *context)
+bus_input_context_candidate_clicked (BusInputContext *context,
+ guint index,
+ guint button,
+ guint state)
{
g_assert (BUS_IS_INPUT_CONTEXT (context));
priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context);
if (priv->engine) {
- bus_engine_proxy_cursor_down (priv->engine);
+ bus_engine_proxy_candidate_clicked (priv->engine,
+ index,
+ button,
+ state);
}
}
void bus_input_context_page_down (BusInputContext *context);
void bus_input_context_cursor_up (BusInputContext *context);
void bus_input_context_cursor_down (BusInputContext *context);
+void bus_input_context_candidate_clicked(BusInputContext *context,
+ guint index,
+ guint button,
+ guint state);
void bus_input_context_set_engine (BusInputContext *context,
BusEngineProxy *factory);
BusEngineProxy *bus_input_context_get_engine (BusInputContext *context);
PAGE_DOWN,
CURSOR_UP,
CURSOR_DOWN,
+ CANDIDATE_CLICKED,
PROPERTY_ACTIVATE,
PROPERTY_SHOW,
PROPERTY_HIDE,
static void bus_panel_proxy_page_down (BusPanelProxy *panel);
static void bus_panel_proxy_cursor_up (BusPanelProxy *panel);
static void bus_panel_proxy_cursor_down (BusPanelProxy *panel);
+static void bus_panel_proxy_candidate_clicked
+ (BusPanelProxy *panel,
+ guint index,
+ guint button,
+ guint state);
static void bus_panel_proxy_property_activate
(BusPanelProxy *panel,
const gchar *prop_name,
klass->cursor_up = bus_panel_proxy_cursor_up;
klass->cursor_down = bus_panel_proxy_cursor_down;
+ klass->candidate_clicked = bus_panel_proxy_candidate_clicked;
klass->property_activate = bus_panel_proxy_property_activate;
ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_panel_proxy_real_destroy;
ibus_marshal_VOID__VOID,
G_TYPE_NONE, 0);
+ panel_signals[CANDIDATE_CLICKED] =
+ g_signal_new (I_("candidate-clicked"),
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(BusPanelProxyClass, candidate_clicked),
+ NULL, NULL,
+ ibus_marshal_VOID__UINT_UINT_UINT,
+ G_TYPE_NONE, 3,
+ G_TYPE_UINT,
+ G_TYPE_UINT,
+ G_TYPE_UINT);
+
panel_signals[PROPERTY_ACTIVATE] =
g_signal_new (I_("property-activate"),
G_TYPE_FROM_CLASS (klass),
}
}
- if (ibus_message_is_signal (message, IBUS_INTERFACE_PANEL, "PropertyActivate")) {
+ if (ibus_message_is_signal (message, IBUS_INTERFACE_PANEL, "CandidateClicked")) {
+ guint index, button, state;
+ gboolean retval;
+
+ retval = ibus_message_get_args (message,
+ &error,
+ G_TYPE_UINT, &index,
+ G_TYPE_UINT, &button,
+ G_TYPE_UINT, &state,
+ G_TYPE_INVALID);
+ if (!retval)
+ goto failed;
+
+ g_signal_emit (panel, panel_signals[CANDIDATE_CLICKED], 0, index, button, state);
+ }
+ else if (ibus_message_is_signal (message, IBUS_INTERFACE_PANEL, "PropertyActivate")) {
gchar *prop_name;
gint prop_state;
gboolean retval;
G_TYPE_INVALID);
}
-static void
-bus_panel_proxy_page_up (BusPanelProxy *panel)
-{
- g_assert (BUS_IS_PANEL_PROXY (panel));
-
- BusPanelProxyPrivate *priv;
- priv = BUS_PANEL_PROXY_GET_PRIVATE (panel);
-
- if (priv->focused_context) {
- bus_input_context_page_up (priv->focused_context);
- }
-}
-
-static void
-bus_panel_proxy_page_down (BusPanelProxy *panel)
-{
- g_assert (BUS_IS_PANEL_PROXY (panel));
-
- BusPanelProxyPrivate *priv;
- priv = BUS_PANEL_PROXY_GET_PRIVATE (panel);
-
- if (priv->focused_context) {
- bus_input_context_page_down (priv->focused_context);
+#define DEFINE_FUNC(name) \
+ static void \
+ bus_panel_proxy_##name (BusPanelProxy *panel) \
+ { \
+ g_assert (BUS_IS_PANEL_PROXY (panel)); \
+ \
+ BusPanelProxyPrivate *priv; \
+ priv = BUS_PANEL_PROXY_GET_PRIVATE (panel); \
+ \
+ if (priv->focused_context) { \
+ bus_input_context_##name (priv->focused_context); \
+ } \
}
-}
-static void
-bus_panel_proxy_cursor_up (BusPanelProxy *panel)
-{
- g_assert (BUS_IS_PANEL_PROXY (panel));
- BusPanelProxyPrivate *priv;
- priv = BUS_PANEL_PROXY_GET_PRIVATE (panel);
-
- if (priv->focused_context) {
- bus_input_context_cursor_up (priv->focused_context);
- }
-}
+DEFINE_FUNC(page_up)
+DEFINE_FUNC(page_down)
+DEFINE_FUNC(cursor_up)
+DEFINE_FUNC(cursor_down)
+#undef DEFINE_FUNC
static void
-bus_panel_proxy_cursor_down (BusPanelProxy *panel)
+bus_panel_proxy_candidate_clicked (BusPanelProxy *panel,
+ guint index,
+ guint button,
+ guint state)
{
g_assert (BUS_IS_PANEL_PROXY (panel));
priv = BUS_PANEL_PROXY_GET_PRIVATE (panel);
if (priv->focused_context) {
- bus_input_context_cursor_down (priv->focused_context);
+ bus_input_context_candidate_clicked (priv->focused_context,
+ index,
+ button,
+ state);
}
}
void (* page_down) (BusPanelProxy *panel);
void (* cursor_up) (BusPanelProxy *panel);
void (* cursor_down) (BusPanelProxy *panel);
+ void (* candidate_clicked) (BusPanelProxy *panel,
+ guint index,
+ guint button,
+ guint state);
void (* property_activate) (BusPanelProxy *panel,
const gchar *prop_name,
def CursorDown(self):
return self.__engine.cursor_down()
+ def CandidateClicked(self, index, button, state):
+ return self.__engine.candidate_clicked(index, button, state)
+
def Enable(self):
return self.__engine.enable()
@method()
def CursorDown(self): pass
+ @method(in_signature="uuu")
+ def CandidateClicked(self, index, button, state):
+ pass
+
@method()
def Enable(self): pass
@signal(signature="v")
def CommitText(self, text): pass
- @signal(signature="ubu")
- def ForwardKeyEvent(self, keyval, is_press, state): pass
+ @signal(signature="uu")
+ def ForwardKeyEvent(self, keyval, state): pass
@signal(signature="vub")
def UpdatePreeditText(self, text, cursor_pos, visible): pass
@signal()
def CursorUp(self): pass
+ @signal(signature="uuu")
+ def CandidateClicked(self, index, button, state): pass
+
@signal()
def CursorDown(self): pass
def cursor_down(self):
self.__proxy.CursorDown()
+ def candidate_clicked(self, index, button, state):
+ self.__proxy.CandidateClicked(index, button, state)
+
def property_activate(self, prop_name, prop_state):
prop_name = dbus.String(prop_name)
prop_state = dbus.Int32(prop_state)
PROPERTY_ACTIVATE,
PROPERTY_SHOW,
PROPERTY_HIDE,
+ CANDIDATE_CLICKED,
LAST_SIGNAL,
};
static void ibus_engine_page_down (IBusEngine *engine);
static void ibus_engine_cursor_up (IBusEngine *engine);
static void ibus_engine_cursor_down (IBusEngine *engine);
+static void ibus_engine_candidate_clicked
+ (IBusEngine *engine,
+ guint index,
+ guint button,
+ guint state);
static void ibus_engine_property_activate
(IBusEngine *engine,
const gchar *prop_name,
klass->page_down = ibus_engine_page_down;
klass->cursor_up = ibus_engine_cursor_up;
klass->cursor_down = ibus_engine_cursor_down;
+ klass->candidate_clicked = ibus_engine_candidate_clicked;
klass->property_activate = ibus_engine_property_activate;
klass->property_show = ibus_engine_property_show;
klass->property_hide = ibus_engine_property_hide;
* IBusEngine::page-up:
* @engine: An IBusEngine.
*
- * Emitted when the page-up key is pressed.
+ * Emitted when the page-up button is pressed.
* Implement the member function page_up() in extended class to receive this signal.
*
* <note><para>@user_data is not actually a valid parameter. It is displayed because of GtkDoc bug.</para></note>
* IBusEngine::page-down:
* @engine: An IBusEngine.
*
- * Emitted when the page-down key is pressed.
+ * Emitted when the page-down button is pressed.
* Implement the member function page_down() in extended class to receive this signal.
*
* <note><para>@user_data is not actually a valid parameter. It is displayed because of GtkDoc bug.</para></note>
* IBusEngine::cursor-up:
* @engine: An IBusEngine.
*
- * Emitted when the up cursor key is pressed.
+ * Emitted when the up cursor button is pressed.
* Implement the member function cursor_up() in extended class to receive this signal.
*
* <note><para>@user_data is not actually a valid parameter. It is displayed because of GtkDoc bug.</para></note>
* IBusEngine::cursor-down:
* @engine: An IBusEngine.
*
- * Emitted when the down cursor key is pressed.
+ * Emitted when the down cursor button is pressed.
* Implement the member function cursor_down() in extended class to receive this signal.
*
* <note><para>@user_data is not actually a valid parameter. It is displayed because of GtkDoc bug.</para></note>
G_TYPE_NONE,
0);
+ /**
+ * IBusEngine::candidate-clicked:
+ * @engine: An IBusEngine.
+ *
+ * Emitted when candidate on lookup table is clicked.
+ * Implement the member function candidate_clicked() in extended class to receive this signal.
+ *
+ * <note><para>@user_data is not actually a valid parameter. It is displayed because of GtkDoc bug.</para></note>
+ */
+ engine_signals[CANDIDATE_CLICKED] =
+ g_signal_new (I_("candidate-clicked"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (IBusEngineClass, candidate_clicked),
+ NULL, NULL,
+ ibus_marshal_VOID__UINT_UINT_UINT,
+ G_TYPE_NONE,
+ 3,
+ G_TYPE_UINT,
+ G_TYPE_UINT,
+ G_TYPE_UINT);
+
/**
* IBusEngine::property-activate:
* @engine: An IBusEngine.
return TRUE;
}
-
if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "ProcessKeyEvent")) {
guint keyval, state;
gboolean retval;
_keypress_fail:
error_message = ibus_message_new_error_printf (message,
DBUS_ERROR_INVALID_ARGS,
- "%s.%s: Can not match signature (ubu) of method",
+ "%s.%s: Can not match signature (uu) of method",
IBUS_INTERFACE_ENGINE, "ProcessKeyEvent");
ibus_connection_send (connection, error_message);
ibus_message_unref (error_message);
return TRUE;
}
+ else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "CandidateClicked")) {
+ guint index, button, state;
+ gboolean retval;
+ IBusError *error = NULL;
+
+ retval = ibus_message_get_args (message,
+ &error,
+ G_TYPE_UINT, &index,
+ G_TYPE_UINT, &button,
+ G_TYPE_UINT, &state,
+ G_TYPE_INVALID);
+
+ if (!retval)
+ goto _candidate_clicked_fail;
+
+ retval = FALSE;
+ g_signal_emit (engine,
+ engine_signals[CANDIDATE_CLICKED],
+ 0,
+ index,
+ button,
+ state,
+ &retval);
+
+ return_message = ibus_message_new_method_return (message);
+ ibus_connection_send (connection, return_message);
+ ibus_message_unref (return_message);
+ return TRUE;
+
+ _candidate_clicked_fail:
+ error_message = ibus_message_new_error_printf (message,
+ DBUS_ERROR_INVALID_ARGS,
+ "%s.%s: Can not match signature (uuu) of method",
+ IBUS_INTERFACE_ENGINE, "CandidateClicked");
+ ibus_connection_send (connection, error_message);
+ ibus_message_unref (error_message);
+ return TRUE;
+ }
else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "PropertyActivate")) {
gchar *name;
guint state;
// g_debug ("cursor-down");
}
+static void
+ibus_engine_candidate_clicked (IBusEngine *engine,
+ guint index,
+ guint button,
+ guint state)
+{
+ // g_debug ("candidate-clicked");
+}
+
static void
ibus_engine_property_activate (IBusEngine *engine,
const gchar *prop_name,
const gchar *prop_name);
void (* property_hide) (IBusEngine *engine,
const gchar *prop_name);
+ void (* candidate_clicked)
+ (IBusEngine *engine,
+ guint index,
+ guint button,
+ guint state);
+
+
/*< private >*/
/* padding */
- gpointer pdummy[9];
+ gpointer pdummy[8];
};
GType ibus_engine_get_type (void);
BOOL:ULONG
VOID:INT,INT,INT,INT
VOID:UINT,UINT
+VOID:UINT,UINT,UINT
VOID:OBJECT,UINT,BOOL
VOID:OBJECT,BOOL
VOID:BOXED,BOOL
# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
# Boston, MA 02111-1307 USA
+import operator
import gtk
import gtk.gdk as gdk
import gobject
import ibus
from ibus._gtk import PangoAttrList
-class Label(gtk.Label): pass
+class EventBox(gtk.EventBox):
+ def __init__(self):
+ super(EventBox, self).__init__()
+ self.connect("realize", self.__realize_cb)
+
+ def __realize_cb(self, widget):
+ widget.window.set_cursor(gdk.Cursor(gdk.HAND2))
+
+gobject.type_register(EventBox, "IBusEventBox")
+
+class Label(gtk.Label):
+ pass
gobject.type_register(Label, "IBusPanelLabel")
class HSeparator(gtk.HBox):
- def __init__ (self):
- gtk.HBox.__init__ (self)
+ def __init__(self):
+ super(HSeparator, self).__init__()
self.pack_start(gtk.HSeparator(), True, True, 4)
class VSeparator(gtk.VBox):
- def __init__ (self):
- gtk.VBox.__init__ (self)
+ def __init__(self):
+ super(VSeparator, self).__init__()
self.pack_start(gtk.VSeparator(), True, True, 4)
class CandidateArea(gtk.HBox):
+ __gsignals__ = {
+ "candidate-clicked" : (
+ gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE,
+ (gobject.TYPE_UINT, gobject.TYPE_UINT, gobject.TYPE_UINT )),
+ }
+
def __init__ (self, orientation):
gtk.HBox.__init__ (self)
self.__orientation = orientation
self.__labels = []
+ self.__candidates = []
self.__create_ui()
def __create_ui(self):
self.pack_start(VSeparator(), False, False, 0)
self.pack_start(self.__vbox2, True, True, 4)
- for i in xrange(0, 16):
- if i < 10:
- label1 = Label("%d." % ((i + 1) % 10))
- else:
- label1 = Label("%c." % chr(97 + i - 10))
+ for i in range(0, 16):
+ label1 = Label("%c." % ("1234567890abcdef"[i]))
label1.set_alignment(0.0, 0.5)
- label1.set_no_show_all(True)
+ label1.show()
label2 = Label()
label2.set_alignment(0.0, 0.5)
- label2.set_no_show_all(True)
+ label1.show()
if self.__orientation == gtk.ORIENTATION_VERTICAL:
label1.set_property("xpad", 8)
label2.set_property("xpad", 8)
- self.__vbox1.pack_start(label1, False, False, 2)
- self.__vbox2.pack_start(label2, False, False, 2)
+ ebox1 = EventBox()
+ ebox1.set_no_show_all(True)
+ ebox1.add(label1)
+ ebox2 = EventBox()
+ ebox2.set_no_show_all(True)
+ ebox2.add(label2)
+ self.__vbox1.pack_start(ebox1, False, False, 2)
+ self.__vbox2.pack_start(ebox2, False, False, 2)
+ self.__candidates.append((ebox1, ebox2))
else:
hbox = gtk.HBox()
+ hbox.show()
hbox.pack_start(label1, False, False, 1)
hbox.pack_start(label2, False, False, 1)
- self.pack_start(hbox, False, False, 4)
+ ebox = EventBox()
+ ebox.set_no_show_all(True)
+ ebox.add(hbox)
+ self.pack_start(ebox, False, False, 4)
+ self.__candidates.append((ebox,))
self.__labels.append((label1, label2))
- self.__labels[0][0].show()
- self.__labels[0][1].show()
+ cursor = gdk.Cursor(gdk.HAND1)
+ for i, ws in enumerate(self.__candidates):
+ for w in ws:
+ w.connect("button-press-event", lambda w, e, i:self.emit("candidate-clicked", i, e.button, e.state), i)
def set_labels(self, labels):
if not labels:
for i in xrange(0, 16):
- if i < 10:
- self.__labels[i][0].set_text("%d." % ((i + 1) % 10))
- else:
- self.__labels[i][0].set_text("%c." % chr(97 + i - 10))
+ self.__labels[i][0].set_text("%c." % ("1234567890abcdef"[i]))
self.__labels[i][0].set_property("attributes", None)
return
def set_candidates(self, candidates, focus_candidate = 0, show_cursor = True):
assert len(candidates) <= len(self.__labels)
- i = 0
- for text, attrs in candidates:
+ for i, (text, attrs) in enumerate(candidates):
if i == focus_candidate and show_cursor:
if attrs == None:
attrs = pango.AttrList()
attrs.insert(attr)
self.__labels[i][1].set_text(text)
- self.__labels[i][1].set_property("attributes", attrs)
- self.__labels[i][0].show()
self.__labels[i][1].show()
+ self.__labels[i][1].set_property("attributes", attrs)
+ for w in self.__candidates[i]:
+ w.show()
- i += 1
-
- for label1, label2 in self.__labels[max(1, len(candidates)):]:
- label1.hide()
- label2.hide()
-
- if len(candidates) == 0:
- self.__labels[0][0].set_text("")
- self.__labels[0][1].set_text("")
- else:
- self.__labels[0][0].set_text("1.")
+ for w in reduce(operator.add, self.__candidates[len(candidates):]):
+ w.hide()
class CandidatePanel(gtk.VBox):
__gproperties__ = {
gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
()),
+ "candidate-clicked" : (
+ gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE,
+ (gobject.TYPE_UINT, gobject.TYPE_UINT, gobject.TYPE_UINT)),
}
def __init__ (self):
# create candidates area
self.__candidate_area = CandidateArea(self.__orientation)
self.__candidate_area.set_no_show_all(True)
+ self.__candidate_area.connect("candidate-clicked", lambda x, i, b, s: self.emit("candidate-clicked", i, b, s))
self.update_lookup_table(self.__lookup_table, self.__lookup_table_visible)
# create state label
lambda widget: self.page_up())
self.__candidate_panel.connect("page-down",
lambda widget: self.page_down())
+ self.__candidate_panel.connect("candidate-clicked",
+ lambda widget, index, button, state: self.candidate_clicked(index, button, state))
self.__status_icon = gtk.StatusIcon()