Reset panel when focused_context be destroyed
[ibus.git] / ibusdaemon / bus.py
blob76bc4f892c25bfbcd71f7c0615d881c31c63b68b
1 #!/usr/bin/env python
2 import weakref
3 import dbus
4 import ibus
5 from ibus import keysyms
6 from contextmanager import ContextManager
7 from factorymanager import FactoryManager
8 from connection import Connection
9 from panel import Panel, DummyPanel
11 class IBus (ibus.Object):
12 def __init__ (self):
13 ibus.Object.__init__ (self)
14 self._connections = {}
15 self._context_manager = ContextManager ()
16 self._factory_manager = FactoryManager ()
17 self._panel = DummyPanel ()
19 self._focused_context = None
20 self._last_focused_context = None
21 self._context_handlers = []
23 self._last_key = None
25 def new_connection (self, dbusconn):
26 assert dbusconn not in self._connections
27 self._connections[dbusconn] = Connection (dbusconn)
29 def remove_connection (self, dbusconn):
30 assert dbusconn in self._connections
32 # destroy the connection
33 self._connections[dbusconn].destroy ()
34 del self._connections[dbusconn]
36 def _lookup_ibus_connection (self, dbusconn):
37 if dbusconn not in self._connections:
38 raise ibus.IBusException ("can not find ibus.Connection")
39 return self._connections[dbusconn]
41 ##########################################################
42 # methods for im context
43 ##########################################################
44 def create_input_context (self, name, dbusconn):
45 ibusconn = self._lookup_ibus_connection (dbusconn)
46 context = self._context_manager.create_input_context (name, ibusconn)
47 factory = self._factory_manager.get_default_factory ()
48 if factory:
49 engine = factory.create_engine ()
50 context.set_engine (engine)
51 return context.get_id ()
53 def release_input_context (self, ic, dbusconn):
54 ibusconn = self._lookup_ibus_connection (dbusconn)
55 self._context_manager.release_input_context (ic, ibusconn)
57 def focus_in (self, ic, dbusconn):
58 context = self._lookup_context (ic, dbusconn)
60 if self._focused_context != context and self._focused_context != None:
61 map (self._focused_context.disconnect, self._context_handlers)
62 self._context_handlers = []
63 self._focused_context.focus_out ()
65 # Install all callback functions
66 id = context.connect ("update-preedit", self._update_preedit_cb)
67 self._context_handlers.append (id)
68 id = context.connect ("update-aux-string", self._update_aux_string_cb)
69 self._context_handlers.append (id)
70 id = context.connect ("update-lookup-table", self._update_lookup_table_cb)
71 self._context_handlers.append (id)
72 id = context.connect ("register-properties", self._register_properties_cb)
73 self._context_handlers.append (id)
74 id = context.connect ("update-property", self._update_property_cb)
75 self._context_handlers.append (id)
76 id = context.connect ("engine-lost", self._engine_lost_cb)
77 self._context_handlers.append (id)
78 id = context.connect ("destroy", self._context_destroy_cb)
79 self._context_handlers.append (id)
81 self._panel.reset ()
82 self._focused_context = context
83 self._last_focused_context = context
84 context.focus_in ()
86 def focus_out (self, ic, dbusconn):
87 context = self._lookup_context (ic, dbusconn)
88 if context == self._focused_context:
89 map (self._focused_context.disconnect, self._context_handlers)
90 self._context_handlers = []
91 self._focused_context = None
92 context.focus_out ()
93 self._panel.reset ()
95 def reset (self, ic, dbusconn):
96 context = self._lookup_context (ic, dbusconn)
97 context.reset ()
99 def is_enabled (self, ic, dbusconn):
100 context = self._lookup_context (ic, dbusconn)
101 return context.is_enabled ()
103 def process_key_event (self, ic, keyval, is_press, state,
104 dbusconn, reply_cb, error_cb):
105 context = self._lookup_context (ic, dbusconn)
107 if self._filter_hotkeys (context, keyval, is_press, state):
108 reply_cb (True)
109 return
110 else:
111 context.process_key_event (keyval, is_press, state, reply_cb, error_cb)
113 def set_cursor_location (self, ic, x, y, w, h, dbusconn):
114 context = self._lookup_context (ic, dbusconn)
115 context.set_cursor_location (x, y, w, h)
116 self._panel.set_cursor_location (x, y, w, h)
118 def _filter_hotkeys (self, context, keyval, is_press, state):
119 if is_press and keyval == keysyms.space \
120 and (state & ~keysyms.MOD2_MASK) == keysyms.CONTROL_MASK:
121 enable = not context.is_enabled ()
122 context.set_enable (enable)
123 if context.get_engine () == None and enable:
124 factory = self._factory_manager.get_default_factory ()
125 if factory:
126 engine = factory.create_engine ()
127 context.set_engine (engine)
128 return True
129 return False
131 def _lookup_context (self, ic, dbusconn):
132 ibusconn = self._lookup_ibus_connection (dbusconn)
133 return self._context_manager.lookup_context (ic, ibusconn)
135 def _update_preedit_cb (self, context, text, attrs, cursor_pos, visible):
136 assert self._focused_context == context
138 self._panel.update_preedit_string (text, attrs, cursor_pos, visible)
140 def _update_aux_string_cb (self, context, text, attrs, visible):
141 assert self._focused_context == context
143 self._panel.update_aux_string (text, attrs, visible)
145 def _update_lookup_table_cb (self, context, lookup_table, visible):
146 assert self._focused_context == context
148 self._panel.update_lookup_table (lookup_table, visible)
150 def _register_properties_cb (self, context, props):
151 assert self._focused_context == context
153 self._panel.register_properties (props)
156 def _update_property_cb (self, context, prop):
157 assert self._focused_context == context
159 self._panel.update_property (prop)
161 def _engine_lost_cb (self, context):
162 assert self._focused_context == context
164 self._panel.reset ()
166 def _context_destroy_cb (self, context):
167 assert context == self._focused_context
168 self._context_handlers = []
169 self._focused_context = None
170 self._panel.reset ()
172 ##########################################################
173 # methods for im engines
174 ##########################################################
175 def register_factories (self, object_paths, dbusconn):
176 ibusconn = self._lookup_ibus_connection (dbusconn)
177 self._factory_manager.register_factories (object_paths, ibusconn)
179 def dispatch_dbus_signal (self, dbusconn, message):
180 ibusconn = self._lookup_ibus_connection (dbusconn)
181 ibusconn.dispatch_dbus_signal (message)
183 def _lookup_engine (self, dbusconn, path):
184 ibusconn = self._lookup_ibus_connection (dbusconn)
185 return self._factory_manager.lookup_engine (ibusconn, path)
188 ##########################################################
189 # methods for panel
190 ##########################################################
191 def register_panel (self, object_path, replace, dbusconn):
192 if not isinstance (self._panel, DummyPanel) and replace == False:
193 raise ibus.Exception ("has have a panel!")
194 if not isinstance (self._panel, DummyPanel):
195 self._panel.destroy ()
196 ibusconn = self._lookup_ibus_connection (dbusconn)
197 self._panel = Panel (ibusconn, object_path)
198 self._panel.connect ("page-up", self._panel_page_up_cb)
199 self._panel.connect ("page-down", self._panel_page_down_cb)
200 self._panel.connect ("cursor-up", self._panel_cursor_up_cb)
201 self._panel.connect ("cursor-down", self._panel_cursor_down_cb)
202 self._panel.connect ("property-activate", self._panel_property_active_cb)
203 self._panel.connect ("destroy", self._panel_destroy_cb)
205 def _panel_page_up_cb (self, panel):
206 assert panel == self._panel
207 if self._focused_context:
208 self._focused_context.page_up ()
210 def _panel_page_down_cb (self, panel):
211 assert panel == self._panel
212 if self._focused_context:
213 self._focused_context.page_down ()
215 def _panel_cursor_up_cb (self, panel):
216 assert panel == self._panel
217 if self._focused_context:
218 self._focused_context.cursor_up ()
220 def _panel_cursor_down_cb (self, panel):
221 assert panel == self._panel
222 if self._focused_context:
223 self._focused_context.cursor_down ()
225 def _panel_property_active_cb (self, panel, prop_name):
226 assert panel == self._panel
227 if self._focused_context:
228 self._focused_context.property_activate (prop_name)
230 def _panel_destroy_cb (self, panel):
231 if panel == self._panel:
232 self._panel = DummyPanel ()
234 ##########################################################
235 # general methods
236 ##########################################################
237 def get_factories (self):
238 return self._factory_manager.get_factories ()
240 def get_factory_info (self, factory_path):
241 return self._factory_manager.get_factory_info (factory_path)
243 def set_factory (self, factory_path):
244 if self._focused_context == None:
245 return
246 self._panel.reset ()
247 factory = self._factory_manager.get_factory (factory_path)
248 engine = factory.create_engine ()
249 self._focused_context.set_engine (engine)
251 class IBusProxy (ibus.IIBus):
252 SUPPORTS_MULTIPLE_CONNECTIONS = True
254 def __init__ (self):
255 ibus.IIBus.__init__ (self)
256 self._ibus = IBus ()
258 def new_connection (self, dbusconn):
259 self._ibus.new_connection (dbusconn)
261 def remove_connection (self, dbusconn):
262 self._ibus.remove_connection (dbusconn)
264 def dispatch_dbus_signal (self, dbusconn, message):
265 return self._ibus.dispatch_dbus_signal (dbusconn, message)
267 def GetIBusAddress (self, dbusconn):
268 return self._ibus_addr
270 def CreateInputContext (self, context_name, dbusconn):
271 return self._ibus.create_input_context (context_name, dbusconn)
273 def ReleaseInputContext (self, ic, dbusconn):
274 self._ibus.release_input_context (ic, dbusconn)
276 def RegisterFactories (self, object_paths, dbusconn):
277 self._ibus.register_factories (object_paths, dbusconn)
279 def UnregisterEngines (self, object_paths, dbusconn):
280 self._ibus.unregister_engines (object_paths, dbusconn)
282 def RegisterPanel (self, object_path, replace, dbusconn):
283 self._ibus.register_panel (object_path, replace, dbusconn)
285 def ProcessKeyEvent (self, ic, keyval, is_press, state, \
286 dbusconn, reply_cb, error_cb):
287 try:
288 self._ibus.process_key_event (ic, keyval, is_press, state,
289 dbusconn, reply_cb, error_cb)
290 except Exception, e:
291 error_cb (e)
293 def SetCursorLocation (self, ic, x, y, w, h, dbusconn):
294 self._ibus.set_cursor_location (ic, x, y, w, h, dbusconn)
296 def FocusIn (self, ic, dbusconn):
297 self._ibus.focus_in (ic, dbusconn)
299 def FocusOut (self, ic, dbusconn):
300 self._ibus.focus_out (ic, dbusconn)
302 def Reset (self, ic, dbusconn):
303 self._ibus.reset (ic, dbusconn)
305 def IsEnabled (self, ic, dbusconn):
306 return self._ibus.is_enabled (ic, dbusconn)
308 def GetFactories (self, dbusconn):
309 return self._ibus.get_factories ()
311 def GetFactoryInfo (self, factory_path, dbusconn):
312 return self._ibus.get_factory_info (factory_path)
314 def SetFactory (self, factory_path, dbusconn):
315 return self._ibus.set_factory (factory_path)