Fix
[platform/core/system/system-popup.git] / src / powerkey / powerkey.c
1 /*
2  *  powerkey-popup
3  *
4  * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18 */
19
20 #include "popup-common.h"
21
22 #define SYSTEMD_STOP_POWER_OFF 4
23
24 #define DEVICED_BUS_NAME        "org.tizen.system.deviced"
25 #define POWER_OBJECT_PATH     "/Org/Tizen/System/DeviceD/Power"
26 #define POWER_INTERFACE_NAME  DEVICED_BUS_NAME".power"
27
28 #define POWER_METHOD            "reboot"
29 #define POWER_OPERATION_OFF     "poweroff"
30 #define POWER_OPERATION_RESTART     "reboot"
31 #define TIMEOUT_POWEROFF 5 /* seconds */
32
33 #define DEVICED_OBJECT_PATH             "/Org/Tizen/System/DeviceD"
34 #define DEVICED_INTERFACE_NAME  DEVICED_BUS_NAME
35
36 int clicked_index = 0;
37
38 static void remove_popup(const struct popup_ops *ops);
39 static void pm_state_changed(keynode_t *key, void *data);
40 static void event_back_key_up(void *data, Evas_Object *obj, void *event_info);
41 static void register_handlers(const struct popup_ops *ops);
42 static void unregister_handlers(const struct popup_ops *ops);
43 static int poweroff_launch(bundle *b, const struct popup_ops *ops);
44 static void poweroff_terminate(const struct popup_ops *ops);
45 static void powerkey_terminate(const struct popup_ops *ops);
46 static void poweroff_clicked(const struct popup_ops *ops);
47 static __attribute__ ((constructor)) void powerkey_register_popup(void);
48 static const struct popup_ops powerkey_ops;
49 static const struct popup_ops poweroff_ops;
50 static const struct popup_ops restart_ops;
51
52 static char *items[] = {
53         "IDS_ST_BODY_POWER_OFF",
54         "IDS_COM_SK_RESTART_ABB"
55 };
56
57 static int restart_launch(bundle *b, const struct popup_ops *ops)
58 {
59         return 0;
60 }
61
62 static void restart_terminate(const struct popup_ops *ops)
63 {
64
65 }
66
67 static void restart_clicked(const struct popup_ops *ops)
68 {
69         Evas_Object *rect, *win;
70         Evas_Coord w, h, size;
71         static int bReset = 0;
72         char *param[2];
73         char data[8];
74         int ret;
75
76         if (bReset == 1) return;
77         bReset = 1;
78
79         unload_simple_popup(ops);
80
81         win = get_window();
82         if (!win) popup_terminate();
83
84         rect = evas_object_rectangle_add(evas_object_evas_get(win));
85         evas_object_geometry_get(win, NULL, NULL, &w, &h);
86         size = max(w, h);
87         evas_object_resize(rect, size, size);
88         evas_object_color_set(rect, 0, 0, 0, 255);
89         evas_object_show(rect);
90
91         param[0] = POWER_OPERATION_RESTART;
92         snprintf(data, sizeof(data), "0");
93         param[1] = data;
94
95         ret = popup_dbus_method_sync(DEVICED_BUS_NAME,
96                         POWER_OBJECT_PATH,
97                         POWER_INTERFACE_NAME,
98                         POWER_METHOD,
99                         "si", param);
100
101         if (ret < 0) _E("Failed to request restart to deviced (%d)", ret);
102 }
103
104 static char* gl_text_get_cb(void *data, Evas_Object *obj, const char *part)
105 {
106         int index = (int) data;
107
108         switch (index) {
109         case 0:
110                 if (!strncmp("elm.text", part, sizeof("elm.text")))
111                         return strdup(_(items[index]));
112                 else
113                         return NULL;
114
115         case 1:
116                 if (!strncmp("elm.text", part, sizeof("elm.text")))
117                         return strdup(_(items[index]));
118                 else
119                         return NULL;
120         }
121
122         return NULL;
123 }
124
125 static void gl_sel_cb(void *data, Evas_Object *obj, void *event_info)
126 {
127         Elm_Object_Item *item = event_info;
128         bundle *b = NULL;
129
130         clicked_index = (int)elm_object_item_data_get(item);
131         unload_simple_popup(data);
132
133         if (clicked_index == 0) {
134                 _D("poweroff is chosen");
135                 load_simple_popup(b, &poweroff_ops);
136         } else if (clicked_index == 1) {
137                 _D("restart is chosen");
138                 load_simple_popup(b, &restart_ops);
139         } else
140                 _E("Wrong button is pressed");
141 }
142
143 static Evas_Object* gl_image_get_cb(void *data, Evas_Object *obj, const char *part)
144 {
145         Evas_Object *img = elm_image_add(obj);
146         Evas_Object *check;
147         int index = (int) data;
148
149         if (!img) {
150                 _E("BAD image");
151                 return NULL;
152         }
153
154         switch (index) {
155         case 0:
156                 if (!strncmp(part, "elm.swallow.icon", sizeof("elm.swallow.icon"))) {
157                         elm_image_file_set(img, RESDIR"/core_power_off.png", NULL);
158                         evas_object_size_hint_min_set(img, ELM_SCALE_SIZE(50), ELM_SCALE_SIZE(50));
159                         _D("Power off img");
160                         return img;
161                 } else if (!strncmp(part, "elm.swallow.icon.end", sizeof("elm.swallow.icon.end"))) {
162                         check = elm_check_add(obj);
163                         return check;
164                 } else
165                         return NULL;
166
167         case 1:
168                 if (!strncmp(part, "elm.swallow.icon", sizeof("elm.swallow.icon"))) {
169                         elm_image_file_set(img, RESDIR"/core_restart.png", NULL);
170                         evas_object_size_hint_min_set(img, ELM_SCALE_SIZE(50), ELM_SCALE_SIZE(50));
171                         _D("Restart img");
172                         return img;
173                 } else if (!strncmp(part, "elm.swallow.icon.end", sizeof("elm.swallow.icon.end"))) {
174                         check = elm_check_add(obj);
175                         return check;
176                 } else
177                         return NULL;
178
179         default:
180                 _E("BAD data!");
181                 return NULL;
182         }
183 }
184
185 int powerkey_list(bundle *b, const struct popup_ops *ops)
186 {
187         Elm_Genlist_Item_Class *itc = elm_genlist_item_class_new();
188         Evas_Object *popup = NULL;
189         Evas_Object *box = NULL;
190         Evas_Object *genlist = NULL;
191         struct object_ops *obj;
192         int i;
193         Evas_Object *win;
194         int ret;
195
196         if (!ops) return -EINVAL;
197
198         ret = get_object_by_ops(ops, &obj);
199         if (ret < 0) return -EINVAL;
200
201         win = get_window();
202         if (!win) return -ENOMEM;
203
204         evas_object_show(win);
205
206         popup = elm_popup_add(win);
207         if (!popup) return -ENOMEM;
208
209         elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 1.0);
210         evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
211
212         elm_object_style_set(genlist, "default");
213
214         /* box */
215         box = elm_box_add(popup);
216         evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
217
218         /* genlist */
219         genlist = elm_genlist_add(box);
220         evas_object_size_hint_weight_set(genlist, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
221         evas_object_size_hint_align_set(genlist, EVAS_HINT_FILL, EVAS_HINT_FILL);
222
223         itc->item_style = "type1";
224         itc->func.text_get = gl_text_get_cb;
225         itc->func.content_get = gl_image_get_cb;
226         itc->func.state_get = NULL;
227         itc->func.del = NULL;
228
229         for (i = 0; i < 2; i++)
230                 elm_genlist_item_append(genlist, itc, (void *) i, NULL, ELM_GENLIST_ITEM_NONE, gl_sel_cb, ops);
231
232         evas_object_show(genlist);
233         elm_box_pack_end(box, genlist);
234         evas_object_size_hint_min_set(box, -1, 350);
235         elm_object_content_set(popup, box);
236
237         evas_object_show(popup);
238         obj->popup = popup;
239
240         elm_genlist_item_class_free(itc);
241         return 0;
242 }
243
244 static void remove_popup(const struct popup_ops *ops)
245 {
246         static bool terminating = false;
247
248         if (terminating) return;
249         terminating = true;
250
251         unload_simple_popup(ops);
252         popup_terminate();
253 }
254
255 static void pm_state_changed(keynode_t *key, void *data)
256 {
257         const struct popup_ops *ops = data;
258
259         if (!key) return;
260         if (vconf_keynode_get_int(key) != VCONFKEY_PM_STATE_LCDOFF) return;
261
262         remove_popup(ops);
263 }
264
265 static void event_back_key_up(void *data, Evas_Object *obj, void *event_info)
266 {
267         const struct popup_ops *ops = data;
268
269         if (ops) remove_popup(ops);
270         terminate_if_no_popup();
271 }
272
273 static void register_handlers(const struct popup_ops *ops)
274 {
275         Evas_Object *win;
276
277         if (vconf_notify_key_changed(
278                 VCONFKEY_PM_STATE,
279                 pm_state_changed,
280                 (void *)ops) != 0)
281                 _E("Failed to register vconf");
282
283         win = get_window();
284         if (win) eext_object_event_callback_add(win, EEXT_CALLBACK_BACK, event_back_key_up, (void*)ops);
285 }
286
287 static void unregister_handlers(const struct popup_ops *ops)
288 {
289         Evas_Object *win;
290
291         vconf_ignore_key_changed(VCONFKEY_PM_STATE, pm_state_changed);
292
293         win = get_window();
294         if (win) eext_object_event_callback_del(win, EEXT_CALLBACK_BACK, event_back_key_up);
295 }
296
297 static int powerkey_list_launch(bundle *b, const struct popup_ops *ops)
298 {
299         register_handlers(ops);
300         return 0;
301 }
302
303 static int poweroff_launch(bundle *b, const struct popup_ops *ops)
304 {
305         register_handlers(ops);
306         return 0;
307 }
308
309 static void poweroff_terminate(const struct popup_ops *ops)
310 {
311         unregister_handlers(ops);
312 }
313
314 static void powerkey_terminate(const struct popup_ops *ops)
315 {
316         unregister_handlers(ops);
317 }
318
319 static void poweroff_clicked(const struct popup_ops *ops)
320 {
321         Evas_Object *rect, *win;
322         Evas_Coord w, h, size;
323         static int bPowerOff = 0;
324         char *param[2];
325         char data[8];
326         int ret;
327
328         if (bPowerOff == 1) return;
329         bPowerOff = 1;
330
331         unload_simple_popup(ops);
332
333         win = get_window();
334         if (!win) popup_terminate();
335
336         rect = evas_object_rectangle_add(evas_object_evas_get(win));
337         evas_object_geometry_get(win, NULL, NULL, &w, &h);
338         size = max(w, h);
339         evas_object_resize(rect, size, size);
340         evas_object_color_set(rect, 0, 0, 0, 255);
341         evas_object_show(rect);
342
343         param[0] = POWER_OPERATION_OFF;
344         snprintf(data, sizeof(data), "0");
345         param[1] = data;
346         ret = popup_dbus_method_sync(DEVICED_BUS_NAME,
347                         POWER_OBJECT_PATH,
348                         POWER_INTERFACE_NAME,
349                         POWER_METHOD,
350                         "si", param);
351         if (ret < 0) _E("Failed to request poweroff to deviced (%d)", ret);
352 }
353
354 static const struct popup_ops restart_ops = {
355         .name                           = "restart",
356         .show                           = load_simple_popup,
357         .title                          = "IDS_COM_SK_RESTART_ABB",
358         .content                        = "IDS_ST_POP_DEVICE_WILL_RESTART",
359         .left_text                      = "IDS_COM_SK_CANCEL",
360         .right_text                     = "IDS_IDLE_BUTTON_RESTART_ABB3",
361         .right                          = restart_clicked,
362         .pre                            = restart_launch,
363         .terminate                      = restart_terminate,
364 };
365
366 static const struct popup_ops poweroff_ops = {
367         .name           = "poweroff",
368         .show           = load_simple_popup,
369         .title          = "IDS_ST_BODY_POWER_OFF",
370         .content        = "IDS_TPLATFORM_BODY_POWER_OFF_THE_DEVICE_Q",
371         .left_text      = "IDS_COM_SK_CANCEL",
372         .right_text     = "IDS_HS_BUTTON_POWER_OFF_ABB2",
373         .right          = poweroff_clicked,
374         .pre            = poweroff_launch,
375         .terminate      = poweroff_terminate,
376 };
377
378 static const struct popup_ops powerkey_ops = {
379         .name           = "powerkey",
380         .show           = powerkey_list,
381         .pre            = powerkey_list_launch,
382         .terminate      = powerkey_terminate,
383 };
384
385 static __attribute__ ((constructor)) void powerkey_register_popup(void)
386 {
387         register_popup(&powerkey_ops);
388         register_popup(&poweroff_ops);
389         register_popup(&restart_ops);
390 }