Something went wrong. Try again.
art software for the rest of us
drawing paint image sdl art
Something went wrong. Try again.
6.1 kB · 185 lines
C++
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186#include "InputRouter.h"#include "HitTest.h"
namespace UI {
InputRouter::InputRouter() = default;
InputRouter::InputRouter(Widget* root) { SetRootWidget(root);}
bool InputRouter::IsAlive(const WidgetReference& reference) { return reference.pointer && !reference.lifetime.expired();}
void InputRouter::SetReference(WidgetReference& reference, Widget* widget) { reference.pointer = widget; reference.lifetime = widget ? widget->GetLifetimeToken() : std::weak_ptr<void>();}
void InputRouter::ClearReference(WidgetReference& reference) { reference.pointer = nullptr; reference.lifetime.reset();}
void InputRouter::SetRootWidget(Widget* root) { SetReference(rootWidget, root); ClearReference(hoveredWidget); ClearReference(activeWidget); ClearReference(focusedWidget); ancestorConsumedPointer = false;}
Widget* InputRouter::GetRootWidget() const { return IsAlive(rootWidget) ? rootWidget.pointer : nullptr;}
Widget* InputRouter::GetHoveredWidget() const { return IsAlive(hoveredWidget) ? hoveredWidget.pointer : nullptr;}
Widget* InputRouter::GetActiveWidget() const { return IsAlive(activeWidget) ? activeWidget.pointer : nullptr;}
Widget* InputRouter::GetFocusedWidget() const { return IsAlive(focusedWidget) ? focusedWidget.pointer : nullptr;}
void InputRouter::SetFocusedWidget(Widget* widget) { if (IsAlive(focusedWidget) && focusedWidget.pointer == widget) { return; }
if (IsAlive(focusedWidget)) { focusedWidget.pointer->SetFocused(false); } ClearReference(focusedWidget); SetReference(focusedWidget, widget); if (IsAlive(focusedWidget) && focusedWidget.pointer->IsFocusable()) { focusedWidget.pointer->SetFocused(true); }}
bool InputRouter::ProcessPointerStream(const std::shared_ptr<PointerStream>& stream) { if (!IsAlive(rootWidget)) { return false; }
const auto event = stream->PeekLatestInput(); Point pointerPos{event.scaledX, event.scaledY}; Widget* hitWidget = HitTest::Perform(rootWidget.pointer, pointerPos);
if (!IsAlive(hoveredWidget) || hitWidget != hoveredWidget.pointer) { if (IsAlive(hoveredWidget)) { hoveredWidget.pointer->SetHovered(false); } SetReference(hoveredWidget, hitWidget); if (IsAlive(hoveredWidget)) { hoveredWidget.pointer->SetHovered(true); } }
if (event.actDirection == PointerDirection::Down) { SetReference(activeWidget, hitWidget); ancestorConsumedPointer = false; if (hitWidget && hitWidget->IsFocusable()) { SetFocusedWidget(hitWidget); } if (IsAlive(activeWidget)) { for (Widget* ancestor = activeWidget.pointer->GetParent(); ancestor; ancestor = ancestor->GetParent()) { if (ancestor->WantsPointerCapture(stream)) { SetReference(activeWidget, ancestor); break; } } if (!IsAlive(activeWidget)) { return false; } activeWidget.pointer->SetPressed(true); bool handled = activeWidget.pointer->OnPointerStream(stream) || activeWidget.pointer != hitWidget; if (!IsAlive(activeWidget)) { ClearReference(activeWidget); } return handled; } } else if (event.actDirection == PointerDirection::Up) { bool handled = false; if (IsAlive(activeWidget)) { handled |= activeWidget.pointer->WantsPointerCapture(stream); if (!IsAlive(activeWidget)) { ClearReference(activeWidget); ancestorConsumedPointer = false; return handled; } for (Widget* ancestor = activeWidget.pointer->GetParent(); ancestor; ancestor = ancestor->GetParent()) { handled |= ancestor->WantsPointerCapture(stream); } if (!ancestorConsumedPointer) { handled |= activeWidget.pointer->OnPointerStream(stream); } if (IsAlive(activeWidget)) { activeWidget.pointer->SetPressed(false); } ClearReference(activeWidget); ancestorConsumedPointer = false; } else if (hitWidget) { ClearReference(activeWidget); handled = hitWidget->OnPointerStream(stream); } return handled; } else { if (IsAlive(activeWidget)) { if (activeWidget.pointer->WantsPointerCapture(stream)) { ancestorConsumedPointer = true; if (!IsAlive(activeWidget)) { ClearReference(activeWidget); } return true; } if (!IsAlive(activeWidget)) { ClearReference(activeWidget); return false; } for (Widget* ancestor = activeWidget.pointer->GetParent(); ancestor; ancestor = ancestor->GetParent()) { if (ancestor->WantsPointerCapture(stream)) { ancestorConsumedPointer = true; return true; } } bool handled = activeWidget.pointer->OnPointerStream(stream); if (!IsAlive(activeWidget)) { ClearReference(activeWidget); } return handled; } if (hitWidget) { ClearReference(activeWidget); return hitWidget->OnPointerStream(stream); } }
return false;}
void InputRouter::ProcessPointerHover(Point scaledPoint) { if (!IsAlive(rootWidget)) { return; }
Widget* hitWidget = HitTest::Perform(rootWidget.pointer, scaledPoint); if (IsAlive(hoveredWidget) && hitWidget == hoveredWidget.pointer) { return; }
if (IsAlive(hoveredWidget)) { hoveredWidget.pointer->SetHovered(false); } SetReference(hoveredWidget, hitWidget); if (IsAlive(hoveredWidget)) { hoveredWidget.pointer->SetHovered(true); }}
}