Back to index

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