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