Upload Tizen2.0 source
[framework/appfw/app-core.git] / src / appcore-rotation.c
1 /*
2  *  app-core
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22
23 #include <errno.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26
27 #include <sensor.h>
28 #include <vconf.h>
29 #include <Ecore_X.h>
30 #include <Ecore.h>
31 #include <X11/Xlib.h>
32
33 #include "appcore-internal.h"
34
35 #define _MAKE_ATOM(a, s)                              \
36    do {                                               \
37         a = ecore_x_atom_get(s);                      \
38         if (!a)                                       \
39           _ERR("##s creation failed.\n");             \
40    } while(0)
41
42 #define STR_ATOM_ROTATION_LOCK                "_E_ROTATION_LOCK"
43
44 static Ecore_X_Atom ATOM_ROTATION_LOCK = 0;
45 static Ecore_X_Window root;
46
47 struct rot_s {
48         int handle;
49         int (*callback) (enum appcore_rm, void *);
50         enum appcore_rm mode;
51         int lock;
52         void *cbdata;
53         int cb_set;
54         int sf_started;
55 };
56 static struct rot_s rot;
57
58 struct rot_evt {
59         enum accelerometer_rotate_state re;
60         enum appcore_rm rm;
61 };
62
63 static struct rot_evt re_to_rm[] = {
64         {
65          ROTATION_EVENT_0,
66           APPCORE_RM_PORTRAIT_NORMAL,
67         },
68         {
69          ROTATION_EVENT_90,
70          APPCORE_RM_LANDSCAPE_NORMAL,
71         },
72         {
73          ROTATION_EVENT_180,
74          APPCORE_RM_PORTRAIT_REVERSE,
75         },
76         {
77          ROTATION_EVENT_270,
78          APPCORE_RM_LANDSCAPE_REVERSE,
79         },
80 };
81
82 static enum appcore_rm changed_m;
83 static void *changed_data;
84 static Ecore_Event_Handler *changed_handle;
85
86 static enum appcore_rm __get_mode(int event_data)
87 {
88         int i;
89         enum appcore_rm m;
90
91         m = APPCORE_RM_UNKNOWN;
92
93         for (i = 0; i < sizeof(re_to_rm) / sizeof(re_to_rm[0]); i++) {
94                 if (re_to_rm[i].re == event_data) {
95                         m = re_to_rm[i].rm;
96                         break;
97                 }
98         }
99
100         return m;
101 }
102
103 static Eina_Bool __property(void *data, int type, void *event)
104 {
105         Ecore_X_Event_Window_Property *ev = event;
106
107         if (!ev)
108                 return ECORE_CALLBACK_PASS_ON;
109
110         if (ev->atom == ATOM_ROTATION_LOCK) {
111                 _DBG("[APP %d] Rotation: %d -> %d, cb_set : %d", getpid(), rot.mode, changed_m, rot.cb_set);
112                 if (rot.cb_set && rot.mode != changed_m) {
113                         rot.callback(changed_m, changed_data);
114                         rot.mode = changed_m;
115                 }
116
117                 ecore_event_handler_del(changed_handle);
118                 changed_handle = NULL;
119         }
120
121         return ECORE_CALLBACK_PASS_ON;
122 }
123
124 static void __changed_cb(unsigned int event_type, sensor_event_data_t *event,
125                        void *data)
126 {
127         int *cb_event_data;
128         enum appcore_rm m;
129         int ret;
130         int val;
131
132         if (rot.lock)
133                 return;
134
135         if (event_type != ACCELEROMETER_EVENT_ROTATION_CHECK) {
136                 errno = EINVAL;
137                 return;
138         }
139
140         cb_event_data = (int *)(event->event_data);
141
142         m = __get_mode(*cb_event_data);
143
144         _DBG("[APP %d] Rotation: %d -> %d", getpid(), rot.mode, m);
145
146         if (rot.callback) {
147                 if (rot.cb_set && rot.mode != m) {
148                         ret = ecore_x_window_prop_card32_get(root, ATOM_ROTATION_LOCK, &val, 1);
149
150                         _DBG("[APP %d] Rotation: %d -> %d, val : %d, ret : %d", getpid(), rot.mode, m, val, ret);
151                         if (!val || ret < 1) {
152                                 rot.callback(m, data);
153                                 rot.mode = m;
154                         } else {
155                                 changed_data = data;
156                                 if(changed_handle) {
157                                          ecore_event_handler_del(changed_handle);
158                                          changed_handle = NULL;
159                                 }
160                                 changed_handle = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, __property, NULL);
161                         }
162                 }
163                 changed_m = m;
164         }
165 }
166
167 static void __lock_cb(keynode_t *node, void *data)
168 {
169         int r;
170         enum appcore_rm m;
171         int ret;
172         int val;
173
174         rot.lock = vconf_keynode_get_bool(node);
175
176         if (rot.lock) {
177                 _DBG("[APP %d] Rotation locked", getpid());
178                 return;
179         }
180
181         _DBG("[APP %d] Rotation unlocked", getpid());
182         if (rot.callback) {
183                 if (rot.cb_set) {
184                         r = appcore_get_rotation_state(&m);
185                         _DBG("[APP %d] Rotmode prev %d -> curr %d", getpid(),
186                              rot.mode, m);
187                         if (!r && rot.mode != m) {
188                                 if(!val) {
189                                         rot.callback(m, data);
190                                         rot.mode = m;
191                                 } else {
192                                         changed_data = data;
193                                         if(changed_handle) {
194                                                  ecore_event_handler_del(changed_handle);
195                                                  changed_handle = NULL;
196                                         }
197                                         changed_handle = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, __property, NULL);
198                                 }
199                         }
200
201                         if(!r)
202                                 changed_m = m;
203                 }
204         }
205 }
206
207 static void __add_rotlock(void *data)
208 {
209         int r;
210         int lock;
211
212         lock = 0;
213         r = vconf_get_bool(VCONFKEY_SETAPPL_ROTATE_LOCK_BOOL, &lock);
214         if (r) {
215                 _DBG("[APP %d] Rotation vconf get bool failed", getpid());
216         }
217
218         rot.lock = lock;
219
220         vconf_notify_key_changed(VCONFKEY_SETAPPL_ROTATE_LOCK_BOOL, __lock_cb,
221                                  data);
222 }
223
224 static void __del_rotlock(void)
225 {
226         vconf_ignore_key_changed(VCONFKEY_SETAPPL_ROTATE_LOCK_BOOL, __lock_cb);
227         rot.lock = 0;
228 }
229
230 EXPORT_API int appcore_set_rotation_cb(int (*cb) (enum appcore_rm, void *),
231                                        void *data)
232 {
233         int r;
234         int handle;
235
236         if (cb == NULL) {
237                 errno = EINVAL;
238                 return -1;
239         }
240
241         if (rot.callback != NULL) {
242                 errno = EALREADY;
243                 return -1;
244         }
245
246         handle = sf_connect(ACCELEROMETER_SENSOR);
247         if (handle < 0) {
248                 _ERR("sf_connect failed: %d", handle);
249                 return -1;
250         }
251
252         r = sf_register_event(handle, ACCELEROMETER_EVENT_ROTATION_CHECK,
253                               NULL, __changed_cb, data);
254         if (r < 0) {
255                 _ERR("sf_register_event failed: %d", r);
256                 sf_disconnect(handle);
257                 return -1;
258         }
259
260         rot.cb_set = 1;
261         rot.callback = cb;
262         rot.cbdata = data;
263
264         r = sf_start(handle, 0);
265         if (r < 0) {
266                 _ERR("sf_start failed: %d", r);
267                 sf_unregister_event(handle, ACCELEROMETER_EVENT_ROTATION_CHECK);
268                 rot.callback = NULL;
269                 rot.cbdata = NULL;
270                 rot.cb_set = 0;
271                 rot.sf_started = 0;
272                 sf_disconnect(handle);
273                 return -1;
274         }
275         rot.sf_started = 1;
276
277         rot.handle = handle;
278         __add_rotlock(data);
279
280         _MAKE_ATOM(ATOM_ROTATION_LOCK, STR_ATOM_ROTATION_LOCK );
281         root =  ecore_x_window_root_first_get();
282         XSelectInput(ecore_x_display_get(), root, PropertyChangeMask);
283
284         return 0;
285 }
286
287 EXPORT_API int appcore_unset_rotation_cb(void)
288 {
289         int r;
290
291         _retv_if(rot.callback == NULL, 0);
292
293         __del_rotlock();
294
295         if (rot.cb_set) {
296                 r = sf_unregister_event(rot.handle,
297                                         ACCELEROMETER_EVENT_ROTATION_CHECK);
298                 if (r < 0) {
299                         _ERR("sf_unregister_event failed: %d", r);
300                         return -1;
301                 }
302                 rot.cb_set = 0;
303         }
304         rot.callback = NULL;
305         rot.cbdata = NULL;
306
307         if (rot.sf_started == 1) {
308                 r = sf_stop(rot.handle);
309                 if (r < 0) {
310                         _ERR("sf_stop failed: %d", r);
311                         return -1;
312                 }
313                 rot.sf_started = 0;
314         }
315
316         r = sf_disconnect(rot.handle);
317         if (r < 0) {
318                 _ERR("sf_disconnect failed: %d", r);
319                 return -1;
320         }
321         rot.handle = -1;
322
323         return 0;
324 }
325
326 EXPORT_API int appcore_get_rotation_state(enum appcore_rm *curr)
327 {
328         int r;
329         unsigned long event;
330
331         if (curr == NULL) {
332                 errno = EINVAL;
333                 return -1;
334         }
335
336         r = sf_check_rotation(&event);
337         if (r < 0) {
338                 _ERR("sf_check_rotation failed: %d", r);
339                 *curr = APPCORE_RM_UNKNOWN;
340                 return -1;
341         }
342
343         *curr = __get_mode(event);
344
345         return 0;
346 }
347
348 EXPORT_API int appcore_pause_rotation_cb(void)
349 {
350         int r;
351
352         _retv_if(rot.callback == NULL, 0);
353         _DBG("[APP %d] appcore_pause_rotation_cb is called", getpid());
354
355         __del_rotlock();
356
357         if (rot.cb_set) {
358                 r = sf_unregister_event(rot.handle,
359                                         ACCELEROMETER_EVENT_ROTATION_CHECK);
360                 if (r < 0) {
361                         _ERR("sf_unregister_event in appcore_internal_sf_stop failed: %d", r);
362                         return -1;
363                 }
364                 rot.cb_set = 0;
365         }
366
367         if (rot.sf_started == 1) {
368                 r = sf_stop(rot.handle);
369                 if (r < 0) {
370                         _ERR("sf_stop in appcore_internal_sf_stop failed: %d",
371                              r);
372                         return -1;
373                 }
374                 rot.sf_started = 0;
375         }
376
377         return 0;
378 }
379
380 EXPORT_API int appcore_resume_rotation_cb(void)
381 {
382         int r;
383         enum appcore_rm m;
384
385         _retv_if(rot.callback == NULL, 0);
386         _DBG("[APP %d] appcore_resume_rotation_cb is called", getpid());
387
388         if (rot.cb_set == 0) {
389                 r = sf_register_event(rot.handle,
390                                       ACCELEROMETER_EVENT_ROTATION_CHECK, NULL,
391                                       __changed_cb, rot.cbdata);
392                 if (r < 0) {
393                         _ERR("sf_register_event in appcore_internal_sf_start failed: %d", r);
394                         return -1;
395                 }
396                 rot.cb_set = 1;
397         }
398
399         if (rot.sf_started == 0) {
400                 r = sf_start(rot.handle, 0);
401                 if (r < 0) {
402                         _ERR("sf_start in appcore_internal_sf_start failed: %d",
403                              r);
404                         sf_unregister_event(rot.handle,
405                                             ACCELEROMETER_EVENT_ROTATION_CHECK);
406                         rot.cb_set = 0;
407                         return -1;
408                 }
409                 rot.sf_started = 1;
410         }
411
412         __add_rotlock(rot.cbdata);
413
414         r = appcore_get_rotation_state(&m);
415         _DBG("[APP %d] Rotmode prev %d -> curr %d", getpid(), rot.mode, m);
416         if (!r && rot.mode != m && rot.lock == 0) {
417                 rot.callback(m, rot.cbdata);
418                 rot.mode = m;
419         }
420
421         return 0;
422 }