| @@ -19,9 +19,9 @@ struct Window; | |||
| struct PatchManager; | |||
| namespace event { | |||
| struct State; | |||
| } // namespace event | |||
| namespace widget { | |||
| struct EventState; | |||
| } // namespace widget | |||
| namespace app { | |||
| @@ -31,7 +31,7 @@ struct Scene; | |||
| /** Contains the application state */ | |||
| struct Context { | |||
| event::State* event = NULL; | |||
| widget::EventState* event = NULL; | |||
| app::Scene* scene = NULL; | |||
| engine::Engine* engine = NULL; | |||
| Window* window = NULL; | |||
| @@ -1,449 +0,0 @@ | |||
| #pragma once | |||
| #include <vector> | |||
| #include <set> | |||
| #include <common.hpp> | |||
| #include <math.hpp> | |||
| /** Remaps Ctrl to Cmd on Mac | |||
| Use this instead of GLFW_MOD_CONTROL, since Cmd should be used on Mac in place of Ctrl on Linux/Windows. | |||
| */ | |||
| #if defined ARCH_MAC | |||
| #define RACK_MOD_CTRL GLFW_MOD_SUPER | |||
| #define RACK_MOD_CTRL_NAME "⌘" | |||
| #else | |||
| #define RACK_MOD_CTRL GLFW_MOD_CONTROL | |||
| #define RACK_MOD_CTRL_NAME "Ctrl" | |||
| #endif | |||
| #define RACK_MOD_SHIFT_NAME "Shift" | |||
| #define RACK_MOD_ALT_NAME "Alt" | |||
| /** Filters actual mod keys from the mod flags. | |||
| Use this if you don't care about GLFW_MOD_CAPS_LOCK and GLFW_MOD_NUM_LOCK. | |||
| Example usage: | |||
| if ((e.mod & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) ... | |||
| */ | |||
| #define RACK_MOD_MASK (GLFW_MOD_SHIFT | GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER) | |||
| namespace rack { | |||
| namespace widget { | |||
| struct Widget; | |||
| } | |||
| /** Handles user interaction with Widget. | |||
| */ | |||
| namespace event { | |||
| /** A per-event state shared and writable by all widgets that recursively handle an event. */ | |||
| struct Context { | |||
| /** Whether the event should continue recursing to children Widgets. */ | |||
| bool propagating = true; | |||
| /** Whether the event has been consumed by an event handler and no more handlers should consume the event. */ | |||
| bool consumed = false; | |||
| /** The widget that responded to the event. */ | |||
| widget::Widget* target = NULL; | |||
| }; | |||
| /** Base class for all events. */ | |||
| struct Base { | |||
| Context* context = NULL; | |||
| /** Prevents the event from being handled by more Widgets. | |||
| */ | |||
| void stopPropagating() const { | |||
| if (!context) | |||
| return; | |||
| context->propagating = false; | |||
| } | |||
| bool isPropagating() const { | |||
| if (!context) | |||
| return true; | |||
| return context->propagating; | |||
| } | |||
| /** 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::Widget* w) const { | |||
| if (!context) | |||
| return; | |||
| context->target = w; | |||
| } | |||
| widget::Widget* getTarget() const { | |||
| if (!context) | |||
| return NULL; | |||
| return context->target; | |||
| } | |||
| /** Sets the target Widget and stops propagating. | |||
| A NULL Widget may be passed to consume but not set a target. | |||
| */ | |||
| void consume(widget::Widget* w) const { | |||
| if (!context) | |||
| return; | |||
| context->propagating = false; | |||
| context->consumed = true; | |||
| context->target = w; | |||
| } | |||
| void unconsume() const { | |||
| if (!context) | |||
| return; | |||
| context->consumed = false; | |||
| } | |||
| bool isConsumed() const { | |||
| if (!context) | |||
| return false; | |||
| return context->consumed; | |||
| } | |||
| }; | |||
| /** An event prototype with a vector position. */ | |||
| struct PositionBase { | |||
| /** The pixel coordinate where the event occurred, relative to the Widget it is called on. */ | |||
| math::Vec pos; | |||
| }; | |||
| #define RACK_HELD 3 | |||
| /** An event prototype with a GLFW key. */ | |||
| struct KeyBase { | |||
| /** The key corresponding to what it would be called in its position on a QWERTY US keyboard. | |||
| For example, the WASD directional keys used for first-person shooters will always be reported as "WASD", regardless if they say "ZQSD" on an AZERTY keyboard. | |||
| You should usually not use these for printable characters such as "Ctrl+V" key commands. Instead, use `keyName`. | |||
| You *should* use these for non-printable keys, such as Escape, arrow keys, Home, F1-12, etc. | |||
| You should also use this for Enter, Tab, and Space. Although they are printable keys, they do not appear in `keyName`. | |||
| See GLFW_KEY_* for the list of possible values. | |||
| */ | |||
| int key; | |||
| /** Platform-dependent "software" key code. | |||
| This variable is only included for completion. There should be no reason for you to use this. | |||
| You should instead use `key` (for non-printable characters) or `keyName` (for printable characters). | |||
| Values are platform independent and can change between different keyboards or keyboard layouts on the same OS. | |||
| */ | |||
| int scancode; | |||
| /** String containing the lowercase key name, if it produces a printable character. | |||
| This is the only variable that correctly represents the label printed on any keyboard layout, whether it's QWERTY, AZERTY, QWERTZ, Dvorak, etc. | |||
| For example, if the user presses the key labeled "q" regardless of the key position, `keyName` will be "q". | |||
| For non-printable characters this is an empty string. | |||
| Enter, Tab, and Space do not give a `keyName`. Use `key` instead. | |||
| Shift has no effect on the key name. Shift+1 results in "1", Shift+q results in "q", etc. | |||
| */ | |||
| std::string keyName; | |||
| /** The type of event occurring with the key. | |||
| Possible values are GLFW_RELEASE, GLFW_PRESS, GLFW_REPEAT, or RACK_HELD. | |||
| RACK_HELD is sent every frame while the key is held. | |||
| */ | |||
| int action; | |||
| /** Bitwise OR of key modifiers, such as Ctrl or Shift. | |||
| Use (mods & RACK_MOD_MASK) == RACK_MOD_CTRL to check for Ctrl on Linux and Windows but Cmd on Mac. | |||
| See GLFW_MOD_* for the list of possible values. | |||
| */ | |||
| int mods; | |||
| }; | |||
| /** An event prototype with a Unicode character. */ | |||
| struct TextBase { | |||
| /** Unicode code point of the character */ | |||
| int codepoint; | |||
| }; | |||
| /** Occurs every frame when the mouse is hovering over a Widget. | |||
| Recurses. | |||
| Consume this event to allow Enter and Leave to occur. | |||
| */ | |||
| struct Hover : Base, PositionBase { | |||
| /** Change in mouse position since the last frame. Can be zero. */ | |||
| math::Vec mouseDelta; | |||
| }; | |||
| /** Occurs each mouse button press or release. | |||
| Recurses. | |||
| Consume this event to allow DoubleClick, Select, Deselect, SelectKey, SelectText, DragStart, DragEnd, DragMove, and DragDrop to occur. | |||
| */ | |||
| struct Button : Base, PositionBase { | |||
| /** GLFW_MOUSE_BUTTON_LEFT, GLFW_MOUSE_BUTTON_RIGHT, GLFW_MOUSE_BUTTON_MIDDLE, etc. */ | |||
| int button; | |||
| /** GLFW_PRESS or GLFW_RELEASE */ | |||
| int action; | |||
| /** GLFW_MOD_* */ | |||
| int mods; | |||
| }; | |||
| /** Occurs when the left mouse button is pressed a second time on the same Widget within a time duration. | |||
| Must consume the Button event (on left button press) to receive this event. | |||
| */ | |||
| struct DoubleClick : Base { | |||
| }; | |||
| /** Occurs when a key is pressed, released, or repeated while the mouse is hovering a Widget. | |||
| Recurses. | |||
| */ | |||
| struct HoverKey : Base, PositionBase, KeyBase { | |||
| }; | |||
| /** Occurs when a character is typed while the mouse is hovering a Widget. | |||
| Recurses. | |||
| */ | |||
| struct HoverText : Base, PositionBase, TextBase { | |||
| }; | |||
| /** Occurs when the mouse scroll wheel is moved while the mouse is hovering a Widget. | |||
| Recurses. | |||
| */ | |||
| struct HoverScroll : Base, PositionBase { | |||
| /** Change of scroll wheel position. */ | |||
| math::Vec scrollDelta; | |||
| }; | |||
| /** Occurs when a Widget begins consuming the Hover event. | |||
| Must consume the Hover event to receive this event. | |||
| The target sets `hoveredWidget`, which allows Leave to occur. | |||
| */ | |||
| struct Enter : Base { | |||
| }; | |||
| /** Occurs when a different Widget is entered. | |||
| Must consume the Hover event (when a Widget is entered) to receive this event. | |||
| */ | |||
| struct Leave : Base { | |||
| }; | |||
| /** Occurs when a Widget begins consuming the Button press event for the left mouse button. | |||
| Must consume the Button event (on left button press) to receive this event. | |||
| The target sets `selectedWidget`, which allows SelectText and SelectKey to occur. | |||
| */ | |||
| struct Select : Base { | |||
| }; | |||
| /** Occurs when a different Widget is selected. | |||
| Must consume the Button event (on left button press, when the Widget is selected) to receive this event. | |||
| */ | |||
| struct Deselect : Base { | |||
| }; | |||
| /** Occurs when a key is pressed, released, or repeated while a Widget is selected. | |||
| Must consume to prevent HoverKey from being triggered. | |||
| */ | |||
| struct SelectKey : Base, KeyBase { | |||
| }; | |||
| /** Occurs when text is typed while a Widget is selected. | |||
| Must consume to prevent HoverKey from being triggered. | |||
| */ | |||
| struct SelectText : Base, TextBase { | |||
| }; | |||
| struct DragBase : Base { | |||
| /** The mouse button held while dragging. */ | |||
| int button; | |||
| }; | |||
| /** Occurs when a Widget begins being dragged. | |||
| Must consume the Button event (on press) to receive this event. | |||
| The target sets `draggedWidget`, which allows DragEnd, DragMove, DragHover, DragEnter, and DragDrop to occur. | |||
| */ | |||
| struct DragStart : DragBase { | |||
| }; | |||
| /** Occurs when a Widget stops being dragged by releasing the mouse button. | |||
| Must consume the Button event (on press, when the Widget drag begins) to receive this event. | |||
| */ | |||
| struct DragEnd : DragBase { | |||
| }; | |||
| /** Occurs every frame on the dragged Widget. | |||
| Must consume the Button event (on press, when the Widget drag begins) to receive this event. | |||
| */ | |||
| struct DragMove : DragBase { | |||
| /** Change in mouse position since the last frame. Can be zero. */ | |||
| math::Vec mouseDelta; | |||
| }; | |||
| /** Occurs every frame when the mouse is hovering over a Widget while another Widget (possibly the same one) is being dragged. | |||
| Recurses. | |||
| Consume this event to allow DragEnter and DragLeave to occur. | |||
| */ | |||
| struct DragHover : DragBase, PositionBase { | |||
| /** The dragged widget */ | |||
| widget::Widget* origin = NULL; | |||
| /** Change in mouse position since the last frame. Can be zero. */ | |||
| math::Vec mouseDelta; | |||
| }; | |||
| /** Occurs when the mouse enters a Widget while dragging. | |||
| Must consume the DragHover event to receive this event. | |||
| The target sets `draggedWidget`, which allows DragLeave to occur. | |||
| */ | |||
| struct DragEnter : DragBase { | |||
| /** The dragged widget */ | |||
| widget::Widget* origin = NULL; | |||
| }; | |||
| /** Occurs when the mouse leaves a Widget while dragging. | |||
| Must consume the DragHover event (when the Widget is entered) to receive this event. | |||
| */ | |||
| struct DragLeave : DragBase { | |||
| /** The dragged widget */ | |||
| widget::Widget* origin = NULL; | |||
| }; | |||
| /** Occurs when the mouse button is released over a Widget while dragging. | |||
| Must consume the Button event (on release) to receive this event. | |||
| */ | |||
| struct DragDrop : DragBase { | |||
| /** The dragged widget */ | |||
| widget::Widget* origin = NULL; | |||
| }; | |||
| /** Occurs when a selection of files from the operating system is dropped onto a Widget. | |||
| Recurses. | |||
| */ | |||
| struct PathDrop : Base, PositionBase { | |||
| PathDrop(const std::vector<std::string>& paths) : paths(paths) {} | |||
| /** List of file paths in the dropped selection */ | |||
| const std::vector<std::string>& paths; | |||
| }; | |||
| /** Occurs after a certain action is triggered on a Widget. | |||
| The concept of an "action" is defined by the type of Widget. | |||
| */ | |||
| struct Action : Base { | |||
| }; | |||
| /** Occurs after the value of a Widget changes. | |||
| The concept of a "value" is defined by the type of Widget. | |||
| */ | |||
| struct Change : Base { | |||
| }; | |||
| /** Occurs when the pixel buffer of this module must be refreshed. | |||
| Recurses. | |||
| */ | |||
| struct Dirty : Base { | |||
| }; | |||
| /** Occurs after a Widget's position is set by Widget::setPosition(). | |||
| */ | |||
| struct Reposition : Base { | |||
| }; | |||
| /** Occurs after a Widget's size is set by Widget::setSize(). | |||
| */ | |||
| struct Resize : Base { | |||
| }; | |||
| /** Occurs after a Widget is added to a parent. | |||
| */ | |||
| struct Add : Base { | |||
| }; | |||
| /** Occurs before a Widget is removed from its parent. | |||
| */ | |||
| struct Remove : Base { | |||
| }; | |||
| /** Occurs after a Widget is shown with Widget::show(). | |||
| Recurses. | |||
| */ | |||
| struct Show : Base { | |||
| }; | |||
| /** Occurs after a Widget is hidden with Widget::hide(). | |||
| Recurses. | |||
| */ | |||
| struct Hide : Base { | |||
| }; | |||
| struct State { | |||
| widget::Widget* rootWidget = NULL; | |||
| /** State widgets | |||
| Don't set these directly unless you know what you're doing. Use the set*() methods instead. | |||
| */ | |||
| widget::Widget* hoveredWidget = NULL; | |||
| widget::Widget* draggedWidget = NULL; | |||
| int dragButton = 0; | |||
| widget::Widget* dragHoveredWidget = NULL; | |||
| widget::Widget* selectedWidget = NULL; | |||
| /** For double-clicking */ | |||
| double lastClickTime = -INFINITY; | |||
| widget::Widget* lastClickedWidget = NULL; | |||
| std::set<int> heldKeys; | |||
| widget::Widget* getRootWidget() { | |||
| return rootWidget; | |||
| } | |||
| widget::Widget* getHoveredWidget() { | |||
| return hoveredWidget; | |||
| } | |||
| widget::Widget* getDraggedWidget() { | |||
| return draggedWidget; | |||
| } | |||
| widget::Widget* getDragHoveredWidget() { | |||
| return dragHoveredWidget; | |||
| } | |||
| widget::Widget* getSelectedWidget() { | |||
| return selectedWidget; | |||
| } | |||
| void setHovered(widget::Widget* w); | |||
| void setDragged(widget::Widget* w, int button); | |||
| void setDragHovered(widget::Widget* w); | |||
| void setSelected(widget::Widget* w); | |||
| /** Prepares a widget for deletion */ | |||
| void finalizeWidget(widget::Widget* w); | |||
| bool handleButton(math::Vec pos, int button, int action, int mods); | |||
| bool handleHover(math::Vec pos, math::Vec mouseDelta); | |||
| bool handleLeave(); | |||
| bool handleScroll(math::Vec pos, math::Vec scrollDelta); | |||
| bool handleText(math::Vec pos, int codepoint); | |||
| bool handleKey(math::Vec pos, int key, int scancode, int action, int mods); | |||
| bool handleDrop(math::Vec pos, const std::vector<std::string>& paths); | |||
| bool handleDirty(); | |||
| }; | |||
| } // namespace event | |||
| } // namespace rack | |||
| @@ -16,6 +16,7 @@ | |||
| #include <helpers.hpp> | |||
| #include <componentlibrary.hpp> | |||
| #include <widget/event.hpp> | |||
| #include <widget/Widget.hpp> | |||
| #include <widget/TransparentWidget.hpp> | |||
| #include <widget/OpaqueWidget.hpp> | |||
| @@ -3,7 +3,6 @@ | |||
| #include <widget/OpaqueWidget.hpp> | |||
| #include <Quantity.hpp> | |||
| #include <context.hpp> | |||
| #include <event.hpp> | |||
| namespace rack { | |||
| @@ -5,7 +5,7 @@ | |||
| #include <math.hpp> | |||
| #include <window.hpp> | |||
| #include <color.hpp> | |||
| #include <event.hpp> | |||
| #include <widget/event.hpp> | |||
| #include <weakptr.hpp> | |||
| @@ -168,60 +168,333 @@ struct Widget : WeakBase { | |||
| } | |||
| } | |||
| /** Override these event callbacks to respond to events. | |||
| See event.hpp for a description of each event. | |||
| using BaseEvent = widget::BaseEvent; | |||
| /** An event prototype with a vector position. */ | |||
| struct PositionBaseEvent { | |||
| /** The pixel coordinate where the event occurred, relative to the Widget it is called on. */ | |||
| math::Vec pos; | |||
| }; | |||
| /** Occurs every frame when the mouse is hovering over a Widget. | |||
| Recurses. | |||
| Consume this event to allow Enter and Leave to occur. | |||
| */ | |||
| virtual void onHover(const event::Hover& e) { | |||
| struct HoverEvent : BaseEvent, PositionBaseEvent { | |||
| /** Change in mouse position since the last frame. Can be zero. */ | |||
| math::Vec mouseDelta; | |||
| }; | |||
| virtual void onHover(const HoverEvent& e) { | |||
| recursePositionEvent(&Widget::onHover, e); | |||
| } | |||
| virtual void onButton(const event::Button& e) { | |||
| /** Occurs each mouse button press or release. | |||
| Recurses. | |||
| Consume this event to allow DoubleClick, Select, Deselect, SelectKey, SelectText, DragStart, DragEnd, DragMove, and DragDrop to occur. | |||
| */ | |||
| struct ButtonEvent : BaseEvent, PositionBaseEvent { | |||
| /** GLFW_MOUSE_BUTTON_LEFT, GLFW_MOUSE_BUTTON_RIGHT, GLFW_MOUSE_BUTTON_MIDDLE, etc. */ | |||
| int button; | |||
| /** GLFW_PRESS or GLFW_RELEASE */ | |||
| int action; | |||
| /** GLFW_MOD_* */ | |||
| int mods; | |||
| }; | |||
| virtual void onButton(const ButtonEvent& e) { | |||
| recursePositionEvent(&Widget::onButton, e); | |||
| } | |||
| virtual void onDoubleClick(const event::DoubleClick& e) {} | |||
| virtual void onHoverKey(const event::HoverKey& e) { | |||
| /** Occurs when the left mouse button is pressed a second time on the same Widget within a time duration. | |||
| Must consume the Button event (on left button press) to receive this event. | |||
| */ | |||
| struct DoubleClickEvent : BaseEvent {}; | |||
| virtual void onDoubleClick(const DoubleClickEvent& e) {} | |||
| /** An event prototype with a GLFW key. */ | |||
| struct KeyBaseEvent { | |||
| /** The key corresponding to what it would be called in its position on a QWERTY US keyboard. | |||
| For example, the WASD directional keys used for first-person shooters will always be reported as "WASD", regardless if they say "ZQSD" on an AZERTY keyboard. | |||
| You should usually not use these for printable characters such as "Ctrl+V" key commands. Instead, use `keyName`. | |||
| You *should* use these for non-printable keys, such as Escape, arrow keys, Home, F1-12, etc. | |||
| You should also use this for Enter, Tab, and Space. Although they are printable keys, they do not appear in `keyName`. | |||
| See GLFW_KEY_* for the list of possible values. | |||
| */ | |||
| int key; | |||
| /** Platform-dependent "software" key code. | |||
| This variable is only included for completion. There should be no reason for you to use this. | |||
| You should instead use `key` (for non-printable characters) or `keyName` (for printable characters). | |||
| Values are platform independent and can change between different keyboards or keyboard layouts on the same OS. | |||
| */ | |||
| int scancode; | |||
| /** String containing the lowercase key name, if it produces a printable character. | |||
| This is the only variable that correctly represents the label printed on any keyboard layout, whether it's QWERTY, AZERTY, QWERTZ, Dvorak, etc. | |||
| For example, if the user presses the key labeled "q" regardless of the key position, `keyName` will be "q". | |||
| For non-printable characters this is an empty string. | |||
| Enter, Tab, and Space do not give a `keyName`. Use `key` instead. | |||
| Shift has no effect on the key name. Shift+1 results in "1", Shift+q results in "q", etc. | |||
| */ | |||
| std::string keyName; | |||
| /** The type of event occurring with the key. | |||
| Possible values are GLFW_RELEASE, GLFW_PRESS, GLFW_REPEAT, or RACK_HELD. | |||
| RACK_HELD is sent every frame while the key is held. | |||
| */ | |||
| int action; | |||
| /** Bitwise OR of key modifiers, such as Ctrl or Shift. | |||
| Use (mods & RACK_MOD_MASK) == RACK_MOD_CTRL to check for Ctrl on Linux and Windows but Cmd on Mac. | |||
| See GLFW_MOD_* for the list of possible values. | |||
| */ | |||
| int mods; | |||
| }; | |||
| /** Occurs when a key is pressed, released, or repeated while the mouse is hovering a Widget. | |||
| Recurses. | |||
| */ | |||
| struct HoverKeyEvent : BaseEvent, PositionBaseEvent, KeyBaseEvent {}; | |||
| virtual void onHoverKey(const HoverKeyEvent& e) { | |||
| recursePositionEvent(&Widget::onHoverKey, e); | |||
| } | |||
| virtual void onHoverText(const event::HoverText& e) { | |||
| /** An event prototype with a Unicode character. */ | |||
| struct TextBaseEvent { | |||
| /** Unicode code point of the character */ | |||
| int codepoint; | |||
| }; | |||
| /** Occurs when a character is typed while the mouse is hovering a Widget. | |||
| Recurses. | |||
| */ | |||
| struct HoverTextEvent : BaseEvent, PositionBaseEvent, TextBaseEvent {}; | |||
| virtual void onHoverText(const HoverTextEvent& e) { | |||
| recursePositionEvent(&Widget::onHoverText, e); | |||
| } | |||
| virtual void onHoverScroll(const event::HoverScroll& e) { | |||
| /** Occurs when the mouse scroll wheel is moved while the mouse is hovering a Widget. | |||
| Recurses. | |||
| */ | |||
| struct HoverScrollEvent : BaseEvent, PositionBaseEvent { | |||
| /** Change of scroll wheel position. */ | |||
| math::Vec scrollDelta; | |||
| }; | |||
| virtual void onHoverScroll(const HoverScrollEvent& e) { | |||
| recursePositionEvent(&Widget::onHoverScroll, e); | |||
| } | |||
| virtual void onEnter(const event::Enter& e) {} | |||
| virtual void onLeave(const event::Leave& e) {} | |||
| virtual void onSelect(const event::Select& e) {} | |||
| virtual void onDeselect(const event::Deselect& e) {} | |||
| virtual void onSelectKey(const event::SelectKey& e) {} | |||
| virtual void onSelectText(const event::SelectText& e) {} | |||
| virtual void onDragStart(const event::DragStart& e) {} | |||
| virtual void onDragEnd(const event::DragEnd& e) {} | |||
| virtual void onDragMove(const event::DragMove& e) {} | |||
| virtual void onDragHover(const event::DragHover& e) { | |||
| /** Occurs when a Widget begins consuming the Hover event. | |||
| Must consume the Hover event to receive this event. | |||
| The target sets `hoveredWidget`, which allows Leave to occur. | |||
| */ | |||
| struct EnterEvent : BaseEvent {}; | |||
| virtual void onEnter(const EnterEvent& e) {} | |||
| /** Occurs when a different Widget is entered. | |||
| Must consume the Hover event (when a Widget is entered) to receive this event. | |||
| */ | |||
| struct LeaveEvent : BaseEvent {}; | |||
| virtual void onLeave(const LeaveEvent& e) {} | |||
| /** Occurs when a Widget begins consuming the Button press event for the left mouse button. | |||
| Must consume the Button event (on left button press) to receive this event. | |||
| The target sets `selectedWidget`, which allows SelectText and SelectKey to occur. | |||
| */ | |||
| struct SelectEvent : BaseEvent {}; | |||
| virtual void onSelect(const SelectEvent& e) {} | |||
| /** Occurs when a different Widget is selected. | |||
| Must consume the Button event (on left button press, when the Widget is selected) to receive this event. | |||
| */ | |||
| struct DeselectEvent : BaseEvent {}; | |||
| virtual void onDeselect(const DeselectEvent& e) {} | |||
| /** Occurs when a key is pressed, released, or repeated while a Widget is selected. | |||
| Must consume to prevent HoverKey from being triggered. | |||
| */ | |||
| struct SelectKeyEvent : BaseEvent, KeyBaseEvent {}; | |||
| virtual void onSelectKey(const SelectKeyEvent& e) {} | |||
| /** Occurs when text is typed while a Widget is selected. | |||
| Must consume to prevent HoverKey from being triggered. | |||
| */ | |||
| struct SelectTextEvent : BaseEvent, TextBaseEvent {}; | |||
| virtual void onSelectText(const SelectTextEvent& e) {} | |||
| struct DragBaseEvent : BaseEvent { | |||
| /** The mouse button held while dragging. */ | |||
| int button; | |||
| }; | |||
| /** Occurs when a Widget begins being dragged. | |||
| Must consume the Button event (on press) to receive this event. | |||
| The target sets `draggedWidget`, which allows DragEnd, DragMove, DragHover, DragEnter, and DragDrop to occur. | |||
| */ | |||
| struct DragStartEvent : DragBaseEvent {}; | |||
| virtual void onDragStart(const DragStartEvent& e) {} | |||
| /** Occurs when a Widget stops being dragged by releasing the mouse button. | |||
| Must consume the Button event (on press, when the Widget drag begins) to receive this event. | |||
| */ | |||
| struct DragEndEvent : DragBaseEvent {}; | |||
| virtual void onDragEnd(const DragEndEvent& e) {} | |||
| /** Occurs every frame on the dragged Widget. | |||
| Must consume the Button event (on press, when the Widget drag begins) to receive this event. | |||
| */ | |||
| struct DragMoveEvent : DragBaseEvent { | |||
| /** Change in mouse position since the last frame. Can be zero. */ | |||
| math::Vec mouseDelta; | |||
| }; | |||
| virtual void onDragMove(const DragMoveEvent& e) {} | |||
| /** Occurs every frame when the mouse is hovering over a Widget while another Widget (possibly the same one) is being dragged. | |||
| Recurses. | |||
| Consume this event to allow DragEnter and DragLeave to occur. | |||
| */ | |||
| struct DragHoverEvent : DragBaseEvent, PositionBaseEvent { | |||
| /** The dragged widget */ | |||
| Widget* origin = NULL; | |||
| /** Change in mouse position since the last frame. Can be zero. */ | |||
| math::Vec mouseDelta; | |||
| }; | |||
| virtual void onDragHover(const DragHoverEvent& e) { | |||
| recursePositionEvent(&Widget::onDragHover, e); | |||
| } | |||
| virtual void onDragEnter(const event::DragEnter& e) {} | |||
| virtual void onDragLeave(const event::DragLeave& e) {} | |||
| virtual void onDragDrop(const event::DragDrop& e) {} | |||
| virtual void onPathDrop(const event::PathDrop& e) { | |||
| /** Occurs when the mouse enters a Widget while dragging. | |||
| Must consume the DragHover event to receive this event. | |||
| The target sets `draggedWidget`, which allows DragLeave to occur. | |||
| */ | |||
| struct DragEnterEvent : DragBaseEvent { | |||
| /** The dragged widget */ | |||
| Widget* origin = NULL; | |||
| }; | |||
| virtual void onDragEnter(const DragEnterEvent& e) {} | |||
| /** Occurs when the mouse leaves a Widget while dragging. | |||
| Must consume the DragHover event (when the Widget is entered) to receive this event. | |||
| */ | |||
| struct DragLeaveEvent : DragBaseEvent { | |||
| /** The dragged widget */ | |||
| Widget* origin = NULL; | |||
| }; | |||
| virtual void onDragLeave(const DragLeaveEvent& e) {} | |||
| /** Occurs when the mouse button is released over a Widget while dragging. | |||
| Must consume the Button event (on release) to receive this event. | |||
| */ | |||
| struct DragDropEvent : DragBaseEvent { | |||
| /** The dragged widget */ | |||
| Widget* origin = NULL; | |||
| }; | |||
| virtual void onDragDrop(const DragDropEvent& e) {} | |||
| /** Occurs when a selection of files from the operating system is dropped onto a Widget. | |||
| Recurses. | |||
| */ | |||
| struct PathDropEvent : BaseEvent, PositionBaseEvent { | |||
| PathDropEvent(const std::vector<std::string>& paths) : paths(paths) {} | |||
| /** List of file paths in the dropped selection */ | |||
| const std::vector<std::string>& paths; | |||
| }; | |||
| virtual void onPathDrop(const PathDropEvent& e) { | |||
| recursePositionEvent(&Widget::onPathDrop, e); | |||
| } | |||
| virtual void onAction(const event::Action& e) {} | |||
| virtual void onChange(const event::Change& e) {} | |||
| virtual void onDirty(const event::Dirty& e) { | |||
| /** Occurs after a certain action is triggered on a Widget. | |||
| The concept of an "action" is defined by the type of Widget. | |||
| */ | |||
| struct ActionEvent : BaseEvent {}; | |||
| virtual void onAction(const ActionEvent& e) {} | |||
| /** Occurs after the value of a Widget changes. | |||
| The concept of a "value" is defined by the type of Widget. | |||
| */ | |||
| struct ChangeEvent : BaseEvent {}; | |||
| virtual void onChange(const ChangeEvent& e) {} | |||
| /** Occurs when the pixel buffer of this module must be refreshed. | |||
| Recurses. | |||
| */ | |||
| struct DirtyEvent : BaseEvent {}; | |||
| virtual void onDirty(const DirtyEvent& e) { | |||
| recurseEvent(&Widget::onDirty, e); | |||
| } | |||
| virtual void onReposition(const event::Reposition& e) {} | |||
| virtual void onResize(const event::Resize& e) {} | |||
| virtual void onAdd(const event::Add& e) {} | |||
| virtual void onRemove(const event::Remove& e) {} | |||
| virtual void onShow(const event::Show& e) { | |||
| /** Occurs after a Widget's position is set by Widget::setPosition(). | |||
| */ | |||
| struct RepositionEvent : BaseEvent {}; | |||
| virtual void onReposition(const RepositionEvent& e) {} | |||
| /** Occurs after a Widget's size is set by Widget::setSize(). | |||
| */ | |||
| struct ResizeEvent : BaseEvent {}; | |||
| virtual void onResize(const ResizeEvent& e) {} | |||
| /** Occurs after a Widget is added to a parent. | |||
| */ | |||
| struct AddEvent : BaseEvent {}; | |||
| virtual void onAdd(const AddEvent& e) {} | |||
| /** Occurs before a Widget is removed from its parent. | |||
| */ | |||
| struct RemoveEvent : BaseEvent {}; | |||
| virtual void onRemove(const RemoveEvent& e) {} | |||
| /** Occurs after a Widget is shown with Widget::show(). | |||
| Recurses. | |||
| */ | |||
| struct ShowEvent : BaseEvent {}; | |||
| virtual void onShow(const ShowEvent& e) { | |||
| recurseEvent(&Widget::onShow, e); | |||
| } | |||
| virtual void onHide(const event::Hide& e) { | |||
| /** Occurs after a Widget is hidden with Widget::hide(). | |||
| Recurses. | |||
| */ | |||
| struct HideEvent : BaseEvent {}; | |||
| virtual void onHide(const HideEvent& e) { | |||
| recurseEvent(&Widget::onHide, e); | |||
| } | |||
| }; | |||
| } // namespace widget | |||
| /** Deprecated Rack v1 event namespace. | |||
| Use `ExampleWidget` instead of `event::Example` in new code. | |||
| */ | |||
| namespace event { | |||
| using Base = widget::BaseEvent; | |||
| using PositionBase = widget::Widget::PositionBaseEvent; | |||
| using KeyBase = widget::Widget::KeyBaseEvent; | |||
| using TextBase = widget::Widget::TextBaseEvent; | |||
| using Hover = widget::Widget::HoverEvent; | |||
| using Button = widget::Widget::ButtonEvent; | |||
| using DoubleClick = widget::Widget::DoubleClickEvent; | |||
| using HoverKey = widget::Widget::HoverKeyEvent; | |||
| using HoverText = widget::Widget::HoverTextEvent; | |||
| using HoverScroll = widget::Widget::HoverScrollEvent; | |||
| using Enter = widget::Widget::EnterEvent; | |||
| using Leave = widget::Widget::LeaveEvent; | |||
| using Select = widget::Widget::SelectEvent; | |||
| using Deselect = widget::Widget::DeselectEvent; | |||
| using SelectKey = widget::Widget::SelectKeyEvent; | |||
| using SelectText = widget::Widget::SelectTextEvent; | |||
| using DragBase = widget::Widget::DragBaseEvent; | |||
| using DragStart = widget::Widget::DragStartEvent; | |||
| using DragEnd = widget::Widget::DragEndEvent; | |||
| using DragMove = widget::Widget::DragMoveEvent; | |||
| using DragHover = widget::Widget::DragHoverEvent; | |||
| using DragEnter = widget::Widget::DragEnterEvent; | |||
| using DragLeave = widget::Widget::DragLeaveEvent; | |||
| using DragDrop = widget::Widget::DragDropEvent; | |||
| using PathDrop = widget::Widget::PathDropEvent; | |||
| using Action = widget::Widget::ActionEvent; | |||
| using Change = widget::Widget::ChangeEvent; | |||
| using Dirty = widget::Widget::DirtyEvent; | |||
| using Reposition = widget::Widget::RepositionEvent; | |||
| using Resize = widget::Widget::ResizeEvent; | |||
| using Add = widget::Widget::AddEvent; | |||
| using Remove = widget::Widget::RemoveEvent; | |||
| using Show = widget::Widget::ShowEvent; | |||
| using Hide = widget::Widget::HideEvent; | |||
| } | |||
| } // namespace rack | |||
| @@ -0,0 +1,155 @@ | |||
| #pragma once | |||
| #include <vector> | |||
| #include <set> | |||
| #include <common.hpp> | |||
| #include <math.hpp> | |||
| /** Remaps Ctrl to Cmd on Mac | |||
| Use this instead of GLFW_MOD_CONTROL, since Cmd should be used on Mac in place of Ctrl on Linux/Windows. | |||
| */ | |||
| #if defined ARCH_MAC | |||
| #define RACK_MOD_CTRL GLFW_MOD_SUPER | |||
| #define RACK_MOD_CTRL_NAME "⌘" | |||
| #else | |||
| #define RACK_MOD_CTRL GLFW_MOD_CONTROL | |||
| #define RACK_MOD_CTRL_NAME "Ctrl" | |||
| #endif | |||
| #define RACK_MOD_SHIFT_NAME "Shift" | |||
| #define RACK_MOD_ALT_NAME "Alt" | |||
| /** Filters actual mod keys from the mod flags. | |||
| Use this if you don't care about GLFW_MOD_CAPS_LOCK and GLFW_MOD_NUM_LOCK. | |||
| Example usage: | |||
| if ((e.mod & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) ... | |||
| */ | |||
| #define RACK_MOD_MASK (GLFW_MOD_SHIFT | GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER) | |||
| /** A key action state representing the the key is (still) being held. | |||
| */ | |||
| #define RACK_HELD 3 | |||
| namespace rack { | |||
| namespace widget { | |||
| struct Widget; | |||
| /** A per-event state shared and writable by all widgets that recursively handle an event. */ | |||
| struct EventContext { | |||
| /** Whether the event should continue recursing to children Widgets. */ | |||
| bool propagating = true; | |||
| /** Whether the event has been consumed by an event handler and no more handlers should consume the event. */ | |||
| bool consumed = false; | |||
| /** The widget that responded to the event. */ | |||
| Widget* target = NULL; | |||
| }; | |||
| /** Base class for all events. */ | |||
| struct BaseEvent { | |||
| EventContext* context = NULL; | |||
| /** Prevents the event from being handled by more Widgets. | |||
| */ | |||
| void stopPropagating() const { | |||
| if (!context) | |||
| return; | |||
| context->propagating = false; | |||
| } | |||
| bool isPropagating() const { | |||
| if (!context) | |||
| return true; | |||
| return context->propagating; | |||
| } | |||
| /** 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) | |||
| return; | |||
| context->target = w; | |||
| } | |||
| Widget* getTarget() const { | |||
| if (!context) | |||
| return NULL; | |||
| return context->target; | |||
| } | |||
| /** Sets the target Widget and stops propagating. | |||
| A NULL Widget may be passed to consume but not set a target. | |||
| */ | |||
| void consume(Widget* w) const { | |||
| if (!context) | |||
| return; | |||
| context->propagating = false; | |||
| context->consumed = true; | |||
| context->target = w; | |||
| } | |||
| void unconsume() const { | |||
| if (!context) | |||
| return; | |||
| context->consumed = false; | |||
| } | |||
| bool isConsumed() const { | |||
| if (!context) | |||
| return false; | |||
| return context->consumed; | |||
| } | |||
| }; | |||
| struct EventState { | |||
| Widget* rootWidget = NULL; | |||
| /** State widgets | |||
| Don't set these directly unless you know what you're doing. Use the set*() methods instead. | |||
| */ | |||
| Widget* hoveredWidget = NULL; | |||
| Widget* draggedWidget = NULL; | |||
| int dragButton = 0; | |||
| Widget* dragHoveredWidget = NULL; | |||
| Widget* selectedWidget = NULL; | |||
| /** For double-clicking */ | |||
| double lastClickTime = -INFINITY; | |||
| Widget* lastClickedWidget = NULL; | |||
| std::set<int> heldKeys; | |||
| Widget* getRootWidget() { | |||
| return rootWidget; | |||
| } | |||
| Widget* getHoveredWidget() { | |||
| return hoveredWidget; | |||
| } | |||
| Widget* getDraggedWidget() { | |||
| return draggedWidget; | |||
| } | |||
| Widget* getDragHoveredWidget() { | |||
| return dragHoveredWidget; | |||
| } | |||
| Widget* getSelectedWidget() { | |||
| return selectedWidget; | |||
| } | |||
| void setHovered(Widget* w); | |||
| void setDragged(Widget* w, int button); | |||
| void setDragHovered(Widget* w); | |||
| void setSelected(Widget* w); | |||
| /** Prepares a widget for deletion */ | |||
| void finalizeWidget(Widget* w); | |||
| bool handleButton(math::Vec pos, int button, int action, int mods); | |||
| bool handleHover(math::Vec pos, math::Vec mouseDelta); | |||
| bool handleLeave(); | |||
| bool handleScroll(math::Vec pos, math::Vec scrollDelta); | |||
| bool handleText(math::Vec pos, int codepoint); | |||
| bool handleKey(math::Vec pos, int key, int scancode, int action, int mods); | |||
| bool handleDrop(math::Vec pos, const std::vector<std::string>& paths); | |||
| bool handleDirty(); | |||
| }; | |||
| } // namespace widget | |||
| } // namespace rack | |||
| @@ -5,7 +5,6 @@ | |||
| #include <context.hpp> | |||
| #include <patch.hpp> | |||
| #include <settings.hpp> | |||
| #include <event.hpp> | |||
| #include <engine/Engine.hpp> | |||
| #include <engine/Port.hpp> | |||
| @@ -1,6 +1,5 @@ | |||
| #include <ui/Button.hpp> | |||
| #include <context.hpp> | |||
| #include <event.hpp> | |||
| namespace rack { | |||
| @@ -1,6 +1,5 @@ | |||
| #include <ui/ChoiceButton.hpp> | |||
| #include <context.hpp> | |||
| #include <event.hpp> | |||
| namespace rack { | |||
| @@ -70,7 +70,7 @@ void MenuItem::doAction() { | |||
| if (disabled) | |||
| return; | |||
| event::Context cAction; | |||
| widget::EventContext cAction; | |||
| event::Action eAction; | |||
| eAction.context = &cAction; | |||
| // Consume event by default, but allow action to un-consume it to prevent the menu from being removed. | |||
| @@ -33,7 +33,7 @@ void ZoomWidget::setZoom(float zoom) { | |||
| this->zoom = zoom; | |||
| // Trigger Dirty event | |||
| event::Context cDirty; | |||
| widget::EventContext cDirty; | |||
| event::Dirty eDirty; | |||
| eDirty.context = &cDirty; | |||
| Widget::onDirty(eDirty); | |||
| @@ -1,42 +1,42 @@ | |||
| #include <event.hpp> | |||
| #include <widget/event.hpp> | |||
| #include <widget/Widget.hpp> | |||
| #include <context.hpp> | |||
| #include <window.hpp> | |||
| namespace rack { | |||
| namespace event { | |||
| namespace widget { | |||
| void State::setHovered(widget::Widget* w) { | |||
| void EventState::setHovered(widget::Widget* w) { | |||
| if (w == hoveredWidget) | |||
| return; | |||
| if (hoveredWidget) { | |||
| // Trigger Leave event | |||
| Leave eLeave; | |||
| // Trigger LeaveEvent | |||
| Widget::LeaveEvent eLeave; | |||
| hoveredWidget->onLeave(eLeave); | |||
| hoveredWidget = NULL; | |||
| } | |||
| if (w) { | |||
| // Trigger Enter event | |||
| Context cEnter; | |||
| // Trigger EnterEvent | |||
| EventContext cEnter; | |||
| cEnter.target = w; | |||
| Enter eEnter; | |||
| Widget::EnterEvent eEnter; | |||
| eEnter.context = &cEnter; | |||
| w->onEnter(eEnter); | |||
| hoveredWidget = cEnter.target; | |||
| } | |||
| } | |||
| void State::setDragged(widget::Widget* w, int button) { | |||
| void EventState::setDragged(widget::Widget* w, int button) { | |||
| if (w == draggedWidget) | |||
| return; | |||
| if (draggedWidget) { | |||
| // Trigger DragEnd event | |||
| DragEnd eDragEnd; | |||
| // Trigger DragEndEvent | |||
| Widget::DragEndEvent eDragEnd; | |||
| eDragEnd.button = dragButton; | |||
| draggedWidget->onDragEnd(eDragEnd); | |||
| draggedWidget = NULL; | |||
| @@ -45,10 +45,10 @@ void State::setDragged(widget::Widget* w, int button) { | |||
| dragButton = button; | |||
| if (w) { | |||
| // Trigger DragStart event | |||
| Context cDragStart; | |||
| // Trigger DragStartEvent | |||
| EventContext cDragStart; | |||
| cDragStart.target = w; | |||
| DragStart eDragStart; | |||
| Widget::DragStartEvent eDragStart; | |||
| eDragStart.context = &cDragStart; | |||
| eDragStart.button = dragButton; | |||
| w->onDragStart(eDragStart); | |||
| @@ -56,13 +56,13 @@ void State::setDragged(widget::Widget* w, int button) { | |||
| } | |||
| } | |||
| void State::setDragHovered(widget::Widget* w) { | |||
| void EventState::setDragHovered(widget::Widget* w) { | |||
| if (w == dragHoveredWidget) | |||
| return; | |||
| if (dragHoveredWidget) { | |||
| // Trigger DragLeave event | |||
| DragLeave eDragLeave; | |||
| // Trigger DragLeaveEvent | |||
| Widget::DragLeaveEvent eDragLeave; | |||
| eDragLeave.button = dragButton; | |||
| eDragLeave.origin = draggedWidget; | |||
| dragHoveredWidget->onDragLeave(eDragLeave); | |||
| @@ -70,10 +70,10 @@ void State::setDragHovered(widget::Widget* w) { | |||
| } | |||
| if (w) { | |||
| // Trigger DragEnter event | |||
| Context cDragEnter; | |||
| // Trigger DragEnterEvent | |||
| EventContext cDragEnter; | |||
| cDragEnter.target = w; | |||
| DragEnter eDragEnter; | |||
| Widget::DragEnterEvent eDragEnter; | |||
| eDragEnter.context = &cDragEnter; | |||
| eDragEnter.button = dragButton; | |||
| eDragEnter.origin = draggedWidget; | |||
| @@ -82,29 +82,29 @@ void State::setDragHovered(widget::Widget* w) { | |||
| } | |||
| } | |||
| void State::setSelected(widget::Widget* w) { | |||
| void EventState::setSelected(widget::Widget* w) { | |||
| if (w == selectedWidget) | |||
| return; | |||
| if (selectedWidget) { | |||
| // Trigger Deselect event | |||
| Deselect eDeselect; | |||
| // Trigger DeselectEvent | |||
| Widget::DeselectEvent eDeselect; | |||
| selectedWidget->onDeselect(eDeselect); | |||
| selectedWidget = NULL; | |||
| } | |||
| if (w) { | |||
| // Trigger Select event | |||
| Context cSelect; | |||
| // Trigger SelectEvent | |||
| EventContext cSelect; | |||
| cSelect.target = w; | |||
| Select eSelect; | |||
| Widget::SelectEvent eSelect; | |||
| eSelect.context = &cSelect; | |||
| w->onSelect(eSelect); | |||
| selectedWidget = cSelect.target; | |||
| } | |||
| } | |||
| void State::finalizeWidget(widget::Widget* w) { | |||
| void EventState::finalizeWidget(widget::Widget* w) { | |||
| if (hoveredWidget == w) | |||
| setHovered(NULL); | |||
| if (draggedWidget == w) | |||
| @@ -117,14 +117,14 @@ void State::finalizeWidget(widget::Widget* w) { | |||
| lastClickedWidget = NULL; | |||
| } | |||
| bool State::handleButton(math::Vec pos, int button, int action, int mods) { | |||
| bool EventState::handleButton(math::Vec pos, int button, int action, int mods) { | |||
| bool cursorLocked = APP->window->isCursorLocked(); | |||
| widget::Widget* clickedWidget = NULL; | |||
| if (!cursorLocked) { | |||
| // Trigger Button event | |||
| Context cButton; | |||
| Button eButton; | |||
| // Trigger ButtonEvent | |||
| EventContext cButton; | |||
| Widget::ButtonEvent eButton; | |||
| eButton.context = &cButton; | |||
| eButton.pos = pos; | |||
| eButton.button = button; | |||
| @@ -142,8 +142,8 @@ bool State::handleButton(math::Vec pos, int button, int action, int mods) { | |||
| setDragHovered(NULL); | |||
| if (clickedWidget && draggedWidget) { | |||
| // Trigger DragDrop event | |||
| DragDrop eDragDrop; | |||
| // Trigger DragDropEvent | |||
| Widget::DragDropEvent eDragDrop; | |||
| eDragDrop.button = dragButton; | |||
| eDragDrop.origin = draggedWidget; | |||
| clickedWidget->onDragDrop(eDragDrop); | |||
| @@ -163,8 +163,8 @@ bool State::handleButton(math::Vec pos, int button, int action, int mods) { | |||
| if (clickedWidget | |||
| && clickTime - lastClickTime <= doubleClickDuration | |||
| && lastClickedWidget == clickedWidget) { | |||
| // Trigger DoubleClick event | |||
| DoubleClick eDoubleClick; | |||
| // Trigger DoubleClickEvent | |||
| Widget::DoubleClickEvent eDoubleClick; | |||
| clickedWidget->onDoubleClick(eDoubleClick); | |||
| // Reset double click | |||
| lastClickTime = -INFINITY; | |||
| @@ -180,7 +180,7 @@ bool State::handleButton(math::Vec pos, int button, int action, int mods) { | |||
| return !!clickedWidget; | |||
| } | |||
| bool State::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||
| bool EventState::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||
| bool cursorLocked = APP->window->isCursorLocked(); | |||
| // Fake a key RACK_HELD event for each held key | |||
| @@ -195,9 +195,9 @@ bool State::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||
| if (draggedWidget) { | |||
| bool dragHovered = false; | |||
| if (!cursorLocked) { | |||
| // Trigger DragHover event | |||
| Context cDragHover; | |||
| DragHover eDragHover; | |||
| // Trigger DragHoverEvent | |||
| EventContext cDragHover; | |||
| Widget::DragHoverEvent eDragHover; | |||
| eDragHover.context = &cDragHover; | |||
| eDragHover.button = dragButton; | |||
| eDragHover.pos = pos; | |||
| @@ -206,13 +206,13 @@ bool State::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||
| rootWidget->onDragHover(eDragHover); | |||
| setDragHovered(cDragHover.target); | |||
| // If consumed, don't continue after DragMove so Hover is not triggered. | |||
| // If consumed, don't continue after DragMoveEvent so HoverEvent is not triggered. | |||
| if (cDragHover.target) | |||
| dragHovered = true; | |||
| } | |||
| // Trigger DragMove event | |||
| DragMove eDragMove; | |||
| // Trigger DragMoveEvent | |||
| Widget::DragMoveEvent eDragMove; | |||
| eDragMove.button = dragButton; | |||
| eDragMove.mouseDelta = mouseDelta; | |||
| draggedWidget->onDragMove(eDragMove); | |||
| @@ -221,9 +221,9 @@ bool State::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||
| } | |||
| if (!cursorLocked) { | |||
| // Trigger Hover event | |||
| Context cHover; | |||
| Hover eHover; | |||
| // Trigger HoverEvent | |||
| EventContext cHover; | |||
| Widget::HoverEvent eHover; | |||
| eHover.context = &cHover; | |||
| eHover.pos = pos; | |||
| eHover.mouseDelta = mouseDelta; | |||
| @@ -236,7 +236,7 @@ bool State::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||
| return false; | |||
| } | |||
| bool State::handleLeave() { | |||
| bool EventState::handleLeave() { | |||
| heldKeys.clear(); | |||
| // When leaving the window, don't un-hover widgets because the mouse might be dragging. | |||
| // setDragHovered(NULL); | |||
| @@ -244,10 +244,10 @@ bool State::handleLeave() { | |||
| return true; | |||
| } | |||
| bool State::handleScroll(math::Vec pos, math::Vec scrollDelta) { | |||
| // Trigger HoverScroll event | |||
| Context cHoverScroll; | |||
| HoverScroll eHoverScroll; | |||
| bool EventState::handleScroll(math::Vec pos, math::Vec scrollDelta) { | |||
| // Trigger HoverScrollEvent | |||
| EventContext cHoverScroll; | |||
| Widget::HoverScrollEvent eHoverScroll; | |||
| eHoverScroll.context = &cHoverScroll; | |||
| eHoverScroll.pos = pos; | |||
| eHoverScroll.scrollDelta = scrollDelta; | |||
| @@ -256,10 +256,10 @@ bool State::handleScroll(math::Vec pos, math::Vec scrollDelta) { | |||
| return !!cHoverScroll.target; | |||
| } | |||
| bool State::handleDrop(math::Vec pos, const std::vector<std::string>& paths) { | |||
| // Trigger PathDrop event | |||
| Context cPathDrop; | |||
| PathDrop ePathDrop(paths); | |||
| bool EventState::handleDrop(math::Vec pos, const std::vector<std::string>& paths) { | |||
| // Trigger PathDropEvent | |||
| EventContext cPathDrop; | |||
| Widget::PathDropEvent ePathDrop(paths); | |||
| ePathDrop.context = &cPathDrop; | |||
| ePathDrop.pos = pos; | |||
| rootWidget->onPathDrop(ePathDrop); | |||
| @@ -267,11 +267,11 @@ bool State::handleDrop(math::Vec pos, const std::vector<std::string>& paths) { | |||
| return !!cPathDrop.target; | |||
| } | |||
| bool State::handleText(math::Vec pos, int codepoint) { | |||
| bool EventState::handleText(math::Vec pos, int codepoint) { | |||
| if (selectedWidget) { | |||
| // Trigger SelectText event | |||
| Context cSelectText; | |||
| SelectText eSelectText; | |||
| // Trigger SelectTextEvent | |||
| EventContext cSelectText; | |||
| Widget::SelectTextEvent eSelectText; | |||
| eSelectText.context = &cSelectText; | |||
| eSelectText.codepoint = codepoint; | |||
| selectedWidget->onSelectText(eSelectText); | |||
| @@ -279,9 +279,9 @@ bool State::handleText(math::Vec pos, int codepoint) { | |||
| return true; | |||
| } | |||
| // Trigger HoverText event | |||
| Context cHoverText; | |||
| HoverText eHoverText; | |||
| // Trigger HoverText | |||
| EventContext cHoverText; | |||
| Widget::HoverTextEvent eHoverText; | |||
| eHoverText.context = &cHoverText; | |||
| eHoverText.pos = pos; | |||
| eHoverText.codepoint = codepoint; | |||
| @@ -290,7 +290,7 @@ bool State::handleText(math::Vec pos, int codepoint) { | |||
| return !!cHoverText.target; | |||
| } | |||
| bool State::handleKey(math::Vec pos, int key, int scancode, int action, int mods) { | |||
| bool EventState::handleKey(math::Vec pos, int key, int scancode, int action, int mods) { | |||
| // Update heldKey state | |||
| if (action == GLFW_PRESS) { | |||
| heldKeys.insert(key); | |||
| @@ -302,9 +302,9 @@ bool State::handleKey(math::Vec pos, int key, int scancode, int action, int mods | |||
| } | |||
| if (selectedWidget) { | |||
| // Trigger SelectKey event | |||
| Context cSelectKey; | |||
| SelectKey eSelectKey; | |||
| // Trigger SelectKeyEvent | |||
| EventContext cSelectKey; | |||
| Widget::SelectKeyEvent eSelectKey; | |||
| eSelectKey.context = &cSelectKey; | |||
| eSelectKey.key = key; | |||
| eSelectKey.scancode = scancode; | |||
| @@ -318,9 +318,9 @@ bool State::handleKey(math::Vec pos, int key, int scancode, int action, int mods | |||
| return true; | |||
| } | |||
| // Trigger HoverKey event | |||
| Context cHoverKey; | |||
| HoverKey eHoverKey; | |||
| // Trigger HoverKeyEvent | |||
| EventContext cHoverKey; | |||
| Widget::HoverKeyEvent eHoverKey; | |||
| eHoverKey.context = &cHoverKey; | |||
| eHoverKey.pos = pos; | |||
| eHoverKey.key = key; | |||
| @@ -334,15 +334,15 @@ bool State::handleKey(math::Vec pos, int key, int scancode, int action, int mods | |||
| return !!cHoverKey.target; | |||
| } | |||
| bool State::handleDirty() { | |||
| // Trigger Dirty event | |||
| Context cDirty; | |||
| Dirty eDirty; | |||
| bool EventState::handleDirty() { | |||
| // Trigger DirtyEvent | |||
| EventContext cDirty; | |||
| Widget::DirtyEvent eDirty; | |||
| eDirty.context = &cDirty; | |||
| rootWidget->onDirty(eDirty); | |||
| return true; | |||
| } | |||
| } // namespace event | |||
| } // namespace widget | |||
| } // namespace rack | |||
| @@ -12,10 +12,10 @@ | |||
| #include <window.hpp> | |||
| #include <asset.hpp> | |||
| #include <widget/Widget.hpp> | |||
| #include <app/Scene.hpp> | |||
| #include <keyboard.hpp> | |||
| #include <gamepad.hpp> | |||
| #include <event.hpp> | |||
| #include <context.hpp> | |||
| #include <patch.hpp> | |||
| #include <settings.hpp> | |||
| @@ -183,7 +183,7 @@ int main(int argc, char* argv[]) { | |||
| contextSet(new Context); | |||
| APP->engine = new engine::Engine; | |||
| if (!settings::headless) { | |||
| APP->event = new event::State; | |||
| APP->event = new widget::EventState; | |||
| APP->history = new history::State; | |||
| APP->window = new Window; | |||
| APP->scene = new app::Scene; | |||