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