tizen 2.3 release
[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_internal_deprecated.h>
28 //#include <sensor_auto_rotation.h>
29
30 #include <vconf.h>
31 #include <Ecore_X.h>
32 #include <Ecore.h>
33 #include <X11/Xlib.h>
34
35 #include "appcore-internal.h"
36
37 #define _MAKE_ATOM(a, s)                              \
38    do {                                               \
39         a = ecore_x_atom_get(s);                      \
40         if (!a)                                       \
41           _ERR("##s creation failed.\n");             \
42    } while(0)
43
44 #define STR_ATOM_ROTATION_LOCK                "_E_ROTATION_LOCK"
45 #define MAX_LOCAL_BUFSZ 128
46
47 static Ecore_X_Atom ATOM_ROTATION_LOCK = 0;
48 static Ecore_X_Window root;
49
50 struct rot_s {
51         int handle;
52         int (*callback) (void *event_info, enum appcore_rm, void *);
53         enum appcore_rm mode;
54         int lock;
55         void *cbdata;
56         int cb_set;
57         int sf_started;
58
59         struct ui_wm_rotate* wm_rotate;
60 };
61 static struct rot_s rot;
62
63 struct rot_evt {
64         int re;
65         enum appcore_rm rm;
66 };
67
68 static struct rot_evt re_to_rm[] = {
69         {
70                 AUTO_ROTATION_DEGREE_0,
71                 APPCORE_RM_PORTRAIT_NORMAL,
72         },
73         {
74                 AUTO_ROTATION_DEGREE_90,
75                 APPCORE_RM_LANDSCAPE_NORMAL,
76         },
77         {
78                 AUTO_ROTATION_DEGREE_180,
79                 APPCORE_RM_PORTRAIT_REVERSE,
80         },
81         {
82                 AUTO_ROTATION_DEGREE_270,
83                 APPCORE_RM_LANDSCAPE_REVERSE,
84         },
85 };
86
87 static enum appcore_rm __get_mode(int event_data)
88 {
89         int i;
90         enum appcore_rm m;
91
92         m = APPCORE_RM_UNKNOWN;
93
94         for (i = 0; i < sizeof(re_to_rm) / sizeof(re_to_rm[0]); i++) {
95                 if (re_to_rm[i].re == event_data) {
96                         m = re_to_rm[i].rm;
97                         break;
98                 }
99         }
100
101         return m;
102 }
103
104 static void __changed_cb(unsigned int event_type, sensor_event_data_t *event,
105                        void *data)
106 {
107         int *cb_event_data;
108         enum appcore_rm m;
109         int ret;
110
111         if (rot.lock)
112                 return;
113
114         if (event_type != AUTO_ROTATION_EVENT_CHANGE_STATE) {
115                 errno = EINVAL;
116                 return;
117         }
118
119         cb_event_data = (int *)(event->event_data);
120
121         m = __get_mode(*cb_event_data);
122
123         _DBG("[APP %d] Rotation: %d -> %d", getpid(), rot.mode, m);
124         if (rot.callback) {
125                 if (rot.cb_set && rot.mode != m) {
126                         _DBG("[APP %d] Rotation: %d -> %d", getpid(), rot.mode, m);
127                         rot.callback((void *)&m, m, data);
128                         rot.mode = m;
129                 }
130         }
131
132 }
133
134 static void __lock_cb(keynode_t *node, void *data)
135 {
136         int r;
137         enum appcore_rm m;
138
139         rot.lock = !vconf_keynode_get_bool(node);
140
141         if (rot.lock) {
142                 m = APPCORE_RM_PORTRAIT_NORMAL;
143                 if (rot.mode != m) {
144                         rot.callback((void *)&m, m, data);
145                         rot.mode = m;
146                 }
147                 _DBG("[APP %d] Rotation locked", getpid());
148                 return;
149         }
150
151         _DBG("[APP %d] Rotation unlocked", getpid());
152         if (rot.callback) {
153                 if (rot.cb_set) {
154                         r = appcore_get_rotation_state(&m);
155                         _DBG("[APP %d] Rotmode prev %d -> curr %d", getpid(),
156                              rot.mode, m);
157                         if (!r && rot.mode != m) {
158                                 rot.callback((void *)&m, m, data);
159                                 rot.mode = m;
160                         }
161                 }
162         }
163 }
164
165 static void __add_rotlock(void *data)
166 {
167         int r;
168         int lock;
169
170         lock = 0;
171         r = vconf_get_bool(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, &lock);
172         if (r) {
173                 _DBG("[APP %d] Rotation vconf get bool failed", getpid());
174         }
175
176         rot.lock = !lock;
177
178         vconf_notify_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, __lock_cb,
179                                  data);
180 }
181
182 static void __del_rotlock(void)
183 {
184         vconf_ignore_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, __lock_cb);
185         rot.lock = 0;
186 }
187
188 EXPORT_API int appcore_set_rotation_cb(int (*cb) (void *event_info, enum appcore_rm, void *),
189                                        void *data)
190 {
191         if (rot.wm_rotate) {
192                 return rot.wm_rotate->set_rotation_cb(cb, data);
193         } else {
194                 int r;
195                 int handle;
196
197                 if (cb == NULL) {
198                         errno = EINVAL;
199                         return -1;
200                 }
201
202                 if (rot.callback != NULL) {
203                         errno = EALREADY;
204                         return -1;
205                 }
206
207                 handle = sf_connect(AUTO_ROTATION_SENSOR);
208                 if (handle < 0) {
209                         _ERR("sf_connect failed: %d", handle);
210                         return -1;
211                 }
212
213                 r = sf_register_event(handle, AUTO_ROTATION_EVENT_CHANGE_STATE,
214                                       NULL, __changed_cb, data);
215                 if (r < 0) {
216                         _ERR("sf_register_event failed: %d", r);
217                         sf_disconnect(handle);
218                         return -1;
219                 }
220
221                 rot.cb_set = 1;
222                 rot.callback = cb;
223                 rot.cbdata = data;
224
225                 r = sf_start(handle, 0);
226                 if (r < 0) {
227                         _ERR("sf_start failed: %d", r);
228                         r = sf_unregister_event(handle, AUTO_ROTATION_EVENT_CHANGE_STATE);
229                         if (r < 0) {
230                                 _ERR("sf_unregister_event failed: %d", r);
231                         }
232                         rot.callback = NULL;
233                         rot.cbdata = NULL;
234                         rot.cb_set = 0;
235                         rot.sf_started = 0;
236                         sf_disconnect(handle);
237                         return -1;
238                 }
239                 rot.sf_started = 1;
240
241                 rot.handle = handle;
242                 __add_rotlock(data);
243
244                 _MAKE_ATOM(ATOM_ROTATION_LOCK, STR_ATOM_ROTATION_LOCK );
245                 root =  ecore_x_window_root_first_get();
246                 XSelectInput(ecore_x_display_get(), root, PropertyChangeMask);
247         }
248         return 0;
249 }
250
251 EXPORT_API int appcore_unset_rotation_cb(void)
252 {
253         if (rot.wm_rotate) {
254                 return rot.wm_rotate->unset_rotation_cb();
255         }
256         else {
257                 int r;
258
259                 _retv_if(rot.callback == NULL, 0);
260
261                 __del_rotlock();
262
263                 if (rot.cb_set) {
264                         r = sf_unregister_event(rot.handle,
265                                                 AUTO_ROTATION_EVENT_CHANGE_STATE);
266                         if (r < 0) {
267                                 _ERR("sf_unregister_event failed: %d", r);
268                                 return -1;
269                         }
270                         rot.cb_set = 0;
271                 }
272                 rot.callback = NULL;
273                 rot.cbdata = NULL;
274
275                 if (rot.sf_started == 1) {
276                         r = sf_stop(rot.handle);
277                         if (r < 0) {
278                                 _ERR("sf_stop failed: %d", r);
279                                 return -1;
280                         }
281                         rot.sf_started = 0;
282                 }
283
284                 r = sf_disconnect(rot.handle);
285                 if (r < 0) {
286                         _ERR("sf_disconnect failed: %d", r);
287                         return -1;
288                 }
289                 rot.handle = -1;
290         }
291         return 0;
292 }
293
294 EXPORT_API int appcore_get_rotation_state(enum appcore_rm *curr)
295 {
296         if (rot.wm_rotate) {
297                 return rot.wm_rotate->get_rotation_state(curr);
298         }
299         else {
300                 int r;
301                 unsigned long event;
302                 sensor_data_t data;
303
304                 if (curr == NULL) {
305                         errno = EINVAL;
306                         return -1;
307                 }
308
309                 r = sf_get_data(rot.handle, AUTO_ROTATION_BASE_DATA_SET, &data);
310                 if (r == 1 && data.value_count > 0) {
311                         event = data.values[0];
312                 } else {
313                         _ERR("sf_get_data for AUTO_ROTATION_BASE_DATA_SET failed: %d", r);
314                         *curr = APPCORE_RM_UNKNOWN;
315                         return -1;
316                 }
317
318                 *curr = __get_mode(event);
319         }
320         return 0;
321 }
322
323 EXPORT_API int appcore_pause_rotation_cb(void)
324 {
325         if (rot.wm_rotate) {
326                 return rot.wm_rotate->pause_rotation_cb();
327         }
328         else {
329                 int r;
330
331                 _retv_if(rot.callback == NULL, 0);
332                 _DBG("[APP %d] appcore_pause_rotation_cb is called", getpid());
333
334                 __del_rotlock();
335
336                 if (rot.cb_set) {
337                         r = sf_unregister_event(rot.handle,
338                                                 AUTO_ROTATION_EVENT_CHANGE_STATE);
339                         if (r < 0) {
340                                 _ERR("sf_unregister_event in appcore_internal_sf_stop failed: %d", r);
341                                 return -1;
342                         }
343                         rot.cb_set = 0;
344                 }
345
346                 if (rot.sf_started == 1) {
347                         r = sf_stop(rot.handle);
348                         if (r < 0) {
349                                 _ERR("sf_stop in appcore_internal_sf_stop failed: %d",
350                                      r);
351                                 return -1;
352                         }
353                         rot.sf_started = 0;
354                 }
355         }
356
357         return 0;
358 }
359
360 EXPORT_API int appcore_resume_rotation_cb(void)
361 {
362         if (rot.wm_rotate) {
363                 return rot.wm_rotate->resume_rotation_cb();
364         }
365         else {
366                 int r,ret;
367                 enum appcore_rm m;
368
369                 _retv_if(rot.callback == NULL, 0);
370                 _DBG("[APP %d] appcore_resume_rotation_cb is called", getpid());
371
372                 if (rot.cb_set == 0) {
373                         r = sf_register_event(rot.handle,
374                                               AUTO_ROTATION_EVENT_CHANGE_STATE, NULL,
375                                               __changed_cb, rot.cbdata);
376                         if (r < 0) {
377                                 _ERR("sf_register_event in appcore_internal_sf_start failed: %d", r);
378                                 return -1;
379                         }
380                         rot.cb_set = 1;
381                 }
382
383                 if (rot.sf_started == 0) {
384                         r = sf_start(rot.handle, 0);
385                         if (r < 0) {
386                                 _ERR("sf_start in appcore_internal_sf_start failed: %d",
387                                      r);
388                                 ret = sf_unregister_event(rot.handle,
389                                                     AUTO_ROTATION_EVENT_CHANGE_STATE);
390                                 if (ret < 0)
391                                         _ERR("sf_unregister_event failed: %d", ret);
392                                 rot.cb_set = 0;
393                                 return -1;
394                         }
395                         rot.sf_started = 1;
396                 }
397
398                 __add_rotlock(rot.cbdata);
399
400                 r = appcore_get_rotation_state(&m);
401                 _DBG("[APP %d] Rotmode prev %d -> curr %d", getpid(), rot.mode, m);
402                 if (!r && rot.mode != m && rot.lock == 0) {
403                         rot.callback((void *)&m, m, rot.cbdata);
404                         rot.mode = m;
405                 }
406         }
407         return 0;
408 }
409
410 EXPORT_API int appcore_set_wm_rotation(struct ui_wm_rotate* wm_rotate)
411 {
412         if (!wm_rotate) return -1;
413
414         if (rot.callback) {
415                 wm_rotate->set_rotation_cb(rot.callback, rot.cbdata);
416                 appcore_unset_rotation_cb();
417         }
418         rot.wm_rotate = wm_rotate;
419         _DBG("[APP %d] Support wm rotate:%p", getpid(), wm_rotate);
420         return 0;
421 }