2 * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <Elementary.h>
20 #include <Ecore_Input.h>
23 #include <dd-display.h>
30 #include "dbus_util.h"
32 #include "process_mgr.h"
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
39 #define APP_CONTROL_OPERATION_MAIN_KEY "__APP_SVC_OP_TYPE__"
40 #define APP_CONTROL_OPERATION_MAIN_VALUE "http://tizen.org/appcontrol/operation/main"
42 #define USE_DBUS_POWEROFF 1
43 #define W_TASKMGR_PKGNAME "org.tizen.w-taskmanager"
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;
55 Eina_Bool is_long_press;
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,
68 .is_cancel = EINA_FALSE,
73 static Eina_Bool _powerkey_timer_cb(void *data)
75 _W("%s, powerkey count[%d]", __func__, key_info.powerkey_count);
77 key_info.power_release_timer = NULL;
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);
86 _W("just turn on LCD by powerkey.. starter ignore powerkey operation");
88 return ECORE_CALLBACK_CANCEL;
91 if (key_info.powerkey_count % 2 == 0) {
93 _W("powerkey double press");
94 key_info.powerkey_count = 0;
95 return ECORE_CALLBACK_CANCEL;
97 key_info.powerkey_count = 0;
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;
105 _W("just turn on LCD by powerkey.. starter ignore powerkey operation");
106 return ECORE_CALLBACK_CANCEL;
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;
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;
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;
127 home_mgr_launch_home_by_power();
129 return ECORE_CALLBACK_CANCEL;
133 static Eina_Bool _long_press_timer_cb(void* data)
135 key_info.power_long_press_timer = NULL;
136 key_info.is_long_press = EINA_TRUE;
137 key_info.powerkey_count = 0;
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;
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");
150 #if USE_DBUS_POWEROFF
151 dbus_util_send_poweroff_signal();
153 _D("launch power off syspopup");
154 process_mgr_syspopup_launch("poweroff-syspopup", NULL, NULL, NULL, NULL);
157 feedback_initialize();
158 feedback_play_type(FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_HOLD);
159 feedback_deinitialize();
161 return ECORE_CALLBACK_CANCEL;
165 static Eina_Bool _key_release_cb(void *data, int type, void *event)
167 Evas_Event_Key_Up *ev = event;
169 retv_if(!ev, ECORE_CALLBACK_RENEW);
170 retv_if(!ev->keyname, ECORE_CALLBACK_RENEW);
172 _D("_key_release_cb : %s Released", ev->keyname);
174 if (!strcmp(ev->keyname, KEY_POWER)) {
175 _W("POWER Key is released");
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");
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");
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;
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;
205 if(key_info.is_lcd_on) {
206 key_info.power_release_timer = ecore_timer_add(POWERKEY_TIMER_SEC, _powerkey_timer_cb, NULL);
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);
211 if (!key_info.power_release_timer) {
212 _E("Critical, cannot add a timer for powerkey");
214 } else if (!strcmp(ev->keyname, KEY_CANCEL)) {
215 _D("CANCEL Key is released");
216 key_info.is_cancel = EINA_FALSE;
219 return ECORE_CALLBACK_RENEW;
224 static Eina_Bool _key_press_cb(void *data, int type, void *event)
226 Evas_Event_Key_Down *ev = event;
228 retv_if(!ev, ECORE_CALLBACK_RENEW);
229 retv_if(!ev->keyname, ECORE_CALLBACK_RENEW);
231 _D("_key_press_cb : %s Pressed", ev->keyname);
233 if (!strcmp(ev->keyname, KEY_POWER)) {
234 _W("POWER Key is pressed");
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;
249 key_info.powerkey_count++;
250 _W("powerkey count : %d", key_info.powerkey_count);
252 if(key_info.power_release_timer) {
253 ecore_timer_del(key_info.power_release_timer);
254 key_info.power_release_timer = NULL;
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;
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");
267 } else if (!strcmp(ev->keyname, KEY_CANCEL)) {
268 _D("CANCEL key is pressed");
269 key_info.is_cancel = EINA_TRUE;
272 return ECORE_CALLBACK_RENEW;
277 static Eina_Bool _w_gesture_hold_cb(void *data, int ev_type, void *ev)
279 Ecore_X_Event_Gesture_Notify_Hold *e = ev;
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;
286 if (SETTING_PSMODE_WEARABLE_ENHANCED == status_passive_get()->setappl_psmode) {
287 _E("UPS Mode, ignore gesture");
288 return ECORE_CALLBACK_RENEW;
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);
300 return ECORE_CALLBACK_RENEW;
305 void hw_key_create_window(void)
310 _W("hw_key_create_window");
312 key_info.win = ecore_x_window_input_new(0, 0, 0, 1, 1);
314 _E("Failed to create hidden window");
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());
322 ret = utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_POWER, SHARED_GRAB);
324 _E("utilx_grab_key KEY_POWER GrabSHARED_GRAB failed, ret[%d]", ret);
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");
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");
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);
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");
348 void hw_key_destroy_window(void)
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;
357 status = ecore_x_gesture_event_ungrab(key_info.win, ECORE_X_GESTURE_EVENT_HOLD, GRAB_TWO_FINGERS);
359 _E("ECORE_X_GESTURE_EVENT_HOLD UnGrab(%d fingers) failed, status[%d]\n", GRAB_TWO_FINGERS, status);
362 if (key_info.key_up) {
363 ecore_event_handler_del(key_info.key_up);
364 key_info.key_up = NULL;
367 if (key_info.key_down) {
368 ecore_event_handler_del(key_info.key_down);
369 key_info.key_down = NULL;
372 utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_POWER);
374 ecore_x_window_delete_request_send(key_info.win);