linux 下软键盘的弹出与隐藏

来源:互联网 发布:网络预约出租车驾驶员 编辑:程序博客网 时间:2024/05/20 22:30

   研究的软键盘是基于 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 ();  }

原创粉丝点击