5 # Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com>
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2 of the License, or (at your option) any later version.
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Lesser General Public License for more details.
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this program; if not, write to the
19 # Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20 # Boston, MA 02111-1307 USA
25 from ibus
import keysyms
26 from ibus
import modifier
27 from contextmanager
import ContextManager
28 from factorymanager
import FactoryManager
29 from connection
import Connection
30 from panel
import Panel
, DummyPanel
32 class IBus (ibus
.Object
):
34 ibus
.Object
.__init
__ (self
)
35 self
._connections
= {}
36 self
._context
_manager
= ContextManager ()
37 self
._factory
_manager
= FactoryManager ()
38 self
._panel
= DummyPanel ()
40 self
._focused
_context
= None
41 self
._last
_focused
_context
= None
42 self
._context
_handlers
= []
46 def new_connection (self
, dbusconn
):
47 assert dbusconn
not in self
._connections
48 self
._connections
[dbusconn
] = Connection (dbusconn
)
50 def remove_connection (self
, dbusconn
):
51 assert dbusconn
in self
._connections
53 # destroy the connection
54 self
._connections
[dbusconn
].destroy ()
55 del self
._connections
[dbusconn
]
57 def _lookup_ibus_connection (self
, dbusconn
):
58 if dbusconn
not in self
._connections
:
59 raise ibus
.IBusException ("can not find ibus.Connection")
60 return self
._connections
[dbusconn
]
62 ##########################################################
63 # methods for im context
64 ##########################################################
65 def create_input_context (self
, name
, dbusconn
):
66 ibusconn
= self
._lookup
_ibus
_connection
(dbusconn
)
67 context
= self
._context
_manager
.create_input_context (name
, ibusconn
)
68 factory
= self
._factory
_manager
.get_default_factory ()
70 engine
= factory
.create_engine ()
71 context
.set_engine (engine
)
72 return context
.get_id ()
74 def release_input_context (self
, ic
, dbusconn
):
75 ibusconn
= self
._lookup
_ibus
_connection
(dbusconn
)
76 self
._context
_manager
.release_input_context (ic
, ibusconn
)
78 def focus_in (self
, ic
, dbusconn
):
79 context
= self
._lookup
_context
(ic
, dbusconn
)
81 if self
._focused
_context
!= context
and self
._focused
_context
!= None:
82 self
._remove
_focused
_context
_handlers
()
83 self
._focused
_context
.focus_out ()
85 self
._focused
_context
= context
86 self
._install
_focused
_context
_handlers
()
88 self
._panel
.focus_in (context
.get_id ())
89 self
._last
_focused
_context
= context
92 def focus_out (self
, ic
, dbusconn
):
93 context
= self
._lookup
_context
(ic
, dbusconn
)
95 if context
== self
._focused
_context
:
96 self
._remove
_focused
_context
_handlers
()
97 self
._focused
_context
= None
100 self
._panel
.focus_out (context
.get_id ())
102 def reset (self
, ic
, dbusconn
):
103 context
= self
._lookup
_context
(ic
, dbusconn
)
106 def is_enabled (self
, ic
, dbusconn
):
107 context
= self
._lookup
_context
(ic
, dbusconn
)
108 return context
.is_enabled ()
110 def process_key_event (self
, ic
, keyval
, is_press
, state
,
111 dbusconn
, reply_cb
, error_cb
):
112 context
= self
._lookup
_context
(ic
, dbusconn
)
114 if self
._filter
_hotkeys
(context
, keyval
, is_press
, state
):
118 context
.process_key_event (keyval
, is_press
, state
, reply_cb
, error_cb
)
120 def set_cursor_location (self
, ic
, x
, y
, w
, h
, dbusconn
):
121 context
= self
._lookup
_context
(ic
, dbusconn
)
122 context
.set_cursor_location (x
, y
, w
, h
)
123 self
._panel
.set_cursor_location (x
, y
, w
, h
)
125 def _filter_hotkeys (self
, context
, keyval
, is_press
, state
):
126 if is_press
and keyval
== keysyms
.space \
127 and (state
& ~modifier
.MOD2_MASK
) == modifier
.CONTROL_MASK
:
128 enable
= not context
.is_enabled ()
129 context
.set_enable (enable
)
130 if context
.get_engine () == None and enable
:
131 factory
= self
._factory
_manager
.get_default_factory ()
133 engine
= factory
.create_engine ()
134 context
.set_engine (engine
)
135 self
._panel
.states_changed ()
139 def _lookup_context (self
, ic
, dbusconn
):
140 ibusconn
= self
._lookup
_ibus
_connection
(dbusconn
)
141 return self
._context
_manager
.lookup_context (ic
, ibusconn
)
143 def _install_focused_context_handlers (self
):
144 # Install all callback functions
145 if self
._focused
_context
== None:
148 ("update-preedit", self
._update
_preedit
_cb
),
149 ("update-aux-string", self
._update
_aux
_string
_cb
),
150 ("update-lookup-table", self
._update
_lookup
_table
_cb
),
151 ("register-properties", self
._register
_properties
_cb
),
152 ("update-property", self
._update
_property
_cb
),
153 ("engine-lost", self
._engine
_lost
_cb
),
154 ("destroy", self
._context
_destroy
_cb
)
156 for name
, handler
in signals
:
157 id = self
._focused
_context
.connect (name
, handler
)
158 self
._context
_handlers
.append (id)
160 def _remove_focused_context_handlers (self
):
161 if self
._focused
_context
== None:
163 map (self
._focused
_context
.disconnect
, self
._context
_handlers
)
164 self
._context
_handlers
= []
166 def _update_preedit_cb (self
, context
, text
, attrs
, cursor_pos
, visible
):
167 assert self
._focused
_context
== context
169 self
._panel
.update_preedit_string (text
, attrs
, cursor_pos
, visible
)
171 def _update_aux_string_cb (self
, context
, text
, attrs
, visible
):
172 assert self
._focused
_context
== context
174 self
._panel
.update_aux_string (text
, attrs
, visible
)
176 def _update_lookup_table_cb (self
, context
, lookup_table
, visible
):
177 assert self
._focused
_context
== context
179 self
._panel
.update_lookup_table (lookup_table
, visible
)
181 def _register_properties_cb (self
, context
, props
):
182 assert self
._focused
_context
== context
184 self
._panel
.register_properties (props
)
187 def _update_property_cb (self
, context
, prop
):
188 assert self
._focused
_context
== context
190 self
._panel
.update_property (prop
)
192 def _engine_lost_cb (self
, context
):
193 assert self
._focused
_context
== context
197 def _context_destroy_cb (self
, context
):
198 assert context
== self
._focused
_context
199 self
._remove
_focused
_context
_handlers
()
200 self
._focused
_context
= None
203 ##########################################################
204 # methods for im engines
205 ##########################################################
206 def register_factories (self
, object_paths
, dbusconn
):
207 ibusconn
= self
._lookup
_ibus
_connection
(dbusconn
)
208 self
._factory
_manager
.register_factories (object_paths
, ibusconn
)
210 def dispatch_dbus_signal (self
, dbusconn
, message
):
211 ibusconn
= self
._lookup
_ibus
_connection
(dbusconn
)
212 ibusconn
.dispatch_dbus_signal (message
)
214 def _lookup_engine (self
, dbusconn
, path
):
215 ibusconn
= self
._lookup
_ibus
_connection
(dbusconn
)
216 return self
._factory
_manager
.lookup_engine (ibusconn
, path
)
219 ##########################################################
221 ##########################################################
222 def register_panel (self
, object_path
, replace
, dbusconn
):
223 if not isinstance (self
._panel
, DummyPanel
) and replace
== False:
224 raise ibus
.Exception ("has have a panel!")
225 if not isinstance (self
._panel
, DummyPanel
):
226 self
._panel
.destroy ()
227 ibusconn
= self
._lookup
_ibus
_connection
(dbusconn
)
228 self
._panel
= Panel (ibusconn
, object_path
)
229 self
._panel
.connect ("page-up", self
._panel
_page
_up
_cb
)
230 self
._panel
.connect ("page-down", self
._panel
_page
_down
_cb
)
231 self
._panel
.connect ("cursor-up", self
._panel
_cursor
_up
_cb
)
232 self
._panel
.connect ("cursor-down", self
._panel
_cursor
_down
_cb
)
233 self
._panel
.connect ("property-activate", self
._panel
_property
_active
_cb
)
234 self
._panel
.connect ("property-show", self
._panel
_property
_show
_cb
)
235 self
._panel
.connect ("property-hide", self
._panel
_property
_hide
_cb
)
236 self
._panel
.connect ("destroy", self
._panel
_destroy
_cb
)
238 def _panel_page_up_cb (self
, panel
):
239 assert panel
== self
._panel
240 if self
._focused
_context
:
241 self
._focused
_context
.page_up ()
243 def _panel_page_down_cb (self
, panel
):
244 assert panel
== self
._panel
245 if self
._focused
_context
:
246 self
._focused
_context
.page_down ()
248 def _panel_cursor_up_cb (self
, panel
):
249 assert panel
== self
._panel
250 if self
._focused
_context
:
251 self
._focused
_context
.cursor_up ()
253 def _panel_cursor_down_cb (self
, panel
):
254 assert panel
== self
._panel
255 if self
._focused
_context
:
256 self
._focused
_context
.cursor_down ()
258 def _panel_property_active_cb (self
, panel
, prop_name
, prop_state
):
259 assert panel
== self
._panel
260 if self
._focused
_context
:
261 self
._focused
_context
.property_activate (prop_name
, prop_state
)
263 def _panel_property_show_cb (self
, panel
, prop_name
):
264 assert panel
== self
._panel
265 if self
._focused
_context
:
266 self
._focused
_context
.property_show (prop_name
)
268 def _panel_property_hide_cb (self
, panel
, prop_name
):
269 assert panel
== self
._panel
270 if self
._focused
_context
:
271 self
._focused
_context
.property_hide (prop_name
)
273 def _panel_destroy_cb (self
, panel
):
274 if panel
== self
._panel
:
275 self
._panel
= DummyPanel ()
277 ##########################################################
279 ##########################################################
280 def get_factories (self
):
281 return self
._factory
_manager
.get_factories ()
283 def get_factory_info (self
, factory_path
):
284 return self
._factory
_manager
.get_factory_info (factory_path
)
286 def set_factory (self
, factory_path
):
287 if self
._focused
_context
== None:
290 factory
= self
._factory
_manager
.get_factory (factory_path
)
291 engine
= factory
.create_engine ()
292 self
._focused
_context
.set_engine (engine
)
294 def get_input_context_states (self
, ic
, dbusconn
):
295 context
= self
._lookup
_context
(ic
, dbusconn
)
296 factory_path
= "" if context
.get_factory () == None else context
.get_factory ().get_object_path ()
297 return factory_path
, context
.is_enabled ()
300 class IBusProxy (ibus
.IIBus
):
301 SUPPORTS_MULTIPLE_CONNECTIONS
= True
304 ibus
.IIBus
.__init
__ (self
)
307 def new_connection (self
, dbusconn
):
308 self
._ibus
.new_connection (dbusconn
)
310 def remove_connection (self
, dbusconn
):
311 self
._ibus
.remove_connection (dbusconn
)
313 def dispatch_dbus_signal (self
, dbusconn
, message
):
314 return self
._ibus
.dispatch_dbus_signal (dbusconn
, message
)
316 def GetIBusAddress (self
, dbusconn
):
317 return self
._ibus
_addr
319 def CreateInputContext (self
, context_name
, dbusconn
):
320 return self
._ibus
.create_input_context (context_name
, dbusconn
)
322 def ReleaseInputContext (self
, ic
, dbusconn
):
323 self
._ibus
.release_input_context (ic
, dbusconn
)
325 def RegisterFactories (self
, object_paths
, dbusconn
):
326 self
._ibus
.register_factories (object_paths
, dbusconn
)
328 def UnregisterEngines (self
, object_paths
, dbusconn
):
329 self
._ibus
.unregister_engines (object_paths
, dbusconn
)
331 def RegisterPanel (self
, object_path
, replace
, dbusconn
):
332 self
._ibus
.register_panel (object_path
, replace
, dbusconn
)
334 def ProcessKeyEvent (self
, ic
, keyval
, is_press
, state
, \
335 dbusconn
, reply_cb
, error_cb
):
337 self
._ibus
.process_key_event (ic
, keyval
, is_press
, state
,
338 dbusconn
, reply_cb
, error_cb
)
342 def SetCursorLocation (self
, ic
, x
, y
, w
, h
, dbusconn
):
343 self
._ibus
.set_cursor_location (ic
, x
, y
, w
, h
, dbusconn
)
345 def FocusIn (self
, ic
, dbusconn
):
346 self
._ibus
.focus_in (ic
, dbusconn
)
348 def FocusOut (self
, ic
, dbusconn
):
349 self
._ibus
.focus_out (ic
, dbusconn
)
351 def Reset (self
, ic
, dbusconn
):
352 self
._ibus
.reset (ic
, dbusconn
)
354 def IsEnabled (self
, ic
, dbusconn
):
355 return self
._ibus
.is_enabled (ic
, dbusconn
)
357 def GetFactories (self
, dbusconn
):
358 return self
._ibus
.get_factories ()
360 def GetFactoryInfo (self
, factory_path
, dbusconn
):
361 return self
._ibus
.get_factory_info (factory_path
)
363 def SetFactory (self
, factory_path
, dbusconn
):
364 return self
._ibus
.set_factory (factory_path
)
366 def GetInputContextStates (self
, ic
, dbusconn
):
367 return self
._ibus
.get_input_context_states (ic
, dbusconn
)