@@ -18,6 +18,7 @@ struct ParamWidget : widget::OpaqueWidget { | |||||
void step() override; | void step() override; | ||||
void draw(const DrawArgs &args) override; | void draw(const DrawArgs &args) override; | ||||
void onButton(const widget::ButtonEvent &e) override; | void onButton(const widget::ButtonEvent &e) override; | ||||
void onDoubleClick(const widget::DoubleClickEvent &e) override; | void onDoubleClick(const widget::DoubleClickEvent &e) override; | ||||
void onEnter(const widget::EnterEvent &e) override; | void onEnter(const widget::EnterEvent &e) override; | ||||
@@ -1,5 +1,5 @@ | |||||
#pragma once | #pragma once | ||||
#include "widget/OverlayWidget.hpp" | |||||
#include "widget/OpaqueWidget.hpp" | |||||
#include "ui/common.hpp" | #include "ui/common.hpp" | ||||
@@ -8,7 +8,7 @@ namespace ui { | |||||
/** Deletes itself from parent when clicked */ | /** Deletes itself from parent when clicked */ | ||||
struct MenuOverlay : widget::OverlayWidget { | |||||
struct MenuOverlay : widget::OpaqueWidget { | |||||
void step() override; | void step() override; | ||||
void onButton(const widget::ButtonEvent &e) override; | void onButton(const widget::ButtonEvent &e) override; | ||||
void onHoverKey(const widget::HoverKeyEvent &e) override; | void onHoverKey(const widget::HoverKeyEvent &e) override; | ||||
@@ -22,8 +22,8 @@ struct TextField : widget::OpaqueWidget { | |||||
TextField(); | TextField(); | ||||
void draw(const DrawArgs &args) override; | void draw(const DrawArgs &args) override; | ||||
void onButton(const widget::ButtonEvent &e) override; | |||||
void onHover(const widget::HoverEvent &e) override; | void onHover(const widget::HoverEvent &e) override; | ||||
void onButton(const widget::ButtonEvent &e) override; | |||||
void onEnter(const widget::EnterEvent &e) override; | void onEnter(const widget::EnterEvent &e) override; | ||||
void onSelect(const widget::SelectEvent &e) override; | void onSelect(const widget::SelectEvent &e) override; | ||||
void onSelectText(const widget::SelectTextEvent &e) override; | void onSelectText(const widget::SelectTextEvent &e) override; | ||||
@@ -1,31 +0,0 @@ | |||||
#pragma once | |||||
#include "widget/Widget.hpp" | |||||
namespace rack { | |||||
namespace widget { | |||||
/** A Widget that consumes recursing events without giving a chance for children to consume. | |||||
*/ | |||||
struct ObstructWidget : Widget { | |||||
void onHover(const HoverEvent &e) override { | |||||
e.consume(this); | |||||
} | |||||
void onButton(const ButtonEvent &e) override { | |||||
e.consume(this); | |||||
} | |||||
void onHoverKey(const HoverKeyEvent &e) override { | |||||
e.consume(this); | |||||
} | |||||
void onHoverText(const HoverTextEvent &e) override { | |||||
e.consume(this); | |||||
} | |||||
void onDragHover(const DragHoverEvent &e) override { | |||||
e.consume(this); | |||||
} | |||||
}; | |||||
} // namespace widget | |||||
} // namespace rack |
@@ -6,35 +6,43 @@ namespace rack { | |||||
namespace widget { | namespace widget { | ||||
/** A Widget that consumes recursing events but gives a chance for children to consume first. | |||||
You can of course override the events. | |||||
You may also call OpaqueWidget::on*() from the overridden method to continue recursing/consuming the event. | |||||
/** A Widget that stops propagation of all recursive PositionEvents but gives a chance for children to consume first. | |||||
Remember to call these methods in your subclass if you wish to preserve default OpaqueWidget behavior. | |||||
*/ | */ | ||||
struct OpaqueWidget : Widget { | struct OpaqueWidget : Widget { | ||||
void onHover(const HoverEvent &e) override { | void onHover(const HoverEvent &e) override { | ||||
Widget::onHover(e); | Widget::onHover(e); | ||||
if (!e.getConsumed()) | |||||
e.consume(this); | |||||
e.stopPropagating(); | |||||
// Consume if not consumed by child | |||||
if (!e.getTarget()) | |||||
e.setTarget(this); | |||||
} | } | ||||
void onButton(const ButtonEvent &e) override { | void onButton(const ButtonEvent &e) override { | ||||
Widget::onButton(e); | Widget::onButton(e); | ||||
if (!e.getConsumed()) | |||||
e.consume(this); | |||||
e.stopPropagating(); | |||||
// Consume if not consumed by child | |||||
if (!e.getTarget()) | |||||
e.setTarget(this); | |||||
} | } | ||||
void onHoverKey(const HoverKeyEvent &e) override { | void onHoverKey(const HoverKeyEvent &e) override { | ||||
Widget::onHoverKey(e); | Widget::onHoverKey(e); | ||||
if (!e.getConsumed()) | |||||
e.consume(this); | |||||
e.stopPropagating(); | |||||
} | } | ||||
void onHoverText(const HoverTextEvent &e) override { | void onHoverText(const HoverTextEvent &e) override { | ||||
Widget::onHoverText(e); | Widget::onHoverText(e); | ||||
if (!e.getConsumed()) | |||||
e.consume(this); | |||||
e.stopPropagating(); | |||||
} | |||||
void onHoverScroll(const HoverScrollEvent &e) override { | |||||
Widget::onHoverScroll(e); | |||||
e.stopPropagating(); | |||||
} | } | ||||
void onDragHover(const DragHoverEvent &e) override { | void onDragHover(const DragHoverEvent &e) override { | ||||
Widget::onDragHover(e); | Widget::onDragHover(e); | ||||
if (!e.getConsumed()) | |||||
e.consume(this); | |||||
e.stopPropagating(); | |||||
} | |||||
void onPathDrop(const PathDropEvent &e) override { | |||||
Widget::onPathDrop(e); | |||||
e.stopPropagating(); | |||||
} | } | ||||
}; | }; | ||||
@@ -1,25 +0,0 @@ | |||||
#pragma once | |||||
#include "widget/OpaqueWidget.hpp" | |||||
namespace rack { | |||||
namespace widget { | |||||
/** Like OpaqueWidget but consumes even more events. */ | |||||
struct OverlayWidget : OpaqueWidget { | |||||
void onHoverScroll(const HoverScrollEvent &e) override { | |||||
Widget::onHoverScroll(e); | |||||
if (!e.getConsumed()) | |||||
e.consume(this); | |||||
} | |||||
void onPathDrop(const PathDropEvent &e) override { | |||||
Widget::onPathDrop(e); | |||||
if (!e.getConsumed()) | |||||
e.consume(this); | |||||
} | |||||
}; | |||||
} // namespace widget | |||||
} // namespace rack |
@@ -98,13 +98,18 @@ struct Widget { | |||||
template <typename TMethod, class TEvent> | template <typename TMethod, class TEvent> | ||||
void recurseEvent(TMethod f, const TEvent &e) { | void recurseEvent(TMethod f, const TEvent &e) { | ||||
for (auto it = children.rbegin(); it != children.rend(); it++) { | for (auto it = children.rbegin(); it != children.rend(); it++) { | ||||
// Stop propagation if requested | |||||
if (!e.isPropagating()) | |||||
break; | |||||
Widget *child = *it; | Widget *child = *it; | ||||
// Filter child by visibility | // Filter child by visibility | ||||
if (!child->visible) | if (!child->visible) | ||||
continue; | continue; | ||||
// Clone event for (currently) no reason | |||||
TEvent e2 = e; | |||||
// Call child event handler | // Call child event handler | ||||
(child->*f)(e); | |||||
(child->*f)(e2); | |||||
} | } | ||||
} | } | ||||
@@ -112,6 +117,9 @@ struct Widget { | |||||
template <typename TMethod, class TEvent> | template <typename TMethod, class TEvent> | ||||
void recursePositionEvent(TMethod f, const TEvent &e) { | void recursePositionEvent(TMethod f, const TEvent &e) { | ||||
for (auto it = children.rbegin(); it != children.rend(); it++) { | for (auto it = children.rbegin(); it != children.rend(); it++) { | ||||
// Stop propagation if requested | |||||
if (!e.isPropagating()) | |||||
break; | |||||
Widget *child = *it; | Widget *child = *it; | ||||
// Filter child by visibility and position | // Filter child by visibility and position | ||||
if (!child->visible) | if (!child->visible) | ||||
@@ -124,9 +132,6 @@ struct Widget { | |||||
e2.pos = e.pos.minus(child->box.pos); | e2.pos = e.pos.minus(child->box.pos); | ||||
// Call child event handler | // Call child event handler | ||||
(child->*f)(e2); | (child->*f)(e2); | ||||
// Stop iterating if consumed | |||||
if (e.getConsumed()) | |||||
break; | |||||
} | } | ||||
} | } | ||||
@@ -13,10 +13,8 @@ struct Widget; | |||||
/** A per-event state shared and writable by all widgets that recursively handle an event. */ | /** A per-event state shared and writable by all widgets that recursively handle an event. */ | ||||
struct EventContext { | struct EventContext { | ||||
/** The Widget that consumes the event. | |||||
This stops propagation of the event if applicable. | |||||
*/ | |||||
Widget *consumed = NULL; | |||||
Widget *target = NULL; | |||||
bool propagating = true; | |||||
}; | }; | ||||
@@ -24,12 +22,33 @@ struct EventContext { | |||||
struct Event { | struct Event { | ||||
EventContext *context = NULL; | EventContext *context = NULL; | ||||
void consume(Widget *w) const { | |||||
/** Prevents the Event from being handled by more Widgets. | |||||
*/ | |||||
void stopPropagating() const { | |||||
if (context) | if (context) | ||||
context->consumed = w; | |||||
context->propagating = false; | |||||
} | } | ||||
Widget *getConsumed() const { | |||||
return context ? context->consumed : NULL; | |||||
bool isPropagating() const { | |||||
if (context) | |||||
return context->propagating; | |||||
return true; | |||||
} | |||||
/** Tells the event handler that a particular Widget consumed the event. | |||||
You usually want to stop propagation as well, so call consume() instead. | |||||
*/ | |||||
void setTarget(Widget *w) const { | |||||
if (context) | |||||
context->target = w; | |||||
} | |||||
Widget *getTarget() const { | |||||
if (context) | |||||
return context->target; | |||||
return NULL; | |||||
} | |||||
/** Sets the target Widget and stops propagation. */ | |||||
void consume(Widget *w) const { | |||||
setTarget(w); | |||||
stopPropagating(); | |||||
} | } | ||||
}; | }; | ||||
@@ -27,7 +27,7 @@ struct BlankPanel : Widget { | |||||
}; | }; | ||||
struct ModuleResizeHandle : Widget { | |||||
struct ModuleResizeHandle : OpaqueWidget { | |||||
bool right = false; | bool right = false; | ||||
float dragX; | float dragX; | ||||
Rect originalBox; | Rect originalBox; | ||||
@@ -59,13 +59,13 @@ struct ModuleResizeHandle : Widget { | |||||
const float minWidth = 3 * RACK_GRID_WIDTH; | const float minWidth = 3 * RACK_GRID_WIDTH; | ||||
if (right) { | if (right) { | ||||
newBox.size.x += deltaX; | newBox.size.x += deltaX; | ||||
newBox.size.x = fmaxf(newBox.size.x, minWidth); | |||||
newBox.size.x = roundf(newBox.size.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH; | |||||
newBox.size.x = std::fmax(newBox.size.x, minWidth); | |||||
newBox.size.x = std::round(newBox.size.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH; | |||||
} | } | ||||
else { | else { | ||||
newBox.size.x -= deltaX; | newBox.size.x -= deltaX; | ||||
newBox.size.x = fmaxf(newBox.size.x, minWidth); | |||||
newBox.size.x = roundf(newBox.size.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH; | |||||
newBox.size.x = std::fmax(newBox.size.x, minWidth); | |||||
newBox.size.x = std::round(newBox.size.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH; | |||||
newBox.pos.x = originalBox.pos.x + originalBox.size.x - newBox.size.x; | newBox.pos.x = originalBox.pos.x + originalBox.size.x - newBox.size.x; | ||||
} | } | ||||
APP->scene->rack->requestModuleBox(m, newBox); | APP->scene->rack->requestModuleBox(m, newBox); | ||||
@@ -1,6 +1,5 @@ | |||||
#include "app/ModuleBrowser.hpp" | #include "app/ModuleBrowser.hpp" | ||||
#include "widget/OpaqueWidget.hpp" | #include "widget/OpaqueWidget.hpp" | ||||
#include "widget/OverlayWidget.hpp" | |||||
#include "widget/TransparentWidget.hpp" | #include "widget/TransparentWidget.hpp" | ||||
#include "widget/ZoomWidget.hpp" | #include "widget/ZoomWidget.hpp" | ||||
#include "ui/ScrollWidget.hpp" | #include "ui/ScrollWidget.hpp" | ||||
@@ -53,21 +52,22 @@ static float modelScore(plugin::Model *model, const std::string &search) { | |||||
} | } | ||||
struct BrowserOverlay : widget::OverlayWidget { | |||||
struct BrowserOverlay : widget::OpaqueWidget { | |||||
void step() override { | void step() override { | ||||
box = parent->box.zeroPos(); | box = parent->box.zeroPos(); | ||||
// Only step if visible, since there are potentially thousands of descendants that don't need to be stepped. | // Only step if visible, since there are potentially thousands of descendants that don't need to be stepped. | ||||
if (visible) | if (visible) | ||||
OverlayWidget::step(); | |||||
OpaqueWidget::step(); | |||||
} | } | ||||
void onButton(const widget::ButtonEvent &e) override { | void onButton(const widget::ButtonEvent &e) override { | ||||
OverlayWidget::onButton(e); | |||||
if (e.getConsumed() != this) | |||||
OpaqueWidget::onButton(e); | |||||
if (e.getTarget() != this) | |||||
return; | return; | ||||
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) { | if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) { | ||||
hide(); | hide(); | ||||
e.consume(this); | |||||
} | } | ||||
} | } | ||||
}; | }; | ||||
@@ -291,7 +291,7 @@ struct BrowserSearchField : ui::TextField { | |||||
} | } | ||||
} | } | ||||
if (!e.getConsumed()) | |||||
if (!e.getTarget()) | |||||
ui::TextField::onSelectKey(e); | ui::TextField::onSelectKey(e); | ||||
} | } | ||||
@@ -615,7 +615,7 @@ struct ModuleBrowser : widget::OpaqueWidget { | |||||
inline void ModelBox::onButton(const widget::ButtonEvent &e) { | inline void ModelBox::onButton(const widget::ButtonEvent &e) { | ||||
OpaqueWidget::onButton(e); | OpaqueWidget::onButton(e); | ||||
if (e.getConsumed() != this) | |||||
if (e.getTarget() != this) | |||||
return; | return; | ||||
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) { | if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) { | ||||
@@ -321,15 +321,20 @@ void ModuleWidget::onHover(const widget::HoverEvent &e) { | |||||
void ModuleWidget::onButton(const widget::ButtonEvent &e) { | void ModuleWidget::onButton(const widget::ButtonEvent &e) { | ||||
widget::OpaqueWidget::onButton(e); | widget::OpaqueWidget::onButton(e); | ||||
if (e.getTarget() != this) | |||||
return; | |||||
if (e.getConsumed() == this) { | |||||
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) { | |||||
createContextMenu(); | |||||
} | |||||
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) { | |||||
createContextMenu(); | |||||
e.consume(this); | |||||
} | } | ||||
} | } | ||||
void ModuleWidget::onHoverKey(const widget::HoverKeyEvent &e) { | void ModuleWidget::onHoverKey(const widget::HoverKeyEvent &e) { | ||||
widget::OpaqueWidget::onHoverKey(e); | |||||
if (e.getTarget() != this) | |||||
return; | |||||
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { | if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { | ||||
switch (e.key) { | switch (e.key) { | ||||
case GLFW_KEY_I: { | case GLFW_KEY_I: { | ||||
@@ -376,9 +381,6 @@ void ModuleWidget::onHoverKey(const widget::HoverKeyEvent &e) { | |||||
} break; | } break; | ||||
} | } | ||||
} | } | ||||
if (!e.getConsumed()) | |||||
widget::OpaqueWidget::onHoverKey(e); | |||||
} | } | ||||
void ModuleWidget::onDragStart(const widget::DragStartEvent &e) { | void ModuleWidget::onDragStart(const widget::DragStartEvent &e) { | ||||
@@ -51,7 +51,7 @@ struct ParamField : ui::TextField { | |||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
if (!e.getConsumed()) | |||||
if (!e.getTarget()) | |||||
TextField::onSelectKey(e); | TextField::onSelectKey(e); | ||||
} | } | ||||
}; | }; | ||||
@@ -140,6 +140,10 @@ void ParamWidget::draw(const DrawArgs &args) { | |||||
} | } | ||||
void ParamWidget::onButton(const widget::ButtonEvent &e) { | void ParamWidget::onButton(const widget::ButtonEvent &e) { | ||||
OpaqueWidget::onButton(e); | |||||
if (e.getTarget() != this) | |||||
return; | |||||
// Touch parameter | // Touch parameter | ||||
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT && (e.mods & WINDOW_MOD_MASK) == 0) { | if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT && (e.mods & WINDOW_MOD_MASK) == 0) { | ||||
if (paramQuantity) { | if (paramQuantity) { | ||||
@@ -152,9 +156,6 @@ void ParamWidget::onButton(const widget::ButtonEvent &e) { | |||||
createContextMenu(); | createContextMenu(); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
if (!e.getConsumed()) | |||||
OpaqueWidget::onButton(e); | |||||
} | } | ||||
void ParamWidget::onDoubleClick(const widget::DoubleClickEvent &e) { | void ParamWidget::onDoubleClick(const widget::DoubleClickEvent &e) { | ||||
@@ -60,6 +60,8 @@ void PortWidget::draw(const DrawArgs &args) { | |||||
} | } | ||||
void PortWidget::onButton(const widget::ButtonEvent &e) { | void PortWidget::onButton(const widget::ButtonEvent &e) { | ||||
OpaqueWidget::onButton(e); | |||||
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) { | if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) { | ||||
CableWidget *cw = APP->scene->rack->getTopCable(this); | CableWidget *cw = APP->scene->rack->getTopCable(this); | ||||
if (cw) { | if (cw) { | ||||
@@ -72,7 +74,6 @@ void PortWidget::onButton(const widget::ButtonEvent &e) { | |||||
delete cw; | delete cw; | ||||
} | } | ||||
} | } | ||||
e.consume(this); | |||||
} | } | ||||
void PortWidget::onEnter(const widget::EnterEvent &e) { | void PortWidget::onEnter(const widget::EnterEvent &e) { | ||||
@@ -123,7 +123,7 @@ void RackWidget::onHover(const widget::HoverEvent &e) { | |||||
void RackWidget::onHoverKey(const widget::HoverKeyEvent &e) { | void RackWidget::onHoverKey(const widget::HoverKeyEvent &e) { | ||||
OpaqueWidget::onHoverKey(e); | OpaqueWidget::onHoverKey(e); | ||||
if (e.getConsumed() != this) | |||||
if (e.getTarget() != this) | |||||
return; | return; | ||||
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { | if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { | ||||
@@ -132,6 +132,7 @@ void RackWidget::onHoverKey(const widget::HoverKeyEvent &e) { | |||||
if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) { | if ((e.mods & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) { | ||||
pastePresetClipboardAction(); | pastePresetClipboardAction(); | ||||
} | } | ||||
e.consume(this); | |||||
} break; | } break; | ||||
} | } | ||||
} | } | ||||
@@ -144,10 +145,12 @@ void RackWidget::onDragHover(const widget::DragHoverEvent &e) { | |||||
void RackWidget::onButton(const widget::ButtonEvent &e) { | void RackWidget::onButton(const widget::ButtonEvent &e) { | ||||
OpaqueWidget::onButton(e); | OpaqueWidget::onButton(e); | ||||
if (e.getConsumed() == this) { | |||||
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) { | |||||
APP->scene->moduleBrowser->show(); | |||||
} | |||||
if (e.getTarget() != this) | |||||
return; | |||||
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) { | |||||
APP->scene->moduleBrowser->show(); | |||||
e.consume(this); | |||||
} | } | ||||
} | } | ||||
@@ -72,6 +72,10 @@ void Scene::draw(const DrawArgs &args) { | |||||
} | } | ||||
void Scene::onHoverKey(const widget::HoverKeyEvent &e) { | void Scene::onHoverKey(const widget::HoverKeyEvent &e) { | ||||
OpaqueWidget::onHoverKey(e); | |||||
if (e.getTarget() != this) | |||||
return; | |||||
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { | if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { | ||||
switch (e.key) { | switch (e.key) { | ||||
case GLFW_KEY_N: { | case GLFW_KEY_N: { | ||||
@@ -127,12 +131,13 @@ void Scene::onHoverKey(const widget::HoverKeyEvent &e) { | |||||
} | } | ||||
} | } | ||||
} | } | ||||
if (!e.getConsumed()) | |||||
OpaqueWidget::onHoverKey(e); | |||||
} | } | ||||
void Scene::onPathDrop(const widget::PathDropEvent &e) { | void Scene::onPathDrop(const widget::PathDropEvent &e) { | ||||
OpaqueWidget::onPathDrop(e); | |||||
if (e.getTarget() != this) | |||||
return; | |||||
if (e.paths.size() >= 1) { | if (e.paths.size() >= 1) { | ||||
const std::string &path = e.paths[0]; | const std::string &path = e.paths[0]; | ||||
if (string::filenameExtension(string::filename(path)) == "vcv") { | if (string::filenameExtension(string::filename(path)) == "vcv") { | ||||
@@ -140,9 +145,6 @@ void Scene::onPathDrop(const widget::PathDropEvent &e) { | |||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
} | } | ||||
if (!e.getConsumed()) | |||||
OpaqueWidget::onPathDrop(e); | |||||
} | } | ||||
void Scene::runCheckVersion() { | void Scene::runCheckVersion() { | ||||
@@ -423,7 +423,7 @@ struct AccountEmailField : ui::TextField { | |||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
if (!e.getConsumed()) | |||||
if (!e.getTarget()) | |||||
ui::TextField::onSelectKey(e); | ui::TextField::onSelectKey(e); | ||||
} | } | ||||
}; | }; | ||||
@@ -437,7 +437,7 @@ struct AccountPasswordField : ui::PasswordField { | |||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
if (!e.getConsumed()) | |||||
if (!e.getTarget()) | |||||
ui::PasswordField::onSelectKey(e); | ui::PasswordField::onSelectKey(e); | ||||
} | } | ||||
}; | }; | ||||
@@ -78,7 +78,7 @@ void MenuItem::doAction() { | |||||
// Consume event by default, but allow action to un-consume it to prevent the menu from being removed. | // Consume event by default, but allow action to un-consume it to prevent the menu from being removed. | ||||
eAction.consume(this); | eAction.consume(this); | ||||
onAction(eAction); | onAction(eAction); | ||||
if (!cAction.consumed) | |||||
if (!cAction.target) | |||||
return; | return; | ||||
MenuOverlay *overlay = getAncestorOfType<MenuOverlay>(); | MenuOverlay *overlay = getAncestorOfType<MenuOverlay>(); | ||||
@@ -19,16 +19,20 @@ void MenuOverlay::step() { | |||||
void MenuOverlay::onButton(const widget::ButtonEvent &e) { | void MenuOverlay::onButton(const widget::ButtonEvent &e) { | ||||
widget::OpaqueWidget::onButton(e); | widget::OpaqueWidget::onButton(e); | ||||
if (e.getTarget() != this) | |||||
return; | |||||
if (e.getConsumed() == this && e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) { | |||||
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) { | |||||
requestedDelete = true; | requestedDelete = true; | ||||
} | } | ||||
} | } | ||||
void MenuOverlay::onHoverKey(const widget::HoverKeyEvent &e) { | void MenuOverlay::onHoverKey(const widget::HoverKeyEvent &e) { | ||||
widget::OpaqueWidget::onHoverKey(e); | widget::OpaqueWidget::onHoverKey(e); | ||||
if (e.getTarget() != this) | |||||
return; | |||||
if (e.getConsumed() == this && e.action == GLFW_PRESS && e.key == GLFW_KEY_ESCAPE) { | |||||
if (e.action == GLFW_PRESS && e.key == GLFW_KEY_ESCAPE) { | |||||
requestedDelete = true; | requestedDelete = true; | ||||
} | } | ||||
} | } | ||||
@@ -70,7 +70,7 @@ void ScrollWidget::onHover(const widget::HoverEvent &e) { | |||||
void ScrollWidget::onHoverScroll(const widget::HoverScrollEvent &e) { | void ScrollWidget::onHoverScroll(const widget::HoverScrollEvent &e) { | ||||
widget::Widget::onHoverScroll(e); | widget::Widget::onHoverScroll(e); | ||||
if (e.getConsumed()) | |||||
if (e.getTarget() != this) | |||||
return; | return; | ||||
// Scroll only if the scrollbars are visible | // Scroll only if the scrollbars are visible | ||||
@@ -30,21 +30,23 @@ void TextField::draw(const DrawArgs &args) { | |||||
nvgResetScissor(args.vg); | nvgResetScissor(args.vg); | ||||
} | } | ||||
void TextField::onButton(const widget::ButtonEvent &e) { | |||||
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) { | |||||
cursor = selection = getTextPosition(e.pos); | |||||
} | |||||
widget::OpaqueWidget::onButton(e); | |||||
} | |||||
void TextField::onHover(const widget::HoverEvent &e) { | void TextField::onHover(const widget::HoverEvent &e) { | ||||
widget::OpaqueWidget::onHover(e); | |||||
if (this == APP->event->draggedWidget) { | if (this == APP->event->draggedWidget) { | ||||
int pos = getTextPosition(e.pos); | int pos = getTextPosition(e.pos); | ||||
if (pos != selection) { | if (pos != selection) { | ||||
cursor = pos; | cursor = pos; | ||||
} | } | ||||
} | } | ||||
widget::OpaqueWidget::onHover(e); | |||||
} | |||||
void TextField::onButton(const widget::ButtonEvent &e) { | |||||
widget::OpaqueWidget::onButton(e); | |||||
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) { | |||||
cursor = selection = getTextPosition(e.pos); | |||||
} | |||||
} | } | ||||
void TextField::onEnter(const widget::EnterEvent &e) { | void TextField::onEnter(const widget::EnterEvent &e) { | ||||
@@ -23,7 +23,7 @@ void EventState::setHovered(Widget *w) { | |||||
EnterEvent eEnter; | EnterEvent eEnter; | ||||
eEnter.context = &cEnter; | eEnter.context = &cEnter; | ||||
w->onEnter(eEnter); | w->onEnter(eEnter); | ||||
hoveredWidget = cEnter.consumed; | |||||
hoveredWidget = cEnter.target; | |||||
} | } | ||||
} | } | ||||
@@ -44,7 +44,7 @@ void EventState::setDragged(Widget *w) { | |||||
DragStartEvent eDragStart; | DragStartEvent eDragStart; | ||||
eDragStart.context = &cDragStart; | eDragStart.context = &cDragStart; | ||||
w->onDragStart(eDragStart); | w->onDragStart(eDragStart); | ||||
draggedWidget = cDragStart.consumed; | |||||
draggedWidget = cDragStart.target; | |||||
} | } | ||||
} | } | ||||
@@ -67,7 +67,7 @@ void EventState::setDragHovered(Widget *w) { | |||||
eDragEnter.context = &cDragEnter; | eDragEnter.context = &cDragEnter; | ||||
eDragEnter.origin = draggedWidget; | eDragEnter.origin = draggedWidget; | ||||
w->onDragEnter(eDragEnter); | w->onDragEnter(eDragEnter); | ||||
dragHoveredWidget = cDragEnter.consumed; | |||||
dragHoveredWidget = cDragEnter.target; | |||||
} | } | ||||
} | } | ||||
@@ -88,7 +88,7 @@ void EventState::setSelected(Widget *w) { | |||||
SelectEvent eSelect; | SelectEvent eSelect; | ||||
eSelect.context = &cSelect; | eSelect.context = &cSelect; | ||||
w->onSelect(eSelect); | w->onSelect(eSelect); | ||||
selectedWidget = cSelect.consumed; | |||||
selectedWidget = cSelect.target; | |||||
} | } | ||||
} | } | ||||
@@ -110,7 +110,7 @@ void EventState::handleButton(math::Vec pos, int button, int action, int mods) { | |||||
eButton.action = action; | eButton.action = action; | ||||
eButton.mods = mods; | eButton.mods = mods; | ||||
rootWidget->onButton(eButton); | rootWidget->onButton(eButton); | ||||
Widget *clickedWidget = cButton.consumed; | |||||
Widget *clickedWidget = cButton.target; | |||||
if (button == GLFW_MOUSE_BUTTON_LEFT) { | if (button == GLFW_MOUSE_BUTTON_LEFT) { | ||||
if (action == GLFW_PRESS) { | if (action == GLFW_PRESS) { | ||||
@@ -171,7 +171,7 @@ void EventState::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||||
eDragHover.origin = draggedWidget; | eDragHover.origin = draggedWidget; | ||||
rootWidget->onDragHover(eDragHover); | rootWidget->onDragHover(eDragHover); | ||||
setDragHovered(cDragHover.consumed); | |||||
setDragHovered(cDragHover.target); | |||||
return; | return; | ||||
} | } | ||||
@@ -184,7 +184,7 @@ void EventState::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||||
eHover.mouseDelta = mouseDelta; | eHover.mouseDelta = mouseDelta; | ||||
rootWidget->onHover(eHover); | rootWidget->onHover(eHover); | ||||
setHovered(cHover.consumed); | |||||
setHovered(cHover.target); | |||||
} | } | ||||
void EventState::handleLeave() { | void EventState::handleLeave() { | ||||
@@ -219,7 +219,7 @@ void EventState::handleText(math::Vec pos, int codepoint) { | |||||
eSelectText.context = &cSelectText; | eSelectText.context = &cSelectText; | ||||
eSelectText.codepoint = codepoint; | eSelectText.codepoint = codepoint; | ||||
selectedWidget->onSelectText(eSelectText); | selectedWidget->onSelectText(eSelectText); | ||||
if (cSelectText.consumed) | |||||
if (cSelectText.target) | |||||
return; | return; | ||||
} | } | ||||
@@ -243,7 +243,7 @@ void EventState::handleKey(math::Vec pos, int key, int scancode, int action, int | |||||
eSelectKey.action = action; | eSelectKey.action = action; | ||||
eSelectKey.mods = mods; | eSelectKey.mods = mods; | ||||
selectedWidget->onSelectKey(eSelectKey); | selectedWidget->onSelectKey(eSelectKey); | ||||
if (cSelectKey.consumed) | |||||
if (cSelectKey.target) | |||||
return; | return; | ||||
} | } | ||||