Added call for on_show callback
[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
23 #include <vconf.h>
24 #include <vconf-keys.h>
25
26 #include <glib.h>
27 #ifdef WAYLAND
28 #include <Ecore_Wayland.h>
29 #include <input-method-client-protocol.h>
30 #else
31 #include <Ecore_X.h>
32 #include <X11/Xlib.h>
33 #include <X11/Xatom.h>
34 #endif
35
36 #ifdef WEBSOCKET
37  /* This websocket agent is for supporting Tizen 2.X legacy web IMEs that uses websocket */
38 CWebHelperAgentWebSocket g_websocket;
39 #endif
40
41 #ifdef WAYLAND
42 struct WaylandKeyboard
43 {
44     Ecore_Evas *ee;
45     Ecore_Wl_Window *wl_win;
46     const char *ee_engine;
47
48     struct wl_surface *surface;
49     struct wl_input_panel *ip;
50     struct wl_output *output;
51     struct wl_input_panel_surface *ips;
52 };
53
54 struct WaylandKeyboard wlkb = {0};
55
56 #define RENDER_PRE_TIMEOUT 1.0f
57 static Ecore_Timer *_render_pre_timer = NULL;
58 static void delete_render_pre_timer()
59 {
60     if (_render_pre_timer) {
61         ecore_timer_del(_render_pre_timer);
62         _render_pre_timer = NULL;
63     }
64 }
65 #endif
66
67 using namespace scl;
68
69 CSCLCoreUIEFL::CSCLCoreUIEFL()
70 {
71     m_initialized = FALSE;
72
73     m_backend_identifier = "EFL";
74
75     m_rotation_degree = 0;
76     m_main_window = SCLWINDOW_INVALID;
77 }
78
79 CSCLCoreUIEFL::~CSCLCoreUIEFL()
80 {
81 }
82
83 sclboolean CSCLCoreUIEFL::init()
84 {
85     m_initialized = TRUE;
86     m_rotation_degree = -1;
87
88     for (int loop = 0;loop < OPTION_WINDOW_TYPE_MAX;loop++) {
89         m_option_window_info[loop].window = SCLWINDOW_INVALID;
90     }
91
92 #ifdef WEBSOCKET
93     g_websocket.init();
94 #endif
95
96     return TRUE;
97 }
98
99 void CSCLCoreUIEFL::fini()
100 {
101     m_initialized = FALSE;
102
103 #ifdef WEBSOCKET
104     g_websocket.exit();
105 #endif
106 }
107
108 sclwindow CSCLCoreUIEFL::get_main_window()
109 {
110     if (m_initialized) {
111         return m_main_window;
112     } else {
113         return NULL;
114     }
115 }
116
117 void CSCLCoreUIEFL::set_keyboard_size_hints(SclSize portrait, SclSize landscape)
118 {
119     Evas_Object *main_window = NATIVE_WINDOW_CAST(m_main_window);
120
121 #ifdef WAYLAND
122     ecore_wl_window_rotation_geometry_set(elm_win_wl_window_get(main_window),   0, 0, 0, portrait.width, portrait.height);
123     ecore_wl_window_rotation_geometry_set(elm_win_wl_window_get(main_window),  90, 0, 0, landscape.height, landscape.width);
124     ecore_wl_window_rotation_geometry_set(elm_win_wl_window_get(main_window), 180, 0, 0, portrait.width, portrait.height);
125     ecore_wl_window_rotation_geometry_set(elm_win_wl_window_get(main_window), 270, 0, 0, landscape.height, landscape.width);
126 #else
127     /*
128     ecore_x_e_window_rotation_geometry_set(elm_win_xwindow_get(main_window),   0, 0, 0, portrait.width, portrait.height);
129     ecore_x_e_window_rotation_geometry_set(elm_win_xwindow_get(main_window),  90, 0, 0, landscape.height, landscape.width);
130     ecore_x_e_window_rotation_geometry_set(elm_win_xwindow_get(main_window), 180, 0, 0, portrait.width, portrait.height);
131     ecore_x_e_window_rotation_geometry_set(elm_win_xwindow_get(main_window), 270, 0, 0, landscape.height, landscape.width);
132     */
133 #endif
134 }
135
136 static void language_changed_cb(keynode_t *key, void* data)
137 {
138     char clang[_POSIX_PATH_MAX] = {0};
139     char *vconf_str = vconf_get_str(VCONFKEY_LANGSET);
140     if (vconf_str) {
141         snprintf(clang, sizeof(clang), "%s", vconf_str);
142         free(vconf_str);
143     }
144     LOGD("current language is %s\n", clang);
145
146     CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
147     if (impl) {
148         ISCLCoreEventCallback *callback = impl->get_core_event_callback();
149         if (callback) {
150             callback->on_set_display_language(clang);
151         }
152     }
153 }
154
155 static void accessibility_changed_cb(keynode_t *key, void* data)
156 {
157     int vconf_value = 0;
158     if (vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, &vconf_value) == 0) {
159         LOGD("accessibility state : %d\n", vconf_value);
160
161         CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
162         if (impl) {
163             ISCLCoreEventCallback *callback = impl->get_core_event_callback();
164             if (callback) {
165                 callback->on_set_accessibility_state(vconf_value);
166             }
167         }
168     }
169 }
170
171 #ifdef WAYLAND
172 static void win_rotation_changed_cb(void *data, Evas_Object *obj, void *event)
173 {
174     int degree = elm_win_rotation_get(obj);
175     LOGD("rotation angle : %d\n", degree);
176
177     ISCLCoreEventCallback *callback = NULL;
178     CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
179     if (impl) {
180         callback = impl->get_core_event_callback();
181     }
182
183     CSCLCoreUIEFL *coreui = static_cast<CSCLCoreUIEFL*>(data);
184     if (coreui) {
185         coreui->set_screen_rotation_degree(degree);
186     }
187     if (callback) {
188         callback->on_set_rotation_degree(degree);
189     }
190 }
191 #else
192 static Eina_Bool _client_message_cb(void *data, int type, void *event)
193 {
194     Ecore_X_Event_Client_Message *ev = (Ecore_X_Event_Client_Message *)event;
195
196     ISCLCoreEventCallback *callback = NULL;
197     CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
198     Evas_Object *main_window = NULL;
199     if (impl) {
200         callback = impl->get_core_event_callback();
201         main_window = NATIVE_WINDOW_CAST(impl->get_main_window());
202     }
203
204 #ifndef APPLY_WINDOW_MANAGER_CHANGE
205 #else
206     if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE) {
207         LOGD("ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE , %d %d\n", ev->data.l[0], gFHiddenState);
208         angle = ev->data.l[0];
209         ise_set_screen_direction(angle);
210         if (!gFHiddenState) {
211             ise_show(gLastIC);
212         }
213     } else if (ev->message_type == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE) {
214         LOGD("ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE , %d\n", ev->data.l[0]);
215         elm_win_keyboard_mode_set(main_window, (Elm_Win_Keyboard_Mode)(ev->data.l[0]));
216         gFHiddenState = !(ev->data.l[0]);
217     }
218 #endif
219
220     if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST) {
221         if (ev->win == elm_win_xwindow_get(main_window)) {
222             int degree = ev->data.l[1];
223             CSCLCoreUIEFL *coreui = static_cast<CSCLCoreUIEFL*>(data);
224             if (coreui) {
225                 coreui->set_screen_rotation_degree(degree);
226             }
227             LOGD("_ECORE_X_ATOM_E_WINDOW_ROTATION_REQUEST, %d\n", degree);
228             if (callback) {
229                 callback->on_set_rotation_degree(degree);
230             }
231             Ecore_X_Window control_window = 0;
232             Ecore_X_Atom atom = ecore_x_atom_get("_ISF_CONTROL_WINDOW");
233             Ecore_X_Window root = ecore_x_window_root_first_get();
234             if (ecore_x_window_prop_xid_get(root, atom, ECORE_X_ATOM_WINDOW, &control_window, 1) == 1) {
235                 ecore_x_client_message32_send(control_window, ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST,
236                     ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
237                     ev->data.l[0], ev->data.l[1], ev->data.l[2], ev->data.l[3], ev->data.l[4]);
238             }
239         }
240     }
241
242     return ECORE_CALLBACK_RENEW;
243 }
244 #endif
245
246 int CSCLCoreUIEFL::get_screen_rotation_degree()
247 {
248     int angle = 0;
249
250 #ifdef WAYLAND
251     angle = elm_win_rotation_get(NATIVE_WINDOW_CAST(m_main_window));
252 #else
253     if (m_rotation_degree == -1) {
254         int  ret = 0;
255         Atom type_return;
256         int  format_return;
257         unsigned long    nitems_return;
258         unsigned long    bytes_after_return;
259         unsigned char   *data_window = NULL;
260         unsigned char   *data_angle = NULL;
261
262         Ecore_X_Window app_window = 0;
263
264         Evas_Object *keypad_win = NATIVE_WINDOW_CAST(m_main_window);
265
266         LOGD("Trying to get app window degree for %p\n", keypad_win);
267         Ecore_X_Window win = elm_win_xwindow_get(NATIVE_WINDOW_CAST(keypad_win));
268         ret = XGetWindowProperty((Display *)ecore_x_display_get(),
269             ecore_x_window_root_get(win),
270             ecore_x_atom_get("_ISF_ACTIVE_WINDOW"),
271             0, G_MAXLONG, False, XA_WINDOW, &type_return,
272             &format_return, &nitems_return, &bytes_after_return,
273             &data_window);
274
275         if (ret == Success) {
276             if ((type_return == XA_WINDOW) && (format_return == 32) && (data_window)) {
277                 app_window = *(Window *)data_window;
278
279                 ret = XGetWindowProperty((Display *)ecore_x_display_get(), app_window,
280                     ecore_x_atom_get("_E_ILLUME_ROTATE_WINDOW_ANGLE"),
281                     0, G_MAXLONG, False, XA_CARDINAL, &type_return,
282                     &format_return, &nitems_return, &bytes_after_return,
283                     &data_angle);
284
285                 LOGD("app_window : %p, ret %d, %d, %p\n", app_window, ret, type_return, data_angle);
286                 if (ret == Success) {
287                     if (data_angle) {
288                         if (type_return == XA_CARDINAL) {
289                             angle = *(unsigned int*)data_angle;
290                             LOGD("current rotation angle is %p %d\n", app_window, angle);
291                         }
292                         XFree(data_angle);
293                     }
294                 }
295             }
296             if (data_window)
297                 XFree(data_window);
298         }
299     } else {
300         angle = m_rotation_degree;
301     }
302 #endif
303
304     return angle;
305 }
306
307 static void signal_handler(int sig) {
308     elm_exit();
309 }
310
311 #ifdef WAYLAND
312 static bool
313 _wayland_setup(struct WaylandKeyboard *wlkb, Evas_Object *main_window)
314 {
315     Eina_Inlist *globals;
316     struct wl_registry *registry;
317     Ecore_Wl_Global *global;
318
319     if (!(registry = ecore_wl_registry_get()))
320         return false;
321
322     if (!(globals = ecore_wl_globals_get()))
323         return false;
324
325     EINA_INLIST_FOREACH(globals, global)
326     {
327         if (strcmp(global->interface, "wl_input_panel") == 0)
328             wlkb->ip = (wl_input_panel *)wl_registry_bind(registry, global->id, &wl_input_panel_interface, 1);
329         else if (strcmp(global->interface, "wl_output") == 0)
330             wlkb->output = (wl_output *)wl_registry_bind(registry, global->id, &wl_output_interface, 1);
331     }
332
333     if (!wlkb->ip) {
334         LOGW("Can't get wayland input panel interface\n");
335         return false;
336     }
337
338     if (!wlkb->output) {
339         LOGW("Can't get wayland output interface\n");
340         return false;
341     }
342
343     wlkb->ee = ecore_evas_ecore_evas_get(evas_object_evas_get(main_window));
344     if (!wlkb->ee) {
345         LOGW("ERROR: Unable to create Ecore_Evas object\n");
346         return false;
347     }
348
349     /* Set input panel surface */
350     LOGD("Setting up input panel\n");
351     wlkb->wl_win = ecore_evas_wayland_window_get(wlkb->ee);
352     if (!wlkb->wl_win) {
353         LOGW("Couldn't get wayland window\n");
354         return false;
355     }
356
357     ecore_wl_window_type_set(wlkb->wl_win, ECORE_WL_WINDOW_TYPE_NONE);
358     wlkb->surface = ecore_wl_window_surface_create(wlkb->wl_win);
359     if (!wlkb->surface) {
360         LOGW("Couldn't create surface\n");
361         return false;
362     }
363
364     wlkb->ips = wl_input_panel_get_input_panel_surface(wlkb->ip, wlkb->surface);
365     if (!wlkb->ips) {
366         LOGW("Couldn't get input panel surface\n");
367         return false;
368     }
369
370     wl_input_panel_surface_set_toplevel(wlkb->ips, wlkb->output, WL_INPUT_PANEL_SURFACE_POSITION_CENTER_BOTTOM);
371
372     return true;
373 }
374
375 static Eina_Bool
376 check_evas_engine(struct WaylandKeyboard *wlkb)
377 {
378     Eina_Bool ret = EINA_FALSE;
379     const char *env = getenv("ECORE_EVAS_ENGINE");
380
381     if (!env) {
382         if (ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_WAYLAND_SHM)) {
383             env = "wayland_shm";
384         } else if (ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_WAYLAND_EGL)) {
385             env = "wayland_egl";
386         } else {
387             LOGW("ERROR: Ecore_Evas does must be compiled with support for Wayland engines\n");
388             goto err;
389         }
390     } else if (strcmp(env, "wayland_shm") != 0 && strcmp(env, "wayland_egl") != 0) {
391         LOGW("ERROR: ECORE_EVAS_ENGINE must be set to either 'wayland_shm' or 'wayland_egl'\n");
392         goto err;
393     }
394
395     wlkb->ee_engine = env;
396     ret = EINA_TRUE;
397
398 err:
399     return ret;
400 }
401 #endif
402
403 void CSCLCoreUIEFL::run(const sclchar *display)
404 {
405     char *argv[4];
406     int argc = 3;
407
408     CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
409     if (impl) {
410         const sclchar *uuid = impl->get_uuid();
411         if (!uuid)
412             uuid = "";
413
414         argv[0] = const_cast<char *> (uuid);
415         argv[1] = (char *)"--display";
416         argv[2] = const_cast<char *> (display);
417         argv[3] = 0;
418
419         elm_init(argc, argv);
420
421 #ifdef WAYLAND
422         if (!check_evas_engine(&wlkb)) {
423             LOGW("_wlkb_check_evas_engine error!\n");
424             elm_shutdown();
425             return;
426         }
427         LOGD("Selected engine: '%s'\n", wlkb.ee_engine);
428 #endif
429
430         elm_config_accel_preference_set("3d");
431         elm_policy_set(ELM_POLICY_THROTTLE, ELM_POLICY_THROTTLE_NEVER);
432
433         Evas_Object *main_window = elm_win_add(NULL, uuid, ELM_WIN_UTILITY);
434         if (!main_window) {
435             LOGE("Failed to create main window\n");
436             return;
437         }
438
439         m_main_window = SCL_WINDOW_CAST(main_window);
440
441 #ifdef WAYLAND
442         if (!_wayland_setup(&wlkb, main_window)) {
443             LOGW("ERROR: Unable to setup input panel.\n");
444             elm_shutdown();
445             return;
446         }
447 #endif
448
449         elm_win_borderless_set(main_window, EINA_TRUE);
450         elm_win_keyboard_win_set(main_window, EINA_TRUE);
451         elm_win_autodel_set(main_window, EINA_TRUE);
452         elm_win_title_set(main_window, uuid);
453         elm_win_prop_focus_skip_set(main_window, EINA_TRUE);
454         int rots[] = { 0, 90, 180, 270 };
455         elm_win_wm_rotation_available_rotations_set(main_window, rots, (sizeof(rots) / sizeof(int)));
456
457 #ifndef WAYLAND
458         unsigned int set = 1;
459         ecore_x_window_prop_card32_set(elm_win_xwindow_get(main_window),
460             ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
461             &set, 1);
462
463         ecore_x_icccm_name_class_set(elm_win_xwindow_get(main_window), "Virtual Keyboard", "ISF");
464 #endif
465
466         vconf_notify_key_changed(VCONFKEY_LANGSET, language_changed_cb, NULL);
467         vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, accessibility_changed_cb, NULL);
468
469         /* Should we call these callback functions here? */
470         language_changed_cb(NULL, NULL);
471         accessibility_changed_cb(NULL, NULL);
472
473         impl->init(display);
474
475 #ifdef WAYLAND
476         evas_object_smart_callback_add(main_window, "wm,rotation,changed", win_rotation_changed_cb, this);
477 #else
478         Ecore_Event_Handler *XClientMsgHandler =
479             ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, _client_message_cb, this);
480 #endif
481
482         signal(SIGQUIT, signal_handler);
483         signal(SIGTERM, signal_handler);
484         signal(SIGINT,  signal_handler);
485         signal(SIGHUP,  signal_handler);
486
487 #ifdef WAYLAND
488         evas_object_show(main_window);
489 #endif
490
491         elm_run();
492
493         impl->fini();
494
495         vconf_ignore_key_changed(VCONFKEY_LANGSET, language_changed_cb);
496         vconf_ignore_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, accessibility_changed_cb);
497
498 #ifndef WAYLAND
499         if (XClientMsgHandler) {
500             ecore_event_handler_del(XClientMsgHandler);
501             XClientMsgHandler = NULL;
502         }
503 #endif
504
505         elm_shutdown();
506     }
507 }
508
509 static void focus_out_cb(void *data, Evas *e, void *event)
510 {
511     OptionWindowInfo *info = static_cast<OptionWindowInfo*>(data);
512     if (info) {
513         if (info->window) {
514             CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
515             if (impl) {
516                 ISCLCoreEventCallback *callback = impl->get_core_event_callback();
517                 if (callback) {
518                     callback->on_destroy_option_window(info->window);
519                 }
520             }
521
522             evas_object_hide(NATIVE_WINDOW_CAST(info->window));
523             evas_object_del(NATIVE_WINDOW_CAST(info->window));
524             info->window = NULL;
525         }
526     }
527 }
528
529 static void
530 set_transient_for_app_window(Evas_Object *window)
531 {
532     /* Set a transient window for window stack */
533     /* Gets the current XID of the active window into the root window property  */
534 #ifndef WAYLAND
535     Atom type_return;
536     unsigned long nitems_return;
537     unsigned long bytes_after_return;
538     int format_return;
539     unsigned char *data = NULL;
540     Ecore_X_Window xAppWindow;
541     Ecore_X_Window xWindow = elm_win_xwindow_get(window);
542     gint ret = 0;
543
544     ret = XGetWindowProperty((Display *)ecore_x_display_get(), ecore_x_window_root_get(xWindow),
545         ecore_x_atom_get("_ISF_ACTIVE_WINDOW"),
546         0, G_MAXLONG, False, XA_WINDOW, &type_return,
547         &format_return, &nitems_return, &bytes_after_return,
548         &data);
549
550     if (ret == Success) {
551         if (data) {
552             if (type_return == XA_WINDOW) {
553                 xAppWindow = *(Window *)data;
554                 LOGD("TRANSIENT_FOR SET : %x , %x\n", xAppWindow, xWindow);
555                 ecore_x_icccm_transient_for_set(xWindow, xAppWindow);
556             }
557             XFree(data);
558         }
559     }
560 #endif
561 }
562
563 static void
564 set_transient_for_isf_setting_window(Evas_Object *window)
565 {
566     /* Set a transient window for window stack */
567     /* Gets the current XID of the active window into the root window property  */
568 #ifndef WAYLAND
569     Atom type_return;
570     unsigned long nitems_return;
571     unsigned long bytes_after_return;
572     int format_return;
573     unsigned char *data = NULL;
574     Ecore_X_Window xControlWindow, xSettingWindow;
575     Ecore_X_Window xWindow = elm_win_xwindow_get(window);
576     gint ret = 0;
577
578     ret = XGetWindowProperty((Display *)ecore_x_display_get(), ecore_x_window_root_get(xWindow),
579         ecore_x_atom_get("_ISF_CONTROL_WINDOW"),
580         0, G_MAXLONG, False, XA_WINDOW, &type_return,
581         &format_return, &nitems_return, &bytes_after_return,
582         &data);
583
584     if (ret == Success) {
585         if (data) {
586             if (type_return == XA_WINDOW) {
587                 xControlWindow = *(Window *)data;
588
589                 ecore_x_window_prop_xid_get(xControlWindow, ecore_x_atom_get("ISF Setting window"),
590                     ECORE_X_ATOM_WINDOW, &xSettingWindow, 1);
591
592                 LOGD("TRANSIENT_FOR SET : %x , %x\n", xSettingWindow, xWindow);
593                 ecore_x_icccm_transient_for_set(xWindow, xSettingWindow);
594             }
595             XFree(data);
596         }
597     }
598 #endif
599 }
600
601 sclwindow CSCLCoreUIEFL::create_option_window(SCLOptionWindowType type)
602 {
603     if (type < 0 || type >= OPTION_WINDOW_TYPE_MAX) {
604         return SCLWINDOW_INVALID;
605     }
606
607     ISCLCoreEventCallback *callback = NULL;
608     CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
609     if (impl) {
610         callback = impl->get_core_event_callback();
611         if (callback) {
612             sclboolean ret = false;
613             callback->on_check_option_window_availability(&ret);
614             if (ret == false) {
615                 LOGW("on_create_option_window() is not available\n");
616                 return SCLWINDOW_INVALID;
617             }
618         } else {
619             return SCLWINDOW_INVALID;
620         }
621     }
622
623     /* Just in case the previous option window for setting application exists */
624     if (type == OPTION_WINDOW_TYPE_SETTING_APPLICATION) {
625         if (m_option_window_info[type].window != SCLWINDOW_INVALID) {
626             destroy_option_window(m_option_window_info[type].window);
627         }
628     }
629
630     Evas_Object *window = elm_win_util_standard_add("Option window", "Option window");
631
632 #ifndef WAYLAND
633     Evas_Coord win_w = 0, win_h = 0;
634     elm_win_screen_size_get(window, NULL, NULL, &win_w, &win_h);
635     int degree = get_screen_rotation_degree();
636     if (degree == 90 || degree == 270) {
637         evas_object_resize(window, win_h, win_w);
638     } else {
639         evas_object_resize(window, win_w, win_h);
640     }
641 #endif
642
643     int rots[] = { 0, 90, 180, 270 };
644     elm_win_wm_rotation_available_rotations_set(window, rots, (sizeof(rots) / sizeof(int)));
645
646     elm_win_indicator_mode_set(window, ELM_WIN_INDICATOR_SHOW);
647
648     if (callback) {
649         callback->on_create_option_window(window, type);
650     }
651
652     if (type == OPTION_WINDOW_TYPE_NORMAL) {
653         Evas *evas = evas_object_evas_get(window);
654         evas_event_callback_add(evas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, focus_out_cb, &m_option_window_info[type]);
655         set_transient_for_app_window(window);
656     } else if (type == OPTION_WINDOW_TYPE_SETTING_APPLICATION) {
657         set_transient_for_isf_setting_window(window);
658         evas_object_show(window);
659     }
660
661     m_option_window_info[type].window = window;
662
663     return window;
664 }
665
666 void CSCLCoreUIEFL::destroy_option_window(sclwindow window)
667 {
668     CSCLCoreImpl *impl = CSCLCoreImpl::get_instance();
669     if (impl) {
670         ISCLCoreEventCallback *callback = impl->get_core_event_callback();
671         if (callback) {
672             callback->on_destroy_option_window(window);
673         }
674     }
675
676     for (int loop = 0;loop < OPTION_WINDOW_TYPE_MAX;loop++) {
677         if (m_option_window_info[loop].window == window) {
678             evas_object_del(NATIVE_WINDOW_CAST(window));
679             m_option_window_info[loop].window = SCLWINDOW_INVALID;
680         }
681     }
682 }
683
684 void CSCLCoreUIEFL::set_screen_rotation_degree(int degree)
685 {
686     m_rotation_degree = degree;
687 }
688
689 #ifdef WAYLAND
690 static void _render_pre_cb(void *data, Evas *e, void *event_info)
691 {
692     LOGD("_render_pre_cb() called, now invoking wl_input_panel_surface_set_ready()");
693
694     wl_input_panel_surface_set_ready(wlkb.ips, 1);
695
696     Evas_Object *main_window = NATIVE_WINDOW_CAST(data);
697     evas_event_callback_del_full(evas_object_evas_get(main_window),
698         EVAS_CALLBACK_RENDER_PRE, _render_pre_cb, main_window);
699
700     delete_render_pre_timer();
701 }
702
703 static Eina_Bool _render_pre_timeout(void *data)
704 {
705     LOGD("_render_pre_timer expired, forcing to call _render_pre_cb() callback");
706
707     _render_pre_cb(data, NULL, NULL);
708
709     return ECORE_CALLBACK_CANCEL;
710 }
711 #endif
712
713 void CSCLCoreUIEFL::process_keyboard_ui_state_change(KEYBOARD_UI_STATE state)
714 {
715 #ifdef WAYLAND
716     static Evas_Object *force_update_helper_obj = NULL;
717     static int force_update_num = 0;
718
719     if (state == KEYBOARD_UI_STATE_WILL_SHOW) {
720         evas_event_callback_add(evas_object_evas_get(NATIVE_WINDOW_CAST(m_main_window)),
721             EVAS_CALLBACK_RENDER_PRE, _render_pre_cb, (void*)m_main_window);
722         _render_pre_timer = ecore_timer_add(RENDER_PRE_TIMEOUT, _render_pre_timeout, (void*)m_main_window);
723         LOGD("Registered RENDER_PRE callback, _render_pre_cb() and a timer callback");
724     } else if (state == KEYBOARD_UI_STATE_DID_SHOW) {
725         LOGD("Forcing keyboard window to render : %d", force_update_num);
726
727         /* Since the ISE is waiting for RENDER_PRE event, we need to make sure the render event is
728          * occured on our ISE window. Since right now there is no proper way to trigger render event
729          * manually, we are creating a half transparent box above the keyboard window. Need to find
730          * more appropriate way to generate render event */
731         if (force_update_helper_obj) evas_object_del(force_update_helper_obj);
732         force_update_helper_obj = elm_bg_add(NATIVE_WINDOW_CAST(m_main_window));
733         evas_object_color_set(force_update_helper_obj, 255, 255, 255, 1);
734         evas_object_resize(force_update_helper_obj, 1, 1);
735         evas_object_move(force_update_helper_obj, force_update_num % 100, 0);
736         evas_object_layer_set(force_update_helper_obj, EVAS_LAYER_MAX);
737         evas_object_show(force_update_helper_obj);
738         force_update_num++;
739     } else if (state == KEYBOARD_UI_STATE_WILL_HIDE) {
740         if (force_update_helper_obj) evas_object_del(force_update_helper_obj);
741         force_update_helper_obj = NULL;
742     }
743 #endif
744 }