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