41
41
DECLARE_LOGGER(logger, "nux.window");
43
43
WindowCompositor::WindowCompositor(WindowThread* window_thread)
44
: draw_reference_fbo_(0)
45
, read_reference_fbo_(0)
45
46
, window_thread_(window_thread)
47
, currently_rendering_windows_(nullptr)
48
, current_global_clip_rect_(nullptr)
47
50
m_OverlayWindow = NULL;
48
51
_tooltip_window = NULL;
135
138
_view_window_list.end(), window);
136
139
if (it == _view_window_list.end())
138
_view_window_list.push_front(ObjectWeakPtr<BaseWindow>(window));
141
_view_window_list.push_front(WeakBaseWindowPtr(window));
140
143
RenderTargetTextures rt;
192
195
NuxEventType event_type,
193
196
ObjectWeakPtr<InputArea>& area_under_mouse_pointer)
195
ObjectWeakPtr<BaseWindow> window;
198
WeakBaseWindowPtr window;
196
199
GetAreaUnderMouse(mouse_position, event_type, area_under_mouse_pointer, window);
199
202
void WindowCompositor::GetAreaUnderMouse(const Point& mouse_position,
200
203
NuxEventType event_type,
201
204
ObjectWeakPtr<InputArea>& area_under_mouse_pointer,
202
ObjectWeakPtr<BaseWindow>& window)
205
WeakBaseWindowPtr& window)
205
208
area_under_mouse_pointer = NULL;
207
210
// Go through the list of BaseWindo and find the first area over which the
208
211
// mouse pointer is.
209
WindowList::iterator window_it;
210
for (window_it = _view_window_list.begin(); window_it != _view_window_list.end(); ++window_it)
212
for (auto const& window_it : _view_window_list)
212
if ((*window_it).IsValid() && (*window_it)->IsVisible())
214
// Since the mouse is really an input-level thing, we want to know
215
// if the underlying input window is enabled or if the window is
218
if (!window_it.IsValid())
221
if (window_it->InputWindowEnabled() || window_it->IsVisible())
214
Area* area = (*window_it)->FindAreaUnderMouse(mouse_position, event_type);
223
Area* area = window_it->FindAreaUnderMouse(mouse_position, event_type);
217
226
area_under_mouse_pointer = static_cast<InputArea*>(area);
890
899
unsigned int key_symbol,
891
900
unsigned int special_keys_state,
892
901
ObjectWeakPtr<InputArea>& key_focus_area,
893
ObjectWeakPtr<BaseWindow>& window)
902
WeakBaseWindowPtr& window)
895
904
key_focus_area = NULL;
898
907
// Go through the list of BaseWindos and find the first area over which the mouse pointer is.
899
WindowList::iterator window_it;
900
window_it = _view_window_list.begin();
901
while (!key_focus_area.IsValid() && window_it != _view_window_list.end())
908
for (auto const& window_it : _view_window_list)
903
if ((*window_it).IsValid() && (*window_it)->IsVisible())
910
if (window_it.IsValid() && window_it->IsVisible())
905
key_focus_area = NUX_STATIC_CAST(InputArea*, (*window_it)->FindKeyFocusArea(event_type, key_symbol, special_keys_state));
912
key_focus_area = NUX_STATIC_CAST(InputArea*, window_it->FindKeyFocusArea(event_type, key_symbol, special_keys_state));
906
913
if (key_focus_area.IsValid())
908
915
// We have found an area. We are going to exit the while loop.
915
922
// If key_focus_area is NULL, then try the main window layout.
928
935
unsigned int special_keys_state,
929
936
InputArea* root_search_area,
930
937
ObjectWeakPtr<InputArea>& key_focus_area,
931
ObjectWeakPtr<BaseWindow>& window)
938
WeakBaseWindowPtr& window)
933
940
key_focus_area = NULL;
975
982
InputArea* keyboard_event_grab_view = GetKeyboardGrabArea();
977
984
ObjectWeakPtr<InputArea> focus_area; // The view under the mouse
978
ObjectWeakPtr<BaseWindow> base_window; // The BaseWindow below the mouse pointer.
985
WeakBaseWindowPtr base_window; // The BaseWindow below the mouse pointer.
980
987
if (keyboard_event_grab_view)
1206
1213
if (it != _view_window_list.end())
1208
1215
_view_window_list.erase(it);
1209
_view_window_list.push_front(ObjectWeakPtr<BaseWindow> (window));
1216
_view_window_list.push_front(WeakBaseWindowPtr(window));
1212
1219
EnsureAlwaysOnFrontWindow();
1226
1233
if (it != _view_window_list.end())
1228
1235
_view_window_list.erase(it);
1229
_view_window_list.push_back(ObjectWeakPtr<BaseWindow> (window));
1236
_view_window_list.push_back(WeakBaseWindowPtr(window));
1232
1239
EnsureAlwaysOnFrontWindow();
1273
1280
if ((top_pos < bot_pos) && (strict == false))
1275
1282
_view_window_list.erase(it_top);
1276
_view_window_list.insert(it_bot, ObjectWeakPtr<BaseWindow> (top_floating_view));
1283
_view_window_list.insert(it_bot, WeakBaseWindowPtr(top_floating_view));
1279
1286
EnsureAlwaysOnFrontWindow();
1282
1289
void WindowCompositor::SetAlwaysOnFrontWindow(BaseWindow* window)
1284
_always_on_front_window = ObjectWeakPtr<BaseWindow> (window);
1291
_always_on_front_window = WeakBaseWindowPtr(window);
1286
1293
EnsureAlwaysOnFrontWindow();
1353
void AssignWeakBaseWindowMatchingRaw(WindowCompositor::WeakBaseWindowPtr const& w, BaseWindow* bw, WindowCompositor::WeakBaseWindowPtr *ptr)
1355
if (w.IsValid() && w.GetPointer() == bw)
1360
void WindowCompositor::ForEachBaseWindow(ForEachBaseWindowFunc const& func)
1362
for (auto const& window : _view_window_list)
1364
if (window.IsValid())
1368
for (auto const& window : _modal_view_window_list)
1370
if (window.IsValid())
1374
if (m_MenuWindow.IsValid())
1377
if (_tooltip_window.IsValid())
1378
func(_tooltip_window);
1380
if (m_OverlayWindow.IsValid())
1381
func(m_OverlayWindow);
1344
1384
void WindowCompositor::Draw(bool SizeConfigurationEvent, bool force_draw)
1346
1386
inside_rendering_cycle_ = true;
1444
1484
void WindowCompositor::DrawOverlay(bool /* force_draw */)
1446
ObjectWeakPtr<BaseWindow> window = m_OverlayWindow;
1447
1486
int buffer_width = window_thread_->GetGraphicsEngine().GetWindowWidth();
1448
1487
int buffer_height = window_thread_->GetGraphicsEngine().GetWindowHeight();
1450
if (window.IsValid())
1489
if (m_OverlayWindow.IsValid())
1452
1491
//window_thread_->GetGraphicsEngine().SetContext(x, y, buffer_width, buffer_height);
1453
1492
window_thread_->GetGraphicsEngine().SetOrthographicProjectionMatrix(buffer_width, buffer_height);
1469
1508
void WindowCompositor::DrawTooltip(bool /* force_draw */)
1471
ObjectWeakPtr<BaseWindow> window = _tooltip_window;
1472
1510
int buffer_width = window_thread_->GetGraphicsEngine().GetWindowWidth();
1473
1511
int buffer_height = window_thread_->GetGraphicsEngine().GetWindowHeight();
1475
if (window.IsValid())
1513
if (_tooltip_window.IsValid())
1477
1515
//window_thread_->GetGraphicsEngine().SetContext(x, y, buffer_width, buffer_height);
1478
1516
window_thread_->GetGraphicsEngine().SetOrthographicProjectionMatrix(buffer_width, buffer_height);
1501
1539
GetPainter().EmptyBackgroundStack();
1542
void WindowCompositor::PresentAnyReadyWindows()
1544
if (!currently_rendering_windows_ || !current_global_clip_rect_)
1547
GraphicsEngine& graphics_engine = window_thread_->GetGraphicsEngine();
1549
// Present all buffers to the screen
1550
graphics_engine.ApplyClippingRectangle();
1551
CHECKGL(glDepthMask(GL_FALSE));
1553
WindowList &windows = *currently_rendering_windows_;
1554
Geometry &global_clip_rect = *current_global_clip_rect_;
1556
for (auto const& window_ptr : windows)
1558
if (window_ptr.IsNull())
1561
BaseWindow* window = window_ptr.GetPointer();
1563
if (window->IsVisible())
1565
auto const& win_geo = window->GetGeometry();
1567
if (!global_clip_rect.IsIntersecting(win_geo))
1569
// The global clipping area can be seen as a per monitor clipping
1570
// region. It is mostly used in embedded mode with compiz. If we
1571
// get here, it means that the BaseWindow we want to render is not
1572
// in area of the monitor that compiz is currently rendering. So
1577
RenderTargetTextures& rt = GetWindowBuffer(window);
1579
if (rt.color_rt.IsValid())
1581
/* Already been presented */
1582
if (!window->_contents_ready_for_presentation)
1585
/* Caller doesn't want us to render this yet */
1586
if (window_thread_->IsEmbeddedWindow() && !window->AllowPresentationInEmbeddedMode())
1589
// Nux is done rendering a BaseWindow into a texture. The previous call to Deactivate
1590
// has cancelled any opengl framebuffer object that was set.
1591
PresentBufferToScreen(rt.color_rt, win_geo.x, win_geo.y, false, false, window->GetOpacity(), window->premultiply());
1593
window->_contents_ready_for_presentation = false;
1504
1599
void WindowCompositor::RenderTopViews(bool force_draw,
1505
1600
WindowList& windows_to_render,
1506
1601
bool drawModal)
1512
1607
GraphicsEngine& graphics_engine = window_thread_->GetGraphicsEngine();
1513
1608
unsigned int window_width = graphics_engine.GetWindowWidth();
1514
1609
unsigned int window_height = graphics_engine.GetWindowHeight();
1515
GetGraphicsDisplay()->GetGpuDevice()->DeactivateFrameBuffer();
1516
1610
graphics_engine.SetViewport(0, 0, window_width, window_height);
1517
1611
graphics_engine.EmptyClippingRegion();
1519
1613
Geometry global_clip_rect = graphics_engine.GetScissorRect();
1520
1614
global_clip_rect.y = window_height - global_clip_rect.y - global_clip_rect.height;
1616
current_global_clip_rect_ = &global_clip_rect;
1618
// We don't need to restore framebuffers if we didn't update any windows
1619
bool updated_any_windows = false;
1522
1621
// Always make a copy of the windows to render. We have no control over
1523
1622
// the windows we are actually drawing. It has been observed that some
1524
1623
// windows modify the windows stack during the draw process.
1530
1629
// list, lets reverse it as we are constructing, as we want to draw the
1531
1630
// windows from back to front.
1532
1631
WindowList windows(windows_to_render.rbegin(), windows_to_render.rend());
1533
for (WindowList::iterator it = windows.begin(), end = windows.end(); it != end; ++it)
1633
currently_rendering_windows_ = &windows;
1635
for (auto const& window_ptr : windows)
1535
WeakBaseWindowPtr& window_ptr = *it;
1536
1637
if (window_ptr.IsNull())
1539
1640
BaseWindow* window = window_ptr.GetPointer();
1540
1642
if (!drawModal && window->IsModal())
1543
1645
if (window->IsVisible())
1545
if (global_clip_rect.Intersect(window->GetGeometry()).IsNull())
1647
auto const& win_geo = window->GetGeometry();
1648
if (!global_clip_rect.IsIntersecting(win_geo))
1547
1650
// The global clipping area can be seen as a per monitor clipping
1548
1651
// region. It is mostly used in embedded mode with compiz. If we
1589
int x = window->GetBaseX();
1590
int y = window->GetBaseY();
1592
mat.Translate(x, y, 0);
1693
mat.Translate(win_geo.x, win_geo.y, 0);
1593
1694
graphics_engine.SetOrthographicProjectionMatrix(window_width, window_height);
1596
1697
RenderTopViewContent(window, force_draw);
1599
if (rt.color_rt.IsValid())
1601
1699
m_FrameBufferObject->Deactivate();
1603
// Nux is done rendering a BaseWindow into a texture. The previous call to Deactivate
1604
// has cancelled any opengl framebuffer object that was set.
1606
CHECKGL(glDepthMask(GL_FALSE));
1608
graphics_engine.ApplyClippingRectangle();
1609
PresentBufferToScreen(rt.color_rt, window->GetBaseX(), window->GetBaseY(), false, false, window->GetOpacity(), window->premultiply());
1611
1700
CHECKGL(glDepthMask(GL_TRUE));
1612
1701
graphics_engine.GetRenderStates().SetBlend(false);
1702
updated_any_windows = true;
1615
1705
window->_child_need_redraw = false;
1706
window->_contents_ready_for_presentation = true;
1625
m_FrameBufferObject->Deactivate();
1716
/* If any windows were updated, then we need to rebind our
1717
* reference framebuffer */
1718
if (updated_any_windows)
1720
if (GetWindowThread()->IsEmbeddedWindow())
1722
// Restore the reference framebuffer
1723
if (!RestoreReferenceFramebuffer())
1725
LOG_DEBUG(logger) << "RenderTopViews: Setting the Reference fbo has failed.";
1730
GetGraphicsDisplay()->GetGpuDevice()->DeactivateFrameBuffer();
1734
/* Present any windows which haven't yet been presented */
1735
PresentAnyReadyWindows();
1737
currently_rendering_windows_ = nullptr;
1738
current_global_clip_rect_ = nullptr;
1628
1741
void WindowCompositor::RenderMainWindowComposition(bool force_draw)
1720
1833
m_FrameBufferObject->SetDepthTextureAttachment(m_MainDepthRT, 0);
1721
1834
m_FrameBufferObject->Activate();
1725
if (GetWindowThread()->IsEmbeddedWindow() && reference_fbo_)
1727
// In the context of Unity, we may want Nux to restore a specific fbo and render the
1728
// BaseWindow texture into it. That fbo is called a reference framebuffer object. if a
1729
// Reference framebuffer object is present, Nux sets it.
1730
if (!RestoreReferenceFramebuffer())
1732
nuxDebugMsg("[WindowCompositor::RenderTopViews] Setting the Reference fbo has failed.");
1737
GetGraphicsDisplay()->GetGpuDevice()->DeactivateFrameBuffer();
1837
// Reference framebuffer is already restored
1741
1839
window_thread_->GetGraphicsEngine().EmptyClippingRegion();
1742
1840
window_thread_->GetGraphicsEngine().SetOpenGLClippingRectangle(0, 0, window_width, window_height);
1950
2048
// There is a keyboard grab pending. Only an area that is a child of the area that has
1951
2049
// the keyboard grab can be set to receive keyboard events.
1952
nuxDebugMsg("[WindowCompositor::SetKeyFocusArea] There is a keyboard grab pending. Cannot change the keyboard event receiver.");
2050
LOG_DEBUG(logger) << "SetKeyFocusArea: There is a keyboard grab pending. Cannot change the keyboard event receiver.";
2048
2146
WindowList::iterator it;
2050
for (it = _view_window_list.begin(); it != _view_window_list.end(); ++it)
2148
for (auto const& win : _view_window_list)
2052
if (!(*it).IsValid())
2054
if ((*it)->IsVisible())
2056
(*it)->NotifyConfigurationChange(Width, Height);
2153
if (win->IsVisible())
2154
win->NotifyConfigurationChange(Width, Height);
2141
2238
nuxAssert(buffer_width >= 1);
2142
2239
nuxAssert(buffer_height >= 1);
2143
// Restore Main Frame Buffer
2144
m_FrameBufferObject->FormatFrameBufferObject(buffer_width, buffer_height, BITFMT_R8G8B8A8);
2145
m_FrameBufferObject->SetTextureAttachment(0, m_MainColorRT, 0);
2146
m_FrameBufferObject->SetDepthTextureAttachment(m_MainDepthRT, 0);
2147
m_FrameBufferObject->Activate();
2240
// Restore Main Frame Buffer if not in embedded mode
2241
if (!GetWindowThread()->IsEmbeddedWindow())
2243
m_FrameBufferObject->FormatFrameBufferObject(buffer_width, buffer_height, BITFMT_R8G8B8A8);
2244
m_FrameBufferObject->SetTextureAttachment(0, m_MainColorRT, 0);
2245
m_FrameBufferObject->SetDepthTextureAttachment(m_MainDepthRT, 0);
2246
m_FrameBufferObject->Activate();
2250
// Restore reference framebuffer
2251
RestoreReferenceFramebuffer();
2253
// Present any ready windows
2254
PresentAnyReadyWindows();
2149
2257
window_thread_->GetGraphicsEngine().SetViewport(0, 0, buffer_width, buffer_height);
2150
2258
window_thread_->GetGraphicsEngine().SetOrthographicProjectionMatrix(buffer_width, buffer_height);
2429
2537
return (*keyboard_grab_stack_.begin());
2432
void WindowCompositor::SetReferenceFramebuffer(unsigned int fbo_object, Geometry fbo_geometry)
2540
void WindowCompositor::SetReferenceFramebuffer(unsigned int draw_fbo_object, unsigned int read_fbo_object, Geometry const& fbo_geometry)
2434
reference_fbo_ = fbo_object;
2542
draw_reference_fbo_ = draw_fbo_object;
2543
read_reference_fbo_ = read_fbo_object;
2435
2544
reference_fbo_geometry_ = fbo_geometry;
2500
void SetReferenceFramebufferViewport (const nux::Geometry &reference_fbo_geometry_)
2609
void SetReferenceFramebufferViewport(const nux::Geometry &reference_fbo_geometry_)
2502
2611
CHECKGL(glViewport(reference_fbo_geometry_.x,
2503
2612
reference_fbo_geometry_.y,
2509
2618
bool WindowCompositor::RestoreReferenceFramebuffer()
2511
if (!reference_fbo_)
2514
2620
// It is assumed that the reference fbo contains valid textures.
2515
2621
// Nux does the following:
2516
2622
// - Bind the reference fbo (reference_fbo_)
2517
2623
// - Call glDrawBuffer with GL_COLOR_ATTACHMENT0
2518
2624
// - Set the opengl viewport size (reference_fbo_geometry_)
2520
CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, reference_fbo_));
2521
#ifndef NUX_OPENGLES_20
2522
CHECKGL(glDrawBuffer(GL_COLOR_ATTACHMENT0));
2523
CHECKGL(glReadBuffer(GL_COLOR_ATTACHMENT0));
2526
SetReferenceFramebufferViewport (reference_fbo_geometry_);
2528
return CheckExternalFramebufferStatus (GL_FRAMEBUFFER_EXT);
2626
#ifndef NUX_OPENGLES_20
2627
CHECKGL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, draw_reference_fbo_));
2628
CHECKGL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, read_reference_fbo_));
2629
if (draw_reference_fbo_)
2631
CHECKGL(glDrawBuffer(GL_COLOR_ATTACHMENT0));
2635
CHECKGL(glDrawBuffer(GL_BACK));
2638
if (read_reference_fbo_)
2640
CHECKGL(glReadBuffer(GL_COLOR_ATTACHMENT0));
2644
CHECKGL(glReadBuffer(GL_BACK));
2647
nuxAssertMsg(draw_reference_fbo_ == read_reference_fbo_,
2648
"[WindowCompositor::RestoreReferenceFramebuffer]: OpenGL|ES does not"\
2649
" support separate draw and read framebuffer bindings, using the supplied"\
2651
CHECKGL(glBindFramebufferEXT(GL_FRAMEBUFFER, draw_reference_fbo_));
2654
SetReferenceFramebufferViewport(reference_fbo_geometry_);
2656
#ifndef NUX_OPENGLES_20
2657
int restore_status =
2658
(!draw_reference_fbo_ ||
2659
CheckExternalFramebufferStatus(GL_DRAW_FRAMEBUFFER_EXT)) &&
2660
(!read_reference_fbo_ ||
2661
CheckExternalFramebufferStatus(GL_READ_FRAMEBUFFER_EXT));
2663
int restore_status = CheckExternalFramebufferStatus(GL_FRAMEBUFFER);
2666
return restore_status;
2531
2669
void WindowCompositor::RestoreMainFramebuffer()
2533
2671
// This is a bit inefficient as we unbind and then rebind
2534
2672
nux::GetGraphicsDisplay()->GetGpuDevice()->DeactivateFrameBuffer ();
2535
2673
RestoreReferenceFramebuffer ();
2675
/* Present any ready windows after restoring
2676
* the reference framebuffer. This ensures that if
2677
* we need to restore the reference framebuffer to
2678
* get access to its contents through glCopyTexSubImage2D
2679
* that it will also have any rendered views in it too
2681
PresentAnyReadyWindows();
2538
2684
#ifdef NUX_GESTURES_SUPPORT