e084b35c7d0a3727798d2eb22b440bbd50fbd8d3
[platform/core/uifw/libscl-core.git] / src / sclcoreui-efl.cpp
1 /*
2  * Copyright (c) 2014 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include "sclcoreui-efl.h"
19 #include "sclcoreimpl.h"
20 #include <Elementary.h>
21 #include <dlog.h>
22 #include <appcore-efl.h>
23
24 #include <vconf.h>
25 #include <vconf-keys.h>
26
27 #include <glib.h>
28 #include <malloc.h>
29 #ifdef WAYLAND
30 #define EFL_BETA_API_SUPPORT
31 #include <Ecore_Wl2.h>
32 #include <input-method-client-protocol.h>
33 #else
34 #include <Ecore_X.h>
35 #include <X11/Xlib.h>
36 #include <X11/Xatom.h>
37 #endif
38
39 #ifdef WEBSOCKET
40  /* This websocket agent is for supporting Tizen 2.X legacy web IMEs that uses websocket */
41 CWebHelperAgentWebSocket g_websocket;
42 #endif
43
44 static struct appcore_ops ops;
45
46 #ifdef WAYLAND
47 struct WaylandKeyboard
48 {
49     Ecore_Evas *ee;
50     Ecore_Wl2_Window *wl_win;
51
52     struct wl_surface *surface;
53     struct wl_input_panel *ip;
54     struct wl_output *output;
55     struct wl_input_panel_surface *ips;
56 };
57
58 struct WaylandKeyboard wlkb = {0};
59
60 #define RENDER_PRE_TIMEOUT 1.0f
61 static Ecore_Timer *_render_pre_timer = NULL;
62 static void delete_render_pre_timer()
63 {
64     if (_render_pre_timer) {
65         ecore_timer_del(_render_pre_timer);
66         _render_pre_timer = NULL;
67     }
68 }
69 #endif
70
71 using namespace scl;
72
73 CSCLCoreUIEFL::CSCLCoreUIEFL()
74 {
75     m_initialized = FALSE;
76
77     m_backend_identifier = "EFL";
78
79     m_rotation_degree = 0;
80     m_main_window = SCLWINDOW_INVALID;
81     m_appid = NULL;
82     m_display = NULL;
83
84     memset(m_option_window_info, 0x00, sizeof(m_option_window_info));
85 }
86
87 CSCLCoreUIEFL::~CSCLCoreUIEFL()
88 {
89 }
90
91 sclboolean CSCLCoreUIEFL::init()
92 {
93     m_initialized = TRUE;
94     m_rotation_degree = -1;
95
96     for (int loop = 0;loop < OPTION_WINDOW_TYPE_MAX;loop++) {
97         m_option_window_info[loop].window = SCLWINDOW_INVALID;
98     }
99
100 #ifdef WEBSOCKET
101     g_websocket.init();
102 #endif
103
104     return TRUE;
105 }
106
107 void CSCLCoreUIEFL::fini()
108 {
109     m_initialized = FALSE;
110
111 #ifdef WEBSOCKET
112     g_websocket.exit();
113 #endif
114 }
115
116 sclwindow CSCLCoreUIEFL::get_main_window()
117 {
118     if (m_initialized) {
119         return m_main_window;
120     } else {
121         return NULL;
122     }
123 }
124
125 void CSCLCoreUIEFL::set_keyboard_size_hints(SclSize portrait, SclSize landscape)
126 {
127     Evas_Object *main_window = NATIVE_WINDOW_CAST(m_main_window);
128
129 #ifdef WAYLAND
130     Ecore_Wl2_Window *wl_window = (Ecore_Wl2_Window *)elm_win_wl_window_get(main_window);
131     ecore_wl2_window_rotation_geometry_set(wl_window,   0, 0, 0, portrait.width, portrait.height);
132     ecore_wl2_window_rotation_geometry_set(wl_window,  90, 0, 0, landscape.height, landscape.width);
133     ecore_wl2_window_rotation_geometry_set(wl_window, 180, 0, 0, portrait.width, portrait.height);
134     ecore_wl2_window_rotation_geometry_set(wl_window, 270, 0, 0, landscape.height, landscape.width);
135 #else
136     /*
137     ecore_x_e_window_rotation_geometry_set(elm_win_xwindow_get(main_window),   0, 0, 0, portrait.width, portrait.height);
138     ecore_x_e_window_rotation_geometry_set(elm_win_xwindow_get(main_window),  90, 0, 0, landscape.height, landscape.width);
139     ecore_x_e_window_rotation_geometry_set(elm_win_xwindow_get(main_window), 180, 0, 0, portrait.width, portrait.height);
140     ecore_x_e_window_rotation_geometry_set(elm_win_xwindow_get(main_window), 270, 0, 0, landscape.height, landscape.width);
141     */
142 #endif
143     LOGD("%d %d %d %d", portrait.width, portrait.height, landscape.width, landscape.height);
144 }
145
146 void CSCLCoreUIEFL::set_floating_mode(sclboolean floating_mode)
147 {
148     if (wlkb.ips)
149         wl_input_panel_surface_set_floating_panel(wlkb.ips, floating_mode);
150 }
151
152 void CSCLCoreUIEFL::set_floating_drag_enabled(sclboolean enabled)
153 {
154     if (wlkb.ips)
155         wl_input_panel_surface_set_floating_drag_enabled(wlkb.ips, enabled);
156 }
157
158 static int language_changed_cb(void *event_info, void* data)
159 {
160     char clang[_POSIX_PATH_MAX] = {0};
161     char *vconf_str = vconf_get_str(VCONFKEY_LANGSET);
162     if (vconf_str) {
163         snprintf(clang, sizeof(clang), "%s", vconf_str);
164         free(vconf_str);
165     }
166     LOGD("current language is %s\n", clang);
167
168     setenv("LC_ALL", clang, 1);
169     char *r = setlocale(LC_ALL, "");
170     if (r == NULL) {
171         setlocale(LC_ALL, "en_US.UTF-8");
172     }
173
174     CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
175     if (impl) {
176         ISCLCoreEventCallback *callback = impl->get_core_event_callback();
177         if (callback) {
178             callback->on_set_display_language(clang);
179         }
180     }
181
182     return 0;
183 }
184
185 static void accessibility_changed_cb(keynode_t *key, void* data)
186 {
187     int vconf_value = 0;
188     if (vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, &vconf_value) == 0) {
189         LOGD("accessibility state : %d\n", vconf_value);
190
191         CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
192         if (impl) {
193             ISCLCoreEventCallback *callback = impl->get_core_event_callback();
194             if (callback) {
195                 callback->on_set_accessibility_state(vconf_value);
196             }
197         }
198     }
199 }
200
201 #ifdef WAYLAND
202 static void win_rotation_changed_cb(void *data, Evas_Object *obj, void *event)
203 {
204     int degree = elm_win_rotation_get(obj);
205     LOGD("rotation angle : %d\n", degree);
206
207     ISCLCoreEventCallback *callback = NULL;
208     CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
209     if (impl) {
210         callback = impl->get_core_event_callback();
211     }
212
213     CSCLCoreUIEFL *coreui = static_cast<CSCLCoreUIEFL*>(data);
214     if (coreui) {
215         coreui->set_screen_rotation_degree(degree);
216     }
217     if (callback) {
218         callback->on_set_rotation_degree(degree);
219     }
220 }
221 #else
222 static Eina_Bool _client_message_cb(void *data, int type, void *event)
223 {
224     Ecore_X_Event_Client_Message *ev = (Ecore_X_Event_Client_Message *)event;
225
226     ISCLCoreEventCallback *callback = NULL;
227     CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
228     Evas_Object *main_window = NULL;
229     if (impl) {
230         callback = impl->get_core_event_callback();
231         main_window = NATIVE_WINDOW_CAST(impl->get_main_window());
232     }
233
234 #ifndef APPLY_WINDOW_MANAGER_CHANGE
235 #else
236     if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE) {
237         LOGD("ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE , %d %d\n", ev->data.l[0], gFHiddenState);
238         angle = ev->data.l[0];
239         ise_set_screen_direction(angle);
240         if (!gFHiddenState) {
241             ise_show(gLastIC);
242         }
243     } else if (ev->message_type == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE) {
244         LOGD("ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE , %d\n", ev->data.l[0]);
245         elm_win_keyboard_mode_set(main_window, (Elm_Win_Keyboard_Mode)(ev->data.l[0]));
246         gFHiddenState = !(ev->data.l[0]);
247     }
248 #endif
249
250     if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST) {
251         if (ev->win == elm_win_xwindow_get(main_window)) {
252             int degree = ev->data.l[1];
253             CSCLCoreUIEFL *coreui = static_cast<CSCLCoreUIEFL*>(data);
254             if (coreui) {
255                 coreui->set_screen_rotation_degree(degree);
256             }
257             LOGD("_ECORE_X_ATOM_E_WINDOW_ROTATION_REQUEST, %d\n", degree);
258             if (callback) {
259                 callback->on_set_rotation_degree(degree);
260             }
261             Ecore_X_Window control_window = 0;
262             Ecore_X_Atom atom = ecore_x_atom_get("_ISF_CONTROL_WINDOW");
263             Ecore_X_Window root = ecore_x_window_root_first_get();
264             if (ecore_x_window_prop_xid_get(root, atom, ECORE_X_ATOM_WINDOW, &control_window, 1) == 1) {
265                 ecore_x_client_message32_send(control_window, ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST,
266                     ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
267                     ev->data.l[0], ev->data.l[1], ev->data.l[2], ev->data.l[3], ev->data.l[4]);
268             }
269         }
270     }
271
272     return ECORE_CALLBACK_RENEW;
273 }
274 #endif
275
276 int CSCLCoreUIEFL::get_screen_rotation_degree()
277 {
278     int angle = 0;
279
280 #ifdef WAYLAND
281     angle = elm_win_rotation_get(NATIVE_WINDOW_CAST(m_main_window));
282 #else
283     if (m_rotation_degree == -1) {
284         int  ret = 0;
285         Atom type_return;
286         int  format_return;
287         unsigned long    nitems_return;
288         unsigned long    bytes_after_return;
289         unsigned char   *data_window = NULL;
290         unsigned char   *data_angle = NULL;
291
292         Ecore_X_Window app_window = 0;
293
294         Evas_Object *keypad_win = NATIVE_WINDOW_CAST(m_main_window);
295
296         LOGD("Trying to get app window degree for %p\n", keypad_win);
297         Ecore_X_Window win = elm_win_xwindow_get(NATIVE_WINDOW_CAST(keypad_win));
298         ret = XGetWindowProperty((Display *)ecore_x_display_get(),
299             ecore_x_window_root_get(win),
300             ecore_x_atom_get("_ISF_ACTIVE_WINDOW"),
301             0, G_MAXLONG, False, XA_WINDOW, &type_return,
302             &format_return, &nitems_return, &bytes_after_return,
303             &data_window);
304
305         if (ret == Success) {
306             if ((type_return == XA_WINDOW) && (format_return == 32) && (data_window)) {
307                 app_window = *(Window *)data_window;
308
309                 ret = XGetWindowProperty((Display *)ecore_x_display_get(), app_window,
310                     ecore_x_atom_get("_E_ILLUME_ROTATE_WINDOW_ANGLE"),
311                     0, G_MAXLONG, False, XA_CARDINAL, &type_return,
312                     &format_return, &nitems_return, &bytes_after_return,
313                     &data_angle);
314
315                 LOGD("app_window : %p, ret %d, %d, %p\n", app_window, ret, type_return, data_angle);
316                 if (ret == Success) {
317                     if (data_angle) {
318                         if (type_return == XA_CARDINAL) {
319                             angle = *(unsigned int*)data_angle;
320                             LOGD("current rotation angle is %p %d\n", app_window, angle);
321                         }
322                         XFree(data_angle);
323                     }
324                 }
325             }
326             if (data_window)
327                 XFree(data_window);
328         }
329     } else {
330         angle = m_rotation_degree;
331     }
332 #endif
333
334     return angle;
335 }
336
337 static void signal_handler(int sig) {
338     elm_exit();
339 }
340
341 #ifdef WAYLAND
342 static bool
343 _wayland_setup(struct WaylandKeyboard *wlkb, Evas_Object *main_window)
344 {
345     Eina_Iterator *globals;
346     struct wl_registry *registry;
347     Ecore_Wl2_Global *global;
348     Ecore_Wl2_Display *ewd;
349
350     if (!(ewd = ecore_wl2_connected_display_get(NULL)))
351         return false;
352
353     if (!(registry = ecore_wl2_display_registry_get(ewd)))
354         return false;
355
356     if (!(globals = ecore_wl2_display_globals_get(ewd)))
357         return false;
358
359     EINA_ITERATOR_FOREACH(globals, global)
360     {
361         if (strcmp(global->interface, "wl_input_panel") == 0)
362             wlkb->ip = (wl_input_panel *)wl_registry_bind(registry, global->id, &wl_input_panel_interface, 1);
363         else if (strcmp(global->interface, "wl_output") == 0)
364             wlkb->output = (wl_output *)wl_registry_bind(registry, global->id, &wl_output_interface, 1);
365     }
366
367     if (!wlkb->ip) {
368         LOGW("Can't get wayland input panel interface\n");
369         return false;
370     }
371
372     if (!wlkb->output) {
373         LOGW("Can't get wayland output interface\n");
374         return false;
375     }
376
377     wlkb->ee = ecore_evas_ecore_evas_get(evas_object_evas_get(main_window));
378     if (!wlkb->ee) {
379         LOGW("ERROR: Unable to create Ecore_Evas object\n");
380         return false;
381     }
382
383     /* Set input panel surface */
384     LOGD("Setting up input panel\n");
385     wlkb->wl_win = ecore_evas_wayland2_window_get(wlkb->ee);
386     if (!wlkb->wl_win) {
387         LOGW("Couldn't get wayland window\n");
388         return false;
389     }
390
391     ecore_wl2_window_type_set(wlkb->wl_win, ECORE_WL2_WINDOW_TYPE_NONE);
392     Ecore_Wl2_Surface *surface = ecore_wl2_surface_create(wlkb->wl_win, EINA_TRUE);
393     if (!surface) {
394         LOGW("Couldn't create surface\n");
395         return false;
396     }
397
398     wlkb->surface = ecore_wl2_window_surface_get(wlkb->wl_win);
399     if (!wlkb->surface) {
400         LOGW("Couldn't get surface\n");
401         return false;
402     }
403
404     wlkb->ips = wl_input_panel_get_input_panel_surface(wlkb->ip, wlkb->surface);
405     if (!wlkb->ips) {
406         LOGW("Couldn't get input panel surface\n");
407         return false;
408     }
409
410     wl_input_panel_surface_set_toplevel(wlkb->ips, wlkb->output, WL_INPUT_PANEL_SURFACE_POSITION_CENTER_BOTTOM);
411
412     return true;
413 }
414 #endif
415
416 sclboolean CSCLCoreUIEFL::create_main_window()
417 {
418     elm_config_accel_preference_set("3d");
419     elm_policy_set(ELM_POLICY_THROTTLE, ELM_POLICY_THROTTLE_NEVER);
420
421     Evas_Object *main_window = elm_win_add(NULL, m_appid, ELM_WIN_UTILITY);
422     if (!main_window) {
423         LOGE("Failed to create main window\n");
424         return FALSE;
425     }
426
427     m_main_window = SCL_WINDOW_CAST(main_window);
428
429 #ifdef WAYLAND
430     if (!_wayland_setup(&wlkb, main_window)) {
431         LOGW("ERROR: Unable to setup input panel.\n");
432         return FALSE;
433     }
434 #endif
435
436     elm_win_borderless_set(main_window, EINA_TRUE);
437     elm_win_keyboard_win_set(main_window, EINA_TRUE);
438     elm_win_autodel_set(main_window, EINA_TRUE);
439     elm_win_title_set(main_window, m_appid);
440     elm_atspi_accessible_name_set(main_window, "Keyboard");
441     elm_atspi_accessible_role_set(main_window, ELM_ATSPI_ROLE_INPUT_METHOD_WINDOW);
442     elm_win_prop_focus_skip_set(main_window, EINA_TRUE);
443     int rots[] = { 0, 90, 180, 270 };
444     elm_win_wm_rotation_available_rotations_set(main_window, rots, (sizeof(rots) / sizeof(int)));
445
446 #ifndef WAYLAND
447     unsigned int set = 1;
448     ecore_x_window_prop_card32_set(elm_win_xwindow_get(main_window),
449         ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
450         &set, 1);
451
452     ecore_x_icccm_name_class_set(elm_win_xwindow_get(main_window), "Virtual Keyboard", "ISF");
453 #else
454     evas_object_show(main_window);
455 #endif
456
457     Evas_Coord win_w = 0, win_h = 0;
458     elm_win_screen_size_get(main_window, NULL, NULL, &win_w, &win_h);
459     SclSize portrait;
460     portrait.width = win_w;
461     portrait.height = win_h / 3;
462     SclSize landscape;
463     landscape.width = win_h;
464     landscape.height = win_w / 3;
465     set_keyboard_size_hints(portrait, landscape);
466
467 #ifdef WAYLAND
468     evas_object_smart_callback_add(main_window, "wm,rotation,changed", win_rotation_changed_cb, NULL);
469     evas_object_show(main_window);
470 #else
471     Ecore_Event_Handler *XClientMsgHandler =
472         ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, _client_message_cb, this);
473 #endif
474     return TRUE;
475 }
476
477 int CSCLCoreUIEFL::create(void *data)
478 {
479     LOGD("");
480
481     CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
482     if (impl) {
483         if (!impl->prepare()) {
484             appcore_efl_fini();
485             return -1;
486         }
487     }
488
489     appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE, language_changed_cb, NULL);
490
491     vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, accessibility_changed_cb, NULL);
492
493     /* Should we call these callback functions here? */
494     language_changed_cb(NULL, NULL);
495     accessibility_changed_cb(NULL, NULL);
496
497     signal(SIGQUIT, signal_handler);
498     signal(SIGTERM, signal_handler);
499     signal(SIGINT,  signal_handler);
500     signal(SIGHUP,  signal_handler);
501
502     return 0;
503 }
504
505 int CSCLCoreUIEFL::terminate(void *data)
506 {
507     CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
508     if (impl)
509         impl->fini();
510
511     appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE, NULL, NULL);
512
513     vconf_ignore_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, accessibility_changed_cb);
514
515 #ifndef WAYLAND
516     if (XClientMsgHandler) {
517         ecore_event_handler_del(XClientMsgHandler);
518         XClientMsgHandler = NULL;
519     }
520 #endif
521
522     return 0;
523 }
524
525 static int app_create_cb(void *data)
526 {
527     CSCLCoreUIEFL *sclui = static_cast<CSCLCoreUIEFL *>(data);
528     if (sclui) {
529         int ret = sclui->create(data);
530         elm_cache_all_flush();
531         malloc_trim(0);
532         return ret;
533     }
534
535     return -1;
536 }
537
538 static int app_terminate_cb(void *data)
539 {
540     CSCLCoreUIEFL *sclui = static_cast<CSCLCoreUIEFL *>(data);
541     if (sclui)
542         return sclui->terminate(data);
543
544     return -1;
545 }
546
547 void CSCLCoreUIEFL::run(const sclchar *display)
548 {
549     char **argv = new char*[4];
550     int argc = 3;
551     const sclchar *appid = NULL;
552
553     ops.create = app_create_cb;
554     ops.terminate = app_terminate_cb;
555     ops.resume = NULL;
556     ops.pause = NULL;
557     ops.reset = NULL;
558     ops.data = this;
559
560     CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
561     if (impl) {
562         appid = impl->get_uuid();
563     }
564
565     if (!appid)
566         appid = "";
567
568     m_appid = appid;
569     m_display = display;
570
571     argv[0] = const_cast<char *> (appid);
572     argv[1] = (char *)"--display";
573     argv[2] = const_cast<char *> (display);
574     argv[3] = 0;
575
576     LOGD("name : %s\n", appid);
577
578     appcore_efl_main(appid, &argc, (char ***)&argv, &ops);
579
580     delete [] argv;
581 }
582
583 static void focus_out_cb(void *data, Evas *e, void *event)
584 {
585     OptionWindowInfo *info = static_cast<OptionWindowInfo*>(data);
586     if (info) {
587         if (info->window) {
588             CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
589             if (impl) {
590                 ISCLCoreEventCallback *callback = impl->get_core_event_callback();
591                 if (callback) {
592                     callback->on_destroy_option_window(info->window);
593                 }
594             }
595
596             evas_object_hide(NATIVE_WINDOW_CAST(info->window));
597             evas_object_del(NATIVE_WINDOW_CAST(info->window));
598             info->window = NULL;
599         }
600     }
601 }
602
603 static void
604 set_transient_for_app_window(Evas_Object *window)
605 {
606     /* Set a transient window for window stack */
607     /* Gets the current XID of the active window into the root window property  */
608 #ifndef WAYLAND
609     Atom type_return;
610     unsigned long nitems_return;
611     unsigned long bytes_after_return;
612     int format_return;
613     unsigned char *data = NULL;
614     Ecore_X_Window xAppWindow;
615     Ecore_X_Window xWindow = elm_win_xwindow_get(window);
616     gint ret = 0;
617
618     ret = XGetWindowProperty((Display *)ecore_x_display_get(), ecore_x_window_root_get(xWindow),
619         ecore_x_atom_get("_ISF_ACTIVE_WINDOW"),
620         0, G_MAXLONG, False, XA_WINDOW, &type_return,
621         &format_return, &nitems_return, &bytes_after_return,
622         &data);
623
624     if (ret == Success) {
625         if (data) {
626             if (type_return == XA_WINDOW) {
627                 xAppWindow = *(Window *)data;
628                 LOGD("TRANSIENT_FOR SET : %x , %x\n", xAppWindow, xWindow);
629                 ecore_x_icccm_transient_for_set(xWindow, xAppWindow);
630             }
631             XFree(data);
632         }
633     }
634 #endif
635 }
636
637 static void
638 set_transient_for_isf_setting_window(Evas_Object *window)
639 {
640     /* Set a transient window for window stack */
641     /* Gets the current XID of the active window into the root window property  */
642 #ifndef WAYLAND
643     Atom type_return;
644     unsigned long nitems_return;
645     unsigned long bytes_after_return;
646     int format_return;
647     unsigned char *data = NULL;
648     Ecore_X_Window xControlWindow, xSettingWindow;
649     Ecore_X_Window xWindow = elm_win_xwindow_get(window);
650     gint ret = 0;
651
652     ret = XGetWindowProperty((Display *)ecore_x_display_get(), ecore_x_window_root_get(xWindow),
653         ecore_x_atom_get("_ISF_CONTROL_WINDOW"),
654         0, G_MAXLONG, False, XA_WINDOW, &type_return,
655         &format_return, &nitems_return, &bytes_after_return,
656         &data);
657
658     if (ret == Success) {
659         if (data) {
660             if (type_return == XA_WINDOW) {
661                 xControlWindow = *(Window *)data;
662
663                 ecore_x_window_prop_xid_get(xControlWindow, ecore_x_atom_get("ISF Setting window"),
664                     ECORE_X_ATOM_WINDOW, &xSettingWindow, 1);
665
666                 LOGD("TRANSIENT_FOR SET : %x , %x\n", xSettingWindow, xWindow);
667                 ecore_x_icccm_transient_for_set(xWindow, xSettingWindow);
668             }
669             XFree(data);
670         }
671     }
672 #endif
673 }
674
675 sclwindow CSCLCoreUIEFL::create_option_window(SCLOptionWindowType type)
676 {
677     if (type >= OPTION_WINDOW_TYPE_MAX) {
678         return SCLWINDOW_INVALID;
679     }
680
681     ISCLCoreEventCallback *callback = NULL;
682     CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
683     if (impl) {
684         callback = impl->get_core_event_callback();
685         if (callback) {
686             sclboolean ret = false;
687             callback->on_check_option_window_availability(&ret);
688             if (ret == false) {
689                 LOGW("option_window not available\n");
690                 return SCLWINDOW_INVALID;
691             }
692         } else {
693             return SCLWINDOW_INVALID;
694         }
695     }
696
697     /* Just in case the previous option window for setting application exists */
698     if (type == OPTION_WINDOW_TYPE_SETTING_APPLICATION) {
699         if (m_option_window_info[type].window != SCLWINDOW_INVALID) {
700             destroy_option_window(m_option_window_info[type].window);
701         }
702     }
703
704     Evas_Object *window, *bg;
705
706     window = elm_win_add(NATIVE_WINDOW_CAST(m_main_window), "Option window", ELM_WIN_BASIC);
707     if (!window) return NULL;
708
709     elm_win_title_set(window, "Option window");
710     bg = elm_bg_add(window);
711     if (!bg) {
712         evas_object_del(window);
713         return NULL;
714     }
715
716     evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
717     elm_win_resize_object_add(window, bg);
718     evas_object_show(bg);
719
720 #ifndef WAYLAND
721     Evas_Coord win_w = 0, win_h = 0;
722     elm_win_screen_size_get(window, NULL, NULL, &win_w, &win_h);
723     int degree = get_screen_rotation_degree();
724     if (degree == 90 || degree == 270) {
725         evas_object_resize(window, win_h, win_w);
726     } else {
727         evas_object_resize(window, win_w, win_h);
728     }
729 #endif
730
731     int rots[] = { 0, 90, 180, 270 };
732     elm_win_wm_rotation_available_rotations_set(window, rots, (sizeof(rots) / sizeof(int)));
733
734     elm_win_indicator_mode_set(window, ELM_WIN_INDICATOR_SHOW);
735
736     if (callback) {
737         callback->on_create_option_window(window, type);
738     }
739
740     if (type == OPTION_WINDOW_TYPE_NORMAL) {
741         Evas *evas = evas_object_evas_get(window);
742         evas_event_callback_add(evas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, focus_out_cb, &m_option_window_info[type]);
743         set_transient_for_app_window(window);
744     } else if (type == OPTION_WINDOW_TYPE_SETTING_APPLICATION) {
745         set_transient_for_isf_setting_window(window);
746     }
747
748     m_option_window_info[type].window = window;
749
750     return window;
751 }
752
753 bool CSCLCoreUIEFL::show_option_window(SCLOptionWindowType type)
754 {
755     if (type >= OPTION_WINDOW_TYPE_MAX) {
756         return SCLWINDOW_INVALID;
757     }
758
759     ISCLCoreEventCallback *callback = NULL;
760     CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
761     if (impl) {
762         callback = impl->get_core_event_callback();
763         if (callback) {
764             sclboolean ret = false;
765             callback->on_check_option_window_availability(&ret);
766             if (ret == false) {
767                 LOGW("option_window not available\n");
768                 return false;
769             }
770         } else {
771             return false;
772         }
773     }
774
775     if (m_option_window_info[type].window != SCLWINDOW_INVALID) {
776         evas_object_show(static_cast<Evas_Object*>(m_option_window_info[type].window));
777         elm_win_raise(static_cast<Evas_Object*>(m_option_window_info[type].window));
778         return true;
779     }
780
781     return false;
782 }
783
784 void CSCLCoreUIEFL::destroy_option_window(sclwindow window)
785 {
786     CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
787     if (impl) {
788         ISCLCoreEventCallback *callback = impl->get_core_event_callback();
789         if (callback) {
790             callback->on_destroy_option_window(window);
791         }
792     }
793
794     for (int loop = 0;loop < OPTION_WINDOW_TYPE_MAX;loop++) {
795         if (m_option_window_info[loop].window == window) {
796             evas_object_del(NATIVE_WINDOW_CAST(window));
797             m_option_window_info[loop].window = SCLWINDOW_INVALID;
798         }
799     }
800 }
801
802 void CSCLCoreUIEFL::set_screen_rotation_degree(int degree)
803 {
804     m_rotation_degree = degree;
805 }
806
807 #ifdef WAYLAND
808 static void _render_pre_cb(void *data, Evas *e, void *event_info)
809 {
810     LOGD("_render_pre_cb() called, now invoking wl_input_panel_surface_set_ready()");
811
812     wl_input_panel_surface_set_ready(wlkb.ips, 1);
813
814     Evas_Object *main_window = NATIVE_WINDOW_CAST(data);
815     evas_event_callback_del_full(evas_object_evas_get(main_window),
816         EVAS_CALLBACK_RENDER_PRE, _render_pre_cb, main_window);
817
818     delete_render_pre_timer();
819 }
820
821 static Eina_Bool _render_pre_timeout(void *data)
822 {
823     LOGD("_render_pre_timer expired, forcing to call _render_pre_cb() callback");
824
825     _render_pre_cb(data, NULL, NULL);
826
827     return ECORE_CALLBACK_CANCEL;
828 }
829 #endif
830
831 void CSCLCoreUIEFL::process_keyboard_ui_state_change(KEYBOARD_UI_STATE state)
832 {
833 #ifdef WAYLAND
834     if (state == KEYBOARD_UI_STATE_WILL_SHOW) {
835         evas_event_callback_add(evas_object_evas_get(NATIVE_WINDOW_CAST(m_main_window)),
836             EVAS_CALLBACK_RENDER_PRE, _render_pre_cb, (void*)m_main_window);
837         _render_pre_timer = ecore_timer_add(RENDER_PRE_TIMEOUT, _render_pre_timeout, (void*)m_main_window);
838         LOGD("Registered RENDER_PRE callback, _render_pre_cb() and a timer callback");
839     } else if (state == KEYBOARD_UI_STATE_DID_SHOW) {
840         LOGD("Forcing keyboard window to render");
841         evas_render(evas_object_evas_get(NATIVE_WINDOW_CAST(m_main_window)));
842     }
843 #endif
844 }