linux 下软键盘的弹出与隐藏

   研究的软键盘是基于 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,socket,Class,buffer,events,triggers)