update for beta release
[framework/uifw/e17.git] / src / modules / illume2 / e_mod_kbd_device.c
1 #include "e_illume_private.h"
2 #include "e_mod_kbd_device.h"
3
4 /* local function prototypes */
5 static void _e_mod_kbd_device_ignore_load(void);
6 static void _e_mod_kbd_device_ignore_load_file(const char *file);
7 static void _e_mod_kbd_device_kbd_add(const char *udi);
8 static void _e_mod_kbd_device_kbd_del(const char *udi);
9 static void _e_mod_kbd_device_kbd_eval(void);
10 #ifdef HAVE_EEZE
11 # include <Eeze.h>
12 static void _e_mod_kbd_device_udev_event(const char *device, Eeze_Udev_Event event, void *data __UNUSED__, Eeze_Udev_Watch *watch __UNUSED__);
13 #else
14 # include <E_Hal.h>
15 static void _e_mod_kbd_device_cb_input_kbd(void *data __UNUSED__, void *reply, DBusError *err);
16 static void _e_mod_kbd_device_cb_input_kbd_is(void *data, void *reply, DBusError *err);
17 static void _e_mod_kbd_device_dbus_add(void *data __UNUSED__, DBusMessage *msg);
18 static void _e_mod_kbd_device_dbus_del(void *data __UNUSED__, DBusMessage *msg);
19 static void _e_mod_kbd_device_dbus_chg(void *data __UNUSED__, DBusMessage *msg);
20 #endif
21
22 /* local variables */
23 static int have_real_kbd = 0;
24 #ifdef HAVE_EEZE
25 static Eeze_Udev_Watch *watch;
26 #else
27 static E_DBus_Connection *_dbus_conn = NULL;
28 static E_DBus_Signal_Handler *_dev_add = NULL;
29 static E_DBus_Signal_Handler *_dev_del = NULL;
30 static E_DBus_Signal_Handler *_dev_chg = NULL;
31 #endif
32 static Eina_List *_device_kbds = NULL, *_ignore_kbds = NULL;
33
34 void 
35 e_mod_kbd_device_init(void) 
36 {
37    /* load the 'ignored' keyboard file */
38    _e_mod_kbd_device_ignore_load();
39 #ifdef HAVE_EEZE
40    eeze_init();
41    watch = eeze_udev_watch_add(EEZE_UDEV_TYPE_KEYBOARD, EEZE_UDEV_EVENT_NONE,
42                             _e_mod_kbd_device_udev_event, NULL);
43 #else
44    e_dbus_init();
45    e_hal_init();
46    /* try to attach to the system dbus */
47    if (!(_dbus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM))) return;
48
49    /* ask HAL for any input keyboards */
50    e_hal_manager_find_device_by_capability(_dbus_conn, "input.keyboard", 
51                                            _e_mod_kbd_device_cb_input_kbd, NULL);
52
53    /* setup dbus signal handlers for when a device gets added/removed/changed */
54    _dev_add = 
55      e_dbus_signal_handler_add(_dbus_conn, E_HAL_SENDER, 
56                                E_HAL_MANAGER_PATH, 
57                                E_HAL_MANAGER_INTERFACE, 
58                                "DeviceAdded", _e_mod_kbd_device_dbus_add, NULL);
59    _dev_del = 
60      e_dbus_signal_handler_add(_dbus_conn, E_HAL_SENDER, 
61                                E_HAL_MANAGER_PATH, 
62                                E_HAL_MANAGER_INTERFACE, 
63                                "DeviceRemoved", _e_mod_kbd_device_dbus_del, NULL);
64    _dev_chg = 
65      e_dbus_signal_handler_add(_dbus_conn, E_HAL_SENDER, 
66                                E_HAL_MANAGER_PATH, 
67                                E_HAL_MANAGER_INTERFACE, 
68                                "NewCapability", _e_mod_kbd_device_dbus_chg, NULL);
69 #endif
70 }
71
72 void 
73 e_mod_kbd_device_shutdown(void) 
74 {
75    char *str;
76
77 #ifdef HAVE_EEZE
78    if (watch) eeze_udev_watch_del(watch);
79    eeze_shutdown();
80 #else
81    /* remove the dbus signal handlers if we can */
82    if (_dev_add) e_dbus_signal_handler_del(_dbus_conn, _dev_add);
83    if (_dev_del) e_dbus_signal_handler_del(_dbus_conn, _dev_del);
84    if (_dev_chg) e_dbus_signal_handler_del(_dbus_conn, _dev_chg);
85    e_hal_shutdown();
86    e_dbus_shutdown();
87 #endif
88    /* free the list of ignored keyboards */
89    EINA_LIST_FREE(_ignore_kbds, str)
90      eina_stringshare_del(str);
91
92    /* free the list of keyboards */
93    EINA_LIST_FREE(_device_kbds, str)
94      eina_stringshare_del(str);
95 }
96
97 /* local functions */
98 static void 
99 _e_mod_kbd_device_ignore_load(void) 
100 {
101    char buff[PATH_MAX];
102
103    /* load the 'ignore' file from the user's home dir */
104    e_user_dir_concat_static(buff, "keyboards/ignore_built_in_keyboards");
105    _e_mod_kbd_device_ignore_load_file(buff);
106
107    /* load the 'ignore' file from the system/module dir */
108    snprintf(buff, sizeof(buff), 
109             "%s/ignore_built_in_keyboards", _e_illume_mod_dir);
110    _e_mod_kbd_device_ignore_load_file(buff);
111 }
112
113 static void 
114 _e_mod_kbd_device_ignore_load_file(const char *file) 
115 {
116    char buff[PATH_MAX];
117    FILE *f;
118
119    /* can this file be opened */
120    if (!(f = fopen(file, "r"))) return;
121
122    /* parse out the info in the ignore file */
123    while (fgets(buff, sizeof(buff), f))
124      {
125         char *p;
126         int len;
127
128         if (buff[0] == '#') continue;
129         len = strlen(buff);
130         if (len > 0)
131           {
132              if (buff[len - 1] == '\n') buff[len - 1] = 0;
133           }
134         p = buff;
135         while (isspace(*p)) p++;
136
137         /* append this kbd to the ignore list */
138         if (*p) 
139           {
140              _ignore_kbds = 
141                eina_list_append(_ignore_kbds, eina_stringshare_add(p));
142           }
143      }
144    fclose(f);
145 }
146
147 #ifdef HAVE_EEZE
148 static void 
149 _e_mod_kbd_device_udev_event(const char *device, Eeze_Udev_Event event, void *data __UNUSED__, Eeze_Udev_Watch *watch __UNUSED__)
150 {
151    if ((!device) || (!event)) return;
152
153    if (((event & EEZE_UDEV_EVENT_ADD) == EEZE_UDEV_EVENT_ADD) ||
154      ((event & EEZE_UDEV_EVENT_ONLINE) == EEZE_UDEV_EVENT_ONLINE))
155      _e_mod_kbd_device_kbd_add(device);
156    else if (((event & EEZE_UDEV_EVENT_REMOVE) == EEZE_UDEV_EVENT_REMOVE) ||
157      ((event & EEZE_UDEV_EVENT_OFFLINE) == EEZE_UDEV_EVENT_OFFLINE))
158      _e_mod_kbd_device_kbd_del(device);
159
160    _e_mod_kbd_device_kbd_eval();
161 }
162 #else
163 static void 
164 _e_mod_kbd_device_cb_input_kbd(void *data __UNUSED__, void *reply, DBusError *err) 
165 {
166    E_Hal_Manager_Find_Device_By_Capability_Return *ret = reply;
167    Eina_List *l;
168    char *dev;
169
170    if ((!ret) || (!ret->strings)) return;
171
172    /* if dbus errored then cleanup and get out */
173    if (dbus_error_is_set(err)) 
174      {
175         dbus_error_free(err);
176         return;
177      }
178
179    /* for each returned keyboard, add it and evaluate it */
180    EINA_LIST_FOREACH(ret->strings, l, dev) 
181      {
182         _e_mod_kbd_device_kbd_add(dev);
183         _e_mod_kbd_device_kbd_eval();
184      }
185 }
186
187 static void 
188 _e_mod_kbd_device_cb_input_kbd_is(void *data, void *reply, DBusError *err) 
189 {
190    E_Hal_Device_Query_Capability_Return *ret = reply;
191    char *udi = data;
192
193    /* if dbus errored then cleanup and get out */
194    if (dbus_error_is_set(err)) 
195      {
196         dbus_error_free(err);
197         return;
198      }
199
200    /* if it's an input keyboard, than add it and eval */
201    if ((ret) && (ret->boolean)) 
202      {
203         if (udi) 
204           {
205              _e_mod_kbd_device_kbd_add(udi);
206              _e_mod_kbd_device_kbd_eval();
207           }
208      }
209 }
210
211 static void 
212 _e_mod_kbd_device_dbus_add(void *data __UNUSED__, DBusMessage *msg) 
213 {
214    DBusError err;
215    char *udi;
216
217    dbus_error_init(&err);
218    dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &udi, DBUS_TYPE_INVALID);
219    e_hal_device_query_capability(_dbus_conn, udi, "input.keyboard", 
220                                  _e_mod_kbd_device_cb_input_kbd_is, udi);
221 }
222
223 static void 
224 _e_mod_kbd_device_dbus_del(void *data __UNUSED__, DBusMessage *msg) 
225 {
226    DBusError err;
227    char *udi;
228
229    dbus_error_init(&err);
230    dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &udi, DBUS_TYPE_INVALID);
231    if (udi) 
232      {
233         _e_mod_kbd_device_kbd_del(udi);
234         _e_mod_kbd_device_kbd_eval();
235      }
236 }
237
238 static void 
239 _e_mod_kbd_device_dbus_chg(void *data __UNUSED__, DBusMessage *msg) 
240 {
241    DBusError err;
242    char *udi, *cap;
243
244    dbus_error_init(&err);
245    dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &udi, 
246                          DBUS_TYPE_STRING, &cap, DBUS_TYPE_INVALID);
247    if (cap) 
248      {
249         if (!strcmp(cap, "input.keyboard")) 
250           {
251              if (udi) 
252                {
253                   _e_mod_kbd_device_kbd_add(udi);
254                   _e_mod_kbd_device_kbd_eval();
255                }
256           }
257      }
258 }
259 #endif
260
261 static void 
262 _e_mod_kbd_device_kbd_add(const char *udi) 
263 {
264    const char *str;
265    Eina_List *l;
266
267    if (!udi) return;
268    EINA_LIST_FOREACH(_device_kbds, l, str)
269      if (!strcmp(str, udi)) return;
270    _device_kbds = eina_list_append(_device_kbds, eina_stringshare_add(udi));
271 }
272
273 static void 
274 _e_mod_kbd_device_kbd_del(const char *udi) 
275 {
276    const char *str;
277    Eina_List *l;
278
279    if (!udi) return;
280    EINA_LIST_FOREACH(_device_kbds, l, str)
281      if (!strcmp(str, udi)) 
282        {
283           eina_stringshare_del(str);
284           _device_kbds = eina_list_remove_list(_device_kbds, l);
285           break;
286        }
287 }
288
289 static void 
290 _e_mod_kbd_device_kbd_eval(void) 
291 {
292    Eina_List *l, *ll;
293    const char *g, *gg;
294    int have_real = 0;
295
296    have_real = eina_list_count(_device_kbds);
297    EINA_LIST_FOREACH(_device_kbds, l, g)
298      EINA_LIST_FOREACH(_ignore_kbds, ll, gg)
299        if (e_util_glob_match(g, gg)) 
300          {
301             have_real--;
302             break;
303          }
304
305    if (have_real != have_real_kbd) 
306      {
307         have_real_kbd = have_real;
308 #if 0
309 //        if (have_real_kbd) e_mod_kbd_disable();
310         else
311 #endif
312 //          e_mod_kbd_enable();
313      }
314 }