Sdk: Fix segfault when deleting hovered widget
This commit is contained in:
parent
46e684c275
commit
84537fcfb8
|
|
@ -80,7 +80,7 @@ namespace Ndk
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
EntityHandle CreateEntity();
|
const EntityHandle& CreateEntity();
|
||||||
void DestroyEntity(Entity* entity);
|
void DestroyEntity(Entity* entity);
|
||||||
virtual void Layout();
|
virtual void Layout();
|
||||||
void InvalidateNode() override;
|
void InvalidateNode() override;
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ namespace Ndk
|
||||||
|
|
||||||
std::size_t RegisterWidget(BaseWidget* widget);
|
std::size_t RegisterWidget(BaseWidget* widget);
|
||||||
|
|
||||||
inline void SetKeyboardOwner(BaseWidget* widget);
|
inline void SetKeyboardOwner(std::size_t canvasIndex);
|
||||||
|
|
||||||
void UnregisterWidget(std::size_t index);
|
void UnregisterWidget(std::size_t index);
|
||||||
|
|
||||||
|
|
@ -67,10 +67,10 @@ namespace Ndk
|
||||||
NazaraSlot(Nz::EventHandler, OnMouseLeft, m_mouseLeftSlot);
|
NazaraSlot(Nz::EventHandler, OnMouseLeft, m_mouseLeftSlot);
|
||||||
NazaraSlot(Nz::EventHandler, OnTextEntered, m_textEnteredSlot);
|
NazaraSlot(Nz::EventHandler, OnTextEntered, m_textEnteredSlot);
|
||||||
|
|
||||||
|
std::size_t m_keyboardOwner;
|
||||||
|
std::size_t m_hoveredWidget;
|
||||||
std::vector<WidgetBox> m_widgetBoxes;
|
std::vector<WidgetBox> m_widgetBoxes;
|
||||||
Nz::CursorControllerHandle m_cursorController;
|
Nz::CursorControllerHandle m_cursorController;
|
||||||
const WidgetBox* m_hoveredWidget;
|
|
||||||
BaseWidget* m_keyboardOwner;
|
|
||||||
WorldHandle m_world;
|
WorldHandle m_world;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
inline Canvas::Canvas(WorldHandle world, Nz::EventHandler& eventHandler, Nz::CursorControllerHandle cursorController) :
|
inline Canvas::Canvas(WorldHandle world, Nz::EventHandler& eventHandler, Nz::CursorControllerHandle cursorController) :
|
||||||
|
m_hoveredWidget(InvalidCanvasIndex),
|
||||||
|
m_keyboardOwner(InvalidCanvasIndex),
|
||||||
m_cursorController(cursorController),
|
m_cursorController(cursorController),
|
||||||
m_hoveredWidget(nullptr),
|
|
||||||
m_keyboardOwner(nullptr),
|
|
||||||
m_world(std::move(world))
|
m_world(std::move(world))
|
||||||
{
|
{
|
||||||
m_canvas = this;
|
m_canvas = this;
|
||||||
|
|
@ -61,12 +61,12 @@ namespace Ndk
|
||||||
WidgetBox& entry = m_widgetBoxes[index];
|
WidgetBox& entry = m_widgetBoxes[index];
|
||||||
|
|
||||||
entry.cursor = entry.widget->GetCursor();
|
entry.cursor = entry.widget->GetCursor();
|
||||||
if (m_cursorController && m_hoveredWidget == &entry)
|
if (m_cursorController && m_hoveredWidget == index)
|
||||||
m_cursorController->UpdateCursor(Nz::Cursor::Get(entry.cursor));
|
m_cursorController->UpdateCursor(Nz::Cursor::Get(entry.cursor));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Ndk::Canvas::SetKeyboardOwner(BaseWidget* widget)
|
inline void Canvas::SetKeyboardOwner(std::size_t canvasIndex)
|
||||||
{
|
{
|
||||||
m_keyboardOwner = widget;
|
m_keyboardOwner = canvasIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ namespace Ndk
|
||||||
|
|
||||||
void BaseWidget::GrabKeyboard()
|
void BaseWidget::GrabKeyboard()
|
||||||
{
|
{
|
||||||
m_canvas->SetKeyboardOwner(this);
|
m_canvas->SetKeyboardOwner(m_canvasIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseWidget::SetBackgroundColor(const Nz::Color& color)
|
void BaseWidget::SetBackgroundColor(const Nz::Color& color)
|
||||||
|
|
@ -133,9 +133,9 @@ namespace Ndk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityHandle BaseWidget::CreateEntity()
|
const Ndk::EntityHandle& BaseWidget::CreateEntity()
|
||||||
{
|
{
|
||||||
EntityHandle newEntity = m_world->CreateEntity();
|
const EntityHandle& newEntity = m_world->CreateEntity();
|
||||||
newEntity->Enable(m_visible);
|
newEntity->Enable(m_visible);
|
||||||
|
|
||||||
m_entities.emplace_back(newEntity);
|
m_entities.emplace_back(newEntity);
|
||||||
|
|
|
||||||
|
|
@ -28,18 +28,25 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
WidgetBox& entry = m_widgetBoxes[index];
|
WidgetBox& entry = m_widgetBoxes[index];
|
||||||
|
|
||||||
if (m_hoveredWidget == &entry)
|
if (m_hoveredWidget == index)
|
||||||
m_hoveredWidget = nullptr;
|
m_hoveredWidget = InvalidCanvasIndex;
|
||||||
|
|
||||||
if (m_keyboardOwner == entry.widget)
|
if (m_keyboardOwner == index)
|
||||||
m_keyboardOwner = nullptr;
|
m_keyboardOwner = InvalidCanvasIndex;
|
||||||
|
|
||||||
if (m_widgetBoxes.size() > 1U)
|
if (m_widgetBoxes.size() > 1U)
|
||||||
{
|
{
|
||||||
WidgetBox& lastEntry = m_widgetBoxes.back();
|
WidgetBox& lastEntry = m_widgetBoxes.back();
|
||||||
|
std::size_t lastEntryIndex = m_widgetBoxes.size() - 1;
|
||||||
|
|
||||||
entry = std::move(lastEntry);
|
entry = std::move(lastEntry);
|
||||||
entry.widget->UpdateCanvasIndex(index);
|
entry.widget->UpdateCanvasIndex(index);
|
||||||
|
|
||||||
|
if (m_hoveredWidget == lastEntryIndex)
|
||||||
|
m_hoveredWidget = index;
|
||||||
|
|
||||||
|
if (m_keyboardOwner == lastEntryIndex)
|
||||||
|
m_keyboardOwner = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_widgetBoxes.pop_back();
|
m_widgetBoxes.pop_back();
|
||||||
|
|
@ -47,70 +54,78 @@ namespace Ndk
|
||||||
|
|
||||||
void Canvas::OnEventMouseButtonPressed(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseButtonEvent& event)
|
void Canvas::OnEventMouseButtonPressed(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseButtonEvent& event)
|
||||||
{
|
{
|
||||||
if (m_hoveredWidget)
|
if (m_hoveredWidget != InvalidCanvasIndex)
|
||||||
{
|
{
|
||||||
int x = static_cast<int>(std::round(event.x - m_hoveredWidget->box.x));
|
WidgetBox& hoveredWidget = m_widgetBoxes[m_hoveredWidget];
|
||||||
int y = static_cast<int>(std::round(event.y - m_hoveredWidget->box.y));
|
|
||||||
|
|
||||||
m_hoveredWidget->widget->OnMouseButtonPress(x, y, event.button);
|
int x = static_cast<int>(std::round(event.x - hoveredWidget.box.x));
|
||||||
|
int y = static_cast<int>(std::round(event.y - hoveredWidget.box.y));
|
||||||
|
|
||||||
|
hoveredWidget.widget->OnMouseButtonPress(x, y, event.button);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::OnEventMouseButtonRelease(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseButtonEvent & event)
|
void Canvas::OnEventMouseButtonRelease(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseButtonEvent & event)
|
||||||
{
|
{
|
||||||
if (m_hoveredWidget)
|
if (m_hoveredWidget != InvalidCanvasIndex)
|
||||||
{
|
{
|
||||||
int x = static_cast<int>(std::round(event.x - m_hoveredWidget->box.x));
|
WidgetBox& hoveredWidget = m_widgetBoxes[m_hoveredWidget];
|
||||||
int y = static_cast<int>(std::round(event.y - m_hoveredWidget->box.y));
|
|
||||||
|
|
||||||
m_hoveredWidget->widget->OnMouseButtonRelease(x, y, event.button);
|
int x = static_cast<int>(std::round(event.x - hoveredWidget.box.x));
|
||||||
|
int y = static_cast<int>(std::round(event.y - hoveredWidget.box.y));
|
||||||
|
|
||||||
|
hoveredWidget.widget->OnMouseButtonRelease(x, y, event.button);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::OnEventMouseMoved(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseMoveEvent& event)
|
void Canvas::OnEventMouseMoved(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseMoveEvent& event)
|
||||||
{
|
{
|
||||||
const WidgetBox* bestEntry = nullptr;
|
std::size_t bestEntry = InvalidCanvasIndex;
|
||||||
float bestEntryArea = std::numeric_limits<float>::infinity();
|
float bestEntryArea = std::numeric_limits<float>::infinity();
|
||||||
|
|
||||||
Nz::Vector3f mousePos(float(event.x), float(event.y), 0.f);
|
Nz::Vector3f mousePos(float(event.x), float(event.y), 0.f);
|
||||||
for (const WidgetBox& entry : m_widgetBoxes)
|
for (std::size_t i = 0; i < m_widgetBoxes.size(); ++i)
|
||||||
{
|
{
|
||||||
const Nz::Boxf& box = entry.box;
|
const Nz::Boxf& box = m_widgetBoxes[i].box;
|
||||||
|
|
||||||
if (box.Contains(mousePos))
|
if (box.Contains(mousePos))
|
||||||
{
|
{
|
||||||
float area = box.width * box.height;
|
float area = box.width * box.height;
|
||||||
if (area < bestEntryArea)
|
if (area < bestEntryArea)
|
||||||
{
|
{
|
||||||
bestEntry = &entry;
|
bestEntry = i;
|
||||||
bestEntryArea = area;
|
bestEntryArea = area;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bestEntry)
|
if (bestEntry != InvalidCanvasIndex)
|
||||||
{
|
{
|
||||||
if (m_hoveredWidget != bestEntry)
|
if (m_hoveredWidget != bestEntry)
|
||||||
{
|
{
|
||||||
if (m_hoveredWidget)
|
if (m_hoveredWidget != InvalidCanvasIndex)
|
||||||
m_hoveredWidget->widget->OnMouseExit();
|
{
|
||||||
|
WidgetBox& previouslyHovered = m_widgetBoxes[m_hoveredWidget];
|
||||||
|
previouslyHovered.widget->OnMouseExit();
|
||||||
|
}
|
||||||
|
|
||||||
m_hoveredWidget = bestEntry;
|
m_hoveredWidget = bestEntry;
|
||||||
m_hoveredWidget->widget->OnMouseEnter();
|
m_widgetBoxes[m_hoveredWidget].widget->OnMouseEnter();
|
||||||
|
|
||||||
if (m_cursorController)
|
if (m_cursorController)
|
||||||
m_cursorController->UpdateCursor(Nz::Cursor::Get(m_hoveredWidget->cursor));
|
m_cursorController->UpdateCursor(Nz::Cursor::Get(m_widgetBoxes[m_hoveredWidget].cursor));
|
||||||
}
|
}
|
||||||
|
|
||||||
int x = static_cast<int>(std::round(event.x - m_hoveredWidget->box.x));
|
WidgetBox& hoveredWidget = m_widgetBoxes[m_hoveredWidget];
|
||||||
int y = static_cast<int>(std::round(event.y - m_hoveredWidget->box.y));
|
|
||||||
|
|
||||||
bestEntry->widget->OnMouseMoved(x, y, event.deltaX, event.deltaY);
|
int x = static_cast<int>(std::round(event.x - hoveredWidget.box.x));
|
||||||
|
int y = static_cast<int>(std::round(event.y - hoveredWidget.box.y));
|
||||||
|
hoveredWidget.widget->OnMouseMoved(x, y, event.deltaX, event.deltaY);
|
||||||
}
|
}
|
||||||
else if (m_hoveredWidget)
|
else if (m_hoveredWidget != InvalidCanvasIndex)
|
||||||
{
|
{
|
||||||
m_hoveredWidget->widget->OnMouseExit();
|
m_widgetBoxes[m_hoveredWidget].widget->OnMouseExit();
|
||||||
m_hoveredWidget = nullptr;
|
m_hoveredWidget = InvalidCanvasIndex;
|
||||||
|
|
||||||
if (m_cursorController)
|
if (m_cursorController)
|
||||||
m_cursorController->UpdateCursor(Nz::Cursor::Get(Nz::SystemCursor_Default));
|
m_cursorController->UpdateCursor(Nz::Cursor::Get(Nz::SystemCursor_Default));
|
||||||
|
|
@ -119,28 +134,28 @@ namespace Ndk
|
||||||
|
|
||||||
void Canvas::OnEventMouseLeft(const Nz::EventHandler* /*eventHandler*/)
|
void Canvas::OnEventMouseLeft(const Nz::EventHandler* /*eventHandler*/)
|
||||||
{
|
{
|
||||||
if (m_hoveredWidget)
|
if (m_hoveredWidget != InvalidCanvasIndex)
|
||||||
{
|
{
|
||||||
m_hoveredWidget->widget->OnMouseExit();
|
m_widgetBoxes[m_hoveredWidget].widget->OnMouseExit();
|
||||||
m_hoveredWidget = nullptr;
|
m_hoveredWidget = InvalidCanvasIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::OnEventKeyPressed(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event)
|
void Canvas::OnEventKeyPressed(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event)
|
||||||
{
|
{
|
||||||
if (m_keyboardOwner)
|
if (m_keyboardOwner != InvalidCanvasIndex)
|
||||||
m_keyboardOwner->OnKeyPressed(event);
|
m_widgetBoxes[m_hoveredWidget].widget->OnKeyPressed(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::OnEventKeyReleased(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event)
|
void Canvas::OnEventKeyReleased(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event)
|
||||||
{
|
{
|
||||||
if (m_keyboardOwner)
|
if (m_keyboardOwner != InvalidCanvasIndex)
|
||||||
m_keyboardOwner->OnKeyReleased(event);
|
m_widgetBoxes[m_hoveredWidget].widget->OnKeyReleased(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::OnEventTextEntered(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::TextEvent& event)
|
void Canvas::OnEventTextEntered(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::TextEvent& event)
|
||||||
{
|
{
|
||||||
if (m_keyboardOwner)
|
if (m_keyboardOwner != InvalidCanvasIndex)
|
||||||
m_keyboardOwner->OnTextEntered(event.character, event.repeated);
|
m_widgetBoxes[m_hoveredWidget].widget->OnTextEntered(event.character, event.repeated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue