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