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