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