Back to index

nux  3.0.0
WindowThread.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #include "Nux.h"
00024 #include "Layout.h"
00025 #include "NuxCore/Logger.h"
00026 #include "NuxGraphics/GraphicsEngine.h"
00027 #include "ClientArea.h"
00028 #include "WindowCompositor.h"
00029 #include "TimerProc.h"
00030 #include "SystemThread.h"
00031 #include "FloatingWindow.h"
00032 
00033 #include "WindowThread.h"
00034 
00035 namespace nux
00036 {
00037 namespace
00038 {
00039 logging::Logger logger("nux.windows.thread");
00040 }
00041 
00042   TimerFunctor *m_ScrollTimerFunctor;
00043   TimerHandle m_ScrollTimerHandler;
00044 
00045 // Thread registration call. Hidden from the users. Implemented in Nux.cpp
00046   bool RegisterNuxThread(NThread *ThreadPtr);
00047   void UnregisterNuxThread(NThread *ThreadPtr);
00048 
00049   const int WindowThread::MINIMUM_WINDOW_WIDTH  = 1;
00050   const int WindowThread::MINIMUM_WINDOW_HEIGHT = 1;
00051 
00052   NUX_IMPLEMENT_OBJECT_TYPE(WindowThread);
00053 
00054   WindowThread::WindowThread(const char *WindowTitle, int width, int height, AbstractThread *Parent, bool Modal)
00055     : AbstractThread(Parent)
00056     , window_initial_width_(width)
00057     , window_initial_height_(height)
00058     , window_title_(WindowTitle)
00059     , m_WidgetInitialized(false)
00060     , window_style_(WINDOWSTYLE_NORMAL)
00061     , embedded_window_(false)
00062     , window_size_configuration_event_(false)
00063     , force_rendering_(false)
00064   {
00065     // Thread specific objects
00066     graphics_display_       = NULL;
00067     window_compositor_      = NULL;
00068     painter_                = NULL;
00069     timer_manager_          = NULL;
00070     theme_                  = NULL;
00071     main_layout_            = NULL;
00072     queue_main_layout_ = false;
00073     
00074     // Protection for ThreadCtor and ThreadDtor;
00075     thread_ctor_called_ = false;
00076     thread_dtor_called_ = false;
00077 
00078     //
00079     wait_for_modal_window_   = false;
00080     modal_window_thread_     = 0;
00081     is_modal_window_              = Modal;
00082 
00083     _inside_layout_cycle = 0;
00084     _draw_requested_to_host_wm       = false;
00085     first_pass_        = true;
00086 
00087     _Timelines = new std::list<Timeline*> ();
00088     GTimeVal time_val;
00089     g_get_current_time(&time_val);
00090     last_timeline_frame_time_sec_ = time_val.tv_sec;
00091     last_timeline_frame_time_usec_ = time_val.tv_usec;
00092     _MasterClock = NULL;
00093 
00094 #if (defined(NUX_OS_LINUX) || defined(NUX_USE_GLIB_LOOP_ON_WINDOWS)) && (!defined(NUX_DISABLE_GLIB_LOOP))
00095     main_loop_glib_      = 0;
00096     main_loop_glib_context_   = 0;
00097 #endif
00098 
00099 #if defined(NUX_OS_LINUX)
00100     x11display_ = NULL;
00101     ownx11display_ = false;
00102 #endif
00103     
00104     _pending_wake_up_timer = false;
00105     _inside_main_loop = false;
00106     _inside_timer_loop = false;
00107     async_wake_up_signal_ = new TimerFunctor();
00108     async_wake_up_signal_->time_expires.connect(sigc::mem_fun(this, &WindowThread::AsyncWakeUpCallback));
00109   }
00110 
00111   WindowThread::~WindowThread()
00112   {
00113 #if (defined(NUX_OS_LINUX) || defined(NUX_USE_GLIB_LOOP_ON_WINDOWS)) && (!defined(NUX_DISABLE_GLIB_LOOP))
00114     CleanupGlibLoop();
00115 #endif
00116 
00117     ThreadDtor();
00118     std::list<Timeline*>::iterator li;
00119     for (li=_Timelines->begin(); li!=_Timelines->end(); ++li)
00120     {
00121       (*li)->UnReference();
00122     }
00123     
00124     delete _Timelines;
00125     delete async_wake_up_signal_;
00126 
00127 #if defined(NUX_OS_LINUX)
00128     if (x11display_ && ownx11display_)
00129     {
00130       XCloseDisplay(x11display_);
00131     }
00132 #endif
00133   }
00134 
00135   void WindowThread::ExitMainLoop()
00136   {
00137 #if (defined(NUX_OS_LINUX) || defined(NUX_USE_GLIB_LOOP_ON_WINDOWS)) && (!defined(NUX_DISABLE_GLIB_LOOP))
00138     StopGLibLoop();
00139 #endif
00140   }
00141 
00142   unsigned int WindowThread::AddTimeout(unsigned int timeout_delay)
00143   {
00144 #if (defined(NUX_OS_LINUX) || defined(NUX_USE_GLIB_LOOP_ON_WINDOWS)) && (!defined(NUX_DISABLE_GLIB_LOOP))
00145     return AddGLibTimeout(timeout_delay);
00146 #endif
00147   }
00148 
00149   TimerHandle WindowThread::SetAsyncTimerCallback(int time_ms, TimeOutSignal* timeout_signal, void *user_data)
00150   {
00151     if (timeout_signal == NULL)
00152       return TimerHandle();
00153 
00154     // Use "this->" because if called from a different thread, GetTimer and GetWindowThread are invalid.
00155     TimerHandle handle = this->GetTimerHandler().AddTimerHandler(time_ms, timeout_signal, user_data, this);
00156 
00157     return handle;
00158   }
00159 
00160   void WindowThread::AsyncWakeUpCallback(void* data)
00161   {
00162     this->GetTimerHandler().RemoveTimerHandler(async_wake_up_timer_handle_);
00163     _pending_wake_up_timer = false;
00164   }
00165   
00166   void WindowThread::ProcessDraw(GraphicsEngine &graphics_engine, bool force_draw)
00167   {
00168     if (main_layout_)
00169     {
00170       bool dirty = main_layout_->IsQueuedForDraw();
00171 
00172       if (dirty)
00173       {
00174         // A main layout re computation has happen. It was not initiated physically by resizing the window. We need to draw the background to
00175         // clean any dirty region.
00176         int buffer_width = graphics_engine.GetWindowWidth();
00177         int buffer_height = graphics_engine.GetWindowHeight();
00178         GetPainter().PaintBackground(graphics_engine, Geometry(0, 0, buffer_width, buffer_height));
00179       }
00180 
00181       main_layout_->ProcessDraw(graphics_engine, force_draw || dirty);
00182     }
00183   }
00184 
00185   void WindowThread::RequestRedraw()
00186   {
00187     _draw_requested_to_host_wm = true;
00188     RedrawRequested.emit();
00189     
00190     if (!IsEmbeddedWindow())
00191     {
00192       // If the system is not in embedded mode and an asynchronous request for a Draw is made,
00193       // and the system is not in a timer processing cycle(always followed by a draw cycle) 
00194       // or not in the event processing cycle(also followed by a draw cycle), then we set a 0 delay 
00195       // timer that will wake up the system and initiate a draw cycle.
00196       if ((_inside_main_loop == false) && (_inside_timer_loop == false) && (_pending_wake_up_timer == false))
00197       {
00198         _pending_wake_up_timer = true;
00199         async_wake_up_timer_handle_ = this->GetTimerHandler().AddTimerHandler(0, async_wake_up_signal_, this);
00200       }
00201     }
00202   }
00203 
00204   void WindowThread::ClearRedrawFlag()
00205   {
00206     _draw_requested_to_host_wm = false;
00207   }
00208 
00209   bool WindowThread::IsRedrawNeeded() const
00210   {
00211     return _draw_requested_to_host_wm;
00212   }
00213 
00214   void WindowThread::SetLayout(Layout *layout)
00215   {
00216     main_layout_ = layout;
00217 
00218     if (main_layout_)
00219     {
00220       int w = graphics_display_->GetGraphicsEngine()->GetContextWidth();
00221       int h = graphics_display_->GetGraphicsEngine()->GetContextHeight();
00222 
00223       main_layout_->Reference();
00224       main_layout_->SetScaleFactor(1);
00225 
00226       StartLayoutCycle();
00227       main_layout_->SetGeometry(0, 0, w, h);
00228       main_layout_->ComputeContentSize();
00229       main_layout_->ComputeContentPosition(0, 0);
00230       StopLayoutCycle();
00231 
00232       RemoveQueuedLayout();
00233     }
00234   }
00235 
00236   Layout* WindowThread::GetLayout()
00237   {
00238     return main_layout_;
00239   }
00240 
00241   void WindowThread::QueueLayout()
00242   {
00243     queue_main_layout_ = true;
00244     RequestRedraw();
00245   }
00246 
00247   void WindowThread::ReconfigureLayout()
00248   {
00249     int w = graphics_display_->GetGraphicsEngine()->GetWindowWidth();
00250     int h = graphics_display_->GetGraphicsEngine()->GetWindowHeight();
00251 
00252     if (main_layout_)
00253     {
00254       StartLayoutCycle();
00255       main_layout_->SetGeometry(0, 0, w, h);
00256       main_layout_->ComputeContentSize();
00257       main_layout_->ComputeContentPosition(0, 0);
00258       StopLayoutCycle();
00259     }
00260 
00261     RemoveQueuedLayout();
00262     queue_main_layout_ = false;
00263   }
00264 
00265   bool WindowThread::QueueObjectLayout(Area *area)
00266   {
00267     NUX_RETURN_VALUE_IF_NULL(area, false);
00268 
00269     std::list<Area *>::iterator it;
00270     it = find(_queued_layout_list.begin(), _queued_layout_list.end(), area);
00271     if (it == _queued_layout_list.end())
00272     {
00273       _queued_layout_list.push_back(area);
00274     }
00275 
00276     return true;
00277   }
00278 
00279   bool WindowThread::RemoveObjectFromLayoutQueue(Area *area)
00280   {
00281     NUX_RETURN_VALUE_IF_NULL(area, false);
00282 
00283     std::list<Area *>::iterator it;
00284     it = find(_queued_layout_list.begin(), _queued_layout_list.end(), area);
00285 
00286     if (it != _queued_layout_list.end())
00287     {
00288       _queued_layout_list.erase(it);
00289       return true;
00290     }
00291     return false;
00292   }
00293 
00294   void WindowThread::RemoveQueuedLayout()
00295   {
00296     _queued_layout_list.clear();
00297   }
00298 
00299   void WindowThread::ComputeQueuedLayout()
00300   {
00301     StartLayoutCycle();
00302     std::list<Area *>::iterator it;
00303 
00304     for (it = _queued_layout_list.begin(); it != _queued_layout_list.end(); it++)
00305     {
00306       Area *area = *it;
00307 
00308       if (area->Type().IsDerivedFromType(View::StaticObjectType))
00309       {
00310         View *view  = NUX_STATIC_CAST(View *, area);
00311 
00312         if (!view->CanBreakLayout())
00313           view->QueueDraw();
00314       }
00315       else if (area->Type().IsDerivedFromType(Layout::StaticObjectType))
00316       {
00317         Layout *layout = NUX_STATIC_CAST(Layout *, area);
00318         layout->QueueDraw();
00319       }
00320       else
00321       {
00322         continue;
00323       }
00324 
00325       (*it)->ComputeContentSize();
00326     }
00327 
00328     StopLayoutCycle();
00329     
00330     RemoveQueuedLayout();
00331   }
00332 
00333   void WindowThread::StartLayoutCycle()
00334   {
00335     _inside_layout_cycle = true;
00336   }
00337 
00338   void WindowThread::StopLayoutCycle()
00339   {
00340     _inside_layout_cycle = false;
00341   }
00342 
00343 
00344   bool WindowThread::IsInsideLayoutCycle() const
00345   {
00346     return _inside_layout_cycle;
00347   }
00348 
00349   void WindowThread::ComputeElementLayout(Area *area, bool recurse_to_top_level_layout)
00350   {
00351     NUX_RETURN_IF_NULL(area);
00352 
00353     bool alreadyComputingLayout = IsInsideLayoutCycle();
00354 
00355     if ((!alreadyComputingLayout) && (!recurse_to_top_level_layout))
00356     {
00357       // When computing the layout, setting the size of widgets may cause the system to recurse 
00358       // upward an look for the up most container which size is affected by its this area.
00359       // This happens in Area::InitiateResizeLayout();
00360       // The search upward is not done if we are already in a layout cycle.
00361       StartLayoutCycle();
00362     }
00363 
00364     if (area->Type().IsDerivedFromType(View::StaticObjectType))
00365     {
00366       View *ic = NUX_STATIC_CAST(View *, area);
00367       ic->QueueDraw();
00368     }
00369     else if (area->Type().IsDerivedFromType(Layout::StaticObjectType))
00370     {
00371       Layout *layout = NUX_STATIC_CAST(Layout *, area);
00372       layout->QueueDraw();
00373     }
00374 
00375     area->ComputeContentSize();
00376 
00377     if (!alreadyComputingLayout)
00378       StopLayoutCycle();
00379   }
00380 
00381   void WindowThread::AddTimeline(Timeline *timeline)
00382   {
00383     _Timelines->push_back(timeline);
00384     _Timelines->unique();
00385     StartMasterClock();
00386   }
00387 
00388   void WindowThread::RemoveTimeline(Timeline *timeline)
00389   {
00390     _Timelines->remove(timeline);
00391     if (_Timelines->size() == 0)
00392     {
00393       StopMasterClock();
00394     }
00395   }
00396 
00397   int WindowThread::Run(void *ptr)
00398   {
00399     if (GetWindowThread() != this)
00400     {
00401       nuxDebugMsg("Cannot run a several WindowThreads in the same window.");
00402       return 1;
00403     }
00404 
00405     if (!IsEmbeddedWindow() && (thread_ctor_called_ == false))
00406     {
00407       nuxDebugMsg("Call WindowThread::Start to run this window in its own thread.");
00408       return 1;
00409     }
00410 
00411     if (user_init_func_ && (m_WidgetInitialized == false))
00412     {
00413       (*user_init_func_) (this, initialization_data_);
00414       m_WidgetInitialized = true;
00415     }
00416 
00417     return MainLoop();
00418   }
00419 
00420   int WindowThread::MainLoop()
00421   {
00422     if (IsEmbeddedWindow())
00423     {
00424       window_compositor_->FormatRenderTargets(graphics_display_->GetWindowWidth(), graphics_display_->GetWindowHeight());
00425       InitGlibLoop();
00426       RunGlibLoop();
00427       return 0;
00428     }
00429     else
00430     {
00431       graphics_display_->ShowWindow();
00432     }
00433     // Called the first time so we can initialize the size of the render targets
00434     // At this stage, the size of the window is known.
00435     window_compositor_->FormatRenderTargets(graphics_display_->GetWindowWidth(), graphics_display_->GetWindowHeight());
00436 
00437     while (GetThreadState() != THREADSTOP)
00438     {
00439       if (GetThreadState() == THREADRUNNING)
00440       {
00441 #if (defined(NUX_OS_LINUX) || defined(NUX_USE_GLIB_LOOP_ON_WINDOWS)) && (!defined(NUX_DISABLE_GLIB_LOOP))
00442         InitGlibLoop();
00443         RunGlibLoop();
00444 #else
00445         ExecutionLoop();
00446 #endif
00447 
00448         if (parent_)
00449         {
00450           if (parent_->Type().IsObjectType(SystemThread::StaticObjectType))
00451             static_cast<SystemThread *> (parent_)->ChildHasFinished(this);
00452 
00453           if (parent_->Type().IsObjectType(WindowThread::StaticObjectType))
00454             static_cast<WindowThread *> (parent_)->ChildHasFinished(this);
00455 
00456           {
00457             SetThreadState(THREADSTOP);
00458             // All children window must be terminated.
00459             TerminateChildWindows();
00460             JoinChildThreads();
00461 
00462             std::list<AbstractThread*>::iterator it;
00463             for (it = children_thread_list_.begin(); it != children_thread_list_.end(); ++it)
00464             {
00465               delete (*it);
00466             }
00467             children_thread_list_.clear();
00468           }
00469         }
00470         else
00471         {
00472           SetThreadState(THREADSTOP);
00473           // All child window must be terminated.
00474           TerminateChildWindows();
00475           JoinChildThreads();
00476 
00477           std::list<AbstractThread*>::iterator it;
00478           for (it = children_thread_list_.begin(); it != children_thread_list_.end(); ++it)
00479           {
00480             delete (*it);
00481           }
00482           children_thread_list_.clear();
00483         }
00484       }
00485       else
00486       {
00487         // Do not sleep. Just return and let the GraphicsDisplay::SwapBuffer do the sleep if necessary.
00488       }
00489     }
00490 
00491     return 0;
00492   }
00493 
00494   extern EventToNameStruct EventToName[];
00495 
00496 #if (defined(NUX_OS_LINUX) || defined(NUX_USE_GLIB_LOOP_ON_WINDOWS)) && (!defined(NUX_DISABLE_GLIB_LOOP))
00497   unsigned int WindowThread::ExecutionLoop(unsigned int timer_id)
00498 #else
00499   unsigned int WindowThread::ExecutionLoop()
00500 #endif
00501   {
00502     Event event;
00503 
00504     if (!IsEmbeddedWindow() && graphics_display_->IsPauseThreadGraphicsRendering())
00505     {
00506       // Do not sleep. Just return and let the GraphicsDisplay::SwapBuffer do the sleep if necessary.
00507       return 0;
00508     }
00509 
00510 #if (!defined(NUX_OS_LINUX) && !defined(NUX_USE_GLIB_LOOP_ON_WINDOWS)) || defined(NUX_DISABLE_GLIB_LOOP)
00511     while (true)
00512 #endif
00513     {
00514       _inside_main_loop = true;
00515 
00516       if (first_pass_)
00517       {
00518         // Reset the timers that were called before the mainloop got initialized.
00519         GetTimer().StartEarlyTimerObjects();
00520       }
00521 
00522       memset(&event, 0, sizeof(Event));
00523       graphics_display_->GetSystemEvent(&event);
00524 
00525       if ((event.type == NUX_DND_ENTER_WINDOW) ||
00526         (event.type == NUX_DND_LEAVE_WINDOW))
00527       {
00528         GetWindowCompositor().ResetDnDArea();
00529       }
00530 
00531       // Call event inspectors.
00532       CallEventInspectors(&event);
00533 
00534       if ((event.type == NUX_TERMINATE_APP) || (this->GetThreadState() == THREADSTOP))
00535       {
00536           return 0;
00537       }
00538       
00539       if (event.type == NUX_SIZE_CONFIGURATION)
00540       {
00541         window_size_configuration_event_ = true;
00542         Rect r = graphics_display_->GetWindowGeometry();
00543         window_configuration.emit(r.x, r.y, r.width, r.height);
00544       }
00545 
00546       int w, h;
00547       // Call gGfx_OpenGL.getWindowSize after the gGfx_OpenGL.get_event.
00548       // Otherwise, w and h may not be correct for the current frame if a resizing happened.
00549       graphics_display_->GetWindowSize(w, h);
00550 
00551       if ((event.type == NUX_MOUSE_PRESSED) ||
00552           (event.type == NUX_MOUSE_RELEASED) ||
00553           (event.type == NUX_MOUSE_DOUBLECLICK) ||
00554           (event.type == NUX_MOUSE_MOVE) ||
00555           (event.type == NUX_SIZE_CONFIGURATION) ||
00556           (event.type == NUX_KEYDOWN) ||
00557           (event.type == NUX_KEYUP) ||
00558           (event.type == NUX_NC_WINDOW_CONFIGURATION) ||
00559           (event.type == NUX_WINDOW_ENTER_FOCUS) ||
00560           (event.type == NUX_WINDOW_EXIT_FOCUS) ||
00561           (event.type == NUX_WINDOW_MOUSELEAVE) ||
00562           (event.type == NUX_DND_MOVE) ||
00563           (event.type == NUX_DND_DROP) ||
00564           (event.type == NUX_DND_ENTER) ||
00565           (event.type == NUX_DND_LEAVE) ||
00566           (event.type == NUX_MOUSE_WHEEL))
00567       {
00568           //DISPATCH EVENT HERE
00569           //event.Application = Application;
00570           window_compositor_->ProcessEvent(event);
00571       }
00572 
00573       if (event.type == NUX_SIZE_CONFIGURATION)
00574       {
00575           if (!graphics_display_->isWindowMinimized())
00576           {
00577               graphics_display_->SetViewPort(0, 0, event.width, event.height);
00578               ReconfigureLayout();
00579               window_compositor_->FormatRenderTargets(event.width, event.height);
00580           }
00581           window_compositor_->FloatingAreaConfigureNotify(event.width, event.height);
00582           window_size_configuration_event_ = true;
00583       }
00584 
00585       // Some action may have caused layouts and areas to request a recompute. 
00586       // Process them here before the Draw section.
00587       if (!graphics_display_->isWindowMinimized() && !IsEmbeddedWindow())
00588       {
00589         if (queue_main_layout_)
00590         {
00591           ReconfigureLayout();
00592         }
00593         else 
00594         {
00595           // Compute the layouts that have been queued.
00596           ComputeQueuedLayout();
00597         }
00598       }
00599       
00600       _inside_main_loop = false;
00601 
00602       if (!graphics_display_->IsPauseThreadGraphicsRendering() || IsEmbeddedWindow())
00603       {
00604         bool SwapGLBuffer = false;
00605         
00606         // Warn the host window manager to initiate a draw cycle.
00607         bool request_draw_cycle_to_host_wm = false;
00608 
00609         if (first_pass_)
00610         {
00611           if (IsEmbeddedWindow())
00612           {
00613             request_draw_cycle_to_host_wm = true;
00614             force_rendering_ = true;
00615           }
00616           else
00617           {
00618             window_compositor_->Draw(window_size_configuration_event_, true);
00619           }
00620           first_pass_ = false;
00621         }
00622         else
00623         {
00624           bool b = (event.type == NUX_MOUSE_PRESSED) ||
00625                    (event.type == NUX_MOUSE_RELEASED) ||
00626                    (event.type == NUX_MOUSE_DOUBLECLICK) ||
00627                    //(event.type == NUX_MOUSE_MOVE) ||
00628                    (event.type == NUX_SIZE_CONFIGURATION) ||
00629                    (event.type == NUX_KEYDOWN) ||
00630                    (event.type == NUX_KEYUP) ||
00631                    (event.type == NUX_NC_WINDOW_CONFIGURATION) ||
00632                    (event.type == NUX_WINDOW_ENTER_FOCUS) ||
00633                    (event.type == NUX_WINDOW_EXIT_FOCUS) ||
00634                    (event.type == NUX_WINDOW_DIRTY);
00635 
00636           if (b && window_compositor_->IsTooltipActive())
00637           {
00638             // Cancel the tooltip since an event that should cause the tooltip to disappear has occurred.
00639             window_compositor_->CancelTooltip();
00640             b |= true;
00641           }
00642 
00643           if (!window_compositor_->ValidateMouseInsideTooltipArea(event.x, event.y) && window_compositor_->IsTooltipActive())
00644           {
00645             // Cancel the tooltip since an event that should cause the tooltip to disappear has occurred.
00646             window_compositor_->CancelTooltip();
00647             b |= true;
00648           }
00649 
00650           if (b || IsRedrawNeeded())
00651           {
00652             if (IsEmbeddedWindow())
00653             {
00654               request_draw_cycle_to_host_wm = true;
00655             }
00656             else
00657             {
00658               window_compositor_->Draw(window_size_configuration_event_, false);
00659             }
00660             SwapGLBuffer = true;
00661           }
00662           else if (window_compositor_->GetWidgetDrawingOverlay() != 0)
00663           {
00664             if (IsEmbeddedWindow())
00665             {
00666               request_draw_cycle_to_host_wm = true;
00667             }
00668             else
00669             {
00670               window_compositor_->Draw(window_size_configuration_event_, false);
00671             }
00672             SwapGLBuffer = false;
00673           }
00674 
00675         }
00676 
00677         if (!IsEmbeddedWindow())
00678         {
00679           if (SwapGLBuffer)
00680           {
00681             // Something was rendered! Swap the rendering buffer!
00682             graphics_display_->SwapBuffer(true);
00683           }
00684 
00685           ClearRedrawFlag();
00686           GetWindowThread()->GetGraphicsEngine().ResetStats();
00687         }
00688         else if (IsEmbeddedWindow() && (_draw_requested_to_host_wm == false) && request_draw_cycle_to_host_wm)
00689         {
00690           RequestRedraw();
00691         }
00692         window_size_configuration_event_ = false;
00693       }
00694     }
00695 
00696     return 1;
00697   }
00698 
00699   unsigned int SpawnThread(NThread &thread)
00700   {
00701     return 0;
00702   }
00703 
00704   bool WindowThread::IsWaitingforModalWindow() const
00705   {
00706     return wait_for_modal_window_;
00707   }
00708 
00709   bool WindowThread::IsModalWindow() const
00710   {
00711     return is_modal_window_;
00712   }
00713 
00714   void WindowThread::AddChildThread(AbstractThread *window)
00715   {
00716     if (window == NULL)
00717       return;
00718 
00719     std::list<AbstractThread*>::iterator it;
00720     it = find(children_thread_list_.begin(), children_thread_list_.end(), window);
00721 
00722     if (it == children_thread_list_.end())
00723     {
00724       children_thread_list_.push_back(window);
00725     }
00726   }
00727 
00728   void WindowThread::RemoveChildThread(AbstractThread *window)
00729   {
00730     nuxAssert(window);
00731     std::list<AbstractThread*>::iterator it;
00732     it = find(children_thread_list_.begin(), children_thread_list_.end(), window);
00733 
00734     if (it != children_thread_list_.end())
00735     {
00736       children_thread_list_.erase(it);
00737     }
00738   }
00739 
00740   void WindowThread::ChildHasFinished(AbstractThread *thread)
00741   {
00742     RemoveChildThread(thread);
00743 
00744     if (thread->Type().IsObjectType(WindowThread::StaticObjectType))
00745     {
00746       SuspendChildGraphics(static_cast<WindowThread*> (thread));
00747     }
00748 
00749     thread->SetThreadState(THREADSTOP);
00750   }
00751 
00752   void WindowThread::TerminateChildThreads()
00753   {
00754     std::list<AbstractThread*>::iterator it;
00755 
00756     for (it = children_thread_list_.begin(); it != children_thread_list_.end(); it++)
00757     {
00758       (*it)->SetThreadState(THREADSTOP);
00759 
00760       if ((*it)->Type().IsObjectType(WindowThread::StaticObjectType))
00761       {
00762         // Terminate by shutting down the main loop
00763         static_cast<WindowThread*>(*it)->ExitMainLoop();
00764       }
00765 
00766       if ((*it)->Type().IsObjectType(SystemThread::StaticObjectType))
00767       {
00768         // Just kill the thread
00769         static_cast<SystemThread*>(*it)->Stop(true);
00770       }
00771     }
00772   }
00773 
00774   ThreadState WindowThread::Start(void *ptr)
00775   {
00776     if (!parent_)
00777     {
00778       return NThread::Start();
00779     }
00780     else
00781     {
00782       if (parent_->Type().IsObjectType(SystemThread::StaticObjectType))
00783       {
00784         return static_cast<SystemThread *> (parent_)->StartChildThread(this, true);
00785       }
00786       else if (parent_->Type().IsObjectType(WindowThread::StaticObjectType))
00787       {
00788         return static_cast<WindowThread *> (parent_)->StartChildThread(this, true);
00789       }
00790 
00791       nuxAssertMsg(0, "[WindowThread::Start] This should not happen.");
00792       return THREAD_START_ERROR;
00793     }
00794   }
00795 
00796   ThreadState WindowThread::StartChildThread(AbstractThread *thread, bool Modal)
00797   {
00798     if (wait_for_modal_window_)
00799     {
00800       // This window is already waiting for a modal window. It cannot start another windows.
00801       return thread->GetThreadState();
00802     }
00803 
00804     ThreadState state = thread->NThread::Start();
00805     //if(state == THREADRUNNING)
00806     {
00807       if (thread->Type().IsObjectType(WindowThread::StaticObjectType))
00808       {
00809         // While the child window is being created, the rendering is paused.
00810         // This is necessary to active OpenGL objects context sharing.
00811         // Cancel the pause by sending the message NUX_THREADMSG_START_RENDERING to this thread.
00812         //graphics_display_->PauseThreadGraphicsRendering();
00813 
00814         if (static_cast<WindowThread *> (thread)->is_modal_window_)
00815         {
00816           DisableMouseKeyboardInput();
00817           modal_window_thread_ = static_cast<WindowThread *> (thread);
00818 //                 std::list<NThread*>::iterator it;
00819 //                 for (it = children_thread_list_.begin(); it != children_thread_list_.end(); it++)
00820 //                 {
00821 //                     static_cast<WindowThread*>(*it)->wait_for_modal_window_ = true;
00822 //                     // WIN32: Disable Mouse and Keyboard inputs for all windows child of this window
00823 //                     ::EnableWindow(static_cast<WindowThread*>(*it)->graphics_display_->GetWindowHandle(), FALSE);
00824 //                 }
00825 //                 // WIN32
00826 //                 ::EnableWindow(graphics_display_->GetWindowHandle(), FALSE);
00827 //                 wait_for_modal_window_ = true;
00828         }
00829 
00830         static_cast<WindowThread *> (thread)->wait_for_modal_window_ = false;
00831 
00832         AddChildThread(thread);
00833       }
00834     }
00835     return state;
00836   }
00837 
00838   ThreadState WindowThread::SuspendChildGraphics(WindowThread *thread)
00839   {
00840     if (wait_for_modal_window_)
00841     {
00842       if (modal_window_thread_ != thread)
00843       {
00844         nuxAssertMsg(0, "[WindowThread::SuspendChildGraphics] cannot supend thread that is not the modal window.");
00845         return thread->GetThreadState();
00846       }
00847     }
00848 
00849     ThreadState state = thread->GetThreadState();
00850 
00851     if (wait_for_modal_window_)
00852     {
00853       modal_window_thread_ = 0;
00854 
00855       EnableMouseKeyboardInput();
00856 //         std::list<NThread*>::iterator it;
00857 //         for (it = children_thread_list_.begin(); it != children_thread_list_.end(); it++)
00858 //         {
00859 //             static_cast<WindowThread*>(*it)->wait_for_modal_window_ = false;
00860 //
00861 //             // WIN32
00862 //             ::EnableWindow(static_cast<WindowThread*>(*it)->graphics_display_->GetWindowHandle(), TRUE);
00863 //         }
00864     }
00865 
00866     // WIN32
00867 #if defined(NUX_OS_WINDOWS)
00868     ::EnableWindow(graphics_display_->GetWindowHandle(), TRUE);
00869 #elif defined(NUX_OS_LINUX)
00870 
00871 #endif
00872     return state;
00873   }
00874 
00875   bool WindowThread::ProcessTimelines(GTimeVal *frame_time)
00876   {
00877     // go through our timelines and tick them
00878     // return true if we still have active timelines
00879 
00880     long msecs;
00881     msecs = (frame_time->tv_sec - last_timeline_frame_time_sec_) * 1000 +
00882             (frame_time->tv_usec - last_timeline_frame_time_usec_) / 1000;
00883 
00884     if (msecs < 0)
00885     {
00886       last_timeline_frame_time_sec_ = frame_time->tv_sec;
00887       last_timeline_frame_time_usec_ = frame_time->tv_usec;
00888       return true;
00889     }
00890 
00891     if (msecs > 0)
00892     {
00893       last_timeline_frame_time_sec_ += msecs / 1000;
00894       last_timeline_frame_time_usec_ += msecs * 1000;
00895     }
00896 
00897     std::list<Timeline*>::iterator li;
00898     std::list<Timeline*> timelines_copy;
00899 
00900     for (li=_Timelines->begin(); li!=_Timelines->end(); ++li)
00901     {
00902       (*li)->Reference();
00903       timelines_copy.push_back((*li));
00904     }
00905 
00906     for(li=timelines_copy.begin(); li!=timelines_copy.end(); ++li)
00907     {
00908       (*li)->DoTick(msecs);
00909     }
00910 
00911     // unreference again
00912     for (li=timelines_copy.begin(); li!=timelines_copy.end(); ++li)
00913       (*li)->UnReference();
00914 
00915     // return if we have any timelines left
00916     return (_Timelines->size() != 0);
00917   }
00918 
00919   void WindowThread::EnableMouseKeyboardInput()
00920   {
00921     std::list<AbstractThread*>::iterator it;
00922 
00923     for (it = children_thread_list_.begin(); it != children_thread_list_.end(); it++)
00924     {
00925       if (NUX_STATIC_CAST(WindowThread *, *it)->Type().IsObjectType(WindowThread::StaticObjectType))
00926       {
00927         NUX_STATIC_CAST(WindowThread *, *it)->EnableMouseKeyboardInput();
00928       }
00929     }
00930 
00931     // WIN32: Enable Mouse and Keyboard inputs for all windows child of this window
00932 #if defined(NUX_OS_WINDOWS)
00933     ::EnableWindow(graphics_display_->GetWindowHandle(), TRUE);
00934 #elif defined(NUX_OS_LINUX)
00935 
00936 #endif
00937     wait_for_modal_window_ = false;
00938   }
00939 
00940   void WindowThread::DisableMouseKeyboardInput()
00941   {
00942     std::list<AbstractThread*>::iterator it;
00943 
00944     for (it = children_thread_list_.begin(); it != children_thread_list_.end(); it++)
00945     {
00946       if (NUX_STATIC_CAST(WindowThread *, *it)->Type().IsObjectType(WindowThread::StaticObjectType))
00947       {
00948         NUX_STATIC_CAST(WindowThread *, *it)->DisableMouseKeyboardInput();
00949       }
00950     }
00951 
00952     // WIN32: Disable Mouse and Keyboard inputs for all windows child of this window
00953 #if defined(NUX_OS_WINDOWS)
00954     ::EnableWindow(graphics_display_->GetWindowHandle(), FALSE);
00955 #elif defined(NUX_OS_LINUX)
00956 
00957 #endif
00958     wait_for_modal_window_ = true;
00959   }
00960 
00961   bool WindowThread::ThreadCtor()
00962   {
00963     if(thread_ctor_called_)
00964     {
00965       nuxDebugMsg("[WindowThread::ThreadCtor] ThreadCtor should not be entered more than once per WindowThread.");
00966       return true;
00967     }
00968 
00969 #if defined(NUX_OS_WINDOWS)
00970     SetWin32ThreadName(GetThreadId(), window_title_.c_str());
00971 #endif
00972 
00973     if (RegisterNuxThread(this) == FALSE)
00974     {
00975       nuxDebugMsg("[WindowThread::ThreadCtor] Failed to register the WindowThread.");
00976       return false;
00977     }
00978 
00979     inlSetThreadLocalStorage(ThreadLocal_InalogicAppImpl, this);
00980     GraphicsDisplay *parent_window = NULL;
00981 
00982     if (parent_ && static_cast<WindowThread *> (parent_)->Type().IsObjectType(WindowThread::StaticObjectType))
00983     {
00984       parent_window = &static_cast<WindowThread *> (parent_)->GetGraphicsDisplay();
00985     }
00986     else
00987     {
00988       parent_window = NULL;
00989     }
00990 
00991     graphics_display_ = gGLWindowManager.CreateGLWindow(window_title_.c_str(), window_initial_width_, window_initial_height_, window_style_, parent_window, false);
00992 
00993     if (graphics_display_ == NULL)
00994     {
00995       nuxDebugMsg("[WindowThread::ThreadCtor] Failed to create the window.");
00996       return false;
00997     }
00998 
00999     if (parent_ && parent_->Type().IsObjectType(WindowThread::StaticObjectType))
01000     {
01001       // Cancel the effect of PauseThreadGraphicsRendering on the parent window.
01002       //PostThreadMessage(parent_->GetThreadId(), NUX_THREADMSG_START_RENDERING, (UINT_PTR)((void*)this), 0);
01003     }
01004 
01005     painter_ = new BasePainter(this);
01006     timer_manager_ = new TimerHandler(this);
01007     window_compositor_ = new WindowCompositor(this);
01008 
01009     SetThreadState(THREADRUNNING);
01010     thread_ctor_called_ = true;
01011     return true;
01012   }
01013 
01014 #if defined(NUX_OS_WINDOWS)
01015   bool WindowThread::ThreadCtor(HWND WindowHandle, HDC WindowDCHandle, HGLRC OpenGLRenderingContext)
01016   {
01017     nuxAssertMsg(thread_ctor_called_ == false, "[WindowThread::ThreadCtor] ThreadCtor should not be entered more than once per WindowThread.");
01018     if(thread_ctor_called_)
01019     {
01020       return true;
01021     }
01022 
01023 #if defined(NUX_OS_WINDOWS)
01024     SetWin32ThreadName(GetThreadId(), window_title_.c_str());
01025 #endif
01026 
01027     if (RegisterNuxThread(this) == FALSE)
01028     {
01029       nuxDebugMsg("[WindowThread::ThreadCtor] Failed to register the WindowThread.");
01030       return false;
01031     }
01032 
01033     inlSetThreadLocalStorage(ThreadLocal_InalogicAppImpl, this);
01034     GraphicsDisplay *ParentWindow = 0;
01035 
01036     if (parent_ && static_cast<WindowThread *> (parent_)->Type().IsObjectType(WindowThread::StaticObjectType))
01037     {
01038       ParentWindow = &static_cast<WindowThread *> (parent_)->GetGraphicsDisplay();
01039     }
01040     else
01041     {
01042       ParentWindow = 0;
01043     }
01044 
01045     graphics_display_ = gGLWindowManager.CreateFromForeignWindow(WindowHandle, WindowDCHandle, OpenGLRenderingContext);
01046 
01047     if (graphics_display_ == 0)
01048     {
01049       nuxDebugMsg("[WindowThread::ThreadCtor] Failed to create the window.");
01050       return false;
01051     }
01052 
01053     if (parent_ && parent_->Type().IsObjectType(WindowThread::StaticObjectType))
01054     {
01055       // Cancel the effect of PauseThreadGraphicsRendering on the parent window.
01056       //PostThreadMessage(parent_->GetThreadId(), NUX_THREADMSG_START_RENDERING, (UINT_PTR)((void*)this), 0);
01057     }
01058 
01059     painter_ = new BasePainter(this);
01060     timer_manager_ = new TimerHandler(this);
01061     window_compositor_ = new WindowCompositor(this);
01062 
01063     SetThreadState(THREADRUNNING);
01064     thread_ctor_called_ = true;
01065 
01066     // Set initial states
01067     int w = graphics_display_->GetWindowWidth();
01068     int h = graphics_display_->GetWindowHeight();
01069 
01070     graphics_display_->SetViewPort(0, 0, w, h);
01071     window_compositor_->FormatRenderTargets(w, h);
01072     window_compositor_->FloatingAreaConfigureNotify(w, h);
01073 
01074     return true;
01075   }
01076 #elif defined(NUX_OS_LINUX)
01077 #ifdef NUX_OPENGLES_20
01078   bool WindowThread::ThreadCtor(Display *X11Display, Window X11Window, EGLContext OpenGLContext)
01079 #else
01080   bool WindowThread::ThreadCtor(Display *X11Display, Window X11Window, GLXContext OpenGLContext)
01081 #endif
01082   {
01083     nuxAssertMsg(thread_ctor_called_ == false, "[WindowThread::ThreadCtor] ThreadCtor should not be entered more than once per WindowThread.");
01084     if(thread_ctor_called_)
01085     {
01086       return true;
01087     }
01088 
01089     if (RegisterNuxThread(this) == FALSE)
01090     {
01091       nuxDebugMsg("[WindowThread::ThreadCtor] Failed to register the WindowThread.");
01092       return false;
01093     }
01094 
01095     inlSetThreadLocalStorage(ThreadLocal_InalogicAppImpl, this);
01096 
01097     if (X11Display)
01098     {
01099       x11display_ = X11Display;
01100       ownx11display_ = false;
01101     }
01102     else
01103     {
01104       x11display_ = XOpenDisplay(NULL);
01105       ownx11display_ = true;
01106     }
01107       
01108     graphics_display_ = gGLWindowManager.CreateFromForeignWindow(x11display_, X11Window, OpenGLContext);
01109 
01110     if (graphics_display_ == 0)
01111     {
01112       nuxDebugMsg("[WindowThread::ThreadCtor] Failed to create the window.");
01113       return false;
01114     }
01115 
01116     if (parent_ && parent_->Type().IsObjectType(WindowThread::StaticObjectType))
01117     {
01118       // Cancel the effect of PauseThreadGraphicsRendering on the parent window.
01119       //PostThreadMessage(parent_->GetThreadId(), NUX_THREADMSG_START_RENDERING, (UINT_PTR)((void*)this), 0);
01120     }
01121 
01122     painter_ = new BasePainter(this);
01123     timer_manager_ = new TimerHandler(this);
01124     window_compositor_ = new WindowCompositor(this);
01125 
01126     SetThreadState(THREADRUNNING);
01127     thread_ctor_called_ = true;
01128 
01129     // Set initial states
01130     int w = graphics_display_->GetWindowWidth();
01131     int h = graphics_display_->GetWindowHeight();
01132 
01133     graphics_display_->SetViewPort(0, 0, w, h);
01134     window_compositor_->FormatRenderTargets(w, h);
01135     window_compositor_->FloatingAreaConfigureNotify(w, h);
01136 
01137     return true;
01138   }
01139 #endif
01140 
01141   bool WindowThread::ThreadDtor()
01142   {
01143     if(thread_dtor_called_)
01144     {
01145       return true;
01146     }
01147 
01148     // Cleanup
01149     RemoveQueuedLayout();
01150 
01151     window_compositor_->BeforeDestructor();
01152 
01153     if (main_layout_)
01154     {
01155       main_layout_->UnReference();
01156     }
01157 
01158     NUX_SAFE_DELETE(window_compositor_);
01159     NUX_SAFE_DELETE(timer_manager_);
01160     NUX_SAFE_DELETE(painter_);
01161     NUX_SAFE_DELETE(theme_);
01162     NUX_SAFE_DELETE(graphics_display_);
01163 
01164 #if defined(NUX_OS_WINDOWS)
01165     PostThreadMessage(NUX_GLOBAL_OBJECT_INSTANCE(NProcess).GetMainThreadID(),
01166                        NUX_THREADMSG_THREAD_TERMINATED,
01167                        NUX_GLOBAL_OBJECT_INSTANCE(NProcess).GetCurrentThreadID(),
01168                        0);
01169 #elif defined(NUX_OS_LINUX)
01170 
01171 #else
01172 #error PostThreadMessage not implemented for this platform.
01173 #endif
01174 
01175     inlSetThreadLocalStorage(ThreadLocal_InalogicAppImpl, 0);
01176     UnregisterNuxThread(this);
01177     thread_dtor_called_ = true;
01178     return true;
01179   }
01180 
01181   void WindowThread::SetWindowSize(int width, int height)
01182   {
01183     if (graphics_display_)
01184     {
01185       if (IsEmbeddedWindow())
01186       {
01187         // This is a passive way to set the window size through out the NuxGraphics system. This call gets the 
01188         // current window size and sets its accordingly to all sub-system.
01189         graphics_display_->ResetWindowSize();
01190       }
01191       else
01192       {
01193         graphics_display_->SetWindowSize(width, height);
01194         ReconfigureLayout();
01195       }
01196     }
01197   }
01198 
01199   void WindowThread::SetWindowBackgroundPaintLayer(AbstractPaintLayer *background_layer)
01200   {
01201     if (background_layer == NULL)
01202       return;
01203 
01204     if (window_compositor_)
01205       window_compositor_->SetBackgroundPaintLayer(background_layer);
01206   }
01207   
01208   void WindowThread::AddToDrawList(View *view)
01209   {
01210     Area *parent;
01211     Geometry geo, pgeo;
01212     
01213     geo = view->GetAbsoluteGeometry();
01214     parent = view->GetToplevel();
01215     
01216     if (parent && (view != parent))
01217     {
01218 //       pgeo = parent->GetGeometry();
01219 //       geo.x += pgeo.x;
01220 //       geo.y += pgeo.y;
01221 
01222       if (parent->Type().IsDerivedFromType(BaseWindow::StaticObjectType))
01223       {
01224         BaseWindow* window = NUX_STATIC_CAST(BaseWindow*, parent);
01225         window->_child_need_redraw = true;
01226       }
01227     }
01228 
01229     if (view->Type().IsDerivedFromType(BaseWindow::StaticObjectType))
01230     {
01231       // If the view is a BaseWindow, allow it to mark itself for redraw, as if it was its own  child.
01232       BaseWindow* window = NUX_STATIC_CAST(BaseWindow*, view);
01233       window->_child_need_redraw = true;
01234     }
01235 
01236     m_dirty_areas.push_back(geo);
01237   }
01238   
01239   void WindowThread::ClearDrawList()
01240   {
01241     m_dirty_areas.clear();
01242   }
01243   
01244   std::vector<Geometry> WindowThread::GetDrawList()
01245   {
01246     return m_dirty_areas;
01247   }
01248 
01249   bool WindowThread::IsEmbeddedWindow()
01250   {
01251     return embedded_window_;
01252   }
01253 
01254 #if defined(NUX_OS_WINDOWS)
01255   bool WindowThread::ProcessForeignEvent(HWND hWnd, MSG msg, WPARAM wParam, LPARAM lParam, void *data)
01256 #elif defined(NUX_OS_LINUX)
01257   bool WindowThread::ProcessForeignEvent(XEvent *xevent, void *data)
01258 #endif
01259   {
01260     if (graphics_display_->IsPauseThreadGraphicsRendering())
01261     {
01262       return false;
01263     }
01264 
01265     Event nux_event;
01266     memset(&nux_event, 0, sizeof(Event));
01267 #if defined(NUX_OS_WINDOWS)
01268     graphics_display_->ProcessForeignWin32Event(hWnd, msg, wParam, lParam, &nux_event);
01269 #elif defined(NUX_OS_LINUX)
01270     graphics_display_->ProcessForeignX11Event(xevent, &nux_event);
01271 #endif
01272 
01273     if (nux_event.type == NUX_TERMINATE_APP || (this->GetThreadState() == THREADSTOP))
01274     {
01275       return false;
01276     }
01277 
01278     if (nux_event.type == NUX_SIZE_CONFIGURATION)
01279     {
01280       window_size_configuration_event_ = true;
01281     }
01282 
01283     int w, h;
01284     // Call gGfx_OpenGL.getWindowSize after the gGfx_OpenGL.get_event.
01285     // Otherwise, w and h may not be correct for the current frame if a resizing happened.
01286     graphics_display_->GetWindowSize(w, h);
01287 
01288     if (nux_event.type == NUX_MOUSE_PRESSED ||
01289         (nux_event.type == NUX_MOUSE_RELEASED) ||
01290         (nux_event.type == NUX_MOUSE_DOUBLECLICK) ||
01291         (nux_event.type == NUX_MOUSE_MOVE) ||
01292         (nux_event.type == NUX_SIZE_CONFIGURATION) ||
01293         (nux_event.type == NUX_KEYDOWN) ||
01294         (nux_event.type == NUX_KEYUP) ||
01295         (nux_event.type == NUX_NC_WINDOW_CONFIGURATION) ||
01296         (nux_event.type == NUX_WINDOW_ENTER_FOCUS) ||
01297         (nux_event.type == NUX_WINDOW_EXIT_FOCUS) ||
01298         (nux_event.type == NUX_WINDOW_MOUSELEAVE) ||
01299         (nux_event.type == NUX_MOUSE_WHEEL))
01300     {
01301         //DISPATCH EVENT HERE
01302         //nux_event.Application = Application;
01303         window_compositor_->ProcessEvent(nux_event);
01304     }
01305 
01306     if (nux_event.type == NUX_SIZE_CONFIGURATION)
01307     {
01308         if (!graphics_display_->isWindowMinimized())
01309         {
01310             graphics_display_->SetViewPort(0, 0, nux_event.width, nux_event.height);
01311             ReconfigureLayout();
01312             window_compositor_->FormatRenderTargets(nux_event.width, nux_event.height);
01313         }
01314         window_compositor_->FloatingAreaConfigureNotify(nux_event.width, nux_event.height);
01315         window_size_configuration_event_ = true;
01316     }
01317 
01318     // Some action may have caused layouts and areas to request a recompute. 
01319     // Process them here before the Draw section.
01320     if (!graphics_display_->isWindowMinimized())
01321     {
01322       if (queue_main_layout_)
01323       {
01324         ReconfigureLayout();
01325       }
01326       else 
01327       {
01328         // Compute the layouts that have been queued.
01329         ComputeQueuedLayout();
01330       }
01331     }
01332 
01333     // Warn the host window manager to initiate a draw cycle.
01334     bool request_draw_cycle_to_host_wm = false;
01335 
01336     if (this->first_pass_)
01337     {
01338       request_draw_cycle_to_host_wm = true;
01339       force_rendering_ = true;
01340       //window_compositor_->Draw(window_size_configuration_event_, true);
01341       this->first_pass_ = false;
01342     }
01343     else
01344     {
01345       bool b = (nux_event.type == NUX_MOUSE_PRESSED) ||
01346                (nux_event.type == NUX_MOUSE_RELEASED) ||
01347                (nux_event.type == NUX_MOUSE_DOUBLECLICK) ||
01348                //(event.type == NUX_MOUSE_MOVE) ||
01349                (nux_event.type == NUX_SIZE_CONFIGURATION) ||
01350                (nux_event.type == NUX_KEYDOWN) ||
01351                (nux_event.type == NUX_KEYUP) ||
01352                (nux_event.type == NUX_NC_WINDOW_CONFIGURATION) ||
01353                (nux_event.type == NUX_WINDOW_ENTER_FOCUS) ||
01354                (nux_event.type == NUX_WINDOW_EXIT_FOCUS) ||
01355                (nux_event.type == NUX_WINDOW_DIRTY);
01356 
01357       if (b && window_compositor_->IsTooltipActive())
01358       {
01359         // Cancel the tooltip since an event that should cause the tooltip to disappear has occurred.
01360         window_compositor_->CancelTooltip();
01361         b |= true;
01362       }
01363 
01364       if (!window_compositor_->ValidateMouseInsideTooltipArea(nux_event.x, nux_event.y) && window_compositor_->IsTooltipActive())
01365       {
01366         // Cancel the tooltip since an event that should cause the tooltip to disappear has occurred.
01367         window_compositor_->CancelTooltip();
01368         b |= true;
01369       }
01370 
01371       if (b || IsRedrawNeeded())
01372       {
01373         request_draw_cycle_to_host_wm = true;
01374       }
01375       else if (window_compositor_->GetWidgetDrawingOverlay() != 0)
01376       {
01377         request_draw_cycle_to_host_wm = true;
01378       }
01379     }
01380 
01381     if (!_draw_requested_to_host_wm && request_draw_cycle_to_host_wm)
01382       RequestRedraw();
01383 
01384     return request_draw_cycle_to_host_wm;
01385   }
01386 
01387   void WindowThread::RenderInterfaceFromForeignCmd(Geometry *clip)
01388   {
01389     nuxAssertMsg(IsEmbeddedWindow() == true, "[WindowThread::RenderInterfaceFromForeignCmd] You can only call RenderInterfaceFromForeignCmd if the window was created with CreateFromForeignWindow.");
01390 
01391     if (!IsEmbeddedWindow())
01392       return;
01393     
01394     IOpenGLShaderProgram::SetShaderTracking(true);
01395 
01396     // Set Nux opengl states. The other plugin in compiz have changed the GPU opengl states.
01397     // Nux keep tracks of its own opengl states and restore them before doing any drawing.
01398     GetWindowThread()->GetGraphicsEngine().GetRenderStates().SubmitChangeStates();
01399 
01400     GetWindowThread()->GetGraphicsEngine().SetOpenGLClippingRectangle(0, 0, GetWindowThread()->GetGraphicsEngine().GetWindowWidth(),
01401         GetWindowThread()->GetGraphicsEngine().GetWindowHeight());
01402 
01403     if (graphics_display_->IsPauseThreadGraphicsRendering() == false)
01404     {
01405       ComputeQueuedLayout();
01406       
01407       if (clip)
01408         GetWindowThread()->GetGraphicsEngine().SetGlobalClippingRectangle(Rect(clip->x, clip->y, clip->width, clip->height));
01409         
01410       window_compositor_->Draw(window_size_configuration_event_, force_rendering_);
01411       
01412       if (clip)
01413         GetWindowThread()->GetGraphicsEngine().DisableGlobalClippingRectangle();
01414       // When rendering in embedded mode, nux does not attempt to measure the frame rate...
01415 
01416       // Cleanup
01417       GetWindowThread()->GetGraphicsEngine().ResetStats();
01418       ClearRedrawFlag();
01419 
01420       window_size_configuration_event_ = false;
01421       force_rendering_ = false;
01422     }
01423 
01424     CHECKGL( glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
01425 
01426     graphics_display_->GetGpuDevice()->DeactivateFrameBuffer();
01427     IOpenGLShaderProgram::SetShaderTracking(false);
01428 
01429     if (IsEmbeddedWindow() && window_compositor_->reference_fbo_)
01430     {
01431       // Restore the reference framebuffer
01432       if (!window_compositor_->RestoreReferenceFramebuffer())
01433       {
01434         nuxDebugMsg("[WindowCompositor::RenderTopViews] Setting the Reference fbo has failed.");
01435       }
01436     }
01437   }
01438 
01439   int WindowThread::InstallEventInspector(EventInspector function, void* data)
01440   {
01441     NUX_RETURN_VALUE_IF_NULL(function, 0);
01442 
01443     std::map < int, EventInspectorStorage >::iterator it;
01444 
01445     for (it = _event_inspectors_map.begin(); it != _event_inspectors_map.end(); it++)
01446     {
01447       if ((*it).second._function == function)
01448       {
01449         // The inspector has already been added. Return its unique id
01450         return (*it).second._uid;
01451       }
01452     }
01453 
01454     // This is a new Event Inspector
01455     EventInspectorStorage new_inspector;
01456     new_inspector._function = function;
01457     new_inspector._data = data;
01458     new_inspector._uid = NUX_GLOBAL_OBJECT_INSTANCE(UniqueIndex).GetUniqueIndex();
01459 
01460     _event_inspectors_map [new_inspector._uid] = new_inspector;
01461     return new_inspector._uid;
01462   }
01463 
01464   bool WindowThread::RemoveEventInspector(int event_inspector_id)
01465   {
01466     NUX_RETURN_VALUE_IF_NULL(event_inspector_id, false);
01467 
01468     std::map < int, EventInspectorStorage >::iterator it;
01469 
01470     for (it = _event_inspectors_map.begin(); it != _event_inspectors_map.end(); it++)
01471     {
01472       if ((*it).second._uid == event_inspector_id)
01473       {
01474         _event_inspectors_map.erase(it);
01475         return true;
01476       }
01477     }
01478     return false;
01479   }
01480 
01481   bool WindowThread::RemoveEventInspector(EventInspector function)
01482   {
01483     NUX_RETURN_VALUE_IF_NULL(function, false);
01484 
01485     std::map < int, EventInspectorStorage >::iterator it;
01486 
01487     for (it = _event_inspectors_map.begin(); it != _event_inspectors_map.end(); it++)
01488     {
01489       if ((*it).second._function == function)
01490       {
01491         _event_inspectors_map.erase(it);
01492         return true;
01493       }
01494     }
01495     return false;
01496   }
01497 
01498   bool WindowThread::CallEventInspectors(Event* event)
01499   {
01500     int n = _event_inspectors_map.size();
01501     if (n == 0)
01502     {
01503       // No event inspector installed.
01504       return false;
01505     }
01506 
01507     bool discard_event = false;
01508     std::map < int, EventInspectorStorage >::iterator it;
01509 
01510     for (it = _event_inspectors_map.begin(); it != _event_inspectors_map.end(); it++)
01511     {
01512       EventInspector callback = (*it).second._function;
01513 
01514       if (callback == 0)
01515         continue;
01516 
01517       int ret = callback(0, event, (*it).second._data);
01518 
01519       if (ret)
01520       {
01521         discard_event = true;
01522       }
01523     }
01524 
01525     return discard_event;
01526   }
01527 
01528 
01529   GraphicsDisplay& WindowThread::GetGraphicsDisplay() const
01530   {
01531     return *graphics_display_;
01532   }
01533 
01534   GraphicsEngine& WindowThread::GetGraphicsEngine() const
01535   {
01536     return *graphics_display_->GetGraphicsEngine();
01537   }
01538 
01539   WindowCompositor& WindowThread::GetWindowCompositor() const
01540   {
01541     return *window_compositor_;
01542   }
01543 
01544   BasePainter& WindowThread::GetPainter() const
01545   {
01546     return *painter_;
01547   }
01548 
01549   TimerHandler& WindowThread::GetTimerHandler() const
01550   {
01551     return *timer_manager_;
01552   }
01553 
01554   UXTheme& WindowThread::GetTheme() const
01555   {
01556     if (!theme_)
01557     {
01558       LOG_INFO(logger) << "Lazily creating nux::UXTheme";
01559       const_cast<WindowThread*>(this)->theme_ = new UXTheme();
01560     }
01561     return *theme_;
01562   }
01563 
01564   std::string WindowThread::GetWindowTitle() const
01565   {
01566     return window_title_;
01567   }
01568 }
01569