Fix bug in dead timer cb
[apps/native/starter.git] / src / mobile / hw_key.c
1 /*
2  * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifdef HAVE_X11
18 #include <app.h>
19 #include <bundle.h>
20 #include <Elementary.h>
21 #include <Ecore_X.h>
22 #include <Ecore_Input.h>
23 #include <dd-deviced.h>
24 #include <syspopup_caller.h>
25 #include <utilX.h>
26 #include <vconf.h>
27 #include <system/media_key.h>
28 #include <aul.h>
29 #include <feedback.h>
30 #include <system_settings.h>
31
32 #include "hw_key.h"
33 #include "home_mgr.h"
34 #include "util.h"
35 #include "dbus_util.h"
36 #include "lock_mgr.h"
37 #include "status.h"
38 #include "process_mgr.h"
39 #include "lock_pwd_util.h"
40
41 #define APPID_CAMERA "org.tizen.camera-app"
42 #define APPID_CALLLOG "org.tizen.calllog"
43 #define APPID_MUSIC_PLAYER "org.tizen.music-player"
44 #define APPID_TASKMGR "org.tizen.task-mgr"
45 #define APPID_BROWSER "org.tizen.browser"
46 #define APPID_EMAIL "org.tizen.email"
47 #define APPID_DIALER "org.tizen.phone"
48
49 #define STR_ATOM_XKEY_COMPOSITION "_XKEY_COMPOSITION"
50 #define STR_ATOM_KEYROUTER_NOTIWINDOW "_KEYROUTER_NOTIWINDOW"
51
52 #define LONG_PRESS_TIMER_SEC 0.4
53 #define HOMEKEY_TIMER_SEC 0.2
54 #define CANCEL_KEY_TIMER_SEC 0.3
55
56 static struct {
57         Ecore_X_Window win;
58         Ecore_Event_Handler *key_up;
59         Ecore_Event_Handler *key_down;
60         Ecore_Timer *home_long_press_timer;
61         Ecore_Timer *home_multi_press_timer;
62         Eina_Bool cancel;
63         Ecore_X_Window keyrouter_notiwindow;
64         int homekey_count;
65 } key_info = {
66         .win = 0x0,
67         .key_up = NULL,
68         .key_down = NULL,
69         .home_long_press_timer = NULL,
70         .home_multi_press_timer = NULL,
71         .cancel = EINA_FALSE,
72         .keyrouter_notiwindow = 0x0,
73         .homekey_count = 0,
74 };
75
76
77
78 static void _after_launch_taskmgr(int pid)
79 {
80         if(0 < pid) {
81                 if(dbus_util_send_oomadj(pid, OOM_ADJ_VALUE_DEFAULT) < 0){
82                         _E("failed to send oom dbus signal");
83                 }
84         }
85 }
86
87
88
89 static Eina_Bool _launch_taskmgr_cb(void* data)
90 {
91         int val = -1;
92
93         _D("Launch TASKMGR");
94
95         key_info.home_long_press_timer = NULL;
96
97         if (vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &val) < 0) {
98                 _E("Cannot get VCONFKEY for lock state");
99         } else if (VCONFKEY_IDLE_LOCK == val) {
100                 _E("lock state, ignore home key long press..!!");
101                 return ECORE_CALLBACK_CANCEL;
102         }
103
104         process_mgr_must_launch(APPID_TASKMGR, NULL, NULL, NULL, _after_launch_taskmgr);
105
106         return ECORE_CALLBACK_CANCEL;
107 }
108
109
110
111 static void _release_multimedia_key(const char *value)
112 {
113         ret_if(NULL == value);
114         _D("Multimedia key is released with %s", value);
115         process_mgr_must_launch(APPID_MUSIC_PLAYER, "multimedia_key", value, NULL, NULL);
116 }
117
118
119
120 static Eina_Bool _launch_by_home_key(void *data)
121 {
122         int ret = 0;
123
124         if (status_passive_get()->idle_lock_state > VCONFKEY_IDLE_UNLOCK) {
125                 return ECORE_CALLBACK_CANCEL;
126         }
127
128         ret = home_mgr_open_home(NULL);
129         if(ret > 0) {
130                 dbus_util_send_home_raise_signal();
131         }
132
133         return ECORE_CALLBACK_CANCEL;
134 }
135
136
137
138 static Eina_Bool _home_multi_press_timer_cb(void *data)
139 {
140         _W("homekey count[%d]", key_info.homekey_count);
141
142         key_info.home_multi_press_timer = NULL;
143
144         if(0 == key_info.homekey_count % 2) {
145                 key_info.homekey_count = 0;
146                 return ECORE_CALLBACK_CANCEL;
147         } else if(key_info.homekey_count >= 3) {
148                 key_info.homekey_count = 0;
149                 return ECORE_CALLBACK_CANCEL;
150         }
151
152         /* Single homekey operation */
153         key_info.homekey_count = 0;
154         _launch_by_home_key(data);
155
156         return ECORE_CALLBACK_CANCEL;
157
158 }
159
160
161
162 #define SERVICE_OPERATION_POPUP_SEARCH "http://samsung.com/appcontrol/operation/search"
163 #define SEARCH_PKG_NAME "org.tizen.sfinder"
164 static int _launch_search(void)
165 {
166         app_control_h app_control;
167         int ret = APP_CONTROL_ERROR_NONE;
168
169         app_control_create(&app_control);
170         app_control_set_operation(app_control, APP_CONTROL_OPERATION_DEFAULT);
171         app_control_set_app_id(app_control, SEARCH_PKG_NAME);
172
173         ret = app_control_send_launch_request(app_control, NULL, NULL);
174
175         if(ret != APP_CONTROL_ERROR_NONE) {
176                 _E("Cannot launch search!! err[%d]", ret);
177         }
178
179         app_control_destroy(app_control);
180         return ret;
181 }
182
183
184
185 static void _cancel_key_events(void)
186 {
187         key_info.homekey_count = 0;
188
189         if (key_info.home_long_press_timer) {
190                 ecore_timer_del(key_info.home_long_press_timer);
191                 key_info.home_long_press_timer = NULL;
192         }
193
194         if(key_info.home_multi_press_timer) {
195                 ecore_timer_del(key_info.home_multi_press_timer);
196                 key_info.home_multi_press_timer = NULL;
197         }
198 }
199
200
201
202 static Eina_Bool _key_release_cb(void *data, int type, void *event)
203 {
204         Evas_Event_Key_Up *ev = event;
205
206         retv_if(!ev, ECORE_CALLBACK_RENEW);
207         retv_if(!ev->keyname, ECORE_CALLBACK_RENEW);
208
209         _D("_key_release_cb : %s Released", ev->keyname);
210
211         /* Priority 1 : Cancel event */
212         if (!strcmp(ev->keyname, KEY_CANCEL)) {
213                 _D("CANCEL Key is released");
214                 key_info.cancel = EINA_FALSE;
215                 return ECORE_CALLBACK_RENEW;
216         }
217
218         if (EINA_TRUE == key_info.cancel) {
219                 _D("CANCEL is on");
220                 return ECORE_CALLBACK_RENEW;
221         }
222
223         /* Priority 2 : Execute before checking the lock status */
224         if (!strcmp(ev->keyname, KEY_MEDIA)) {
225                 _release_multimedia_key("KEY_PLAYCD");
226                 return ECORE_CALLBACK_RENEW;
227         }
228
229         /* Priority 3 : Check the lock status */
230         if ((status_passive_get()->idle_lock_state  == VCONFKEY_IDLE_LOCK)
231                 && (status_active_get()->setappl_screen_lock_type_int > SETTING_SCREEN_LOCK_TYPE_NONE)) {
232                 if (!strcmp(ev->keyname, KEY_BACK)) {
233                         _D("Back key is released");
234                         lock_pwd_util_back_key_relased();
235                 } else {
236                         _D("phone lock state, ignore home key.");
237                 }
238                 return ECORE_CALLBACK_RENEW;
239         }
240
241         /* Priority 4 : These keys are only activated after checking the lock state */
242         if (!strcmp(ev->keyname, KEY_END)) {
243         } else if (!strcmp(ev->keyname, KEY_CONFIG)) {
244         } else if (!strcmp(ev->keyname, KEY_SEND)) {
245         } else if (!strcmp(ev->keyname, KEY_HOME)) {
246                 _W("Home Key is released");
247
248                 syspopup_destroy_all();
249
250                 if(key_info.home_multi_press_timer) {
251                         _D("delete homekey timer");
252                         ecore_timer_del(key_info.home_multi_press_timer);
253                         key_info.home_multi_press_timer = NULL;
254                 }
255
256                 if (key_info.home_long_press_timer) {
257                         ecore_timer_del(key_info.home_long_press_timer);
258                         key_info.home_long_press_timer = NULL;
259                 } else {
260                         key_info.homekey_count = 0;
261                         return ECORE_CALLBACK_RENEW;
262                 }
263
264                 key_info.home_multi_press_timer = ecore_timer_add(HOMEKEY_TIMER_SEC, _home_multi_press_timer_cb, NULL);
265                 if (!key_info.home_multi_press_timer) {
266                         _E("Critical! cannot add a timer for home multi press");
267                 }
268                 return ECORE_CALLBACK_RENEW;
269         } else if (!strcmp(ev->keyname, KEY_PAUSE)) {
270         } else if (!strcmp(ev->keyname, KEY_APPS)) {
271                 _D("App tray key is released");
272         } else if (!strcmp(ev->keyname, KEY_TASKSWITCH)) {
273                 _D("Task switch key is released");
274                 _launch_taskmgr_cb(NULL);
275         } else if (!strcmp(ev->keyname, KEY_WEBPAGE)) {
276                 _D("Web page key is released");
277                 process_mgr_must_open(APPID_BROWSER, NULL, NULL);
278         } else if (!strcmp(ev->keyname, KEY_MAIL)) {
279                 _D("Mail key is released");
280                 process_mgr_must_open(APPID_EMAIL, NULL, NULL);
281         } else if (!strcmp(ev->keyname, KEY_CONNECT)) {
282                 _D("Connect key is released");
283                 process_mgr_must_open(APPID_DIALER, NULL, NULL);
284         } else if (!strcmp(ev->keyname, KEY_SEARCH)) {
285                 _D("Search key is released");
286                 if (_launch_search() < 0) {
287                         _E("Failed to launch the search");
288                 }
289         } else if (!strcmp(ev->keyname, KEY_VOICE)) {
290                 _D("Voice key is released");
291         }
292
293         return ECORE_CALLBACK_RENEW;
294 }
295
296
297
298 static Eina_Bool _key_press_cb(void *data, int type, void *event)
299 {
300         Evas_Event_Key_Down *ev = event;
301
302         retv_if(!ev, ECORE_CALLBACK_RENEW);
303         retv_if(!ev->keyname, ECORE_CALLBACK_RENEW);
304
305         _D("_key_press_cb : %s Pressed", ev->keyname);
306
307         /* Priority 1 : Cancel */
308         /*              every reserved events have to be canceld when cancel key is pressed */
309         if (!strcmp(ev->keyname, KEY_CANCEL)) {
310                 _D("Cancel button is pressed");
311                 key_info.cancel = EINA_TRUE;
312                 _cancel_key_events();
313                 return ECORE_CALLBACK_RENEW;
314         }
315
316         if (EINA_TRUE == key_info.cancel) {
317                 _D("CANCEL is on");
318                 return ECORE_CALLBACK_RENEW;
319         }
320
321         /* Priority 2 : Check the lock status */
322         if ((status_passive_get()->idle_lock_state == VCONFKEY_IDLE_LOCK)
323                 && (status_active_get()->setappl_screen_lock_type_int > SETTING_SCREEN_LOCK_TYPE_NONE)) {
324                 _D("phone lock state, ignore key events.");
325                 _cancel_key_events();
326                 return ECORE_CALLBACK_RENEW;
327         }
328
329         /* Priority 3 : other keys */
330         if (!strcmp(ev->keyname, KEY_SEND)) {
331                 _D("Launch calllog");
332                 process_mgr_must_open(APPID_CALLLOG, NULL, NULL);
333         } else if(!strcmp(ev->keyname, KEY_CONFIG)) {
334                 _D("Launch camera");
335                 process_mgr_must_open(APPID_CAMERA, NULL, NULL);
336         } else if (!strcmp(ev->keyname, KEY_HOME)) {
337                 _W("Home Key is pressed");
338                 if (key_info.home_long_press_timer) {
339                         ecore_timer_del(key_info.home_long_press_timer);
340                         key_info.home_long_press_timer = NULL;
341                 }
342
343                 key_info.homekey_count++;
344                 _W("homekey count : %d", key_info.homekey_count);
345
346                 if(key_info.home_multi_press_timer) {
347                         ecore_timer_del(key_info.home_multi_press_timer);
348                         key_info.home_multi_press_timer = NULL;
349                         _D("delete homekey timer");
350                 }
351
352                 _D("create long press timer");
353                 key_info.home_long_press_timer = ecore_timer_add(LONG_PRESS_TIMER_SEC, _launch_taskmgr_cb, NULL);
354                 if (!key_info.home_long_press_timer) {
355                         _E("Failed to add timer for long press detection");
356                 }
357         } else if (!strcmp(ev->keyname, KEY_MEDIA)) {
358                 _D("Media key is pressed");
359         } else if (!strcmp(ev->keyname, KEY_APPS)) {
360                 _D("App tray key is pressed");
361         } else if (!strcmp(ev->keyname, KEY_TASKSWITCH)) {
362                 _D("Task switch key is pressed");
363         } else if (!strcmp(ev->keyname, KEY_WEBPAGE)) {
364                 _D("Web page key is pressed");
365         } else if (!strcmp(ev->keyname, KEY_MAIL)) {
366                 _D("Mail key is pressed");
367         } else if (!strcmp(ev->keyname, KEY_SEARCH)) {
368                 _D("Search key is pressed");
369         } else if (!strcmp(ev->keyname, KEY_VOICE)) {
370                 _D("Voice key is pressed");
371         } else if (!strcmp(ev->keyname, KEY_CONNECT)) {
372                 _D("Connect key is pressed");
373         }
374
375         return ECORE_CALLBACK_RENEW;
376 }
377
378
379
380 void _media_key_event_cb(media_key_e key, media_key_event_e status, void *user_data)
381 {
382         _D("MEDIA KEY EVENT : %d", key);
383         if (MEDIA_KEY_STATUS_PRESSED == status) return;
384
385         switch (key) {
386         case MEDIA_KEY_PAUSE:
387                 _release_multimedia_key("KEY_PAUSECD");
388                 break;
389         case MEDIA_KEY_PLAY:
390                 _release_multimedia_key("KEY_PLAYCD");
391                 break;
392         case MEDIA_KEY_PLAYPAUSE:
393                 _release_multimedia_key("KEY_PLAYPAUSECD");
394                 break;
395         default:
396                 _E("cannot reach here, key[%d]", key);
397                 break;
398         }
399 }
400
401
402
403 void hw_key_create_window(void)
404 {
405         int ret;
406         Ecore_X_Atom atomNotiWindow;
407         Ecore_X_Window keyrouter_notiwindow;
408
409         key_info.win = ecore_x_window_input_new(0, 0, 0, 1, 1);
410         if (!key_info.win) {
411                 _D("Failed to create hidden window");
412                 return;
413         }
414         ecore_x_event_mask_unset(key_info.win, ECORE_X_EVENT_MASK_NONE);
415         ecore_x_icccm_title_set(key_info.win, "menudaemon,key,receiver");
416         ecore_x_netwm_name_set(key_info.win, "menudaemon,key,receiver");
417         ecore_x_netwm_pid_set(key_info.win, getpid());
418
419         utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_HOME, SHARED_GRAB);
420         utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_VOLUMEDOWN, SHARED_GRAB);
421         utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_VOLUMEUP, SHARED_GRAB);
422         utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_CONFIG, SHARED_GRAB);
423         utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_MEDIA, SHARED_GRAB);
424         utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_APPS, SHARED_GRAB);
425         utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_TASKSWITCH, SHARED_GRAB);
426         utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_WEBPAGE, SHARED_GRAB);
427         utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_MAIL, SHARED_GRAB);
428         utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_SEARCH, SHARED_GRAB);
429         utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_VOICE, SHARED_GRAB);
430         utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_CONNECT, SHARED_GRAB);
431         utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_POWER, SHARED_GRAB);
432
433         key_info.key_up = ecore_event_handler_add(ECORE_EVENT_KEY_UP, _key_release_cb, NULL);
434         if (!key_info.key_up)
435                 _E("Failed to register a key up event handler");
436
437         key_info.key_down = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _key_press_cb, NULL);
438         if (!key_info.key_down)
439                 _E("Failed to register a key down event handler");
440
441         /* Get notifwindow */
442         atomNotiWindow = ecore_x_atom_get(STR_ATOM_KEYROUTER_NOTIWINDOW);
443         ret = ecore_x_window_prop_window_get(ecore_x_window_root_first_get(), atomNotiWindow, &keyrouter_notiwindow, 1);
444         if (ret > 0) {
445                 _D("Succeed to get keyrouter notiwindow ! ret = %d (win=0x%x)\n"
446                                 , ret, keyrouter_notiwindow);
447                 ecore_x_window_sniff(keyrouter_notiwindow);
448                 key_info.keyrouter_notiwindow = keyrouter_notiwindow;
449         } else {
450                 _E("Failed to get keyrouter notiwindow! ret = %d, atomNotiWindow = 0x%x, keyrouter_notiwindow = 0x%x"
451                                 , ret, atomNotiWindow, keyrouter_notiwindow);
452         }
453
454         media_key_reserve(_media_key_event_cb, NULL);
455 }
456
457
458
459 void hw_key_destroy_window(void)
460 {
461         utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_HOME);
462         utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_VOLUMEDOWN);
463         utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_VOLUMEUP);
464         utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_CONFIG);
465         utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_MEDIA);
466         utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_APPS);
467         utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_TASKSWITCH);
468         utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_WEBPAGE);
469         utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_MAIL);
470         utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_SEARCH);
471         utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_VOICE);
472         utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_CONNECT);
473
474         if (key_info.key_up) {
475                 ecore_event_handler_del(key_info.key_up);
476                 key_info.key_up = NULL;
477         }
478
479         if (key_info.key_down) {
480                 ecore_event_handler_del(key_info.key_down);
481                 key_info.key_down = NULL;
482         }
483
484         ecore_x_window_delete_request_send(key_info.win);
485         key_info.win = 0x0;
486
487         media_key_release();
488 }
489 #endif //HAVE_X11
490
491 // End of a file