Include sensor_internal.h instead of sensor.h
[platform/core/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.h>
28 #include <vconf.h>
29 #include <Ecore.h>
30 #include "appcore-internal.h"
31
32 #ifdef X11
33 #include <Ecore_X.h>
34 #include <X11/Xlib.h>
35
36 /*Fixme: to be added for wayland works*/
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
46 static Ecore_X_Atom ATOM_ROTATION_LOCK = 0;
47 static Ecore_X_Window root;
48 #endif
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         enum accelerometer_rotate_state re;
65         enum appcore_rm rm;
66 };
67
68 static struct rot_evt re_to_rm[] = {
69         {
70          ROTATION_EVENT_0,
71           APPCORE_RM_PORTRAIT_NORMAL,
72         },
73         {
74          ROTATION_EVENT_90,
75          APPCORE_RM_LANDSCAPE_NORMAL,
76         },
77         {
78          ROTATION_EVENT_180,
79          APPCORE_RM_PORTRAIT_REVERSE,
80         },
81         {
82          ROTATION_EVENT_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 != ACCELEROMETER_EVENT_ROTATION_CHECK) {
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
125         if (rot.callback) {
126                 if (rot.cb_set && rot.mode != m) {
127                         _DBG("[APP %d] Rotation: %d -> %d", getpid(), rot.mode, m);
128                         rot.callback((void *)&m, m, data);
129                         rot.mode = m;
130                 }
131         }
132 }
133
134 static void __lock_cb(keynode_t *node, void *data)
135 {
136         int r;
137         enum appcore_rm m;
138         int ret;
139
140         rot.lock = !vconf_keynode_get_bool(node);
141
142         if (rot.lock) {
143                 m = APPCORE_RM_PORTRAIT_NORMAL;
144                 if (rot.mode != m) {
145                         rot.callback((void *)&m, m, data);
146                         rot.mode = m;
147                 }
148                 _DBG("[APP %d] Rotation locked", getpid());
149                 return;
150         }
151
152         _DBG("[APP %d] Rotation unlocked", getpid());
153         if (rot.callback) {
154                 if (rot.cb_set) {
155                         r = appcore_get_rotation_state(&m);
156                         _DBG("[APP %d] Rotmode prev %d -> curr %d", getpid(),
157                              rot.mode, m);
158                         if (!r && rot.mode != m) {
159                                 rot.callback((void *)&m, m, data);
160                                 rot.mode = m;
161                         }
162                 }
163         }
164 }
165
166 static void __add_rotlock(void *data)
167 {
168         int r;
169         int lock;
170
171         lock = 0;
172         r = vconf_get_bool(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, &lock);
173         if (r) {
174                 _DBG("[APP %d] Rotation vconf get bool failed", getpid());
175         }
176
177         rot.lock = !lock;
178
179         vconf_notify_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, __lock_cb,
180                                  data);
181 }
182
183 static void __del_rotlock(void)
184 {
185         vconf_ignore_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, __lock_cb);
186         rot.lock = 0;
187 }
188
189 EXPORT_API int appcore_set_rotation_cb(int (*cb) (void *evnet_info, enum appcore_rm, void *),
190                                        void *data)
191 {
192         if (rot.wm_rotate) {
193                 return rot.wm_rotate->set_rotation_cb(cb, data);
194         }
195         else {
196                 int r;
197                 int handle;
198
199                 if (cb == NULL) {
200                         errno = EINVAL;
201                         return -1;
202                 }
203
204                 if (rot.callback != NULL) {
205                         errno = EALREADY;
206                         return -1;
207                 }
208
209                 handle = sf_connect(ACCELEROMETER_SENSOR);
210                 if (handle < 0) {
211                         _ERR("sf_connect failed: %d", handle);
212                         return -1;
213                 }
214
215                 r = sf_register_event(handle, ACCELEROMETER_EVENT_ROTATION_CHECK,
216                                       NULL, __changed_cb, data);
217                 if (r < 0) {
218                         _ERR("sf_register_event failed: %d", r);
219                         sf_disconnect(handle);
220                         return -1;
221                 }
222
223                 rot.cb_set = 1;
224                 rot.callback = cb;
225                 rot.cbdata = data;
226
227                 r = sf_start(handle, 0);
228                 if (r < 0) {
229                         _ERR("sf_start failed: %d", r);
230                         r = sf_unregister_event(handle, ACCELEROMETER_EVENT_ROTATION_CHECK);
231                         if (r < 0) {
232                                 _ERR("sf_unregister_event failed: %d", r);
233                         }
234                         rot.callback = NULL;
235                         rot.cbdata = NULL;
236                         rot.cb_set = 0;
237                         rot.sf_started = 0;
238                         sf_disconnect(handle);
239                         return -1;
240                 }
241                 rot.sf_started = 1;
242
243                 rot.handle = handle;
244                 __add_rotlock(data);
245
246 #ifdef X11
247                 _MAKE_ATOM(ATOM_ROTATION_LOCK, STR_ATOM_ROTATION_LOCK );
248                 root =  ecore_x_window_root_first_get();
249                 XSelectInput(ecore_x_display_get(), root, PropertyChangeMask);
250 #endif
251         }
252         return 0;
253 }
254
255 EXPORT_API int appcore_unset_rotation_cb(void)
256 {
257         if (rot.wm_rotate) {
258                 return rot.wm_rotate->unset_rotation_cb();
259         }
260         else {
261                 int r;
262
263                 _retv_if(rot.callback == NULL, 0);
264
265                 __del_rotlock();
266
267                 if (rot.cb_set) {
268                         r = sf_unregister_event(rot.handle,
269                                                 ACCELEROMETER_EVENT_ROTATION_CHECK);
270                         if (r < 0) {
271                                 _ERR("sf_unregister_event failed: %d", r);
272                                 return -1;
273                         }
274                         rot.cb_set = 0;
275                 }
276                 rot.callback = NULL;
277                 rot.cbdata = NULL;
278
279                 if (rot.sf_started == 1) {
280                         r = sf_stop(rot.handle);
281                         if (r < 0) {
282                                 _ERR("sf_stop failed: %d", r);
283                                 return -1;
284                         }
285                         rot.sf_started = 0;
286                 }
287
288                 r = sf_disconnect(rot.handle);
289                 if (r < 0) {
290                         _ERR("sf_disconnect failed: %d", r);
291                         return -1;
292                 }
293                 rot.handle = -1;
294         }
295         return 0;
296 }
297
298 EXPORT_API int appcore_get_rotation_state(enum appcore_rm *curr)
299 {
300         if (rot.wm_rotate) {
301                 return rot.wm_rotate->get_rotation_state(curr);
302         }
303         else {
304                 int r;
305                 unsigned long event;
306
307                 if (curr == NULL) {
308                         errno = EINVAL;
309                         return -1;
310                 }
311
312                 r = sf_check_rotation(&event);
313                 if (r < 0) {
314                         _ERR("sf_check_rotation failed: %d", r);
315                         *curr = APPCORE_RM_UNKNOWN;
316                         return -1;
317                 }
318
319                 *curr = __get_mode(event);
320         }
321         return 0;
322 }
323
324 EXPORT_API int appcore_pause_rotation_cb(void)
325 {
326         if (rot.wm_rotate) {
327                 return rot.wm_rotate->pause_rotation_cb();
328         }
329         else {
330                 int r;
331
332                 _retv_if(rot.callback == NULL, 0);
333                 _DBG("[APP %d] appcore_pause_rotation_cb is called", getpid());
334
335                 __del_rotlock();
336
337                 if (rot.cb_set) {
338                         r = sf_unregister_event(rot.handle,
339                                                 ACCELEROMETER_EVENT_ROTATION_CHECK);
340                         if (r < 0) {
341                                 _ERR("sf_unregister_event in appcore_internal_sf_stop failed: %d", r);
342                                 return -1;
343                         }
344                         rot.cb_set = 0;
345                 }
346
347                 if (rot.sf_started == 1) {
348                         r = sf_stop(rot.handle);
349                         if (r < 0) {
350                                 _ERR("sf_stop in appcore_internal_sf_stop failed: %d",
351                                      r);
352                                 return -1;
353                         }
354                         rot.sf_started = 0;
355                 }
356         }
357
358         return 0;
359 }
360
361 EXPORT_API int appcore_resume_rotation_cb(void)
362 {
363         if (rot.wm_rotate) {
364                 return rot.wm_rotate->resume_rotation_cb();
365         }
366         else {
367                 int r,ret;
368                 enum appcore_rm m;
369
370                 _retv_if(rot.callback == NULL, 0);
371                 _DBG("[APP %d] appcore_resume_rotation_cb is called", getpid());
372
373                 if (rot.cb_set == 0) {
374                         r = sf_register_event(rot.handle,
375                                               ACCELEROMETER_EVENT_ROTATION_CHECK, NULL,
376                                               __changed_cb, rot.cbdata);
377                         if (r < 0) {
378                                 _ERR("sf_register_event in appcore_internal_sf_start failed: %d", r);
379                                 return -1;
380                         }
381                         rot.cb_set = 1;
382                 }
383
384                 if (rot.sf_started == 0) {
385                         r = sf_start(rot.handle, 0);
386                         if (r < 0) {
387                                 _ERR("sf_start in appcore_internal_sf_start failed: %d",
388                                      r);
389                                 ret = sf_unregister_event(rot.handle,
390                                                     ACCELEROMETER_EVENT_ROTATION_CHECK);
391                                 if (ret < 0)
392                                         _ERR("sf_unregister_event failed: %d", ret);
393                                 rot.cb_set = 0;
394                                 return -1;
395                         }
396                         rot.sf_started = 1;
397                 }
398
399                 __add_rotlock(rot.cbdata);
400
401                 r = appcore_get_rotation_state(&m);
402                 _DBG("[APP %d] Rotmode prev %d -> curr %d", getpid(), rot.mode, m);
403                 if (!r && rot.mode != m && rot.lock == 0) {
404                         rot.callback((void *)&m, m, rot.cbdata);
405                         rot.mode = m;
406                 }
407         }
408         return 0;
409 }
410
411 EXPORT_API int appcore_set_wm_rotation(struct ui_wm_rotate* wm_rotate)
412 {
413         if (!wm_rotate) return -1;
414
415         if (rot.callback) {
416                 wm_rotate->set_rotation_cb(rot.callback, rot.cbdata);
417                 appcore_unset_rotation_cb();
418         }
419         rot.wm_rotate = wm_rotate;
420         _DBG("[APP %d] Support wm rotate:%p", getpid(), wm_rotate);
421         return 0;
422 }