研究的软键盘是基于 matchbox-keyboard 实现的。并结合scim-bridge
首先我们看下scim-bridge在各个图形库的插件目录
三种插件目录分别位于
/usr/lib/qt4/plugins/inputmethods/im-scim-bridge.so
/usr/lib/clutter-imcontext/immodules/im-scim-bridge.so
/usr/lib/gtk-2.0/immodules/im-scim-bridge.so
下面的图,是focus in/focus out的通信流程
+------------+ +------------+ +----------------+
| Qt-plugin | | GTK plugin | | Clutter plugin |
+------------+ +------------+ +----------------+
| | |
+--------------------------------------------+
|socket
+---------------+
| scimbridge |
+---------------+
|socket
+-------------------------+
| SCIM |
| +---------------+ |
| | mbkeyboard.so | |
| +---------------+ |
+-------------------------+
|
send X event
|
+-------------------+
| matchbox-keyboard |
+-------------------+
scim-bridge client
scim-bridge分为两大部分agent和client, client作为插件,如Qt放在inputmethod目录下,用来获得输入窗口状态。基类的注册
class ScimBridgeInputContextPlugin: public QInputContextPlugin
{
}
Q_EXPORT_PLUGIN2 (ScimBridgeInputContextPlugin, ScimBridgeInputContextPlugin)
创建私有成员
/* 当有输入窗口时,就会调用QInputContextPlugin::create函数
* 参考 http://qt-project.org/doc/qt-4.8/qinputcontextplugin.html#create
*/
QInputContext *ScimBridgeInputContextPlugin::create (const QString &key)
{
return ScimBridgeClientIMContext::alloc ();
}创建好的私有成员,实现了X消息过滤,focus_in, focus_out等的操作
focus_in
void ScimBridgeClientIMContextImpl::focus_in ()
{
if (scim_bridge_client_is_messenger_opened ()) {
if (scim_bridge_client_change_focus (this, TRUE)) {
scim_bridge_perrorln ("An IOException occurred at focus_in ()");
}
}
retval_t scim_bridge_client_change_focus (const ScimBridgeClientIMContext *imcontext, boolean focus_in)
{
pending_response.header = SCIM_BRIDGE_MESSAGE_FOCUS_CHANGED;
if (scim_bridge_messenger_send_message (messenger, NULL)) {
}
}
retval_t scim_bridge_messenger_send_message (ScimBridgeMessenger *messenger, const struct timeval *timeout)
{
ssize_t written_bytes = send (fd, messenger->sending_buffer + buffer_offset, sizeof (char) * write_size, MSG_NOSIGNAL);
}
scim-bridge agent
retval_t ScimBridgeAgentImpl::run_event_loop ()
{
const int retval = select (max_fd + 1, &read_set, &write_set, &error_set, NULL);
const scim_bridge_agent_event_type_t triggers = client->get_trigger_events ();
---
scim_bridge_agent_event_type_t ScimBridgeAgentClientListenerImpl::get_trigger_events () const
{
if (received_messages.size () > 0) triggers |= SCIM_BRIDGE_AGENT_EVENT_INTERRUPT;
if (scim_bridge_messenger_get_sending_buffer_size (messenger) > 0) triggers |= SCIM_BRIDGE_AGENT_EVENT_WRITE;
}
---
if (interrupted && (triggers & SCIM_BRIDGE_AGENT_EVENT_INTERRUPT)) {
events |= SCIM_BRIDGE_AGENT_EVENT_INTERRUPT;
}
if (!client->handle_event (events)) {
}
}
bool ScimBridgeAgentClientListenerImpl::handle_event (scim_bridge_agent_event_type_t event_type)
{
if (event_type & SCIM_BRIDGE_AGENT_EVENT_INTERRUPT) {
if (process_message (message) == RETVAL_FAILED) {
}
}
}
retval_t ScimBridgeAgentClientListenerImpl::process_message (const ScimBridgeMessage *message)
{
if() {
} else if (strcmp (message_header, SCIM_BRIDGE_MESSAGE_CHANGE_FOCUS) == 0) {
return change_focus (imcontext_id, focus_in);
}
}
retval_t ScimBridgeAgentClientListenerImpl::change_focus (scim_bridge_imcontext_id_t imcontext_id, bool focus_in)
{
agent->change_focus (imcontext_id, focus_in);
scim_bridge_messenger_push_message (messenger, message);
}
/* class ScimBridgeAgentClientListenerImpl: public ScimBridgeAgentClientListener {
private:
ScimBridgeAgentProtected *agent;
* }
*/
void ScimBridgeAgentImpl::change_focus (scim_bridge_imcontext_id_t imcontext_id, bool focus_in)
{
imcontext->focus_in ();
}
void ScimBridgeAgentIMContextImpl::focus_in ()
{
get_imengine ()->focus_in ();
}
本文探讨了如何在Linux系统中结合matchbox-keyboard和scim-bridge来实现软键盘的弹出与隐藏。详细介绍了scim-bridge client的基类注册、私有成员创建以及focus_in事件处理,同时提到了scim-bridge agent在图形库插件中的应用。
2611

被折叠的 条评论
为什么被折叠?



