Upload initial version
[platform/core/uifw/libscl-ui-nui.git] / scl / sclwindows.cpp
1 /*
2  * Copyright (c) 2012 - 2014 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 "sclwindows.h"
19 #ifdef  __WIN32__
20 #include "sclwindows-win32.h"
21 #elif defined(__EFL__)
22 #include "sclwindows-efl.h"
23 #elif defined(__NUI__)
24 #include "sclwindows-nui.h"
25 #else
26 #include "sclwindows-gtk.h"
27 #endif
28 #include "scldebug.h"
29 #include "sclevents.h"
30 #include "sclresourcecache.h"
31 #include "sclcontroller.h"
32 #include "sclactionstate.h"
33 #include "sclres_manager.h"
34 #include "sclkeyfocushandler.h"
35 #include "sclanimator.h"
36 #include "scleventhandler.h"
37 #include <dlog.h>
38
39 using namespace scl;
40
41 CSCLWindows::CSCLWindows()
42 {
43     SCL_DEBUG();
44
45     sclint loop;
46
47     m_impl = NULL;
48
49     memset(&m_base_window_context, 0x00, sizeof(SclWindowContext));
50     memset(&m_magnifier_window_context, 0x00, sizeof(SclWindowContext));
51     memset(&m_dim_window_context, 0x00, sizeof(SclWindowContext));
52     memset(m_popup_window_context, 0x00, sizeof(SclWindowContext) * MAX_POPUP_WINDOW);
53
54     m_pending_update = FALSE;
55     m_initialized = FALSE;
56
57     for (loop = 0;loop < MAX_ZORDER_NUM;loop++) {
58         m_Z_order_list[loop] = SCLWINDOW_INVALID;
59     }
60 }
61
62 CSCLWindows::~CSCLWindows()
63 {
64     SCL_DEBUG();
65
66     if (m_impl) {
67         delete m_impl;
68         m_impl = NULL;
69     }
70 }
71
72 void CSCLWindows::init()
73 {
74     int loop;
75     CSCLWindowsImpl *impl = get_scl_windows_impl();
76     if (impl) {
77         impl->init();
78     }
79     for (loop = 0;loop < MAX_ZORDER_NUM;loop++) {
80         m_Z_order_list[loop] = SCLWINDOW_INVALID;
81     }
82     m_initialized = TRUE;
83 }
84
85 void CSCLWindows::fini()
86 {
87     CSCLWindowsImpl* impl = get_scl_windows_impl();
88
89     if (impl) {
90         impl->fini();
91
92         if (SCLWINDOW_INVALID != m_base_window_context.window) {
93             impl->destroy_window(m_base_window_context.window);
94             m_base_window_context.window = SCLWINDOW_INVALID;
95         }
96
97         if (SCLWINDOW_INVALID != m_magnifier_window_context.window) {
98             impl->destroy_window(m_magnifier_window_context.window);
99             m_magnifier_window_context.window = SCLWINDOW_INVALID;
100         }
101
102         if (SCLWINDOW_INVALID != m_dim_window_context.window) {
103             impl->destroy_window(m_dim_window_context.window);
104             m_dim_window_context.window = SCLWINDOW_INVALID;
105         }
106
107         for (int loop = 0;loop < MAX_POPUP_WINDOW;loop++) {
108             if (m_popup_window_context[loop].window != SCLWINDOW_INVALID) {
109                 if (!m_popup_window_context[loop].is_virtual) {
110                     impl->destroy_window(m_popup_window_context[loop].window);
111                 }
112                 m_popup_window_context[loop].window = SCLWINDOW_INVALID;
113             }
114         }
115     }
116
117     m_initialized = FALSE;
118 }
119
120 CSCLWindowsImpl*
121 CSCLWindows::get_scl_windows_impl()
122 {
123     if (m_impl == 0) {
124 #ifdef  __WIN32__
125         m_impl = new CSCLWindowsImplWin32;
126 #elif defined(__EFL__)
127         m_impl = new CSCLWindowsImplEfl;
128 #elif defined(__NUI__)
129         m_impl = new CSCLWindowsImplNui;
130 #else
131         m_impl = new CSCLWindowsImplGtk;
132 #endif
133     }
134     return m_impl;
135 }
136
137 CSCLWindows*
138 CSCLWindows::get_instance()
139 {
140     static CSCLWindows instance;
141     return &instance;
142 }
143
144 sclwindow CSCLWindows::open_popup(const SclWindowOpener opener, const SclRectangle &geometry, sclshort inputmode, sclshort layout, SCLPopupType popup_type, sclboolean is_virtual, sclboolean use_dim_window, sclint img_offset_x, sclint img_offset_y, sclint timeout)
145 {
146     sclwindow window = SCLWINDOW_INVALID;
147
148     CSCLEvents *events = CSCLEvents::get_instance();
149     CSCLActionState *state = CSCLActionState::get_instance();
150     CSCLController *controller = CSCLController::get_instance();
151     CSCLResourceCache *cache = CSCLResourceCache::get_instance();
152     CSCLContext *context = CSCLContext::get_instance();
153     CSCLWindows *windows = CSCLWindows::get_instance();
154     CSCLUtils *utils = CSCLUtils::get_instance();
155
156     if (events && state && controller && cache && context && windows && utils) {
157         for (sclint loop = 0;loop < MAX_POPUP_WINDOW;loop++) {
158             if (m_popup_window_context[loop].window != SCLWINDOW_INVALID) {
159                 if (m_popup_window_context[loop].layout == layout) return SCLWINDOW_INVALID;
160             }
161         }
162
163         window = create_window(opener, geometry, inputmode, layout, popup_type, is_virtual, img_offset_x, img_offset_y, timeout);
164         events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
165         if (timeout > 0) {
166             events->create_timer(SCL_TIMER_POPUP_TIMEOUT, timeout, layout);
167         }
168
169         LOGD("create window (%p) x: %d, y:%d, width:%d, height:%d , layout:%d, popuptype:%d",
170             window, geometry.x, geometry.y, geometry.width, geometry.height, layout, popup_type);
171
172         events->connect_window_events(window, SCL_EVENT_MOUSE | SCL_EVENT_EXPOSE);
173         controller->handle_engine_signal(SCL_SIG_POPUP_SHOW, window);
174
175         /* Shows the dim window if it uses the dim_window */
176         if (use_dim_window) {
177             sclwindow dim_window = get_dim_window();
178
179             /* Currently, get_window_rect does not work normally (need to check X). So I have commented it*/
180             SclRectangle rect;
181             get_window_rect(get_base_window(), &rect);
182             resize_window(dim_window, rect.width, rect.height);
183             move_window(dim_window, rect.x, rect.y);
184             events->connect_window_events(dim_window, SCL_EVENT_MOUSE);
185             /*If we use transient_for them the ISE will occur some crash. It needs to check X11*/
186             set_parent(opener.window, dim_window);
187             SclWindowContext *dim_window_context = get_window_context(get_dim_window());
188             if (dim_window_context) {
189                 if (dim_window_context->is_virtual) {
190                     set_parent(opener.window, window);
191                 } else {
192                     set_parent(dim_window, window);
193                 }
194             }
195             show_window(dim_window);
196         } else {
197             /*If we use transient_for them the ISE will occur some crash. It needs to check X11*/
198             set_parent(opener.window, window);
199         }
200         show_window(window);
201
202         push_window_in_Z_order_list(window);
203
204         state->set_cur_action_state(ACTION_STATE_POPUP_INIT);
205
206         const SclLayout *cur_layout = cache->get_cur_layout(window);
207         if (cur_layout) {
208             /* If the newly opened popup window has POPUP_GRAB style, lets press the nearest button on the new window */
209             if (cur_layout->style == LAYOUT_STYLE_POPUP_GRAB) {
210                 sclwindow pressed_window = context->get_cur_pressed_window(context->get_last_touch_device_id());
211                 sclbyte pressed_key = context->get_cur_pressed_key(context->get_last_touch_device_id());
212
213                 const SclLayoutKeyCoordinate* coordinate = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
214
215                 sclwindow moving_window = context->get_cur_moving_window(context->get_last_touch_device_id());
216                 SclPoint moving_point = context->get_cur_moving_point(context->get_last_touch_device_id());
217                 SclWindowContext *moving_window_context = windows->get_window_context(moving_window);
218                 SclWindowContext *popup_window_context = windows->get_window_context(window);
219                 if (moving_window_context && popup_window_context) {
220                     moving_point.x =
221                         (moving_window_context->geometry.x - popup_window_context->geometry.x) + moving_point.x;
222                     moving_point.y =
223                         (moving_window_context->geometry.y - popup_window_context->geometry.y) + moving_point.y;
224                 }
225
226                 /* Find the nearest button on the autopopup window */
227                 sclboolean ended = FALSE;
228                 sclfloat min_dist = (float)((sclu32)(-1));
229                 sclint min_dist_index = NOT_USED;
230                 for (sclint loop = 0;loop < MAX_KEY && !ended;loop++) {
231                     SclButtonContext *popup_button_context = cache->get_cur_button_context(window, loop);
232                     const SclLayoutKeyCoordinate *popup_coordinate = cache->get_cur_layout_key_coordinate(window, loop);
233                     if (popup_button_context && popup_coordinate) {
234                         if (!(popup_button_context->used)) {
235                             ended = TRUE;
236                         } else if (popup_button_context->state != BUTTON_STATE_DISABLED &&
237                             popup_coordinate->button_type != BUTTON_TYPE_UIITEM) {
238                                 if (popup_coordinate) {
239                                     float dist = utils->get_approximate_distance(moving_point.x, moving_point.y,
240                                         popup_coordinate->x + (popup_coordinate->width / 2) -
241                                         cur_layout->mouse_manipulate_x,
242                                         popup_coordinate->y + (popup_coordinate->height / 2) -
243                                         cur_layout->mouse_manipulate_y);
244                                     if (dist < min_dist) {
245                                         min_dist_index = loop;
246                                         min_dist = dist;
247                                     }
248                                 }
249                         }
250                     }
251                 }
252                 /* When we found the nearest button, make it pressed */
253                 if (min_dist_index != NOT_USED) {
254                     const SclLayoutKeyCoordinate *popup_coordinate =
255                         cache->get_cur_layout_key_coordinate(window, min_dist_index);
256                     if (popup_coordinate) {
257                         sclint x = popup_coordinate->x + (popup_coordinate->width / 2) -
258                             cur_layout->mouse_manipulate_x;
259                         sclint y = popup_coordinate->y + (popup_coordinate->height / 2) -
260                             cur_layout->mouse_manipulate_y;
261                         controller->mouse_press(window, x, y, context->get_last_touch_device_id());
262                     }
263                 }
264
265                 /* The below code block seems unnecessary since we already invoked mouse_press() */
266                 /*context->set_cur_pressed_window(context->get_last_touch_device_id(), window);
267                 context->set_cur_pressed_key(context->get_last_touch_device_id(), min_dist_index);
268                 if (button_context) {
269                     button_context->state = BUTTON_STATE_NORMAL;
270                 }*/
271
272                 if (windows && coordinate)
273                     windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
274             }
275         }
276     }
277
278     return window;
279 }
280
281 bool CSCLWindows::close_popup(sclwindow window, sclboolean timed_out)
282 {
283     LOGD("close_popup window (%p)", window);
284
285     CSCLEventHandler *handler = CSCLEventHandler::get_instance();
286
287     if (handler) {
288         SclNotiPopupClosingDesc desc;
289         desc.ui_event_desc = NULL;
290         desc.input_mode = NULL;
291         desc.timed_out = timed_out;
292
293         SclResParserManager *sclres_manager = SclResParserManager::get_instance();
294         if (sclres_manager) {
295             const PSclInputModeConfigure sclres_input_mode_configure =
296                 sclres_manager->get_input_mode_configure_table();
297             SclWindowContext *window_context = get_window_context(window);
298             if (window_context && sclres_input_mode_configure) {
299                 if (scl_check_arrindex(window_context->inputmode, MAX_SCL_INPUT_MODE)) {
300                     desc.input_mode = sclres_input_mode_configure[window_context->inputmode].name;
301                 }
302             }
303         }
304
305         if (SCL_EVENT_PASS_ON == handler->on_event_notification(SCL_UINOTITYPE_POPUP_CLOSING, &desc)) {
306             SclNotiPopupClosedDesc closed_desc;
307             closed_desc.ui_event_desc = NULL;
308             closed_desc.input_mode = desc.input_mode;
309             closed_desc.timed_out = desc.timed_out;
310             handler->on_event_notification(SCL_UINOTITYPE_POPUP_CLOSED, &desc);
311
312             CSCLKeyFocusHandler *focus_handler = CSCLKeyFocusHandler::get_instance();
313             if (focus_handler) {
314                 focus_handler->popup_closed(window);
315             }
316             pop_window_in_Z_order_list(window);
317
318             hide_window(get_dim_window());
319             hide_window(window);
320             return destroy_window(window);
321         }
322     }
323
324     return FALSE;
325 }
326
327 bool CSCLWindows::close_all_popups(sclwindow skip_window /* = SCLWINDOW_INVALID */, sclboolean timed_out)
328 {
329     sclboolean all_closed = TRUE;
330     /* Close all the popup windows except the targetWindow */
331     int loop = 0;
332     sclwindow window;
333     do {
334         window = get_nth_popup_window(loop);
335         if (window) {
336             if (window != skip_window) {
337                 close_popup(window, timed_out);
338             } else {
339                 all_closed = FALSE;
340             }
341         }
342         loop++;
343     } while (window);
344
345     /* If there is a popup still opened, don't destroy POPUP_TIMEOUT timer */
346     return all_closed;
347 }
348
349 sclwindow
350 CSCLWindows::create_base_window(const sclwindow parent, scl16 width, scl16 height)
351 {
352     SCL_DEBUG();
353
354     if (m_initialized) {
355         CSCLWindowsImpl* impl = get_scl_windows_impl();
356
357         m_base_window_context.hidden = TRUE;
358         m_base_window_context.geometry.width = width;
359         m_base_window_context.geometry.height = height;
360         m_base_window_context.is_virtual = FALSE;
361         m_base_window_context.popup_type = POPUP_TYPE_NONE;
362         m_base_window_context.opener.window = parent;
363         m_base_window_context.geometry.x = m_base_window_context.geometry.y = 0;
364         m_base_window_context.etc_info = NULL;
365         m_base_window_context.window = SCLWINDOW_INVALID;
366
367         if (impl) {
368             m_base_window_context.window = impl->create_base_window(parent, &m_base_window_context, width, height);
369             push_window_in_Z_order_list(m_base_window_context.window);
370         }
371     }
372
373     // Update the position information
374     //get_window_context(parent, TRUE);
375
376     return m_base_window_context.window;
377 }
378
379 /**
380  * Creates a new top-level window
381  *
382  * @Code
383  *  CSCLGwes* gwes = CSCLGwes::get_instance();
384  *  sclwindow popupWindow = gwes->m_windows->create_window(window, 100, 500, 200, 100, 4, POPUP_TYPE_BTN_RELEASE_POPUP, FALSE);
385  *  if (popupWindow != NULL) {
386  *     gwes->m_events->connect_window_events(popupWindow, SCL_EVENT_MOUSE | SCL_EVENT_EXPOSE);
387  *      cache->recompute_layout(popupWindow);
388  *      gwes->m_windows->show_window(popupWindow);
389  *  }
390  */
391 sclwindow
392 CSCLWindows::create_window(const SclWindowOpener opener, const SclRectangle &geometry, sclshort inputmode, sclshort layout, SCLPopupType popup_type, sclboolean is_virtual, sclint img_offset_x, sclint img_offset_y, sclint timeout)
393 {
394     SCL_DEBUG();
395
396     CSCLWindowsImpl* impl = get_scl_windows_impl();
397     sclwindow window = SCLWINDOW_INVALID;
398
399     if (impl) {
400         for (sclint loop = 0;loop < MAX_POPUP_WINDOW;loop++) {
401             if (m_popup_window_context[loop].window == SCLWINDOW_INVALID) {
402                 m_popup_window_context[loop].hidden = TRUE;
403                 m_popup_window_context[loop].opener = opener;
404                 m_popup_window_context[loop].etc_info = NULL;
405                 m_popup_window_context[loop].inputmode = inputmode;
406                 m_popup_window_context[loop].layout = layout;
407                 m_popup_window_context[loop].popup_type = popup_type;
408                 m_popup_window_context[loop].is_virtual = is_virtual;
409
410                 m_popup_window_context[loop].geometry = geometry;
411
412                 m_popup_window_context[loop].layout_image_offset.x = img_offset_x;
413                 m_popup_window_context[loop].layout_image_offset.y = img_offset_y;
414
415                 m_popup_window_context[loop].timeout = timeout;
416
417                 if (!is_virtual) {
418                     window = impl->create_window(opener.window,
419                         &(m_popup_window_context[loop]), geometry.width, geometry.height);
420                 } else {
421                     window = reinterpret_cast<sclwindow>(loop + 1);
422                 }
423                 if (window) {
424                     m_popup_window_context[loop].window = window;
425                 }
426                 //set_window_rotation(window, context->get_rotation_degree());
427                 if (!m_popup_window_context[loop].is_virtual) {
428                     impl->move_window(window, geometry.x, geometry.y);
429                 }
430                 break;
431             }
432         }
433
434         // Update the position information
435         //get_window_context(window, TRUE);
436
437         if (window == NULL) {
438             LOGW("Failed to create a new window. The size of window buffer has exceeded.");
439         }
440     }
441     return window;
442 }
443
444 sclwindow
445 CSCLWindows::create_magnifier_window(const sclwindow parent, scl16 x, scl16 y, scl16 width, scl16 height)
446 {
447     SCL_DEBUG();
448
449     CSCLWindowsImpl* impl = get_scl_windows_impl();
450     sclwindow window = SCLWINDOW_INVALID;
451
452     if (impl && m_initialized) {
453         if (m_magnifier_window_context.window == SCLWINDOW_INVALID) {
454             window = impl->create_magnifier_window(parent, &m_magnifier_window_context, width, height);
455             impl->set_keep_above(window, TRUE);
456             if (window) {
457                 m_magnifier_window_context.window = window;
458                 m_magnifier_window_context.geometry.width = width;
459                 m_magnifier_window_context.geometry.height = height;
460                 m_magnifier_window_context.hidden = TRUE;
461             }
462         } else {
463             window = m_magnifier_window_context.window;
464         }
465         set_parent(parent, window);
466
467         if (window == NULL) {
468             LOGW("Failed to create a new window. The size of window buffer has exceeded.");
469         } else {
470             LOGD("Magnifier Window %p created", window);
471         }
472     }
473
474     // Update the position information
475     //get_window_context(window, TRUE);
476
477     return window;
478 }
479
480 sclwindow
481 CSCLWindows::get_magnifier_window()
482 {
483     SCL_DEBUG();
484     return m_magnifier_window_context.window;
485 }
486
487 sclwindow
488 CSCLWindows::create_dim_window(const sclwindow parent, SclWindowContext *window_context, scl16 width, scl16 height)
489 {
490     SCL_DEBUG();
491
492     CSCLWindowsImpl* impl = get_scl_windows_impl();
493     sclwindow window = SCLWINDOW_INVALID;
494
495     SclResParserManager *sclres_manager = SclResParserManager::get_instance();
496     PSclDefaultConfigure default_configure = NULL;
497     if (sclres_manager) {
498         default_configure = sclres_manager->get_default_configure();
499     }
500
501     if (impl && m_initialized && default_configure) {
502         if (m_dim_window_context.window == NULL) {
503             m_dim_window_context.hidden = TRUE;
504             if (default_configure->use_actual_dim_window) {
505                 window = impl->create_dim_window(parent, &m_dim_window_context, width, height);
506             } else {
507                 window = reinterpret_cast<sclwindow>(SCLWINDOW_VIRTUAL_DIM);
508                 m_dim_window_context.is_virtual = TRUE;
509             }
510             if (window) {
511                 m_dim_window_context.window = window;
512             }
513         } else {
514             window = m_dim_window_context.window;
515         }
516
517         if (window == NULL) {
518             LOGW("Failed to create a new window. The size of window buffer has exceeded");
519         }
520     }
521
522     return window;
523 }
524
525 sclwindow
526 CSCLWindows::get_dim_window()
527 {
528     SCL_DEBUG();
529     return m_dim_window_context.window;
530 }
531
532 bool
533 CSCLWindows::destroy_window(sclwindow window)
534 {
535     SCL_DEBUG();
536
537     CSCLWindowsImpl* impl = get_scl_windows_impl();
538     sclboolean ret = FALSE;
539
540     if (impl) {
541         if (window == m_base_window_context.window) {
542             impl->destroy_window(window);
543             memset(&m_base_window_context, 0x00, sizeof(SclWindowContext));
544             m_base_window_context.window = SCLWINDOW_INVALID;
545             ret = TRUE;
546         } else if (window == m_magnifier_window_context.window) {
547             impl->destroy_window(window);
548             memset(&m_magnifier_window_context, 0x00, sizeof(SclWindowContext));
549             m_magnifier_window_context.window = SCLWINDOW_INVALID;
550             ret = TRUE;
551         } else if (window == m_dim_window_context.window) {
552             impl->destroy_window(window);
553             memset(&m_dim_window_context, 0x00, sizeof(SclWindowContext));
554             m_dim_window_context.window = SCLWINDOW_INVALID;
555             ret = TRUE;
556         } else {
557             for (sclint loop = 0;loop < MAX_POPUP_WINDOW;loop++) {
558                 if (m_popup_window_context[loop].window == window) {
559                     impl->destroy_window(window);
560                     memset(&m_popup_window_context[loop], 0x00, sizeof(SclWindowContext));
561                     ret = TRUE;
562                     m_popup_window_context[loop].window = SCLWINDOW_INVALID;
563                     break;
564                 }
565             }
566         }
567     }
568
569     return ret;
570 }
571
572 sclwindow
573 CSCLWindows::get_base_window()
574 {
575     SCL_DEBUG();
576
577     return m_base_window_context.window;
578 }
579
580 sclboolean
581 CSCLWindows::is_base_window(sclwindow window)
582 {
583     SCL_DEBUG();
584
585     sclboolean ret = FALSE;
586
587     if (window != SCLWINDOW_INVALID) {
588         if (window == m_base_window_context.window) {
589             ret = TRUE;
590         }
591     }
592
593     return ret;
594 }
595
596 sclwindow
597 CSCLWindows::find_by_etcinfo(void* etc_info)
598 {
599     SCL_DEBUG();
600
601     sclwindow ret = SCLWINDOW_INVALID;
602
603     if (etc_info == m_base_window_context.etc_info) {
604         ret = m_base_window_context.window;
605     } else if (etc_info == m_magnifier_window_context.etc_info) {
606         ret = m_magnifier_window_context.window;
607     } else if (etc_info == m_dim_window_context.etc_info) {
608         ret = m_dim_window_context.window;
609     } else {
610         for (sclint loop = 0;loop < MAX_POPUP_WINDOW;loop++) {
611             if (etc_info == m_popup_window_context[loop].etc_info) {
612                 ret = m_popup_window_context[loop].window;
613                 break;
614             }
615         }
616     }
617
618     return ret;
619 }
620
621 SclWindowContext*
622 //CSCLWindows::get_window_context(sclwindow window, sclboolean geometry_update)
623 CSCLWindows::get_window_context(sclwindow window)
624 {
625     SCL_DEBUG();
626
627     SclWindowContext* ret = NULL;
628
629     if (window == m_base_window_context.window) {
630         /*if (geometry_update) {
631             SclRectangle rect;
632             get_window_rect(window, &rect);
633             m_base_window_context.geometry.x = rect.x;
634             m_base_window_context.geometry.y = rect.y;
635         }*/
636         ret = &m_base_window_context;
637     } else if (window == m_magnifier_window_context.window) {
638         ret = &m_magnifier_window_context;
639     } else if (window == m_dim_window_context.window) {
640         ret = &m_dim_window_context;
641     } else {
642         for (sclint loop = 0;loop < MAX_POPUP_WINDOW;loop++) {
643             if (m_popup_window_context[loop].window == window) {
644                 /*if (geometry_update) {
645                     SclRectangle rect;
646                     get_window_rect(window, &rect);
647                     m_popup_window_context[loop].geometry.x = rect.x;
648                     m_popup_window_context[loop].geometry.y = rect.y;
649                 }*/
650                 ret = &m_popup_window_context[loop];
651                 break;
652             }
653         }
654     }
655
656     return ret;
657 }
658
659 void
660 CSCLWindows::set_window_context(sclwindow window, SclWindowContext* context)
661 {
662     SCL_DEBUG();
663
664     if (window == m_base_window_context.window) {
665         memcpy(&m_base_window_context, context, sizeof(SclWindowContext));
666     } else {
667         for (sclint loop = 0;loop < MAX_POPUP_WINDOW;loop++) {
668             if (m_popup_window_context[loop].window == window) {
669                 memcpy(&m_popup_window_context[loop], context, sizeof(SclWindowContext));
670                 break;
671             }
672         }
673     }
674 }
675
676 scl8
677 CSCLWindows::find_popup_window_index(sclwindow window)
678 {
679     SCL_DEBUG();
680
681     scl8 ret = NOT_USED;
682
683     for (sclint loop = 0;loop < MAX_POPUP_WINDOW;loop++) {
684         if (m_popup_window_context[loop].window == window) {
685             ret = loop;
686             break;
687         }
688     }
689
690     return ret;
691 }
692
693 void
694 CSCLWindows::move_window(const sclwindow window, scl16 x, scl16 y)
695 {
696     SCL_DEBUG();
697
698     sclboolean is_virtual = FALSE;
699     if (window == m_base_window_context.window) {
700         m_base_window_context.geometry.x = x;
701         m_base_window_context.geometry.y = y;
702         is_virtual = m_base_window_context.is_virtual;
703     } else if (window == m_magnifier_window_context.window) {
704         m_magnifier_window_context.geometry.x = x;
705         m_magnifier_window_context.geometry.y = y;
706         is_virtual = m_magnifier_window_context.is_virtual;
707     } else if (window == m_dim_window_context.window) {
708         m_dim_window_context.geometry.x = x;
709         m_dim_window_context.geometry.y = y;
710         is_virtual = m_dim_window_context.is_virtual;
711     } else {
712         for (sclint loop = 0;loop < MAX_POPUP_WINDOW;loop++) {
713             if (m_popup_window_context[loop].window == window) {
714                 m_popup_window_context[loop].geometry.x = x;
715                 m_popup_window_context[loop].geometry.y = y;
716                 is_virtual = m_popup_window_context[loop].is_virtual;
717                 break;
718             }
719         }
720     }
721     if (!is_virtual) {
722         CSCLWindowsImpl* impl = get_scl_windows_impl();
723         if (impl) {
724             impl->move_window(window, x, y);
725         }
726     }
727 }
728
729 void
730 CSCLWindows::resize_window(const sclwindow window, scl16 width, scl16 height)
731 {
732     SCL_DEBUG();
733
734     sclboolean is_virtual = FALSE;
735     if (window == m_base_window_context.window) {
736         m_base_window_context.geometry.width = width;
737         m_base_window_context.geometry.height = height;
738         is_virtual = m_base_window_context.is_virtual;
739     } else if (window == m_magnifier_window_context.window) {
740         m_magnifier_window_context.geometry.width = width;
741         m_magnifier_window_context.geometry.height = height;
742         is_virtual = m_magnifier_window_context.is_virtual;
743     } else if (window == m_dim_window_context.window) {
744         m_dim_window_context.geometry.width = width;
745         m_dim_window_context.geometry.height = height;
746         is_virtual = m_dim_window_context.is_virtual;
747     } else {
748         for (sclint loop = 0;loop < MAX_POPUP_WINDOW;loop++) {
749             if (m_popup_window_context[loop].window == window) {
750                 m_popup_window_context[loop].geometry.width = width;
751                 m_popup_window_context[loop].geometry.height = height;
752                 is_virtual = m_popup_window_context[loop].is_virtual;
753                 break;
754             }
755         }
756     }
757     if (!is_virtual) {
758         CSCLWindowsImpl* impl = get_scl_windows_impl();
759         if (impl) {
760             impl->resize_window(window, width, height);
761         }
762     }
763 }
764
765 void
766 CSCLWindows::move_resize_window(const sclwindow window, scl16 x, scl16 y, scl16 width, scl16 height)
767 {
768     SCL_DEBUG();
769
770     sclboolean is_virtual = FALSE;
771     if (window == m_base_window_context.window) {
772         m_base_window_context.geometry.x = x;
773         m_base_window_context.geometry.y = y;
774         m_base_window_context.geometry.width = width;
775         m_base_window_context.geometry.height = height;
776         is_virtual = m_base_window_context.is_virtual;
777     } else if (window == m_magnifier_window_context.window) {
778         m_magnifier_window_context.geometry.x = x;
779         m_magnifier_window_context.geometry.y = y;
780         m_magnifier_window_context.geometry.width = width;
781         m_magnifier_window_context.geometry.height = height;
782         is_virtual = m_magnifier_window_context.is_virtual;
783     } else if (window == m_dim_window_context.window) {
784         m_dim_window_context.geometry.x = x;
785         m_dim_window_context.geometry.y = y;
786         m_dim_window_context.geometry.width = width;
787         m_dim_window_context.geometry.height = height;
788         is_virtual = m_dim_window_context.is_virtual;
789     } else {
790         for (sclint loop = 0;loop < MAX_POPUP_WINDOW;loop++) {
791             if (m_popup_window_context[loop].window == window) {
792                 m_popup_window_context[loop].geometry.x = x;
793                 m_popup_window_context[loop].geometry.y = y;
794                 m_popup_window_context[loop].geometry.width = width;
795                 m_popup_window_context[loop].geometry.height = height;
796                 is_virtual = m_popup_window_context[loop].is_virtual;
797                 break;
798             }
799         }
800     }
801     if (!is_virtual) {
802         CSCLWindowsImpl* impl = get_scl_windows_impl();
803         if (impl) {
804             impl->move_resize_window(window, x, y, width, height);
805         }
806     }
807 }
808
809
810 /* Push given window into a Z-order list */
811 void CSCLWindows::push_window_in_Z_order_list(sclwindow window)
812 {
813     SCL_DEBUG();
814
815     sclint loop;
816
817     for (loop = 0;loop < MAX_ZORDER_NUM;loop++) {
818         if (m_Z_order_list[loop] == SCLWINDOW_INVALID) {
819             m_Z_order_list[loop] = window;
820             return;
821         }
822     }
823 }
824
825 /* Pop given window from a Z-order list */
826 void CSCLWindows::pop_window_in_Z_order_list(sclwindow window)
827 {
828     SCL_DEBUG();
829
830     sclint loop;
831     sclboolean found = FALSE;
832
833     for (loop = 0;loop < MAX_ZORDER_NUM - 1;loop++) {
834         if (m_Z_order_list[loop] == window || found) {
835             found = TRUE;
836             m_Z_order_list[loop] = m_Z_order_list[loop + 1];
837         }
838     }
839
840     m_Z_order_list[MAX_ZORDER_NUM - 1] = SCLWINDOW_INVALID;
841 }
842
843 /* Search n-th window in the Z-order stack, starting from the top (TOPMOST window would be the 0 index) */
844 sclwindow CSCLWindows::get_nth_window_in_Z_order_list(sclbyte index)
845 {
846     SCL_DEBUG();
847
848     sclint loop;
849
850     for (loop = MAX_ZORDER_NUM - 1;loop >= 0;loop--) {
851         if (m_Z_order_list[loop] != SCLWINDOW_INVALID) {
852             if (index == 0) {
853                 return m_Z_order_list[loop];
854             }
855             index--;
856         }
857     }
858
859     return SCLWINDOW_INVALID;
860 }
861
862 sclwindow CSCLWindows::get_nth_popup_window(sclbyte index)
863 {
864     SCL_DEBUG();
865
866     scl_assert_return_null(index >= 0 && index < MAX_POPUP_WINDOW);
867
868     if (index < MAX_POPUP_WINDOW) {
869         return m_popup_window_context[index].window;
870     }
871
872     return SCLWINDOW_INVALID;
873 }
874
875 sclbyte CSCLWindows::get_Z_order(sclwindow window)
876 {
877     SCL_DEBUG();
878
879     sclbyte loop;
880     for (loop = 0;loop < MAX_ZORDER_NUM;loop++) {
881         if (m_Z_order_list[loop] == window) {
882             return loop;
883         }
884     }
885     return NOT_USED;
886 }
887
888 void CSCLWindows::set_parent(const sclwindow parent, const sclwindow window)
889 {
890     /* Do not set parent if the window is a virtual window */
891     //SclWindowContext *window_context = get_window_context(window, FALSE);
892     SclWindowContext *window_context = get_window_context(window);
893     if (window_context) {
894         if (!(window_context->is_virtual)) {
895             CSCLWindowsImpl* impl = get_scl_windows_impl();
896             if (impl) {
897                 impl->set_parent(parent, window);
898             }
899         }
900     }
901 }
902
903 void CSCLWindows::set_window_rotation(const sclwindow window, SCLRotation rotation)
904 {
905     SCL_DEBUG();
906
907     CSCLWindowsImpl* impl = get_scl_windows_impl();
908     CSCLUtils *utils = CSCLUtils::get_instance();
909
910     if (impl && utils) {
911         if (window == NULL) {
912             impl->set_window_rotation(m_base_window_context.window, rotation);
913             if (SCLWINDOW_INVALID != m_magnifier_window_context.window) {
914                 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
915                 PSclMagnifierWndConfigure magnifier_configure = NULL;
916                 if (sclres_manager) {
917                     magnifier_configure = sclres_manager->get_magnifier_configure();
918                 }
919                 if (magnifier_configure) {
920                     m_magnifier_window_context.geometry.width =
921                         magnifier_configure->width * utils->get_custom_scale_rate_x();
922                     m_magnifier_window_context.geometry.height =
923                         magnifier_configure->height * utils->get_custom_scale_rate_y();
924
925                     impl->set_window_rotation(m_magnifier_window_context.window, rotation);
926                 }
927             }
928
929             if (SCLWINDOW_INVALID != m_dim_window_context.window) {
930                 /* For individual window rotation */
931                 impl->set_window_rotation(m_dim_window_context.window, rotation);
932                 //resize_window(m_dim_window_context.window, m_base_window_context.width, m_base_winctx.height);
933                 //move_window(m_dim_window_context.window, m_base_window_context.x, m_base_winctx.y);
934                 hide_window(m_dim_window_context.window);
935             }
936             /* For individual window rotation
937             for (int loop = 0;loop < MAX_POPUP_WINDOW;loop++) {
938                 if (m_popup_window_context[loop].window != SCLWINDOW_INVALID) {
939                     if (!m_popup_window_context[loop].isVirtual) {
940                         get_scl_windows_impl()->set_window_rotation(m_popup_window_context[loop].window, degree);
941                     }
942                 }
943             }
944             */
945         } else {
946             impl->set_window_rotation(window, rotation);
947             LOGD("## set_window_rotation : %d", rotation);
948         }
949     }
950
951     // Update the position information
952     //get_window_context(window, TRUE);
953     SclWindowContext *window_context = get_window_context(window);
954     if (window_context) {
955         get_window_rect(window, &(window_context->geometry));
956     }
957 }
958
959
960 void
961 CSCLWindows::show_window(const sclwindow window, sclboolean queue /*= FALSE*/)
962 {
963     SCL_DEBUG();
964
965     if (window == m_base_window_context.window) {
966         m_base_window_context.hidden = FALSE;
967     } else if (window == m_magnifier_window_context.window) {
968         m_magnifier_window_context.hidden = FALSE;
969     } else if (window == m_dim_window_context.window) {
970         m_dim_window_context.hidden = FALSE;
971     } else {
972         for (sclint loop = 0;loop < MAX_POPUP_WINDOW;loop++) {
973             if (m_popup_window_context[loop].window == window) {
974                 m_popup_window_context[loop].hidden = FALSE;
975                 break;
976             }
977         }
978     }
979
980     CSCLWindowsImpl* impl = get_scl_windows_impl();
981     if (impl) {
982         impl->show_window(window, queue);
983     }
984 }
985
986 void
987 CSCLWindows::hide_window(const sclwindow window, sclboolean force /*= FALSE*/)
988 {
989     SCL_DEBUG();
990
991     if (window == m_base_window_context.window) {
992         m_base_window_context.hidden = TRUE;
993     } else if (window == m_magnifier_window_context.window) {
994         m_magnifier_window_context.hidden = TRUE;
995     } else if (window == m_dim_window_context.window) {
996         m_dim_window_context.hidden = TRUE;
997     } else {
998         for (sclint loop = 0;loop < MAX_POPUP_WINDOW;loop++) {
999             if (m_popup_window_context[loop].window == window) {
1000                 m_popup_window_context[loop].hidden = TRUE;
1001                 break;
1002             }
1003         }
1004     }
1005
1006     CSCLWindowsImpl* impl = get_scl_windows_impl();
1007     if (impl) {
1008         impl->hide_window(window, force);
1009     }
1010 }
1011
1012 void
1013 CSCLWindows::set_keep_above(const sclwindow window, sclboolean keep_above)
1014 {
1015     CSCLWindowsImpl* impl = get_scl_windows_impl();
1016     if (impl) {
1017         impl->set_keep_above(window, keep_above);
1018     }
1019 }
1020
1021 void
1022 CSCLWindows::set_update_pending(sclboolean pend)
1023 {
1024     m_pending_update = pend;
1025     if (!pend) {
1026         update_window(m_base_window_context.window);
1027     }
1028 }
1029
1030 sclboolean
1031 CSCLWindows::get_update_pending()
1032 {
1033     return m_pending_update;
1034 }
1035
1036 void
1037 CSCLWindows::update_window(const sclwindow window,
1038                            scl16 x /*= 0*/, scl16 y /*= 0*/, scl16 width /*= 0*/, scl16 height /*= 0*/ )
1039 {
1040     if (!m_pending_update) {
1041         CSCLWindowsImpl* impl = get_scl_windows_impl();
1042         CSCLAnimator *animator = CSCLAnimator::get_instance();
1043         CSCLResourceCache *cache = CSCLResourceCache::get_instance();
1044         CSCLContext *context = CSCLContext::get_instance();
1045         CSCLKeyFocusHandler* focus_handler = CSCLKeyFocusHandler::get_instance();
1046
1047         if (impl) {
1048             impl->update_window(window, x, y, width, height);
1049
1050             /* If we are not updating the whole screen */
1051             if (animator && cache && context && focus_handler && (x != 0 || y != 0 || width != 0 || height != 0)) {
1052                 sclboolean draw_highlight_ui = TRUE;
1053                 SclAnimationState *state = NULL;
1054
1055                 if (animator) {
1056                     sclint id = animator->find_animator_by_type(ANIMATION_TYPE_HIGHLIGHT_UI);
1057                     state = animator->get_animation_state(id);
1058                 }
1059                 if (state) {
1060                     // If currently the highlight UI is being animated, don't update here
1061                     if (state->active) {
1062                         draw_highlight_ui = FALSE;
1063                     }
1064                 }
1065
1066                 SclWindowContext *window_context = get_window_context(window);
1067                 if (focus_handler->get_current_focus_window() == window) {
1068                     sclint startx = 0;
1069                     sclint starty = 0;
1070
1071                     SclWindowContext *base_window_context = get_window_context(get_base_window());
1072                     if (window_context && base_window_context) {
1073                         if (window_context->is_virtual) {
1074                             startx += (window_context->geometry.x - base_window_context->geometry.x);
1075                             starty += (window_context->geometry.y - base_window_context->geometry.y);
1076                         }
1077                     }
1078                     if (draw_highlight_ui && context->get_highlight_ui_enabled()) {
1079                         const SclLayoutKeyCoordinate *coordinate = NULL;
1080                         scl8 current_key_index = focus_handler->get_current_focus_key();
1081                         coordinate = cache->get_cur_layout_key_coordinate(window, current_key_index);
1082                         if (coordinate) {
1083                             // Update the highlighted area as well
1084                             LOGD("startx: %d, starty: %d", startx, starty);
1085                             LOGD("coordinate x(%d), y(%d), w(%d), h(%d)", coordinate->x, coordinate->y, coordinate->width, coordinate->height);
1086
1087                             impl->update_window(window, startx + coordinate->x, starty + coordinate->y, coordinate->width, coordinate->height);
1088                         }
1089                     }
1090                 }
1091             }
1092         }
1093     }
1094 }
1095
1096 sclboolean
1097 CSCLWindows::get_window_rect(const sclwindow window, SclRectangle *rect) {
1098     SCL_DEBUG();
1099
1100     sclboolean is_virtual = FALSE;
1101     sclboolean ret = FALSE;
1102     if (rect) {
1103         if (window == m_base_window_context.window) {
1104             is_virtual = m_base_window_context.is_virtual;
1105             if (is_virtual) {
1106                 *rect = m_base_window_context.geometry;
1107             }
1108         } else if (window == m_magnifier_window_context.window) {
1109             is_virtual = m_magnifier_window_context.is_virtual;
1110             if (is_virtual) {
1111                 *rect = m_magnifier_window_context.geometry;
1112             }
1113         } else if (window == m_dim_window_context.window) {
1114             is_virtual = m_dim_window_context.is_virtual;
1115             if (is_virtual) {
1116                 *rect = m_dim_window_context.geometry;
1117             }
1118         } else {
1119             for (sclint loop = 0;loop < MAX_POPUP_WINDOW;loop++) {
1120                 if (m_popup_window_context[loop].window == window) {
1121                     is_virtual = m_popup_window_context[loop].is_virtual;
1122                     if (is_virtual) {
1123                         *rect = m_popup_window_context[loop].geometry;
1124                     }
1125                     break;
1126                 }
1127             }
1128         }
1129     }
1130     if (!is_virtual) {
1131          CSCLWindowsImpl* impl = get_scl_windows_impl();
1132          if (impl) {
1133              ret = impl->get_window_rect(window, rect);
1134          }
1135     }
1136
1137     return ret;
1138 }
1139
1140 void CSCLWindows::set_window_backend_callback(ISCLUIWindowBackendCallback *callback, void *data)
1141 {
1142     CSCLWindowsImpl* impl = get_scl_windows_impl();
1143     if (impl) {
1144         impl->set_window_backend_callback(callback, data);
1145     }
1146 }