nux-1.16.0
WindowCompositor.cpp
00001 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
00002 /*
00003  * Copyright 2010,2011 Inalogic® Inc.
00004  *
00005  * This program is free software: you can redistribute it and/or modify it
00006  * under the terms of the GNU Lesser General Public License, as
00007  * published by the  Free Software Foundation; either version 2.1 or 3.0
00008  * of the License.
00009  *
00010  * This program is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranties of
00012  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00013  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00014  * License for more details.
00015  *
00016  * You should have received a copy of both the GNU Lesser General Public
00017  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00018  *
00019  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00020  *
00021  */
00022 
00023 
00024 #include "Nux.h"
00025 #include "WindowCompositor.h"
00026 #include "NuxCore/Logger.h"
00027 #include "NuxGraphics/GLError.h"
00028 #include "WindowThread.h"
00029 #include "BaseWindow.h"
00030 #include "MenuPage.h"
00031 #include "PaintLayer.h"
00032 #include "Painter.h"
00033 
00034 #include "NuxGraphics/FontTexture.h"
00035 namespace nux
00036 {
00037 namespace
00038 {
00039 logging::Logger logger("nux.window");
00040 }
00041 
00042   WindowCompositor::WindowCompositor()
00043   {
00044     m_FocusAreaWindow           = NULL;
00045     m_MenuWindow                = NULL;
00046     m_OverlayWindow             = NULL;
00047     _tooltip_window             = NULL;
00048     m_TooltipArea               = NULL;
00049     m_ModalWindow               = NULL;
00050     m_SelectedWindow            = NULL;
00051     _menu_chain                 = NULL;
00052     m_Background                = NULL;
00053     _tooltip_window             = NULL;
00054     m_OverlayWindow             = NULL;
00055     OverlayDrawingCommand       = NULL;
00056     m_CurrentWindow             = NULL;
00057     m_MenuWindow                = NULL;
00058     _mouse_over_area            = NULL;
00059     key_focus_area_             = NULL;
00060     _always_on_front_window     = NULL;
00061     inside_event_cycle_         = false;
00062     inside_rendering_cycle_     = false;
00063     _exclusive_input_area       = NULL;
00064     _in_exclusive_input_mode    = false;
00065     _pending_exclusive_input_mode_action = false;
00066 
00067     _dnd_area                   = NULL;
00068     mouse_over_area_            = NULL;
00069     mouse_owner_area_           = NULL;
00070     _mouse_over_menu_page       = NULL;
00071     _mouse_owner_menu_page      = NULL;
00072     mouse_owner_base_window_    = NULL;
00073     _starting_menu_event_cycle  = false;
00074     _menu_is_active             = false;
00075     _enable_nux_new_event_architecture   = true;
00076     on_menu_closure_continue_with_event_ = false;
00077 
00078     m_FrameBufferObject = GetGraphicsDisplay()->GetGpuDevice()->CreateFrameBufferObject ();
00079     // Do not leave the Fbo binded. Deactivate it.
00080     m_FrameBufferObject->Deactivate ();
00081 
00082     // At this stage, the size of the window may not be known yet.
00083     // FormatRenderTargets will be called the first time runtime gets into WindowThread::ExecutionLoop
00084     m_MainColorRT = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture (2, 2, 1, BITFMT_R8G8B8A8);
00085     m_MainDepthRT = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture (2, 2, 1, BITFMT_D24S8);
00086 
00087     _menu_chain = new std::list<MenuPage*>;
00088     m_PopupRemoved = false;
00089     m_MenuRemoved = false;
00090     m_ModalWindow = NULL;
00091     m_Background = new ColorLayer (Color (0xFF4D4D4D));
00092   }
00093 
00094   WindowCompositor::~WindowCompositor ()
00095   {
00096     _window_to_texture_map.clear ();
00097     m_FrameBufferObject.Release ();
00098     m_MainColorRT.Release ();
00099     m_MainDepthRT.Release ();
00100     _menu_chain->clear();
00101     _view_window_list.clear ();
00102     _modal_view_window_list.clear ();
00103 
00104     NUX_SAFE_DELETE (_menu_chain);
00105     NUX_SAFE_DELETE (m_Background);
00106   }
00107 
00108 
00109   BaseWindow* WindowCompositor::GetSelectedWindow()
00110   {
00111     return m_SelectedWindow.GetPointer ();
00112   }
00113 
00114   WindowCompositor::RenderTargetTextures &WindowCompositor::GetWindowBuffer (BaseWindow *window)
00115   {
00116     static RenderTargetTextures invalid;
00117     std::map< BaseWindow*, RenderTargetTextures >::iterator it = _window_to_texture_map.find (window);
00118 
00119     if (it != _window_to_texture_map.end())
00120     {
00121       return it->second;
00122     }
00123     LOG_WARN(logger) << "No RenderTargetTextures for window.";
00124     return invalid;
00125   }
00126 
00127   void WindowCompositor::RegisterWindow (BaseWindow *window)
00128   {
00129     LOG_DEBUG_BLOCK(logger);
00130     if (!window)
00131       return;
00132 
00133     WindowList::iterator it = find(_view_window_list.begin(),
00134                                    _view_window_list.end(), window);
00135     if (it == _view_window_list.end())
00136     {
00137       _view_window_list.push_front(ObjectWeakPtr<BaseWindow>(window));
00138       m_SelectedWindow = window;
00139 
00140       RenderTargetTextures rt;
00141 
00142       // Don't size the texture to the dimension of the window yet. this will be done later.
00143       auto device = GetGraphicsDisplay()->GetGpuDevice();
00144       rt.color_rt = device->CreateSystemCapableDeviceTexture (2, 2, 1, BITFMT_R8G8B8A8);
00145       rt.depth_rt = device->CreateSystemCapableDeviceTexture (2, 2, 1, BITFMT_D24S8);
00146 
00147       _window_to_texture_map[window] = rt;
00148 
00149       window->object_destroyed.connect(sigc::mem_fun(this, &WindowCompositor::UnRegisterWindow));
00150     }
00151   }
00152 
00153   void WindowCompositor::UnRegisterWindow(Object* obj)
00154   {
00155     LOG_DEBUG_BLOCK(logger);
00156     WeakBaseWindowPtr window(obj);
00157     if (window.IsNull())
00158       return;
00159 
00160     WindowList::iterator it = find(_view_window_list.begin(),
00161                                    _view_window_list.end(), window);
00162     if (it == _view_window_list.end())
00163     {
00164       // look for a weak pointer that has been cleared out.
00165       it = find(_view_window_list.begin(),
00166                 _view_window_list.end(), WeakBaseWindowPtr());
00167     }
00168 
00169     if (it != _view_window_list.end())
00170     {
00171       _view_window_list.erase(it);
00172 
00173       if (_view_window_list.size())
00174         m_SelectedWindow = _view_window_list.front();
00175     }
00176     _window_to_texture_map.erase(window.GetPointer());
00177   }
00178 
00179   Area* WindowCompositor::GetMouseOwnerArea()
00180   {
00181     return mouse_owner_area_;
00182   }
00183 
00185   Point WindowCompositor::GetMousePosition()
00186   {
00187     return _mouse_position;
00188   }
00189 
00190   void WindowCompositor::ResetMousePointerAreas()
00191   {
00192     SetMouseOverArea(NULL);
00193     SetMouseOwnerArea(NULL);
00194     _mouse_over_menu_page   = NULL;
00195     _mouse_owner_menu_page  = NULL;
00196   }
00197 
00198   void WindowCompositor::GetAreaUnderMouse(const Point& mouse_position,
00199                                            NuxEventType event_type,
00200                                            InputArea** area_under_mouse_pointer,
00201                                            BaseWindow** window)
00202   {
00203     *area_under_mouse_pointer = NULL;
00204 
00205     // Go through the list of BaseWindo and find the first area over which the
00206     // mouse pointer is.
00207     WindowList::iterator window_it;
00208 
00209     for (window_it = _view_window_list.begin(); window_it != _view_window_list.end(); ++window_it)
00210     {
00211       if ((*window_it).IsValid() && (*window_it)->IsVisible())
00212       {
00213         InputArea *area = static_cast<InputArea*>((*window_it)->FindAreaUnderMouse(mouse_position, event_type));
00214         if (area)
00215         {
00216           *area_under_mouse_pointer = area;
00217           *window = (*window_it).GetPointer();
00218           return;
00219         }
00220       }
00221     }
00222 
00223     // If area_under_mouse_pointer is NULL, then the mouse pointer is not over
00224     // any of the BaseWindow. Try the main window layout.
00225     if (*area_under_mouse_pointer == NULL)
00226     {
00227       Layout* main_window_layout = GetWindowThread()->GetMainLayout();
00228       if (main_window_layout)
00229         *area_under_mouse_pointer = static_cast<InputArea*>(main_window_layout->FindAreaUnderMouse(mouse_position, event_type));
00230     }
00231   }
00232 
00233   void WindowCompositor::OnMouseOverViewDestroyed(Object* object)
00234   {
00235     if (mouse_over_area_ == object)
00236     {
00237       mouse_over_area_ = NULL;
00238     }
00239   }
00240 
00241   void WindowCompositor::SetMouseOverArea(Area* area)
00242   {
00243     mouse_over_area_ = static_cast<InputArea*>(area);
00244 
00245     mouse_over_view_connection_.disconnect();
00246 
00247     if (mouse_over_area_)
00248     {
00249       mouse_over_view_connection_ = mouse_over_area_->object_destroyed.connect(sigc::mem_fun (this, &WindowCompositor::OnMouseOverViewDestroyed));
00250     }
00251   }
00252 
00253   void WindowCompositor::OnMouseOwnerViewDestroyed(Object* object)
00254   {
00255     if (mouse_owner_area_ == object)
00256     {
00257       mouse_owner_area_ = NULL;
00258     }
00259   }
00260 
00261   void WindowCompositor::SetMouseOwnerArea(Area* area)
00262   {
00263     if (mouse_owner_area_ == area)
00264       return;
00265 
00266     mouse_owner_area_ = static_cast<InputArea*>(area);
00267     dnd_safety_x_ = 0;
00268     dnd_safety_y_ = 0;
00269 
00270     mouse_owner_view_connection_.disconnect();
00271 
00272     if (mouse_owner_area_)
00273     {
00274       mouse_owner_view_connection_ = mouse_owner_area_->object_destroyed.connect(sigc::mem_fun (this, &WindowCompositor::OnMouseOwnerViewDestroyed));
00275     }
00276   }
00277 
00278   void WindowCompositor::OnMouseOwnerBaseWindowDestroyed(Object* object)
00279   {
00280     if (mouse_owner_base_window_ == object)
00281     {
00282       mouse_owner_base_window_ = NULL;
00283     }
00284   }
00285 
00286   void WindowCompositor::SetMouseOwnerBaseWindow(BaseWindow* base_window)
00287   {
00288     mouse_owner_base_window_ = base_window;
00289 
00290     mouse_owner_basewindow_connection_.disconnect();
00291 
00292     if (mouse_owner_base_window_)
00293     {
00294       mouse_owner_basewindow_connection_ = mouse_owner_base_window_->object_destroyed.connect (sigc::mem_fun (this, &WindowCompositor::OnMouseOwnerBaseWindowDestroyed));
00295     }
00296   }
00297 
00298   void WindowCompositor::DndEventCycle (Event &event)
00299   {
00300     if (event.e_event == NUX_DND_MOVE)
00301     {
00302       InputArea *hit_area = NULL;
00303       BaseWindow *hit_base_window = NULL;
00304 
00305       GetAreaUnderMouse(Point(event.e_x, event.e_y), event.e_event, &hit_area, &hit_base_window);
00306 
00307       if (hit_area)
00308       {
00309         SetDnDArea (hit_area);
00310         hit_area->HandleDndMove(event);
00311       }
00312       else
00313       {
00314         ResetDnDArea ();
00315       }
00316     }
00317     else if (event.e_event == NUX_DND_ENTER_WINDOW)
00318     {
00319       // do nothing for now
00320     }
00321     else if (event.e_event == NUX_DND_LEAVE_WINDOW)
00322     {
00323       ResetDnDArea ();
00324     }
00325     else if (event.e_event == NUX_DND_DROP)
00326     {
00327       InputArea *current_dnd_area = GetWindowCompositor().GetDnDArea();
00328       if (current_dnd_area->GetGeometry().IsPointInside (event.e_x - event.e_x_root, event.e_y - event.e_y_root))
00329         current_dnd_area->HandleDndDrop(event);
00330     }
00331   }
00332 
00333   void WindowCompositor::MouseEventCycle(Event &event)
00334   {
00335     // mouse_owner_area_: the view that has the mouse down
00336     // mouse_over_area_: the view that is directly below the mouse pointer
00337 
00338     int dx = event.e_x - _mouse_position.x;
00339     int dy = event.e_y - _mouse_position.y;
00340 
00341     _mouse_position = Point(event.e_x, event.e_y);
00342 
00343     if (mouse_owner_area_ == NULL)
00344     {
00345       // Context: The left mouse button is not down over an area.
00346       // We look for the area where the mouse pointer is located.
00347       
00348       // NUX_MOUSE_RELEASED is tipically processed in cases where mouse_owner_area_ is not NULL.
00349       // See below for the case when NUX_MOUSE_RELEASED is processed here while mouse_owner_area_ is NULL.
00350       if ((event.e_event == NUX_MOUSE_PRESSED) ||
00351         (event.e_event == NUX_MOUSE_MOVE) ||
00352         (event.e_event == NUX_MOUSE_DOUBLECLICK) ||
00353         (event.e_event == NUX_MOUSE_WHEEL) ||
00354         (event.e_event == NUX_WINDOW_MOUSELEAVE) ||
00355         (event.e_event == NUX_MOUSE_RELEASED))
00356       {
00357         InputArea* hit_view = NULL;         // The view under the mouse
00358         BaseWindow* hit_base_window = NULL; // The BaseWindow below the mouse pointer.
00359 
00360         // Look for the area below the mouse pointer in the BaseWindow.
00361         Area *pointer_grab_area = GetPointerGrabArea ();
00362         if (pointer_grab_area)
00363         {
00364           // If there is a pending mouse pointer grab, test that area only
00365           hit_view = NUX_STATIC_CAST(InputArea*, pointer_grab_area->FindAreaUnderMouse(Point(event.e_x, event.e_y), event.e_event));
00366           if ((hit_view == NULL) && (event.e_event == NUX_MOUSE_PRESSED))
00367           {
00368             Geometry geo = pointer_grab_area->GetAbsoluteGeometry();
00369             int x = event.e_x - geo.x;
00370             int y = event.e_y - geo.y;
00371 
00372             NUX_STATIC_CAST(InputArea*, pointer_grab_area)->EmitMouseDownOutsideArea(x, y, event.GetMouseState(), event.GetKeyState());
00373           }
00374         }
00375         else
00376         {
00377           GetAreaUnderMouse(Point(event.e_x, event.e_y), event.e_event, &hit_view, &hit_base_window);
00378           SetMouseOwnerBaseWindow(hit_base_window);
00379         }
00380 
00381         Geometry hit_view_geo;
00382         int hit_view_x = 0;
00383         int hit_view_y = 0;
00384 
00385         if (hit_view)
00386         {
00387           hit_view_geo = hit_view->GetAbsoluteGeometry();
00388           hit_view_x = event.e_x - hit_view_geo.x;
00389           hit_view_y = event.e_y - hit_view_geo.y;
00390         }
00391 
00392         if(event.e_event == NUX_WINDOW_MOUSELEAVE)
00393         {
00394           if (mouse_over_area_ != NULL)
00395           {
00396             // The area where the mouse was in the previous cycle and the area returned by GetAreaUnderMouse are different.
00397             // The area from the previous cycle receive a "mouse leave signal".
00398             Geometry geo = mouse_over_area_->GetAbsoluteGeometry();
00399             int x = event.e_x - geo.x;
00400             int y = event.e_y - geo.y;
00401 
00402             mouse_over_area_->EmitMouseLeaveSignal(x, y, event.GetMouseState(), event.GetKeyState());
00403             SetMouseOverArea(NULL);
00404           }
00405         }
00406         else if (hit_view && (event.e_event == NUX_MOUSE_MOVE))
00407         {
00408           if (hit_view != mouse_over_area_)
00409           {
00410             if (mouse_over_area_ != NULL)
00411             {
00412               // The area where the mouse was in the previous cycle and the area returned by GetAreaUnderMouse are different.
00413               // The area from the previous cycle receive a "mouse leave signal".
00414               Geometry geo = mouse_over_area_->GetAbsoluteGeometry();
00415               int x = event.e_x - geo.x;
00416               int y = event.e_y - geo.y;
00417 
00418               mouse_over_area_->EmitMouseLeaveSignal(x, y, event.GetMouseState(), event.GetKeyState());
00419             }
00420 
00421             // The area we found under the mouse pointer receives a "mouse enter signal".
00422             SetMouseOverArea(hit_view);
00423             mouse_over_area_->EmitMouseEnterSignal(hit_view_x, hit_view_y, event.GetMouseState(), event.GetKeyState());
00424           }
00425 
00426           // Send a "mouse mouse signal".
00427           mouse_over_area_->EmitMouseMoveSignal(hit_view_x, hit_view_y, dx, dy, event.GetMouseState(), event.GetKeyState());
00428         }
00429         else if (hit_view && ((event.e_event == NUX_MOUSE_PRESSED) || (event.e_event == NUX_MOUSE_DOUBLECLICK)))
00430         {
00431           if ((event.e_event == NUX_MOUSE_DOUBLECLICK) && (!hit_view->DoubleClickEnabled()))
00432           {
00433             // If the area does not accept double click events, transform the event into a mouse pressed.
00434             event.e_event = NUX_MOUSE_PRESSED;
00435           }
00436 
00437           bool emit_double_click_signal = false;
00438           if (mouse_over_area_ && (hit_view != mouse_over_area_))
00439           {
00440             // The area where the mouse was in the previous cycle and the area returned by GetAreaUnderMouse are different.
00441             // The area from the previous cycle receive a "mouse leave signal".
00442             // This case should be rare. I would happen if the mouse is over an area and that area is removed and reveals
00443             // a new area. If the next mouse event is a NUX_MOUSE_PRESSED, then the revealed area will be the one 
00444             // that is returned by GetAreaUnderMouse.
00445             Geometry geo = mouse_over_area_->GetAbsoluteGeometry();
00446             int x = event.e_x - geo.x;
00447             int y = event.e_y - geo.y;
00448 
00449             mouse_over_area_->EmitMouseLeaveSignal(x, y, event.GetMouseState(), event.GetKeyState());
00450           }
00451           else if (mouse_over_area_ && (hit_view == mouse_over_area_) && (event.e_event == NUX_MOUSE_DOUBLECLICK))
00452           {
00453             emit_double_click_signal = true;
00454           }
00455 
00456           SetMouseOverArea(hit_view);
00457           SetMouseOwnerArea(hit_view);
00458           _mouse_position_on_owner = Point(hit_view_x, hit_view_y);
00459 
00460           // In the case of a mouse down event, if there is currently a keyboard event receiver and it is different
00461           // from the area returned by GetAreaUnderMouse, then stop that receiver from receiving anymore keyboard events and switch
00462           // make the found area the new receiver (if it accept keyboard events).
00463           if (mouse_over_area_ != GetKeyFocusArea())
00464           {
00465             InputArea* grab_area = GetKeyboardGrabArea();
00466             if (grab_area)
00467             {
00468               if (mouse_over_area_->IsChildOf(grab_area) /*&& mouse_over_area_->AcceptKeyboardEvent()*/)
00469               {
00470                 SetKeyFocusArea(mouse_over_area_);
00471               }
00472               else
00473               {
00474                 SetKeyFocusArea(grab_area);
00475               }
00476             }
00477             else
00478             {
00479               SetKeyFocusArea(mouse_over_area_);
00480             }
00481           }
00482 
00483           if (emit_double_click_signal)
00484           {
00485             mouse_over_area_->EmitMouseDoubleClickSignal(hit_view_x, hit_view_y, event.GetMouseState(), event.GetKeyState());
00486           }
00487           else
00488           {
00489             mouse_over_area_->EmitMouseDownSignal(hit_view_x, hit_view_y, event.GetMouseState(), event.GetKeyState());
00490           }
00491         }
00492         else if (hit_view && (event.e_event == NUX_MOUSE_WHEEL))
00493         {
00494           hit_view->EmitMouseWheelSignal(hit_view_x, hit_view_y, event.e_wheeldelta, event.GetMouseState(), event.GetKeyState());
00495         }
00496         else if (hit_view && (event.e_event == NUX_MOUSE_RELEASED))
00497         {
00498           // We only get a NUX_MOUSE_RELEASED event when the mouse was pressed
00499           // over another area and released here. There are a few situations that can cause 
00500           // mouse_owner_area_ to be NULL on a NUX_MOUSE_RELEASED event:
00501           //  - The mouse down event happens on a area. That area is set into mouse_owner_area_.
00502           //    Then the area is destroyed, before the mouse is released.
00503           //  - The mouse down event happens. Then a call to AddGrabPointer triggers a call to 
00504           //    ResetMousePointerAreas. mouse_owner_area_ is then set to NULL.
00505 
00506           hit_view->EmitMouseUpSignal(hit_view_x, hit_view_y, event.GetMouseState(), event.GetKeyState());
00507         }
00508         else if (hit_view == NULL)
00509         {
00510           if (mouse_over_area_)
00511           {
00512             Geometry geo = mouse_over_area_->GetAbsoluteGeometry();
00513             int x = event.e_x - geo.x;
00514             int y = event.e_y - geo.y;
00515 
00516             mouse_over_area_->EmitMouseLeaveSignal(x, y, event.GetMouseState(), event.GetKeyState());
00517           }
00518 
00519 //           if(GetKeyFocusArea() && (event.e_event == NUX_MOUSE_PRESSED))
00520 //           {
00521 //             InputArea* grab_area = GetKeyFocusArea();
00522 // 
00523 //             if(grab_area)
00524 //             {
00525 //               SetKeyFocusArea(grab_area);
00526 //             }
00527 //             else
00528 //             {
00529 //               SetKeyFocusArea(NULL);
00530 //             }
00531 //           }
00532           SetMouseOverArea(NULL);
00533         }
00534       }
00535     }
00536     else
00537     {
00538       // Context: The left mouse button down over an area. All events goes to that area.
00539       // But we still need to know where the mouse is.
00540 
00541       InputArea* hit_view = NULL;         // The view under the mouse
00542       BaseWindow* hit_base_window = NULL; // The BaseWindow below the mouse pointer.
00543 
00544       GetAreaUnderMouse(Point(event.e_x, event.e_y), event.e_event, &hit_view, &hit_base_window);
00545 
00546       Geometry mouse_owner_geo = mouse_owner_area_->GetAbsoluteGeometry();
00547       int mouse_owner_x = event.e_x - mouse_owner_geo.x;
00548       int mouse_owner_y = event.e_y - mouse_owner_geo.y;
00549 
00550       // the mouse is down over a view
00551       if(event.e_event == NUX_MOUSE_MOVE)
00552       {
00553         int dx = mouse_owner_x - _mouse_position_on_owner.x;
00554         int dy = mouse_owner_y - _mouse_position_on_owner.y;
00555 
00556         if (mouse_owner_area_->_dnd_enabled_as_source)
00557         {
00558           dnd_safety_x_ += dx;
00559           dnd_safety_y_ += dy;
00560 
00561           if (abs (dnd_safety_y_) > 30 || abs (dnd_safety_x_) > 30)
00562           {
00563 #ifdef NUX_OS_LINUX
00564             mouse_owner_area_->StartDragAsSource ();
00565 #endif
00566             ResetMousePointerAreas ();
00567             return;
00568           }
00569         }
00570         else
00571         {
00572           mouse_owner_area_->EmitMouseDragSignal(mouse_owner_x, mouse_owner_y, dx, dy, event.GetMouseState(), event.GetKeyState());
00573         }
00574 
00575         if((mouse_over_area_ == mouse_owner_area_) && (hit_view != mouse_owner_area_))
00576         {
00577           mouse_owner_area_->EmitMouseLeaveSignal(mouse_owner_x, mouse_owner_y, event.GetMouseState(), event.GetKeyState());
00578           SetMouseOverArea(hit_view);
00579         }
00580         else if((mouse_over_area_ != mouse_owner_area_) && (hit_view == mouse_owner_area_))
00581         {
00582           mouse_owner_area_->EmitMouseEnterSignal(mouse_owner_x, mouse_owner_y, event.GetMouseState(), event.GetKeyState());
00583           SetMouseOverArea(mouse_owner_area_);
00584         }
00585 
00586         _mouse_position_on_owner = Point(mouse_owner_x, mouse_owner_y);
00587       }
00588       else if(event.e_event == NUX_MOUSE_RELEASED)
00589       {
00590         mouse_owner_area_->EmitMouseUpSignal(mouse_owner_x, mouse_owner_y, event.GetMouseState(), event.GetKeyState());
00591 
00592         if(hit_view == mouse_owner_area_)
00593         {
00594           mouse_owner_area_->EmitMouseClickSignal(mouse_owner_x, mouse_owner_y, event.GetMouseState(), event.GetKeyState());
00595           SetMouseOverArea(mouse_owner_area_);
00596         }
00597         else
00598         {
00599           SetMouseOverArea(hit_view);
00600         }
00601 
00602         SetMouseOwnerArea(NULL);
00603         _mouse_position_on_owner = Point(0, 0);
00604       }
00605     }
00606   }
00607 
00608   void WindowCompositor::MenuEventCycle(Event& event)
00609   {
00610     // _mouse_owner_menu_page: the menu page that has the mouse down
00611     // _mouse_over_menu_page: the menu page that is directly below the mouse pointer
00612 
00613     _mouse_position = Point(event.e_x, event.e_y);
00614 
00615     if(_mouse_owner_menu_page == NULL)
00616     {
00617       if((event.e_event == NUX_MOUSE_PRESSED) ||
00618         (event.e_event == NUX_MOUSE_RELEASED) ||
00619         (event.e_event == NUX_MOUSE_MOVE) ||
00620         (event.e_event == NUX_MOUSE_DOUBLECLICK) ||
00621         (event.e_event == NUX_MOUSE_WHEEL))
00622       {
00623         // Find the MenuPage under the mouse
00624         MenuPage* hit_menu_page = NULL;
00625         std::list<MenuPage*>::iterator menu_it;
00626         for(menu_it = _menu_chain->begin (); menu_it != _menu_chain->end (); menu_it++)
00627         {
00628           // The leaf of the menu chain is in the front of the list.
00629           hit_menu_page = NUX_STATIC_CAST(MenuPage*, (*menu_it)->FindAreaUnderMouse(Point(event.e_x, event.e_y), event.e_event));
00630           if(hit_menu_page)
00631           {
00632             break;
00633           }
00634         }
00635 
00636         Geometry hit_menu_page_geo;
00637         int hit_menu_page_x = 0;
00638         int hit_menu_page_y = 0;
00639 
00640         if(hit_menu_page)
00641         {
00642           hit_menu_page_geo = hit_menu_page->GetAbsoluteGeometry();
00643           hit_menu_page_x = event.e_x - hit_menu_page_geo.x;
00644           hit_menu_page_y = event.e_y - hit_menu_page_geo.y;
00645         }
00646 
00647         if(hit_menu_page && (event.e_event == NUX_MOUSE_RELEASED))
00648         {
00649           hit_menu_page->EmitMouseUpSignal(hit_menu_page_x, hit_menu_page_y, event.GetMouseState(), event.GetKeyState());
00650 
00651           (*_menu_chain->begin())->sigClosingMenu(*_menu_chain->begin());
00652           (*_menu_chain->begin())->StopMenu();
00653         }
00654         else if(hit_menu_page && (event.e_event == NUX_MOUSE_MOVE))
00655         {
00656           if(hit_menu_page != _mouse_over_menu_page)
00657           {
00658             if(_mouse_over_menu_page != 0)
00659             {
00660               Geometry geo = _mouse_over_menu_page->GetAbsoluteGeometry();
00661               int x = event.e_x - geo.x;
00662               int y = event.e_y - geo.y;
00663 
00664               _mouse_over_menu_page->EmitMouseLeaveSignal(x, y, event.GetMouseState(), event.GetKeyState());
00665             }
00666 
00667             _mouse_over_menu_page = hit_menu_page;
00668             _mouse_over_menu_page->EmitMouseEnterSignal(hit_menu_page_x, hit_menu_page_y, event.GetMouseState(), event.GetKeyState());
00669           }
00670 
00671           _mouse_over_menu_page->EmitMouseMoveSignal(hit_menu_page_x, hit_menu_page_y, event.e_dx, event.e_dy, event.GetMouseState(), event.GetKeyState());
00672         }
00673         else if(hit_menu_page && ((event.e_event == NUX_MOUSE_PRESSED) || (event.e_event == NUX_MOUSE_DOUBLECLICK)))
00674         {
00675           if(!hit_menu_page->DoubleClickEnabled())
00676           {
00677 
00678           }
00679 
00680           if(_mouse_over_menu_page && (hit_menu_page != _mouse_over_menu_page))
00681           {
00682             Geometry geo = _mouse_over_menu_page->GetAbsoluteGeometry();
00683             int x = event.e_x - geo.x;
00684             int y = event.e_y - geo.y;
00685 
00686             _mouse_over_menu_page->EmitMouseLeaveSignal(x, y, event.GetMouseState(), event.GetKeyState());
00687           }
00688 
00689           _mouse_over_menu_page = hit_menu_page;
00690           _mouse_owner_menu_page = hit_menu_page;
00691           _mouse_position_on_owner = Point(hit_menu_page_x, hit_menu_page_y);
00692 
00693           if(_mouse_over_menu_page != GetKeyFocusArea())
00694           {
00695             if(_mouse_over_menu_page->AcceptKeyboardEvent())
00696               SetKeyFocusArea(_mouse_over_menu_page);
00697           }
00698 
00699           _mouse_over_menu_page->EmitMouseDownSignal(hit_menu_page_x, hit_menu_page_y, event.GetMouseState(), event.GetKeyState());
00700         }
00701         else if(hit_menu_page && (event.e_event == NUX_MOUSE_WHEEL))
00702         {
00703           hit_menu_page->EmitMouseWheelSignal(hit_menu_page_x, hit_menu_page_y, event.e_wheeldelta, event.GetMouseState(), event.GetKeyState());
00704         }
00705         else if(hit_menu_page == NULL)
00706         {
00707           if(_mouse_over_menu_page)
00708           {
00709             Geometry geo = _mouse_over_menu_page->GetAbsoluteGeometry();
00710             int x = event.e_x - geo.x;
00711             int y = event.e_y - geo.y;
00712 
00713             _mouse_over_menu_page->EmitMouseLeaveSignal(x, y, event.GetMouseState(), event.GetKeyState());
00714           }
00715 
00716           if(event.e_event == NUX_MOUSE_PRESSED || event.e_event == NUX_MOUSE_DOUBLECLICK)
00717           {
00718             (*_menu_chain->begin())->sigClosingMenu(*_menu_chain->begin());
00719             (*_menu_chain->begin())->StopMenu();
00720 
00721             on_menu_closure_continue_with_event_ = (*_menu_chain->begin())->OnClosureContinueEventCycle();
00722           }
00723           _mouse_over_menu_page = 0;
00724         }
00725       }
00726     }
00727     else
00728     {
00729       // We should never get here for a NUX_MOUSE_PRESSED event.
00730       MenuPage* hit_menu_page = NULL;
00731       std::list<MenuPage*>::iterator menu_it;
00732       for(menu_it = _menu_chain->begin (); menu_it != _menu_chain->end (); menu_it++)
00733       {
00734         // The leaf of the menu chain is in the front of the list.
00735         hit_menu_page = NUX_STATIC_CAST(MenuPage*, (*menu_it)->FindAreaUnderMouse(Point(event.e_x, event.e_y), event.e_event));
00736         if(hit_menu_page)
00737         {
00738           break;
00739         }
00740       }
00741 
00742       Geometry mouse_owner_geo = _mouse_owner_menu_page->GetAbsoluteGeometry();
00743       int mouse_owner_x = event.e_x - mouse_owner_geo.x;
00744       int mouse_owner_y = event.e_y - mouse_owner_geo.y;
00745 
00746       // the mouse is down over a view
00747       if(event.e_event == NUX_MOUSE_MOVE)
00748       {
00749         int dx = mouse_owner_x - _mouse_position_on_owner.x;
00750         int dy = mouse_owner_y - _mouse_position_on_owner.y;
00751 
00752         _mouse_owner_menu_page->EmitMouseDragSignal(mouse_owner_x, mouse_owner_y, dx, dy, event.GetMouseState(), event.GetKeyState());
00753 
00754         if((_mouse_over_menu_page == _mouse_owner_menu_page) && (hit_menu_page != _mouse_owner_menu_page))
00755         {
00756           _mouse_owner_menu_page->EmitMouseLeaveSignal(mouse_owner_x, mouse_owner_y, event.GetMouseState(), event.GetKeyState());
00757           _mouse_over_menu_page = hit_menu_page;
00758         }
00759         else if((_mouse_over_menu_page != _mouse_owner_menu_page) && (hit_menu_page == _mouse_owner_menu_page))
00760         {
00761           _mouse_owner_menu_page->EmitMouseEnterSignal(mouse_owner_x, mouse_owner_y, event.GetMouseState(), event.GetKeyState());
00762           _mouse_over_menu_page = _mouse_owner_menu_page;
00763         }
00764 
00765         _mouse_position_on_owner = Point(mouse_owner_x, mouse_owner_y);
00766       }
00767       else if(event.e_event == NUX_MOUSE_RELEASED)
00768       {
00769         _mouse_owner_menu_page->EmitMouseUpSignal(mouse_owner_x, mouse_owner_y, event.GetMouseState(), event.GetKeyState());
00770 
00771         if(hit_menu_page == _mouse_owner_menu_page)
00772         {
00773           _mouse_owner_menu_page->EmitMouseClickSignal(mouse_owner_x, mouse_owner_y, event.GetMouseState(), event.GetKeyState());
00774           _mouse_over_menu_page = _mouse_owner_menu_page;
00775         }
00776         else
00777         {
00778           _mouse_over_menu_page = hit_menu_page;
00779         }
00780 
00781         (*_menu_chain->begin())->sigClosingMenu(*_menu_chain->begin());
00782         (*_menu_chain->begin())->StopMenu();
00783 
00784         _mouse_owner_menu_page = NULL;
00785         _mouse_position_on_owner = Point(0, 0);
00786       }
00787     }
00788   }
00789 
00790   void WindowCompositor::FindKeyFocusArea(NuxEventType event_type,
00791     unsigned int key_symbol,
00792     unsigned int special_keys_state,
00793     InputArea** key_focus_area,
00794     BaseWindow** window)
00795   {
00796     *key_focus_area = NULL;
00797     *window = NULL;
00798 
00799     // Go through the list of BaseWindos and find the first area over which the mouse pointer is.
00800     WindowList::iterator window_it;
00801     window_it = _view_window_list.begin();
00802     while((*key_focus_area == NULL) && (window_it != _view_window_list.end()))
00803     {
00804       if((*window_it).IsValid() && (*window_it)->IsVisible())
00805       {
00806         *key_focus_area = NUX_STATIC_CAST(InputArea*, (*window_it)->FindKeyFocusArea(event_type, key_symbol, special_keys_state));
00807         if(key_focus_area)
00808         {
00809           // We have found an area. We are going to exit the while loop.
00810           *window = (*window_it).GetPointer();
00811         }
00812       }
00813       ++window_it;
00814     }
00815 
00816     // If key_focus_area is NULL, then try the main window layout.
00817     if(*key_focus_area == NULL)
00818     {
00819       Layout* main_window_layout = GetWindowThread()->GetMainLayout();
00820       if(main_window_layout)
00821       {
00822         *key_focus_area = NUX_STATIC_CAST(InputArea*, main_window_layout->FindKeyFocusArea(event_type, key_symbol, special_keys_state));
00823       }
00824     }
00825   }
00826 
00827   void WindowCompositor::FindKeyFocusAreaFrom(NuxEventType event_type,
00828     unsigned int key_symbol,
00829     unsigned int special_keys_state,
00830     InputArea* root_search_area,
00831     InputArea** key_focus_area,
00832     BaseWindow** window)
00833   {
00834     *key_focus_area = NULL;
00835     *window = NULL;
00836 
00837     if (root_search_area == NULL)
00838     {
00839       return;
00840     }
00841 
00842     *key_focus_area = NUX_STATIC_CAST(InputArea*, root_search_area->FindKeyFocusArea(event_type, key_symbol, special_keys_state));
00843     if (key_focus_area)
00844     {
00845       *window = NUX_STATIC_CAST(BaseWindow*, root_search_area->GetTopLevelViewWindow());
00846     }
00847   }
00848 
00849   void WindowCompositor::SendKeyEvent(InputArea* input_area,
00850     NuxEventType event_type,
00851     unsigned int key_sym,
00852     unsigned long x11_key_code,
00853     unsigned long special_keys_state,
00854     const char* text,
00855     int key_repeat_count)
00856   {
00857     if (input_area == NULL)
00858       return;
00859 
00860     if (event_type == NUX_KEYDOWN)
00861     {
00862       input_area->EmitKeyEventSignal(event_type,
00863         key_sym,
00864         special_keys_state,
00865         text,
00866         key_repeat_count);
00867     }
00868     else if (event_type == NUX_KEYUP)
00869     {
00870       input_area->EmitKeyUpSignal(key_sym, x11_key_code, special_keys_state);
00871     }
00872   }
00873 
00874   void WindowCompositor::KeyboardEventCycle(Event &event)
00875   {
00876     InputArea* keyboard_event_grab_view = GetKeyboardGrabArea();
00877 
00878     InputArea* focus_area = NULL;   // The view under the mouse
00879     BaseWindow* base_window = NULL; // The BaseWindow below the mouse pointer.
00880 
00881     if(keyboard_event_grab_view)
00882     {
00883       // There is a keyboard grab.
00884       // Find the key focus area, under the keyboard grab area. That is to say, the key focus area is in the widget tree 
00885       // whose root is the keyboard grab area. This phase is known as the capture phase.
00886       
00887       FindKeyFocusAreaFrom(event.e_event, event.GetKeySym(), event.GetKeyState(),
00888         keyboard_event_grab_view,
00889         &focus_area,
00890         &base_window);
00891     }
00892     else
00893     {
00894       FindKeyFocusArea(event.e_event, event.GetKeySym(), event.GetKeyState(),
00895         &focus_area,
00896         &base_window);
00897     }
00898 
00899     if (focus_area)
00900       SetKeyFocusArea(focus_area);
00901     else
00902       SetKeyFocusArea(NULL);
00903 
00904     KeyNavDirection direction = KEY_NAV_NONE;
00905 
00906     switch (event.GetKeySym())
00907     {
00908     case NUX_VK_UP:
00909       direction = KEY_NAV_UP;
00910       break;
00911     case NUX_VK_DOWN:
00912       direction = KEY_NAV_DOWN;
00913       break;
00914     case NUX_VK_LEFT:
00915       direction = KEY_NAV_LEFT;
00916       break;
00917     case NUX_VK_RIGHT:
00918       direction = KEY_NAV_RIGHT;
00919       break;
00920     case NUX_VK_LEFT_TAB:
00921       direction = KEY_NAV_TAB_PREVIOUS;
00922       break;
00923     case NUX_VK_TAB:
00924       direction = KEY_NAV_TAB_NEXT;
00925       break;
00926     case NUX_VK_ENTER:
00927     case NUX_KP_ENTER:
00928       // Not sure if Enter should be a navigation key
00929       direction = KEY_NAV_ENTER;
00930       break;
00931     default:
00932       direction = KEY_NAV_NONE;
00933       break;
00934     }
00935 
00936     if (key_focus_area_)
00937     {
00938       if (key_focus_area_->InspectKeyEvent(event.e_event, event.GetKeySym(), event.GetText()))
00939       {
00940         SendKeyEvent(key_focus_area_,
00941                     event.e_event,
00942                     event.GetKeySym(),
00943                     event.e_x11_keycode,
00944                     event.GetKeyState(),
00945                     event.GetText(),
00946                     event.GetKeyRepeatCount());
00947       }
00948       else if (direction == KEY_NAV_NONE)
00949       {
00950         Area* parent = key_focus_area_->GetParentObject();
00951 
00952         while (parent && !parent->InspectKeyEvent(event.e_event, event.GetKeySym(), event.GetText()))
00953         {
00954           parent = parent->GetParentObject();
00955         }
00956 
00957         if (parent)
00958         {
00959           SendKeyEvent(static_cast<InputArea*>(parent),
00960             event.e_event,
00961             event.GetKeySym(),
00962             event.e_x11_keycode,
00963             event.GetKeyState(),
00964             event.GetText(),
00965             event.GetKeyRepeatCount());
00966         }
00967       }
00968       else if (event.e_event == NUX_KEYDOWN)
00969       {        
00970         if (direction == KEY_NAV_ENTER)
00971         {
00972           if (key_focus_area_ && key_focus_area_->Type().IsDerivedFromType(InputArea::StaticObjectType))
00973           {
00974             static_cast<InputArea*>(key_focus_area_)->OnKeyNavFocusActivate.emit(key_focus_area_);
00975           }
00976         }
00977         else
00978         {
00979           InputArea* key_nav_focus = NULL;
00980           Area* parent = key_focus_area_->GetParentObject();
00981           
00982           if (parent)
00983             key_nav_focus = NUX_STATIC_CAST(InputArea*, parent->KeyNavIteration(direction));
00984           
00985           while (key_nav_focus == NULL && parent != NULL)
00986           {
00987             parent = parent->GetParentObject();
00988             if (parent)
00989               key_nav_focus = NUX_STATIC_CAST(InputArea*, parent->KeyNavIteration(direction));
00990           }
00991 
00992           if (key_nav_focus)
00993           {
00994             SetKeyFocusArea(key_nav_focus);
00995           }
00996         }
00997       }
00998     }
00999     else
01000     {
01001       // The event is for the Application itself
01002     }
01003   }
01004 
01005   // NUXTODO: rename as EventCycle
01006   void WindowCompositor::ProcessEvent (Event &event)
01007   {
01008     inside_event_cycle_ = true;
01009     if (_enable_nux_new_event_architecture)
01010     {
01011       if (((event.e_event >= NUX_MOUSE_PRESSED) && (event.e_event <= NUX_MOUSE_WHEEL)) ||
01012       (event.e_event == NUX_WINDOW_MOUSELEAVE))
01013       {
01014         bool menu_active = false;
01015         if (_menu_chain->size())
01016         {
01017           menu_active = true;
01018           MenuEventCycle(event);
01019           CleanMenu();
01020         }
01021 
01022         if((menu_active && on_menu_closure_continue_with_event_) || !(menu_active))
01023         {
01024           MouseEventCycle(event);
01025         }
01026 
01027         on_menu_closure_continue_with_event_ = false;
01028 
01029         if (_starting_menu_event_cycle)
01030         {
01031           _starting_menu_event_cycle = false;
01032         }
01033       }
01034       else if ((event.e_event >= NUX_KEYDOWN) && (event.e_event <= NUX_KEYUP))
01035       {
01036         KeyboardEventCycle(event);
01037       }
01038       else if ((event.e_event >= NUX_DND_MOVE) && (event.e_event <= NUX_DND_LEAVE_WINDOW))
01039       {
01040         DndEventCycle(event);
01041       }
01042     }
01043     inside_event_cycle_ = false;
01044   }
01045 
01046   long WindowCompositor::MenuEventCycle(Event &event, long TraverseInfo, long ProcessEventInfo)
01047   {
01048     long ret = TraverseInfo;
01049     std::list<MenuPage*>::iterator menu_it;
01050 
01051     if (m_MenuWindow.IsValid())
01052     {
01053       event.e_x_root = m_MenuWindow->GetBaseX ();
01054       event.e_y_root = m_MenuWindow->GetBaseY ();
01055     }
01056 
01057     // Let all the menu area check the event first. Beside, they are on top of everything else.
01058     for (menu_it = _menu_chain->begin (); menu_it != _menu_chain->end (); menu_it++)
01059     {
01060       // The deepest menu in the menu cascade is in the front of the list.
01061       ret = (*menu_it)->ProcessEvent (event, ret, ProcessEventInfo);
01062     }
01063 
01064     if ((event.e_event == NUX_MOUSE_PRESSED) && _menu_chain->size ())
01065     {
01066       bool inside = false;
01067 
01068       for (menu_it = _menu_chain->begin (); menu_it != _menu_chain->end (); menu_it++)
01069       {
01070         Geometry geo = (*menu_it)->GetGeometry ();
01071 
01072         if (PT_IN_BOX (event.e_x - event.e_x_root, event.e_y - event.e_y_root,
01073                         geo.x, geo.x + geo.width, geo.y, geo.y + geo.height))
01074         {
01075           inside = true;
01076           break;
01077         }
01078       }
01079 
01080       if (inside == false)
01081       {
01082         (*_menu_chain->begin ())->NotifyMouseDownOutsideMenuCascade (event.e_x - event.e_x_root, event.e_y - event.e_y_root);
01083       }
01084     }
01085 
01086     if (m_MenuWindow.IsValid ())
01087     {
01088       event.e_x_root = 0;
01089       event.e_y_root = 0;
01090     }
01091 
01092     if ( (event.e_event == NUX_MOUSE_RELEASED) )
01093     {
01094       SetWidgetDrawingOverlay (NULL, NULL);
01095     }
01096 
01097     if ( (event.e_event == NUX_SIZE_CONFIGURATION) && _menu_chain->size() )
01098     {
01099       (*_menu_chain->begin() )->NotifyTerminateMenuCascade();
01100     }
01101 
01102     return ret;
01103   }
01104 
01105   void WindowCompositor::StartModalWindow (ObjectWeakPtr<BaseWindow> window)
01106   {
01107     if (window == 0)
01108       return;
01109 
01110     WindowList::iterator it = find (_modal_view_window_list.begin(), _modal_view_window_list.end(), window);
01111 
01112     if (it == _modal_view_window_list.end() )
01113     {
01114       _modal_view_window_list.push_front (window);
01115     }
01116   }
01117 
01118   void WindowCompositor::StopModalWindow (ObjectWeakPtr<BaseWindow> window)
01119   {
01120     if (_modal_view_window_list.size () > 0)
01121     {
01122       if (*_modal_view_window_list.begin () == window)
01123         _modal_view_window_list.pop_front ();
01124     }
01125   }
01126 
01128   void WindowCompositor::PushToFront (BaseWindow *window)
01129   {
01130     if (window == 0)
01131       return;
01132 
01133     WindowList::iterator it = find (_view_window_list.begin(), _view_window_list.end (), window);
01134 
01135     if (it != _view_window_list.end () )
01136     {
01137       _view_window_list.erase (it);
01138       _view_window_list.push_front (ObjectWeakPtr<BaseWindow> (window));
01139     }
01140 
01141     EnsureAlwaysOnFrontWindow ();
01142   }
01143 
01145   void WindowCompositor::PushToBack (BaseWindow *window)
01146   {
01147     if (window == 0)
01148       return;
01149 
01150     if (window == _always_on_front_window)
01151       return;
01152 
01153     WindowList::iterator it = find (_view_window_list.begin (), _view_window_list.end (), window);
01154 
01155     if (it != _view_window_list.end() )
01156     {
01157       _view_window_list.erase (it);
01158       _view_window_list.push_back (ObjectWeakPtr<BaseWindow> (window));
01159     }
01160 
01161     EnsureAlwaysOnFrontWindow ();
01162   }
01163 
01165   void WindowCompositor::PushHigher (BaseWindow *top_floating_view, BaseWindow *bottom_floating_view, bool strict)
01166   {
01167     NUX_RETURN_IF_NULL (bottom_floating_view);
01168     NUX_RETURN_IF_NULL (top_floating_view);
01169     NUX_RETURN_IF_FALSE (bottom_floating_view != top_floating_view)
01170 
01171     WindowList::iterator it;
01172     WindowList::iterator it_top;
01173     WindowList::iterator it_bot;
01174 
01175     int i = 0;
01176     int top_pos = -1;
01177     int bot_pos = -1;
01178 
01179     for (it_top = _view_window_list.begin (), i = 0; it_top != _view_window_list.end (); it_top++, i++)
01180     {
01181       if(*it == bottom_floating_view)
01182       {
01183         it_bot = it;
01184         bot_pos = i;
01185       }
01186 
01187       if(*it == top_floating_view)
01188       {
01189         it_top = it;
01190         top_pos = i;
01191       }
01192 
01193       if ((top_pos >= 0) && (bot_pos >= 0))
01194         break;
01195     }
01196 
01197     if ((it_top == _view_window_list.end ()) || (it_bot == _view_window_list.end ()))
01198     {
01199       return;
01200     }
01201 
01202     if ((top_pos < bot_pos) && (strict == false))
01203     {
01204       _view_window_list.erase (it_top);
01205       _view_window_list.insert (it_bot, ObjectWeakPtr<BaseWindow> (top_floating_view));
01206     }
01207 
01208     EnsureAlwaysOnFrontWindow ();
01209   }
01210 
01211   void WindowCompositor::SetAlwaysOnFrontWindow (BaseWindow *window)
01212   {
01213     _always_on_front_window = ObjectWeakPtr<BaseWindow> (window);
01214 
01215     EnsureAlwaysOnFrontWindow ();
01216   }
01217 
01218   void WindowCompositor::EnsureAlwaysOnFrontWindow ()
01219   {
01220     // Do not re-order while we are traversing the list of BaseWindow.
01221     if (inside_event_cycle_)
01222       return;
01223 
01224     if (_always_on_front_window == NULL)
01225       return;
01226 
01227     WindowList::iterator always_top_it = find (_view_window_list.begin(), _view_window_list.end(), _always_on_front_window);
01228     if ((always_top_it != _view_window_list.end ()) &&
01229         (always_top_it != _view_window_list.begin ()) &&
01230         _always_on_front_window.IsValid())
01231     {
01232       _view_window_list.erase (always_top_it);
01233       _view_window_list.push_front (_always_on_front_window);
01234     }
01235   }
01236 
01237   InputArea *WindowCompositor::GetExclusiveInputArea ()
01238   {
01239     return _exclusive_input_area;
01240   }
01241 
01242   bool WindowCompositor::InExclusiveInputMode ()
01243   {
01244     return _in_exclusive_input_mode;
01245   }
01246 
01247   void WindowCompositor::Draw (bool SizeConfigurationEvent, bool force_draw)
01248   {
01249     inside_rendering_cycle_ = true;
01250     if (!GetWindowThread ()->GetWindow().isWindowMinimized())
01251     {
01252       //int w, h;
01253       GetWindowThread ()->GetGraphicsEngine().GetContextSize (m_Width, m_Height);
01254       GetWindowThread ()->GetGraphicsEngine().SetViewport (0, 0, m_Width, m_Height);
01255       
01256       // Reset the Model view Matrix and the projection matrix
01257       GetWindowThread ()->GetGraphicsEngine().ResetProjectionMatrix ();
01258       
01259       GetWindowThread ()->GetGraphicsEngine().ResetModelViewMatrixStack ();
01260       GetWindowThread ()->GetGraphicsEngine().Push2DTranslationModelViewMatrix (0.375f, 0.375f, 0.0f);
01261 
01262 
01263       if (force_draw || SizeConfigurationEvent)
01264       {
01265         // We fall here after something dramatic has happen to the window such as a resizing. In this case
01266         // everything must be rendered. This is very costly and should happen rarely.
01267         if (!GetWindowThread()->IsEmbeddedWindow())
01268           RenderMainWindowComposition(true);
01269 
01270         {
01271           RenderTopViews(true, _view_window_list, false);
01272           RenderTopViews(true, _modal_view_window_list, true);
01273 
01274           DrawMenu(true);
01275           DrawTooltip(true);
01276           DrawOverlay(true);
01277         }
01278       }
01279       else if (m_PopupRemoved || m_MenuRemoved)
01280       {
01281         // A popup removed cause the whole window to be dirty (at least some part of it).
01282         // So exchange DrawList with a real Draw.
01283         if (!GetWindowThread()->IsEmbeddedWindow())
01284           RenderMainWindowComposition(false);
01285 
01286         {
01287           RenderTopViews(false, _view_window_list, false);
01288           RenderTopViews(false, _modal_view_window_list, true);
01289 
01290           DrawMenu(true);
01291           DrawTooltip(true);
01292           DrawOverlay(true);
01293         }
01294       }
01295       else
01296       {
01297         if (!GetWindowThread()->IsEmbeddedWindow())
01298           RenderMainWindowComposition(false);
01299 
01300         {
01301           RenderTopViews(false, _view_window_list, false);
01302           RenderTopViews(false, _modal_view_window_list, true);
01303 
01304           DrawMenu(true);
01305           DrawTooltip(true);
01306           DrawOverlay(true);
01307         }
01308       }
01309 
01310       m_PopupRemoved = false;
01311       m_MenuRemoved = false;
01312 
01313       GetWindowThread ()->GetGraphicsEngine().Pop2DWindow();
01314     }
01315     inside_rendering_cycle_ = false;
01316   }
01317 
01318   void WindowCompositor::DrawMenu (bool force_draw)
01319   {
01320     ObjectWeakPtr<BaseWindow> window = m_MenuWindow;
01321 
01322     if (window.IsValid ())
01323     {
01324       //GetWindowThread ()->GetGraphicsEngine().SetContext (x, y, buffer_width, buffer_height);
01325       GetWindowThread ()->GetGraphicsEngine().SetOrthographicProjectionMatrix (GetWindowThread ()->GetGraphicsEngine().GetWindowWidth(),
01326           GetWindowThread ()->GetGraphicsEngine().GetWindowHeight() );
01327       GetWindowThread ()->GetGraphicsEngine().EmptyClippingRegion();
01328     }
01329     else
01330     {
01331       GetWindowThread ()->GetGraphicsEngine().SetOrthographicProjectionMatrix (GetWindowThread ()->GetGraphicsEngine().GetWindowWidth(),
01332           GetWindowThread ()->GetGraphicsEngine().GetWindowHeight() );
01333       GetWindowThread ()->GetGraphicsEngine().EmptyClippingRegion();
01334     }
01335 
01336     std::list<MenuPage *>::reverse_iterator rev_it_menu;
01337 
01338     for (rev_it_menu = _menu_chain->rbegin(); rev_it_menu != _menu_chain->rend( ); rev_it_menu++)
01339     {
01340       SetProcessingTopView (m_MenuWindow.GetPointer ());
01341       (*rev_it_menu)->ProcessDraw (GetWindowThread ()->GetGraphicsEngine(), force_draw);
01342       SetProcessingTopView (NULL);
01343     }
01344 
01345 //     GetGraphicsDisplay()->GetGraphicsEngine()->SetContext (0, 0,
01346 //                                             GetWindowThread ()->GetGraphicsEngine().GetWindowWidth(),
01347 //                                             GetWindowThread ()->GetGraphicsEngine().GetWindowHeight() );
01348   }
01349 
01350   void WindowCompositor::DrawOverlay (bool force_draw)
01351   {
01352     ObjectWeakPtr<BaseWindow> window = m_OverlayWindow;
01353     int buffer_width = GetWindowThread ()->GetGraphicsEngine().GetWindowWidth();
01354     int buffer_height = GetWindowThread ()->GetGraphicsEngine().GetWindowHeight();
01355 
01356     if (window.IsValid ())
01357     {
01358       //GetWindowThread ()->GetGraphicsEngine().SetContext (x, y, buffer_width, buffer_height);
01359       GetWindowThread ()->GetGraphicsEngine().SetOrthographicProjectionMatrix (buffer_width, buffer_height);
01360       GetWindowThread ()->GetGraphicsEngine().EmptyClippingRegion();
01361     }
01362     else
01363       GetWindowThread ()->GetGraphicsEngine().SetOpenGLClippingRectangle (0, 0, buffer_width, buffer_height);
01364 
01365     if (OverlayDrawingCommand)
01366     {
01367       SetProcessingTopView (m_OverlayWindow.GetPointer ());
01368       OverlayDrawingCommand->OverlayDrawing (GetWindowThread ()->GetGraphicsEngine() );
01369       SetProcessingTopView (NULL);
01370     }
01371 
01372     //GetGraphicsDisplay()->GetGraphicsEngine()->SetContext (0, 0, buffer_width, buffer_height);
01373   }
01374 
01375   void WindowCompositor::DrawTooltip (bool force_draw)
01376   {
01377     ObjectWeakPtr<BaseWindow> window = _tooltip_window;
01378     int buffer_width = GetWindowThread ()->GetGraphicsEngine().GetWindowWidth();
01379     int buffer_height = GetWindowThread ()->GetGraphicsEngine().GetWindowHeight();
01380 
01381     if (window.IsValid ())
01382     {
01383       //GetWindowThread ()->GetGraphicsEngine().SetContext (x, y, buffer_width, buffer_height);
01384       GetWindowThread ()->GetGraphicsEngine().SetOrthographicProjectionMatrix (buffer_width, buffer_height);
01385       GetWindowThread ()->GetGraphicsEngine().EmptyClippingRegion();
01386     }
01387     else
01388       GetWindowThread ()->GetGraphicsEngine().SetOpenGLClippingRectangle (0, 0, buffer_width, buffer_height);
01389 
01390     if(m_TooltipText.Size())
01391     {
01392         //SetProcessingTopView(_tooltip_window);
01393         GetPainter().PaintShape(GetWindowThread ()->GetGraphicsEngine(), _tooltip_geometry, Color(0xA0000000), eSHAPE_CORNER_ROUND10, true);
01394         GetPainter().PaintTextLineStatic(GetWindowThread ()->GetGraphicsEngine(), GetSysBoldFont(), _tooltip_text_geometry, m_TooltipText, Color(0xFFFFFFFF));
01395         //SetProcessingTopView(NULL);
01396     }
01397 
01398     //GetGraphicsDisplay()->GetGraphicsEngine()->SetContext (0, 0, buffer_width, buffer_height);
01399   }
01400 
01401   void WindowCompositor::RenderTopViewContent (BaseWindow *window, bool force_draw)
01402   {
01403     GetPainter().EmptyBackgroundStack();
01404     SetProcessingTopView (window);
01405     window->ProcessDraw (GetWindowThread ()->GetGraphicsEngine(), force_draw || window->IsRedrawNeeded() );
01406     SetProcessingTopView (NULL);
01407     GetPainter().EmptyBackgroundStack();
01408   }
01409 
01410   void WindowCompositor::RenderTopViews(bool force_draw,
01411                                         WindowList& windows_to_render,
01412                                         bool drawModal)
01413   {
01414     // Before anything, deactivate the current frame buffer, set the viewport 
01415     // to the size of the display and call EmptyClippingRegion().
01416     // Then call GetScissorRect() to get the size of the global clipping area.
01417     // This is is hack until we implement SetGlobalClippingRectangle() (the opposite of SetGlobalClippingRectangle).
01418     GraphicsEngine& graphics_engine = GetWindowThread()->GetGraphicsEngine();
01419     unsigned int window_width = graphics_engine.GetWindowWidth();
01420     unsigned int window_height = graphics_engine.GetWindowHeight();
01421     GetGraphicsDisplay()->GetGpuDevice()->DeactivateFrameBuffer();
01422     graphics_engine.SetViewport(0, 0, window_width, window_height);
01423     graphics_engine.EmptyClippingRegion();
01424 
01425     Geometry global_clip_rect = graphics_engine.GetScissorRect();
01426     global_clip_rect.y = window_height - global_clip_rect.y - global_clip_rect.height;
01427 
01428     // Always make a copy of the windows to render.  We have no control over
01429     // the windows we are actually drawing.  It has been observed that some
01430     // windows modify the windows stack during the draw process.
01431     //
01432     // So... we take a copy of the window list.  As much as I'd love to just
01433     // have BaseWindow* in the container, again, we have no control over the
01434     // windows we are drawing and one may just decide to unregister or destroy
01435     // another window mid-render.  Since we are contructing a copy of the
01436     // list, lets reverse it as we are constructing, as we want to draw the
01437     // windows from back to front.
01438     WindowList windows(windows_to_render.rbegin(), windows_to_render.rend());
01439     for (WindowList::iterator it = windows.begin(), end = windows.end(); it != end; ++it)
01440     {
01441       WeakBaseWindowPtr& window_ptr = *it;
01442       if (window_ptr.IsNull())
01443         continue;
01444 
01445       BaseWindow* window = window_ptr.GetPointer();
01446       if (!drawModal && window->IsModal())
01447         continue;
01448 
01449       if (window->IsVisible())
01450       {
01451         if (global_clip_rect.Intersect(window->GetGeometry()).IsNull())
01452         {
01453           // The global clipping area can be seen as a per monitor clipping
01454           // region. It is mostly used in embedded mode with compiz.  If we
01455           // get here, it means that the BaseWindow we want to render is not
01456           // in area of the monitor that compiz is currently rendering. So
01457           // skip it.
01458           continue;
01459         }
01460 
01461         RenderTargetTextures& rt = GetWindowBuffer(window);
01462 
01463         // Based on the areas that requested a rendering inside the
01464         // BaseWindow, render the BaseWindow or just use its cache.
01465         if (force_draw || window->IsRedrawNeeded() || window->ChildNeedsRedraw())
01466         {
01467           if (rt.color_rt.IsValid() /*&& rt.depth_rt.IsValid()*/)
01468           {
01469             t_s32 buffer_width = window->GetBaseWidth();
01470             t_s32 buffer_height = window->GetBaseHeight();
01471 
01472             if ((rt.color_rt->GetWidth() != buffer_width) ||
01473                 (rt.color_rt->GetHeight() != buffer_height))
01474             {
01475               rt.color_rt = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture (buffer_width, buffer_height, 1, BITFMT_R8G8B8A8);
01476               rt.depth_rt = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture (buffer_width, buffer_height, 1, BITFMT_D24S8);
01477             }
01478 
01479             m_FrameBufferObject->FormatFrameBufferObject (buffer_width, buffer_height, BITFMT_R8G8B8A8);
01480             m_FrameBufferObject->SetRenderTarget ( 0, rt.color_rt->GetSurfaceLevel (0) );
01481             m_FrameBufferObject->SetDepthSurface ( rt.depth_rt->GetSurfaceLevel (0) );
01482             m_FrameBufferObject->Activate();
01483             graphics_engine.SetViewport(0, 0, buffer_width, buffer_height);
01484             graphics_engine.SetOrthographicProjectionMatrix(buffer_width, buffer_height);
01485             graphics_engine.EmptyClippingRegion();
01486 
01487             graphics_engine.SetOpenGLClippingRectangle(0, 0, buffer_width, buffer_height);
01488 
01489             CHECKGL ( glClearColor (0, 0, 0, 0) );
01490             GLuint clear_color_buffer_bit = (force_draw || window->IsRedrawNeeded() ) ? GL_COLOR_BUFFER_BIT : 0;
01491             CHECKGL ( glClear (clear_color_buffer_bit | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) );
01492           }
01493           else
01494           {
01495             int x = window->GetBaseX();
01496             int y = window->GetBaseY();
01497             Matrix4 mat;
01498             mat.Translate (x, y, 0);
01499             graphics_engine.SetOrthographicProjectionMatrix(window_width, window_height);
01500           }
01501 
01502           RenderTopViewContent(window, force_draw);
01503         }
01504 
01505         if (rt.color_rt.IsValid())
01506         {
01507           m_FrameBufferObject->Deactivate();
01508 
01509           // Enable this to render the drop shadow under windows: not perfect yet...
01510           if (0)
01511           {
01512             graphics_engine.EmptyClippingRegion();
01513             graphics_engine.SetOpenGLClippingRectangle(0, 0, window_width, window_height);
01514             graphics_engine.SetViewport(0, 0, window_width, window_height);
01515             graphics_engine.SetOrthographicProjectionMatrix(window_width, window_height);
01516 
01517             Geometry shadow(window->GetBaseX(), window->GetBaseY(),
01518                             window->GetBaseWidth(), window->GetBaseHeight());
01519             //if(window->IsVisibleSizeGrip())
01520             {
01521               shadow.OffsetPosition (4, 4);
01522               GetPainter().PaintShape (graphics_engine, shadow, color::Black,
01523                                        eSHAPE_CORNER_SHADOW);
01524             }
01525 //                    else
01526 //                    {
01527 //                        shadow.OffsetPosition(4, 4);
01528 //                        GetPainter().PaintShape(GetWindowThread ()->GetGraphicsEngine(), shadow, Color(0xFF000000), eSHAPE_CORNER_ROUND10_SHADOW);
01529 //                    }
01530           }
01531 
01532           CHECKGL ( glDepthMask (GL_FALSE) );
01533           {
01534             graphics_engine.ApplyClippingRectangle();
01535             PresentBufferToScreen (rt.color_rt, window->GetBaseX(), window->GetBaseY(), false, false, window->GetOpacity (), window->premultiply());
01536           }
01537           CHECKGL ( glDepthMask (GL_TRUE) );
01538           graphics_engine.GetRenderStates().SetBlend(false);
01539         }
01540 
01541         window->_child_need_redraw = false;
01542       }
01543       else
01544       {
01545         // Invisible window, nothing to draw.
01546         window->_child_need_redraw = false;
01547         window->DoneRedraw();
01548       }
01549     }
01550 
01551     m_FrameBufferObject->Deactivate();
01552   }
01553 
01554 // This function is meant to draw the main window and the small windows but it will not traverse the element.
01555 // It just copies to the backbuffer what it already has in  the framebuffer objects.
01556   void WindowCompositor::PresentRendering()
01557   {
01558     m_FrameBufferObject->Deactivate();
01559     unsigned int window_width, window_height;
01560     window_width = GetWindowThread ()->GetGraphicsEngine().GetWindowWidth();
01561     window_height = GetWindowThread ()->GetGraphicsEngine().GetWindowHeight();
01562     GetWindowThread ()->GetGraphicsEngine().EmptyClippingRegion();
01563     //GetWindowThread ()->GetGraphicsEngine().SetOpenGLClippingRectangle(0, 0, window_width, window_height);
01564     GetWindowThread ()->GetGraphicsEngine().SetViewport (0, 0, window_width, window_height);
01565     GetWindowThread ()->GetGraphicsEngine().SetOrthographicProjectionMatrix (window_width, window_height);
01566 
01567     PresentBufferToScreen (m_MainColorRT, 0, 0, false);
01568 
01569     PageBBox page;
01570     page.xmin = 0;
01571     page.xmax = 100;
01572     page.ymin = 700;
01573     page.ymax = 730;
01574     page.x_margin = 0;
01575     page.y_margin = 0;
01576 
01577     NString FPS = NString::Printf (TEXT ("FPS: %3.2f"), GetWindowThread ()->GetFrameRate() );
01578 
01579     GetWindowThread ()->GetGraphicsEngine().RenderColorTextLineStatic (GetSysBoldFont(), page, FPS, Color (0xffff0000), true, eAlignTextLeft);
01580 
01581     GetWindowThread ()->GetGraphicsEngine().Pop2DWindow();
01582   }
01583 
01584   void WindowCompositor::RenderMainWindowComposition(bool force_draw)
01585   {
01586     t_s32 buffer_width, buffer_height;
01587 
01588     buffer_width = GetWindowThread()->GetGraphicsEngine().GetWindowWidth();
01589     buffer_height = GetWindowThread()->GetGraphicsEngine().GetWindowHeight();
01590 
01591     if ((!m_MainColorRT.IsValid()) || (!m_MainDepthRT.IsValid()) || (m_MainColorRT->GetWidth() != buffer_width) || (m_MainColorRT->GetHeight() != buffer_height))
01592     {
01593       m_MainColorRT = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture (buffer_width, buffer_height, 1, BITFMT_R8G8B8A8);
01594       m_MainDepthRT = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture (buffer_width, buffer_height, 1, BITFMT_D24S8);
01595     }
01596 
01597     m_FrameBufferObject->FormatFrameBufferObject(buffer_width, buffer_height, BITFMT_R8G8B8A8);
01598     m_FrameBufferObject->SetRenderTarget(0, m_MainColorRT->GetSurfaceLevel(0));
01599     m_FrameBufferObject->SetDepthSurface(m_MainDepthRT->GetSurfaceLevel(0));
01600     m_FrameBufferObject->Activate();
01601 
01602     GetWindowThread()->GetGraphicsEngine().EmptyClippingRegion();
01603     GetWindowThread()->GetGraphicsEngine().SetOpenGLClippingRectangle (0, 0, buffer_width, buffer_height);
01604     GetWindowThread()->GetGraphicsEngine().SetViewport (0, 0, buffer_width, buffer_height);
01605     GetWindowThread()->GetGraphicsEngine().SetOrthographicProjectionMatrix (buffer_width, buffer_height);
01606     {
01607       CHECKGL(glClear(/*GL_COLOR_BUFFER_BIT |*/ GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
01608       //Begin 2D Drawing
01609       {
01610         if (force_draw)
01611         {
01612           GetPainter().PushDrawLayer(GetWindowThread()->GetGraphicsEngine(), Geometry (0, 0, buffer_width, buffer_height), m_Background);
01613           //GetPainter().PushBackground(GetWindowThread()->GetGraphicsEngine(), Geometry(0, 0, buffer_width, buffer_height), m_Background, true);
01614 
01615           GetWindowThread()->ProcessDraw(GetWindowThread()->GetGraphicsEngine(), true);
01616 
01617           nuxAssert(GetWindowThread()->GetGraphicsEngine().GetNumberOfClippingRegions() == 0);
01618           GetPainter().PopBackground();
01619           GetPainter().EmptyBackgroundStack();
01620         }
01621         else
01622         {
01623           GetPainter().PushLayer (GetWindowThread()->GetGraphicsEngine(), Geometry (0, 0, buffer_width, buffer_height), m_Background);
01624           //GetPainter().PushBackground(GetWindowThread()->GetGraphicsEngine(), Geometry(0, 0, buffer_width, buffer_height), m_Background, false);
01625 
01626           GetWindowThread()->ProcessDraw(GetWindowThread()->GetGraphicsEngine(), false);
01627 
01628           nuxAssert(GetWindowThread()->GetGraphicsEngine().GetNumberOfClippingRegions() == 0);
01629           GetPainter().PopBackground();
01630           GetPainter().EmptyBackgroundStack();
01631         }
01632       }
01633       // End 2D Drawing
01634     }
01635 
01636     if (key_focus_area_)
01637     {
01638       // key focus test
01639       Geometry geo= key_focus_area_->GetRootGeometry();
01640       //GetGraphicsDisplay()->GetGraphicsEngine()->QRP_Color(geo.x, geo.y, geo.width, geo.height, color::Blue);
01641     }
01642 
01643     GetWindowThread ()->GetGraphicsEngine().SetOrthographicProjectionMatrix (buffer_width, buffer_height);
01644     m_FrameBufferObject->Deactivate();
01645 
01646     unsigned int window_width, window_height;
01647     window_width = GetWindowThread ()->GetGraphicsEngine().GetWindowWidth();
01648     window_height = GetWindowThread ()->GetGraphicsEngine().GetWindowHeight();
01649     GetWindowThread ()->GetGraphicsEngine().EmptyClippingRegion();
01650     GetWindowThread ()->GetGraphicsEngine().SetOpenGLClippingRectangle (0, 0, window_width, window_height);
01651     GetWindowThread ()->GetGraphicsEngine().SetViewport (0, 0, window_width, window_height);
01652     GetWindowThread ()->GetGraphicsEngine().SetOrthographicProjectionMatrix (window_width, window_height);
01653 
01654     PresentBufferToScreen (m_MainColorRT, 0, 0, false);
01655 
01656   }
01657 
01658   void WindowCompositor::PresentBufferToScreen (ObjectPtr<IOpenGLBaseTexture> HWTexture, int x, int y, bool RenderToMainTexture, bool BluredBackground, float opacity, bool premultiply)
01659   {
01660     nuxAssert (HWTexture.IsValid() );
01661 
01662     if (HWTexture.IsNull() )
01663       return;
01664 
01665     t_s32 window_width, window_height;
01666     window_width = GetWindowThread ()->GetGraphicsEngine().GetWindowWidth();
01667     window_height = GetWindowThread ()->GetGraphicsEngine().GetWindowHeight();
01668 
01669 
01670     if (RenderToMainTexture && (HWTexture != m_MainColorRT) )
01671     {
01672       nuxAssert (m_MainColorRT->GetWidth() == window_width);
01673       nuxAssert (m_MainColorRT->GetHeight() == window_height);
01674       m_FrameBufferObject->FormatFrameBufferObject (window_width, window_height, BITFMT_R8G8B8A8);
01675       m_FrameBufferObject->SetRenderTarget ( 0, m_MainColorRT->GetSurfaceLevel (0) );
01676       m_FrameBufferObject->SetDepthSurface ( m_MainDepthRT->GetSurfaceLevel (0) );
01677       m_FrameBufferObject->Activate();
01678     }
01679     else
01680     {
01681       GetGraphicsDisplay()->GetGpuDevice()->DeactivateFrameBuffer();
01682     }
01683 
01684     GetWindowThread()->GetGraphicsEngine().EmptyClippingRegion();
01685     GetWindowThread()->GetGraphicsEngine().SetOpenGLClippingRectangle (0, 0, window_width, window_height);
01686     GetWindowThread()->GetGraphicsEngine().SetViewport (0, 0, window_width, window_height);
01687     GetWindowThread()->GetGraphicsEngine().SetOrthographicProjectionMatrix (window_width, window_height);
01688 
01689     // Render the MAINFBO
01690     {
01691       int src_width, src_height;
01692       src_width = HWTexture->GetWidth();
01693       src_height = HWTexture->GetHeight();
01694 
01695       TexCoordXForm texxform0;
01696       texxform0.FlipVCoord (true);
01697 
01698       if (premultiply)
01699       {
01700         GetWindowThread ()->GetGraphicsEngine().GetRenderStates().SetBlend (true, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
01701         GetGraphicsDisplay()->GetGraphicsEngine()->QRP_1Tex (x, y, src_width, src_height, HWTexture, texxform0, Color (opacity, opacity, opacity, opacity));
01702       }
01703       else
01704       {
01705         GetWindowThread ()->GetGraphicsEngine().GetRenderStates().SetBlend (true, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01706         GetGraphicsDisplay()->GetGraphicsEngine()->QRP_1Tex (x, y, src_width, src_height, HWTexture, texxform0, Color (1.0f, 1.0f, 1.0f, opacity));
01707       }
01708       GetWindowThread ()->GetGraphicsEngine().GetRenderStates().SetBlend (false);
01709     }
01710   }
01711 
01712   void WindowCompositor::AddMenu(MenuPage *menu, BaseWindow *window, bool OverrideCurrentMenuChain)
01713   {
01714     if(_menu_chain->size() == 0)
01715     {
01716       // A menu is opening.
01717       _starting_menu_event_cycle = true;
01718       _menu_is_active = true;
01719     }
01720 
01721     std::list<MenuPage*>::iterator it = find(_menu_chain->begin(), _menu_chain->end(), menu);
01722     if(it == _menu_chain->end())
01723     {
01724       // When adding a MenuPage, make sure that it is a child of the MenuPage in _menu_chain->begin().
01725       if (_menu_chain->size() )
01726       {
01727         if (menu->GetParentMenu() != (*_menu_chain->begin() ) )
01728         {
01729           if (OverrideCurrentMenuChain)
01730           {
01731             // Remove the current menu chain
01732             for (it = _menu_chain->begin(); it != _menu_chain->end(); it++)
01733             {
01734               // Stop all pages
01735               (*it)->StopMenu();
01736             }
01737 
01738             _menu_chain->clear();
01739           }
01740           else
01741           {
01742             // The MenuPage argument is not a descendent of the current menu chain.
01743             return;
01744           }
01745         }
01746       }
01747 
01748       m_MenuWindow = window;
01749       // The deepest menu is added in front of the list and tested first for events.
01750       _menu_chain->push_front (menu);
01751     }
01752   }
01753 
01754   // Be careful never call this function while you are iterating through the elements of _menu_chain.
01755   void WindowCompositor::RemoveMenu (MenuPage *menu)
01756   {
01757     std::list<MenuPage *>::iterator it = find(_menu_chain->begin(), _menu_chain->end(), menu);
01758 
01759     if(it == _menu_chain->end())
01760     {
01761       return;
01762     }
01763 
01764     _menu_chain->erase (it);
01765     m_MenuRemoved = true;
01766 
01767     if(_menu_is_active && (_menu_chain->size() == 0))
01768     {
01769       // The menu is closed
01770       _menu_is_active         = false;
01771       ResetMousePointerAreas();
01772       m_MenuWindow            = NULL;
01773     }
01774   }
01775 
01776   void WindowCompositor::CleanMenu()
01777   {
01778     if (_menu_chain->size() == 0)
01779       return;
01780 
01781     std::list<MenuPage *>::iterator menu_it = _menu_chain->begin();
01782 
01783     while (menu_it != _menu_chain->end() )
01784     {
01785       if ( (*menu_it)->IsActive() == false)
01786       {
01787         menu_it = _menu_chain->erase (menu_it);
01788         m_MenuRemoved = true;
01789       }
01790       else
01791       {
01792         menu_it++;
01793       }
01794     }
01795 
01796     if (_menu_is_active && (_menu_chain->size() == 0))
01797     {
01798       _menu_is_active         = false;
01799       ResetMousePointerAreas();
01800       m_MenuWindow            = NULL;
01801     }
01802   }
01803 
01804   void WindowCompositor::SetWidgetDrawingOverlay (InputArea *ic, BaseWindow* OverlayWindow)
01805   {
01806     OverlayDrawingCommand = ic;
01807     m_OverlayWindow = OverlayWindow;
01808   }
01809 
01810   InputArea *WindowCompositor::GetWidgetDrawingOverlay()
01811   {
01812     return OverlayDrawingCommand;
01813   }
01814 
01815   void WindowCompositor::SetTooltip(InputArea* TooltipArea, const TCHAR *TooltipText, int x, int y)
01816   {
01817     _tooltip_window = GetProcessingTopView();
01818     m_TooltipArea = TooltipArea;
01819     m_TooltipText = TooltipText;
01820     m_TooltipX = x;
01821     m_TooltipY = y;
01822 
01823     if(m_TooltipText.Size())
01824     {
01825       int w = GetSysBoldFont()->GetCharStringWidth(m_TooltipText.GetTCharPtr());
01826       int h = GetSysBoldFont()->GetFontHeight();
01827 
01828       _tooltip_text_geometry = Geometry(
01829           m_TooltipX + 10,
01830           m_TooltipY - h/2 - 2,
01831           w,
01832           h + 4);
01833 
01834       _tooltip_geometry = _tooltip_text_geometry;
01835       _tooltip_geometry.OffsetSize(20, 8);
01836       _tooltip_geometry.OffsetPosition(-10, -4);
01837 
01838       _tooltip_mainwindow_geometry = _tooltip_geometry;
01839 
01840       if(_tooltip_window.IsValid())
01841       {
01842         _tooltip_mainwindow_geometry.OffsetPosition(_tooltip_window->GetBaseX(), _tooltip_window->GetBaseY());
01843       }
01844     }
01845     else
01846     {
01847       _tooltip_mainwindow_geometry = _tooltip_geometry = _tooltip_text_geometry = Geometry(0, 0, 0, 0);
01848     }
01849   }
01850 
01851   Geometry WindowCompositor::GetTooltipGeometry() const
01852   {
01853     return _tooltip_geometry;
01854   }
01855 
01856   Geometry WindowCompositor::GetTooltipMainWindowGeometry() const
01857   {
01858       return _tooltip_mainwindow_geometry;
01859   }
01860 
01861   void WindowCompositor::CancelTooltip()
01862   {
01863     _tooltip_window = NULL;
01864     m_TooltipArea = NULL;
01865     m_TooltipText = TEXT ("");
01866   }
01867 
01868   bool WindowCompositor::ValidateMouseInsideTooltipArea(int x, int y)
01869   {
01870     NUX_RETURN_VALUE_IF_FALSE(m_TooltipArea, false);
01871     NUX_RETURN_VALUE_IF_FALSE(_tooltip_window.IsValid(), false);
01872 
01873     Geometry geo = m_TooltipArea->GetGeometry();
01874     geo.OffsetPosition(_tooltip_window->GetBaseX(), _tooltip_window->GetBaseY());
01875 
01876     return geo.IsPointInside(x, y);
01877   }
01878 
01879   bool WindowCompositor::IsTooltipActive()
01880   {
01881     NUX_RETURN_VALUE_IF_FALSE(m_TooltipArea, false);
01882     return true;
01883   }
01884 
01885   void WindowCompositor::OnKeyNavFocusDestroyed(Object* area)
01886   {
01887     if (key_focus_area_ == area)
01888     {
01889       key_focus_area_ = NULL;
01890     }
01891   }
01892   
01893   void WindowCompositor::SetKeyFocusArea(InputArea *area)
01894   {
01895     InputArea* keyboard_grab_area = GetKeyboardGrabArea();
01896 
01897     if (keyboard_grab_area  && area && (area != keyboard_grab_area) && (!area->IsChildOf(keyboard_grab_area)))
01898     {
01899       // There is a keyboard grab pending. Only an area that is a child of the area that has
01900       // the keyboard grab can be set to receive keyboard events.
01901       nuxDebugMsg("[WindowCompositor::SetKeyFocusArea] There is a keyboard grab pending. Cannot change the keyboard event receiver.");
01902       return;
01903     }
01904 
01905     if (key_focus_area_ == area)
01906     {
01907       return;
01908     }
01909 
01910     if (area && (area->AcceptKeyNavFocus() == false))
01911       return;
01912 
01913     if (key_focus_area_)
01914     {
01915       key_focus_area_->EmitEndKeyboardFocus();
01916       key_focus_area_->ResetUpwardPathToKeyFocusArea();
01917 
01918       if (key_focus_area_->Type().IsDerivedFromType(InputArea::StaticObjectType))
01919       {
01920         static_cast<InputArea*>(key_focus_area_)->OnKeyNavFocusChange.emit(key_focus_area_);
01921       }
01922 
01923       if (key_focus_area_->Type().IsDerivedFromType(View::StaticObjectType))
01924       {
01925         static_cast<View*>(key_focus_area_)->QueueDraw();
01926       }
01927     }
01928 
01929     if (area)
01930     {
01931       key_focus_area_ = area;
01932 
01933       key_focus_area_->SetPathToKeyFocusArea();
01934       key_focus_area_->EmitStartKeyboardFocus();
01935 
01936       if (key_focus_area_->Type().IsDerivedFromType(InputArea::StaticObjectType))
01937       {
01938         static_cast<InputArea*>(key_focus_area_)->OnKeyNavFocusChange.emit(key_focus_area_);
01939       }
01940 
01941       if (key_focus_area_->Type().IsDerivedFromType(View::StaticObjectType))
01942       {
01943         static_cast<View*>(key_focus_area_)->QueueDraw();
01944       }
01945 
01946       key_focus_area_->ChildFocusChanged.emit(key_focus_area_);
01947 
01948     }
01949     else
01950     {
01951       key_focus_area_ = NULL;
01952     }
01953 
01954     // Even if the the area parameter cannot receive keyboard events, it will get the
01955     // keyboard navigatiuon focus.
01956 
01957     if (key_focus_area_)
01958     {
01959       key_focus_area_->begin_key_focus.emit();
01960     }
01961 
01962 
01963     key_focus_area_connection_.disconnect();
01964     if (area)
01965     {
01966       key_focus_area_connection_ = area->object_destroyed.connect (sigc::mem_fun (this, &WindowCompositor::OnKeyNavFocusDestroyed));
01967     }
01968   }
01969 
01970   InputArea* WindowCompositor::GetKeyFocusArea()
01971   {
01972     return key_focus_area_;
01973   }
01974 
01975   void WindowCompositor::SetBackgroundPaintLayer(AbstractPaintLayer *bkg)
01976   {
01977     NUX_SAFE_DELETE (m_Background);
01978     m_Background = bkg->Clone();
01979   }
01980 
01981   void WindowCompositor::FloatingAreaConfigureNotify(int Width, int Height)
01982   {
01983     WindowList::iterator it;
01984 
01985     for (it = _view_window_list.begin(); it != _view_window_list.end(); it++)
01986     {
01987       if (!(*it).IsValid())
01988         continue;
01989       if ((*it)->IsVisible())
01990       {
01991         (*it)->NotifyConfigurationChange (Width, Height);
01992       }
01993     }
01994   }
01995 
01996   void WindowCompositor::FormatRenderTargets (int width, int height)
01997   {
01998     int buffer_width = GetWindowThread()->GetGraphicsEngine().GetWindowWidth();
01999     int buffer_height = GetWindowThread()->GetGraphicsEngine().GetWindowHeight();
02000 
02001     nuxAssert(buffer_width >= 1);
02002     nuxAssert(buffer_height >= 1);
02003 
02004     m_MainColorRT = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture (buffer_width, buffer_height, 1, BITFMT_R8G8B8A8);
02005     m_MainDepthRT = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture (buffer_width, buffer_height, 1, BITFMT_D24S8);
02006 
02007     // Clear the buffer the first time...
02008     m_FrameBufferObject->FormatFrameBufferObject (buffer_width, buffer_height, BITFMT_R8G8B8A8);
02009     m_FrameBufferObject->SetRenderTarget(0, m_MainColorRT->GetSurfaceLevel(0));
02010     m_FrameBufferObject->SetDepthSurface(m_MainDepthRT->GetSurfaceLevel(0));
02011     m_FrameBufferObject->Activate();
02012 
02013     CHECKGL(glClearColor(0.0f, 0.0f, 0.0f, 0.0f) );
02014     CHECKGL(glClearDepth(1.0f) );
02015     CHECKGL(glClearStencil(0) );
02016     CHECKGL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
02017     m_FrameBufferObject->Deactivate();
02018     CHECKGL(glClearColor(0.0f, 0.0f, 0.0f, 0.0f));
02019     CHECKGL(glClearDepth(1.0f));
02020     CHECKGL(glClearStencil(0));
02021     CHECKGL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
02022 
02023 //     m_BlurTexture   = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture (Max (buffer_width, 1), Max (buffer_height, 1), 1, BITFMT_R8G8B8A8);
02024 //     m_FullSceneMip0 = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture (Max (buffer_width / 2, 1), Max (buffer_height / 2, 1), 1, BITFMT_R8G8B8A8);
02025 //     m_FullSceneMip1 = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture (Max (buffer_width / 4, 1), Max (buffer_height / 4, 1), 1, BITFMT_R8G8B8A8);
02026 //     m_FullSceneMip2 = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture (Max (buffer_width / 8, 1), Max (buffer_height / 8, 1), 1, BITFMT_R8G8B8A8);
02027   }
02028 
02029   void WindowCompositor::RestoreRenderingSurface()
02030   {
02031     BaseWindow *top_view = GetProcessingTopView();
02032 
02033     if (top_view && inside_rendering_cycle_)
02034     {
02035       nuxAssert(top_view->Type().IsDerivedFromType (BaseWindow::StaticObjectType));
02036 
02037       RenderTargetTextures rt = GetWindowBuffer(top_view);
02038 
02039       int buffer_width = top_view->GetBaseWidth();
02040       int buffer_height = top_view->GetBaseHeight();
02041 
02042       nuxAssert(buffer_width >= 1);
02043       nuxAssert(buffer_height >= 1);
02044 
02045       if ((rt.color_rt->GetWidth() != buffer_width) || (rt.color_rt->GetHeight() != buffer_height))
02046       {
02047         rt.color_rt = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture(buffer_width, buffer_height, 1, BITFMT_R8G8B8A8);
02048         rt.depth_rt = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture(buffer_width, buffer_height, 1, BITFMT_D24S8);
02049       }
02050 
02051       m_FrameBufferObject->FormatFrameBufferObject(buffer_width, buffer_height, BITFMT_R8G8B8A8);
02052       m_FrameBufferObject->SetRenderTarget(0, rt.color_rt->GetSurfaceLevel(0));
02053       m_FrameBufferObject->SetDepthSurface(rt.depth_rt->GetSurfaceLevel(0));
02054       m_FrameBufferObject->Activate();
02055 
02056       GetWindowThread()->GetGraphicsEngine().SetViewport(0, 0, buffer_width, buffer_height);
02057       GetWindowThread()->GetGraphicsEngine().SetOrthographicProjectionMatrix(buffer_width, buffer_height);
02058       GetWindowThread()->GetGraphicsEngine().ApplyClippingRectangle();
02059       //GetWindowThread()->GetGraphicsEngine().ApplyModelViewMatrix(); ???
02060     }
02061     else
02062     {
02063       int buffer_width = GetWindowThread()->GetGraphicsEngine().GetWindowWidth();
02064       int buffer_height = GetWindowThread()->GetGraphicsEngine().GetWindowHeight();
02065 
02066       nuxAssert(buffer_width >= 1);
02067       nuxAssert(buffer_height >= 1);
02068       // Restore Main Frame Buffer
02069       m_FrameBufferObject->FormatFrameBufferObject(buffer_width, buffer_height, BITFMT_R8G8B8A8);
02070       m_FrameBufferObject->SetRenderTarget(0, m_MainColorRT->GetSurfaceLevel(0));
02071       m_FrameBufferObject->SetDepthSurface(m_MainDepthRT->GetSurfaceLevel(0));
02072       m_FrameBufferObject->Activate();
02073 
02074       GetWindowThread()->GetGraphicsEngine().SetViewport(0, 0, buffer_width, buffer_height);
02075       GetWindowThread()->GetGraphicsEngine().SetOrthographicProjectionMatrix(buffer_width, buffer_height);
02076       GetWindowThread()->GetGraphicsEngine().ApplyClippingRectangle();
02077       //GetWindowThread()->GetGraphicsEngine().ApplyModelViewMatrix(); ???
02078     }
02079   }
02080 
02081   void* WindowCompositor::GetBackupTextureData(BaseWindow *base_window, int &width, int &height, int &format)
02082   {
02083     width = height = format = 0;
02084 
02085     NUX_RETURN_VALUE_IF_NULL(base_window, 0);
02086 
02087     std::map<BaseWindow*, struct RenderTargetTextures>::iterator it;
02088 
02089     it = _window_to_texture_map.find(base_window);
02090 
02091     if (it == _window_to_texture_map.end())
02092     {
02093       return 0;
02094     }
02095 
02096     if ((*it).second.color_rt.IsNull())
02097     {
02098       return 0;
02099     }
02100 
02101     return (*it).second.color_rt->GetSurfaceData(0, width, height, format);
02102   }
02103 
02104 
02105   void WindowCompositor::ResetDnDArea()
02106   {
02107     SetDnDArea(NULL);
02108   }
02109 
02110   void WindowCompositor::SetDnDArea(InputArea* area)
02111   {
02112 #if defined (NUX_OS_LINUX)
02113     if (_dnd_area == area)
02114       return;
02115 
02116     if (_dnd_area)
02117     {
02118       _dnd_area->HandleDndLeave ();
02119       _dnd_area->UnReference ();
02120     }
02121     _dnd_area = area;
02122     
02123     if (_dnd_area)
02124     {
02125       _dnd_area->Reference ();
02126       _dnd_area->HandleDndEnter ();
02127     }
02128 #endif
02129   }
02130 
02131   InputArea* WindowCompositor::GetDnDArea()
02132   {
02133     return _dnd_area;
02134   }
02135 
02136   bool WindowCompositor::GrabPointerAdd(InputArea* area)
02137   {
02138     NUX_RETURN_VALUE_IF_NULL(area, false);
02139     bool result = true;
02140 
02141     if (GetPointerGrabArea() == area)
02142     {
02143       nuxDebugMsg (TEXT ("[WindowCompositor::GrabPointerAdd] The area already has the grab"));
02144       return result;
02145     }
02146     
02147     if (GetWindow().PointerGrabData() != this)
02148       result = GetWindow().GrabPointer(NULL, this, true);
02149 
02150     if (result)
02151       pointer_grab_stack_.push_front(area);
02152 
02153     // reset the mouse pointers areas.
02154     ResetMousePointerAreas();
02155 
02156     return result;
02157   }
02158 
02159   bool WindowCompositor::GrabPointerRemove(InputArea* area)
02160   {
02161     NUX_RETURN_VALUE_IF_NULL(area, false);
02162 
02163     std::list<InputArea*>::iterator it;
02164 
02165     // find the first instance of the area pointer in the stack
02166     it = find(pointer_grab_stack_.begin(), pointer_grab_stack_.end(), area);
02167 
02168     if (it == pointer_grab_stack_.end())
02169       return false;
02170 
02171     pointer_grab_stack_.erase(it);
02172     
02173     if (pointer_grab_stack_.empty())
02174       GetWindow().UngrabPointer(this);
02175     
02176     // reset the mouse pointers areas.
02177     ResetMousePointerAreas();
02178 
02179     return true;
02180   }
02181 
02182   bool WindowCompositor::IsInPointerGrabStack(InputArea* area)
02183   {
02184     NUX_RETURN_VALUE_IF_NULL(area, false);
02185 
02186     std::list<InputArea*>::iterator it;
02187     it = find (pointer_grab_stack_.begin(), pointer_grab_stack_.end(), area);
02188 
02189     if (it == pointer_grab_stack_.end())
02190       return false;
02191 
02192     return true;
02193   }
02194 
02195   InputArea* WindowCompositor::GetPointerGrabArea()
02196   {
02197     if (pointer_grab_stack_.empty())
02198       return NULL;
02199 
02200     return (*pointer_grab_stack_.begin());
02201   }
02202 
02203   bool WindowCompositor::GrabKeyboardAdd(InputArea* area)
02204   {
02205     NUX_RETURN_VALUE_IF_NULL(area, false);
02206     bool result = true;
02207 
02208     if (GetKeyboardGrabArea() == area)
02209     {
02210       nuxDebugMsg(TEXT ("[WindowCompositor::GrabKeyboardAdd] The area already has the grab"));
02211       return result;
02212     }
02213 
02214     if (GetWindow().KeyboardGrabData() != this)
02215     {
02216       result = GetWindow().GrabKeyboard(NULL, this, true);
02217     }
02218     
02219     if (result)
02220     {
02221       InputArea* current_keyboard_grab = GetKeyboardGrabArea();
02222       if (current_keyboard_grab)
02223         current_keyboard_grab->end_keyboard_grab.emit(current_keyboard_grab);
02224 
02225       keyboard_grab_stack_.push_front(area);
02226       
02227       // If there is any area with the key focus, cancel it.
02228       if (key_focus_area_)
02229       {
02230         key_focus_area_->EmitEndKeyboardFocus();
02231         key_focus_area_->ResetUpwardPathToKeyFocusArea();
02232 
02233         if (key_focus_area_->Type().IsDerivedFromType(InputArea::StaticObjectType))
02234         {
02235           static_cast<InputArea*>(key_focus_area_)->OnKeyNavFocusChange.emit(key_focus_area_);
02236         }
02237 
02238         if (key_focus_area_->Type().IsDerivedFromType(View::StaticObjectType))
02239         {
02240           static_cast<View*>(key_focus_area_)->QueueDraw();
02241         }
02242         key_focus_area_ = NULL;
02243       }
02244       // Must be called only after the area has been added to the front of keyboard_grab_stack_.
02245       SetKeyFocusArea(area);
02246 
02247       area->start_keyboard_grab.emit(area);
02248     }
02249     
02250     return result;
02251   }
02252 
02253   bool WindowCompositor::GrabKeyboardRemove(InputArea* area)
02254   {
02255     NUX_RETURN_VALUE_IF_NULL(area, false);
02256 
02257     std::list<InputArea*>::iterator it;
02258 
02259     // find the first instance of the area keyboard in the stack
02260     it = find(keyboard_grab_stack_.begin(), keyboard_grab_stack_.end(), area);
02261 
02262     if (it == keyboard_grab_stack_.end())
02263       return false;
02264 
02265     InputArea* current_keyboard_grab = (*it);
02266     bool has_grab = false;
02267     
02268     if (it == keyboard_grab_stack_.begin())
02269     {
02270       // At the top of the keyboard_grab_stack_. Means it has the keyboard grab.
02271       has_grab = true;
02272     }
02273 
02274     // First remove the area from the grab list
02275     keyboard_grab_stack_.erase(it);
02276 
02277     // Then emit end_keyboard_grab if the area had the keyboard grab
02278     if (has_grab && current_keyboard_grab)
02279     {
02280       current_keyboard_grab->end_keyboard_grab.emit(current_keyboard_grab);
02281     }
02282 
02283     if (keyboard_grab_stack_.empty())
02284     {
02285       GetWindow().UngrabKeyboard(this);
02286     }
02287 
02288     // Must be called only after the area has been added to the front of keyboard_grab_stack_.
02289     if (keyboard_grab_stack_.empty())
02290     {
02291       SetKeyFocusArea(NULL);
02292     }
02293     else
02294     {
02295       // If there is any area with the key focus, cancel it.
02296       if (key_focus_area_)
02297       {
02298         key_focus_area_->EmitEndKeyboardFocus();
02299         key_focus_area_->ResetUpwardPathToKeyFocusArea();
02300 
02301         if (key_focus_area_->Type().IsDerivedFromType(InputArea::StaticObjectType))
02302         {
02303           static_cast<InputArea*>(key_focus_area_)->OnKeyNavFocusChange.emit(key_focus_area_);
02304         }
02305 
02306         if (key_focus_area_->Type().IsDerivedFromType(View::StaticObjectType))
02307         {
02308           static_cast<View*>(key_focus_area_)->QueueDraw();
02309         }
02310         key_focus_area_ = NULL;
02311       }
02312             
02313       it = keyboard_grab_stack_.begin();
02314       SetKeyFocusArea(*it);
02315 
02316       InputArea* new_keyboard_grab = (*it);
02317       new_keyboard_grab->start_keyboard_grab.emit(new_keyboard_grab);
02318     }
02319     
02320     return true;
02321   }
02322 
02323   bool WindowCompositor::IsInKeyboardGrabStack(InputArea* area)
02324   {
02325     NUX_RETURN_VALUE_IF_NULL (area, false);
02326 
02327     std::list<InputArea*>::iterator it;
02328     it = find(keyboard_grab_stack_.begin(), keyboard_grab_stack_.end(), area);
02329 
02330     if (it == keyboard_grab_stack_.end())
02331       return false;
02332 
02333     return true;
02334   }
02335 
02336   InputArea* WindowCompositor::GetKeyboardGrabArea()
02337   {
02338     if (keyboard_grab_stack_.size() == 0)
02339       return NULL;
02340 
02341     return (*keyboard_grab_stack_.begin());
02342   }
02343 }
02344 
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends