Code sync up from tizen 2.4
[apps/native/starter.git] / src / wearable / 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 #include <bundle.h>
18 #include <Elementary.h>
19 #include <Ecore_X.h>
20 #include <Ecore_Input.h>
21 #include <utilX.h>
22
23 #include <dd-display.h>
24 #include <feedback.h>
25 #include <vconf.h>
26
27 #include "hw_key.h"
28 #include "util.h"
29 #include "status.h"
30 #include "dbus_util.h"
31 #include "home_mgr.h"
32 #include "process_mgr.h"
33
34 #define GRAB_TWO_FINGERS 2
35 #define POWERKEY_TIMER_SEC 0.25
36 #define POWERKEY_LCDOFF_TIMER_SEC 0.4
37 #define LONG_PRESS_TIMER_SEC 0.7
38
39 #define APP_CONTROL_OPERATION_MAIN_KEY "__APP_SVC_OP_TYPE__"
40 #define APP_CONTROL_OPERATION_MAIN_VALUE "http://tizen.org/appcontrol/operation/main"
41
42 #define USE_DBUS_POWEROFF 1
43 #define W_TASKMGR_PKGNAME "org.tizen.w-taskmanager"
44
45
46
47 static struct {
48         Ecore_X_Window win;
49         Ecore_Event_Handler *key_up;
50         Ecore_Event_Handler *key_down;
51         Ecore_Event_Handler *two_fingers_hold_hd;
52         Ecore_Timer *power_long_press_timer;
53         Ecore_Timer *power_release_timer;
54         Eina_Bool is_lcd_on;
55         Eina_Bool is_long_press;
56         int powerkey_count;
57         Eina_Bool is_cancel;
58 } key_info = {
59         .win = 0x0,
60         .key_up = NULL,
61         .key_down = NULL,
62         .two_fingers_hold_hd = NULL,
63         .power_long_press_timer = NULL,
64         .power_release_timer = NULL,
65         .is_lcd_on = EINA_FALSE,
66         .is_long_press = EINA_FALSE,
67         .powerkey_count = 0,
68         .is_cancel = EINA_FALSE,
69 };
70
71
72
73 static Eina_Bool _powerkey_timer_cb(void *data)
74 {
75         _W("%s, powerkey count[%d]", __func__, key_info.powerkey_count);
76
77         key_info.power_release_timer = NULL;
78
79         if (VCONFKEY_PM_KEY_LOCK == status_passive_get()->pm_key_ignore) {
80                 _E("Critical Low Batt Clock Mode");
81                 key_info.powerkey_count = 0;
82                 if(key_info.is_lcd_on) {
83                         _W("just turn off LCD");
84                         display_change_state(LCD_OFF);
85                 } else {
86                         _W("just turn on LCD by powerkey.. starter ignore powerkey operation");
87                 }
88                 return ECORE_CALLBACK_CANCEL;
89         }
90
91         if (key_info.powerkey_count % 2 == 0) {
92                 /* double press */
93                 _W("powerkey double press");
94                 key_info.powerkey_count = 0;
95                 return ECORE_CALLBACK_CANCEL;
96         }
97         key_info.powerkey_count = 0;
98
99         if (key_info.is_lcd_on) {
100                 if(VCONFKEY_PM_STATE_LCDOFF <= status_active_get()->pm_state) {
101                         _E("Already lcd state was changed while powerkey op. starter ignore powerkey operation");
102                         return ECORE_CALLBACK_CANCEL;
103                 }
104         } else {
105                 _W("just turn on LCD by powerkey.. starter ignore powerkey operation");
106                 return ECORE_CALLBACK_CANCEL;
107         }
108
109         if (VCONFKEY_CALL_VOICE_ACTIVE == status_passive_get()->call_state) {
110                 _W("call state is [%d] -> just turn off LCD");
111                 display_change_state(LCD_OFF);
112                 return ECORE_CALLBACK_CANCEL;
113         }
114
115         if (VCONFKEY_IDLE_LOCK == status_passive_get()->idle_lock_state) {
116                 _W("lock state is [%d] -> just turn off LCD");
117                 display_change_state(LCD_OFF);
118                 return ECORE_CALLBACK_CANCEL;
119         }
120
121         if (0 < status_passive_get()->remote_lock_islocked) {
122                 _W("remote lock is on top (%d), -> just turn off LCD", status_passive_get()->remote_lock_islocked);
123                 display_change_state(LCD_OFF);
124                 return ECORE_CALLBACK_CANCEL;
125         }
126
127         home_mgr_launch_home_by_power();
128
129         return ECORE_CALLBACK_CANCEL;
130 }
131
132
133 static Eina_Bool _long_press_timer_cb(void* data)
134 {
135         key_info.power_long_press_timer = NULL;
136         key_info.is_long_press = EINA_TRUE;
137         key_info.powerkey_count = 0;
138
139         if (0 < status_passive_get()->remote_lock_islocked){
140                 _W("remote lock is on top (%d), -> just turn off LCD", status_passive_get()->remote_lock_islocked);
141                 return ECORE_CALLBACK_CANCEL;
142         }
143
144         if (key_info.power_release_timer) {
145                 ecore_timer_del(key_info.power_release_timer);
146                 key_info.power_release_timer = NULL;
147                 _D("delete power_release_timer");
148         }
149
150 #if USE_DBUS_POWEROFF
151         dbus_util_send_poweroff_signal();
152 #else
153         _D("launch power off syspopup");
154         process_mgr_syspopup_launch("poweroff-syspopup", NULL, NULL, NULL, NULL);
155 #endif
156
157         feedback_initialize();
158         feedback_play_type(FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_HOLD);
159         feedback_deinitialize();
160
161         return ECORE_CALLBACK_CANCEL;
162 }
163
164
165 static Eina_Bool _key_release_cb(void *data, int type, void *event)
166 {
167         Evas_Event_Key_Up *ev = event;
168
169         retv_if(!ev, ECORE_CALLBACK_RENEW);
170         retv_if(!ev->keyname, ECORE_CALLBACK_RENEW);
171
172         _D("_key_release_cb : %s Released", ev->keyname);
173
174         if (!strcmp(ev->keyname, KEY_POWER)) {
175                 _W("POWER Key is released");
176
177                 if(key_info.power_long_press_timer) {
178                         ecore_timer_del(key_info.power_long_press_timer);
179                         key_info.power_long_press_timer = NULL;
180                         _D("delete long press timer");
181                 }
182
183                 // Check powerkey timer
184                 if(key_info.power_release_timer) {
185                         ecore_timer_del(key_info.power_release_timer);
186                         key_info.power_release_timer = NULL;
187                         _D("delete powerkey timer");
188                 }
189
190                 // Cancel key operation
191                 if (EINA_TRUE == key_info.is_cancel) {
192                         _D("Cancel key is activated");
193                         key_info.is_cancel = EINA_FALSE;
194                         key_info.powerkey_count = 0; //initialize powerkey count
195                         return ECORE_CALLBACK_RENEW;
196                 }
197
198                 // Check long press operation
199                 if(key_info.is_long_press) {
200                         _D("ignore power key release by long poress");
201                         key_info.is_long_press = EINA_FALSE;
202                         return ECORE_CALLBACK_RENEW;
203                 }
204
205                 if(key_info.is_lcd_on) {
206                         key_info.power_release_timer = ecore_timer_add(POWERKEY_TIMER_SEC, _powerkey_timer_cb, NULL);
207                 } else {
208                         _D("lcd off --> [%f]sec timer", POWERKEY_LCDOFF_TIMER_SEC);
209                         key_info.power_release_timer = ecore_timer_add(POWERKEY_LCDOFF_TIMER_SEC, _powerkey_timer_cb, NULL);
210                 }
211                 if (!key_info.power_release_timer) {
212                         _E("Critical, cannot add a timer for powerkey");
213                 }
214         } else if (!strcmp(ev->keyname, KEY_CANCEL)) {
215                 _D("CANCEL Key is released");
216                 key_info.is_cancel = EINA_FALSE;
217         }
218
219         return ECORE_CALLBACK_RENEW;
220 }
221
222
223
224 static Eina_Bool _key_press_cb(void *data, int type, void *event)
225 {
226         Evas_Event_Key_Down *ev = event;
227
228         retv_if(!ev, ECORE_CALLBACK_RENEW);
229         retv_if(!ev->keyname, ECORE_CALLBACK_RENEW);
230
231         _D("_key_press_cb : %s Pressed", ev->keyname);
232
233         if (!strcmp(ev->keyname, KEY_POWER)) {
234                 _W("POWER Key is pressed");
235
236                 /**
237                  * lcd status
238                  * 1 : lcd normal
239                  * 2 : lcd dim
240                  * 3 : lcd off
241                  * 4 : suspend
242                  */
243                 if (VCONFKEY_PM_STATE_LCDDIM >= status_active_get()->pm_state) {
244                         key_info.is_lcd_on = EINA_TRUE;
245                 } else if (VCONFKEY_PM_STATE_LCDOFF <= status_active_get()->pm_state) {
246                         key_info.is_lcd_on = EINA_FALSE;
247                 }
248
249                 key_info.powerkey_count++;
250                 _W("powerkey count : %d", key_info.powerkey_count);
251
252                 if(key_info.power_release_timer) {
253                         ecore_timer_del(key_info.power_release_timer);
254                         key_info.power_release_timer = NULL;
255                 }
256
257                 if (key_info.power_long_press_timer) {
258                         ecore_timer_del(key_info.power_long_press_timer);
259                         key_info.power_long_press_timer = NULL;
260                 }
261
262                 key_info.is_long_press = EINA_FALSE;
263                 key_info.power_long_press_timer = ecore_timer_add(LONG_PRESS_TIMER_SEC, _long_press_timer_cb, NULL);
264                 if(!key_info.power_long_press_timer) {
265                         _E("Failed to add power_long_press_timer");
266                 }
267         } else if (!strcmp(ev->keyname, KEY_CANCEL)) {
268                 _D("CANCEL key is pressed");
269                 key_info.is_cancel = EINA_TRUE;
270         }
271
272         return ECORE_CALLBACK_RENEW;
273 }
274
275
276
277 static Eina_Bool _w_gesture_hold_cb(void *data, int ev_type, void *ev)
278 {
279         Ecore_X_Event_Gesture_Notify_Hold *e = ev;
280
281         if (VCONFKEY_PM_KEY_LOCK == status_passive_get()->pm_key_ignore) {
282                 _E("Critical Low Batt Clock Mode, ignore gesture");
283                 return ECORE_CALLBACK_RENEW;
284         }
285
286         if (SETTING_PSMODE_WEARABLE_ENHANCED == status_passive_get()->setappl_psmode) {
287                 _E("UPS Mode, ignore gesture");
288                 return ECORE_CALLBACK_RENEW;
289         }
290
291         if(e->num_fingers == GRAB_TWO_FINGERS) {
292                 _D("subtype[%d]: hold[%d]\n", e->subtype, e->hold_time);
293                 if (e->subtype == ECORE_X_GESTURE_BEGIN) {
294                         _D("Begin : launch task mgr..!!");
295                         dbus_util_send_cpu_booster_signal();
296                         process_mgr_must_launch(W_TASKMGR_PKGNAME, APP_CONTROL_OPERATION_MAIN_KEY, APP_CONTROL_OPERATION_MAIN_VALUE, NULL, NULL);
297                 }
298         }
299
300         return ECORE_CALLBACK_RENEW;
301 }
302
303
304
305 void hw_key_create_window(void)
306 {
307         int status = -1;
308         int ret = -1;
309
310         _W("hw_key_create_window");
311
312         key_info.win = ecore_x_window_input_new(0, 0, 0, 1, 1);
313         if (!key_info.win) {
314                 _E("Failed to create hidden window");
315                 return;
316         }
317         ecore_x_event_mask_unset(key_info.win, ECORE_X_EVENT_MASK_NONE);
318         ecore_x_icccm_title_set(key_info.win, "w_starter,key,receiver");
319         ecore_x_netwm_name_set(key_info.win, "w_starter,key,receiver");
320         ecore_x_netwm_pid_set(key_info.win, getpid());
321
322         ret = utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_POWER, SHARED_GRAB);
323         if (ret != 0) {
324                 _E("utilx_grab_key KEY_POWER GrabSHARED_GRAB failed, ret[%d]", ret);
325         }
326
327         key_info.key_up = ecore_event_handler_add(ECORE_EVENT_KEY_UP, _key_release_cb, NULL);
328         if (!key_info.key_up) {
329                 _E("Failed to register a key up event handler");
330         }
331
332         key_info.key_down = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _key_press_cb, NULL);
333         if (!key_info.key_down) {
334                 _E("Failed to register a key down event handler");
335         }
336
337         status = ecore_x_gesture_event_grab(key_info.win, ECORE_X_GESTURE_EVENT_HOLD, GRAB_TWO_FINGERS);
338         _E("ECORE_X_GESTURE_EVENT_HOLD Grab(%d fingers) status[%d]\n", GRAB_TWO_FINGERS, status);
339
340         key_info.two_fingers_hold_hd = ecore_event_handler_add(ECORE_X_EVENT_GESTURE_NOTIFY_HOLD, _w_gesture_hold_cb, NULL);
341         if (!key_info.two_fingers_hold_hd) {
342                 _E("Failed to register handler : ECORE_X_EVENT_GESTURE_NOTIFY_TAPNHOLD\n");
343         }
344 }
345
346
347
348 void hw_key_destroy_window(void)
349 {
350         int status;
351
352         if (key_info.two_fingers_hold_hd) {
353                 ecore_event_handler_del(key_info.two_fingers_hold_hd);
354                 key_info.two_fingers_hold_hd = NULL;
355         }
356
357         status = ecore_x_gesture_event_ungrab(key_info.win, ECORE_X_GESTURE_EVENT_HOLD, GRAB_TWO_FINGERS);
358         if (!status) {
359                 _E("ECORE_X_GESTURE_EVENT_HOLD UnGrab(%d fingers) failed, status[%d]\n", GRAB_TWO_FINGERS, status);
360         }
361
362         if (key_info.key_up) {
363                 ecore_event_handler_del(key_info.key_up);
364                 key_info.key_up = NULL;
365         }
366
367         if (key_info.key_down) {
368                 ecore_event_handler_del(key_info.key_down);
369                 key_info.key_down = NULL;
370         }
371
372         utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_POWER);
373
374         ecore_x_window_delete_request_send(key_info.win);
375         key_info.win = 0x0;
376 }
377
378
379
380 // End of a file