@@ -19,9 +19,9 @@ struct Window; | |||||
struct PatchManager; | struct PatchManager; | ||||
namespace event { | |||||
struct State; | |||||
} // namespace event | |||||
namespace widget { | |||||
struct EventState; | |||||
} // namespace widget | |||||
namespace app { | namespace app { | ||||
@@ -31,7 +31,7 @@ struct Scene; | |||||
/** Contains the application state */ | /** Contains the application state */ | ||||
struct Context { | struct Context { | ||||
event::State* event = NULL; | |||||
widget::EventState* event = NULL; | |||||
app::Scene* scene = NULL; | app::Scene* scene = NULL; | ||||
engine::Engine* engine = NULL; | engine::Engine* engine = NULL; | ||||
Window* window = 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 <helpers.hpp> | ||||
#include <componentlibrary.hpp> | #include <componentlibrary.hpp> | ||||
#include <widget/event.hpp> | |||||
#include <widget/Widget.hpp> | #include <widget/Widget.hpp> | ||||
#include <widget/TransparentWidget.hpp> | #include <widget/TransparentWidget.hpp> | ||||
#include <widget/OpaqueWidget.hpp> | #include <widget/OpaqueWidget.hpp> | ||||
@@ -3,7 +3,6 @@ | |||||
#include <widget/OpaqueWidget.hpp> | #include <widget/OpaqueWidget.hpp> | ||||
#include <Quantity.hpp> | #include <Quantity.hpp> | ||||
#include <context.hpp> | #include <context.hpp> | ||||
#include <event.hpp> | |||||
namespace rack { | namespace rack { | ||||
@@ -5,7 +5,7 @@ | |||||
#include <math.hpp> | #include <math.hpp> | ||||
#include <window.hpp> | #include <window.hpp> | ||||
#include <color.hpp> | #include <color.hpp> | ||||
#include <event.hpp> | |||||
#include <widget/event.hpp> | |||||
#include <weakptr.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); | 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); | 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); | 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); | 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); | 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); | 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); | 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); | 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); | 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); | recurseEvent(&Widget::onHide, e); | ||||
} | } | ||||
}; | }; | ||||
} // namespace widget | } // 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 | } // 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 <context.hpp> | ||||
#include <patch.hpp> | #include <patch.hpp> | ||||
#include <settings.hpp> | #include <settings.hpp> | ||||
#include <event.hpp> | |||||
#include <engine/Engine.hpp> | #include <engine/Engine.hpp> | ||||
#include <engine/Port.hpp> | #include <engine/Port.hpp> | ||||
@@ -1,6 +1,5 @@ | |||||
#include <ui/Button.hpp> | #include <ui/Button.hpp> | ||||
#include <context.hpp> | #include <context.hpp> | ||||
#include <event.hpp> | |||||
namespace rack { | namespace rack { | ||||
@@ -1,6 +1,5 @@ | |||||
#include <ui/ChoiceButton.hpp> | #include <ui/ChoiceButton.hpp> | ||||
#include <context.hpp> | #include <context.hpp> | ||||
#include <event.hpp> | |||||
namespace rack { | namespace rack { | ||||
@@ -70,7 +70,7 @@ void MenuItem::doAction() { | |||||
if (disabled) | if (disabled) | ||||
return; | return; | ||||
event::Context cAction; | |||||
widget::EventContext cAction; | |||||
event::Action eAction; | event::Action eAction; | ||||
eAction.context = &cAction; | eAction.context = &cAction; | ||||
// 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. | ||||
@@ -33,7 +33,7 @@ void ZoomWidget::setZoom(float zoom) { | |||||
this->zoom = zoom; | this->zoom = zoom; | ||||
// Trigger Dirty event | // Trigger Dirty event | ||||
event::Context cDirty; | |||||
widget::EventContext cDirty; | |||||
event::Dirty eDirty; | event::Dirty eDirty; | ||||
eDirty.context = &cDirty; | eDirty.context = &cDirty; | ||||
Widget::onDirty(eDirty); | Widget::onDirty(eDirty); | ||||
@@ -1,42 +1,42 @@ | |||||
#include <event.hpp> | |||||
#include <widget/event.hpp> | |||||
#include <widget/Widget.hpp> | #include <widget/Widget.hpp> | ||||
#include <context.hpp> | #include <context.hpp> | ||||
#include <window.hpp> | #include <window.hpp> | ||||
namespace rack { | namespace rack { | ||||
namespace event { | |||||
namespace widget { | |||||
void State::setHovered(widget::Widget* w) { | |||||
void EventState::setHovered(widget::Widget* w) { | |||||
if (w == hoveredWidget) | if (w == hoveredWidget) | ||||
return; | return; | ||||
if (hoveredWidget) { | if (hoveredWidget) { | ||||
// Trigger Leave event | |||||
Leave eLeave; | |||||
// Trigger LeaveEvent | |||||
Widget::LeaveEvent eLeave; | |||||
hoveredWidget->onLeave(eLeave); | hoveredWidget->onLeave(eLeave); | ||||
hoveredWidget = NULL; | hoveredWidget = NULL; | ||||
} | } | ||||
if (w) { | if (w) { | ||||
// Trigger Enter event | |||||
Context cEnter; | |||||
// Trigger EnterEvent | |||||
EventContext cEnter; | |||||
cEnter.target = w; | cEnter.target = w; | ||||
Enter eEnter; | |||||
Widget::EnterEvent eEnter; | |||||
eEnter.context = &cEnter; | eEnter.context = &cEnter; | ||||
w->onEnter(eEnter); | w->onEnter(eEnter); | ||||
hoveredWidget = cEnter.target; | hoveredWidget = cEnter.target; | ||||
} | } | ||||
} | } | ||||
void State::setDragged(widget::Widget* w, int button) { | |||||
void EventState::setDragged(widget::Widget* w, int button) { | |||||
if (w == draggedWidget) | if (w == draggedWidget) | ||||
return; | return; | ||||
if (draggedWidget) { | if (draggedWidget) { | ||||
// Trigger DragEnd event | |||||
DragEnd eDragEnd; | |||||
// Trigger DragEndEvent | |||||
Widget::DragEndEvent eDragEnd; | |||||
eDragEnd.button = dragButton; | eDragEnd.button = dragButton; | ||||
draggedWidget->onDragEnd(eDragEnd); | draggedWidget->onDragEnd(eDragEnd); | ||||
draggedWidget = NULL; | draggedWidget = NULL; | ||||
@@ -45,10 +45,10 @@ void State::setDragged(widget::Widget* w, int button) { | |||||
dragButton = button; | dragButton = button; | ||||
if (w) { | if (w) { | ||||
// Trigger DragStart event | |||||
Context cDragStart; | |||||
// Trigger DragStartEvent | |||||
EventContext cDragStart; | |||||
cDragStart.target = w; | cDragStart.target = w; | ||||
DragStart eDragStart; | |||||
Widget::DragStartEvent eDragStart; | |||||
eDragStart.context = &cDragStart; | eDragStart.context = &cDragStart; | ||||
eDragStart.button = dragButton; | eDragStart.button = dragButton; | ||||
w->onDragStart(eDragStart); | 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) | if (w == dragHoveredWidget) | ||||
return; | return; | ||||
if (dragHoveredWidget) { | if (dragHoveredWidget) { | ||||
// Trigger DragLeave event | |||||
DragLeave eDragLeave; | |||||
// Trigger DragLeaveEvent | |||||
Widget::DragLeaveEvent eDragLeave; | |||||
eDragLeave.button = dragButton; | eDragLeave.button = dragButton; | ||||
eDragLeave.origin = draggedWidget; | eDragLeave.origin = draggedWidget; | ||||
dragHoveredWidget->onDragLeave(eDragLeave); | dragHoveredWidget->onDragLeave(eDragLeave); | ||||
@@ -70,10 +70,10 @@ void State::setDragHovered(widget::Widget* w) { | |||||
} | } | ||||
if (w) { | if (w) { | ||||
// Trigger DragEnter event | |||||
Context cDragEnter; | |||||
// Trigger DragEnterEvent | |||||
EventContext cDragEnter; | |||||
cDragEnter.target = w; | cDragEnter.target = w; | ||||
DragEnter eDragEnter; | |||||
Widget::DragEnterEvent eDragEnter; | |||||
eDragEnter.context = &cDragEnter; | eDragEnter.context = &cDragEnter; | ||||
eDragEnter.button = dragButton; | eDragEnter.button = dragButton; | ||||
eDragEnter.origin = draggedWidget; | 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) | if (w == selectedWidget) | ||||
return; | return; | ||||
if (selectedWidget) { | if (selectedWidget) { | ||||
// Trigger Deselect event | |||||
Deselect eDeselect; | |||||
// Trigger DeselectEvent | |||||
Widget::DeselectEvent eDeselect; | |||||
selectedWidget->onDeselect(eDeselect); | selectedWidget->onDeselect(eDeselect); | ||||
selectedWidget = NULL; | selectedWidget = NULL; | ||||
} | } | ||||
if (w) { | if (w) { | ||||
// Trigger Select event | |||||
Context cSelect; | |||||
// Trigger SelectEvent | |||||
EventContext cSelect; | |||||
cSelect.target = w; | cSelect.target = w; | ||||
Select eSelect; | |||||
Widget::SelectEvent eSelect; | |||||
eSelect.context = &cSelect; | eSelect.context = &cSelect; | ||||
w->onSelect(eSelect); | w->onSelect(eSelect); | ||||
selectedWidget = cSelect.target; | selectedWidget = cSelect.target; | ||||
} | } | ||||
} | } | ||||
void State::finalizeWidget(widget::Widget* w) { | |||||
void EventState::finalizeWidget(widget::Widget* w) { | |||||
if (hoveredWidget == w) | if (hoveredWidget == w) | ||||
setHovered(NULL); | setHovered(NULL); | ||||
if (draggedWidget == w) | if (draggedWidget == w) | ||||
@@ -117,14 +117,14 @@ void State::finalizeWidget(widget::Widget* w) { | |||||
lastClickedWidget = NULL; | 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(); | bool cursorLocked = APP->window->isCursorLocked(); | ||||
widget::Widget* clickedWidget = NULL; | widget::Widget* clickedWidget = NULL; | ||||
if (!cursorLocked) { | if (!cursorLocked) { | ||||
// Trigger Button event | |||||
Context cButton; | |||||
Button eButton; | |||||
// Trigger ButtonEvent | |||||
EventContext cButton; | |||||
Widget::ButtonEvent eButton; | |||||
eButton.context = &cButton; | eButton.context = &cButton; | ||||
eButton.pos = pos; | eButton.pos = pos; | ||||
eButton.button = button; | eButton.button = button; | ||||
@@ -142,8 +142,8 @@ bool State::handleButton(math::Vec pos, int button, int action, int mods) { | |||||
setDragHovered(NULL); | setDragHovered(NULL); | ||||
if (clickedWidget && draggedWidget) { | if (clickedWidget && draggedWidget) { | ||||
// Trigger DragDrop event | |||||
DragDrop eDragDrop; | |||||
// Trigger DragDropEvent | |||||
Widget::DragDropEvent eDragDrop; | |||||
eDragDrop.button = dragButton; | eDragDrop.button = dragButton; | ||||
eDragDrop.origin = draggedWidget; | eDragDrop.origin = draggedWidget; | ||||
clickedWidget->onDragDrop(eDragDrop); | clickedWidget->onDragDrop(eDragDrop); | ||||
@@ -163,8 +163,8 @@ bool State::handleButton(math::Vec pos, int button, int action, int mods) { | |||||
if (clickedWidget | if (clickedWidget | ||||
&& clickTime - lastClickTime <= doubleClickDuration | && clickTime - lastClickTime <= doubleClickDuration | ||||
&& lastClickedWidget == clickedWidget) { | && lastClickedWidget == clickedWidget) { | ||||
// Trigger DoubleClick event | |||||
DoubleClick eDoubleClick; | |||||
// Trigger DoubleClickEvent | |||||
Widget::DoubleClickEvent eDoubleClick; | |||||
clickedWidget->onDoubleClick(eDoubleClick); | clickedWidget->onDoubleClick(eDoubleClick); | ||||
// Reset double click | // Reset double click | ||||
lastClickTime = -INFINITY; | lastClickTime = -INFINITY; | ||||
@@ -180,7 +180,7 @@ bool State::handleButton(math::Vec pos, int button, int action, int mods) { | |||||
return !!clickedWidget; | 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(); | bool cursorLocked = APP->window->isCursorLocked(); | ||||
// Fake a key RACK_HELD event for each held key | // 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) { | if (draggedWidget) { | ||||
bool dragHovered = false; | bool dragHovered = false; | ||||
if (!cursorLocked) { | if (!cursorLocked) { | ||||
// Trigger DragHover event | |||||
Context cDragHover; | |||||
DragHover eDragHover; | |||||
// Trigger DragHoverEvent | |||||
EventContext cDragHover; | |||||
Widget::DragHoverEvent eDragHover; | |||||
eDragHover.context = &cDragHover; | eDragHover.context = &cDragHover; | ||||
eDragHover.button = dragButton; | eDragHover.button = dragButton; | ||||
eDragHover.pos = pos; | eDragHover.pos = pos; | ||||
@@ -206,13 +206,13 @@ bool State::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||||
rootWidget->onDragHover(eDragHover); | rootWidget->onDragHover(eDragHover); | ||||
setDragHovered(cDragHover.target); | 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) | if (cDragHover.target) | ||||
dragHovered = true; | dragHovered = true; | ||||
} | } | ||||
// Trigger DragMove event | |||||
DragMove eDragMove; | |||||
// Trigger DragMoveEvent | |||||
Widget::DragMoveEvent eDragMove; | |||||
eDragMove.button = dragButton; | eDragMove.button = dragButton; | ||||
eDragMove.mouseDelta = mouseDelta; | eDragMove.mouseDelta = mouseDelta; | ||||
draggedWidget->onDragMove(eDragMove); | draggedWidget->onDragMove(eDragMove); | ||||
@@ -221,9 +221,9 @@ bool State::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||||
} | } | ||||
if (!cursorLocked) { | if (!cursorLocked) { | ||||
// Trigger Hover event | |||||
Context cHover; | |||||
Hover eHover; | |||||
// Trigger HoverEvent | |||||
EventContext cHover; | |||||
Widget::HoverEvent eHover; | |||||
eHover.context = &cHover; | eHover.context = &cHover; | ||||
eHover.pos = pos; | eHover.pos = pos; | ||||
eHover.mouseDelta = mouseDelta; | eHover.mouseDelta = mouseDelta; | ||||
@@ -236,7 +236,7 @@ bool State::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||||
return false; | return false; | ||||
} | } | ||||
bool State::handleLeave() { | |||||
bool EventState::handleLeave() { | |||||
heldKeys.clear(); | heldKeys.clear(); | ||||
// When leaving the window, don't un-hover widgets because the mouse might be dragging. | // When leaving the window, don't un-hover widgets because the mouse might be dragging. | ||||
// setDragHovered(NULL); | // setDragHovered(NULL); | ||||
@@ -244,10 +244,10 @@ bool State::handleLeave() { | |||||
return true; | 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.context = &cHoverScroll; | ||||
eHoverScroll.pos = pos; | eHoverScroll.pos = pos; | ||||
eHoverScroll.scrollDelta = scrollDelta; | eHoverScroll.scrollDelta = scrollDelta; | ||||
@@ -256,10 +256,10 @@ bool State::handleScroll(math::Vec pos, math::Vec scrollDelta) { | |||||
return !!cHoverScroll.target; | 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.context = &cPathDrop; | ||||
ePathDrop.pos = pos; | ePathDrop.pos = pos; | ||||
rootWidget->onPathDrop(ePathDrop); | rootWidget->onPathDrop(ePathDrop); | ||||
@@ -267,11 +267,11 @@ bool State::handleDrop(math::Vec pos, const std::vector<std::string>& paths) { | |||||
return !!cPathDrop.target; | return !!cPathDrop.target; | ||||
} | } | ||||
bool State::handleText(math::Vec pos, int codepoint) { | |||||
bool EventState::handleText(math::Vec pos, int codepoint) { | |||||
if (selectedWidget) { | if (selectedWidget) { | ||||
// Trigger SelectText event | |||||
Context cSelectText; | |||||
SelectText eSelectText; | |||||
// Trigger SelectTextEvent | |||||
EventContext cSelectText; | |||||
Widget::SelectTextEvent eSelectText; | |||||
eSelectText.context = &cSelectText; | eSelectText.context = &cSelectText; | ||||
eSelectText.codepoint = codepoint; | eSelectText.codepoint = codepoint; | ||||
selectedWidget->onSelectText(eSelectText); | selectedWidget->onSelectText(eSelectText); | ||||
@@ -279,9 +279,9 @@ bool State::handleText(math::Vec pos, int codepoint) { | |||||
return true; | return true; | ||||
} | } | ||||
// Trigger HoverText event | |||||
Context cHoverText; | |||||
HoverText eHoverText; | |||||
// Trigger HoverText | |||||
EventContext cHoverText; | |||||
Widget::HoverTextEvent eHoverText; | |||||
eHoverText.context = &cHoverText; | eHoverText.context = &cHoverText; | ||||
eHoverText.pos = pos; | eHoverText.pos = pos; | ||||
eHoverText.codepoint = codepoint; | eHoverText.codepoint = codepoint; | ||||
@@ -290,7 +290,7 @@ bool State::handleText(math::Vec pos, int codepoint) { | |||||
return !!cHoverText.target; | 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 | // Update heldKey state | ||||
if (action == GLFW_PRESS) { | if (action == GLFW_PRESS) { | ||||
heldKeys.insert(key); | heldKeys.insert(key); | ||||
@@ -302,9 +302,9 @@ bool State::handleKey(math::Vec pos, int key, int scancode, int action, int mods | |||||
} | } | ||||
if (selectedWidget) { | if (selectedWidget) { | ||||
// Trigger SelectKey event | |||||
Context cSelectKey; | |||||
SelectKey eSelectKey; | |||||
// Trigger SelectKeyEvent | |||||
EventContext cSelectKey; | |||||
Widget::SelectKeyEvent eSelectKey; | |||||
eSelectKey.context = &cSelectKey; | eSelectKey.context = &cSelectKey; | ||||
eSelectKey.key = key; | eSelectKey.key = key; | ||||
eSelectKey.scancode = scancode; | eSelectKey.scancode = scancode; | ||||
@@ -318,9 +318,9 @@ bool State::handleKey(math::Vec pos, int key, int scancode, int action, int mods | |||||
return true; | return true; | ||||
} | } | ||||
// Trigger HoverKey event | |||||
Context cHoverKey; | |||||
HoverKey eHoverKey; | |||||
// Trigger HoverKeyEvent | |||||
EventContext cHoverKey; | |||||
Widget::HoverKeyEvent eHoverKey; | |||||
eHoverKey.context = &cHoverKey; | eHoverKey.context = &cHoverKey; | ||||
eHoverKey.pos = pos; | eHoverKey.pos = pos; | ||||
eHoverKey.key = key; | eHoverKey.key = key; | ||||
@@ -334,15 +334,15 @@ bool State::handleKey(math::Vec pos, int key, int scancode, int action, int mods | |||||
return !!cHoverKey.target; | 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; | eDirty.context = &cDirty; | ||||
rootWidget->onDirty(eDirty); | rootWidget->onDirty(eDirty); | ||||
return true; | return true; | ||||
} | } | ||||
} // namespace event | |||||
} // namespace widget | |||||
} // namespace rack | } // namespace rack |
@@ -12,10 +12,10 @@ | |||||
#include <window.hpp> | #include <window.hpp> | ||||
#include <asset.hpp> | #include <asset.hpp> | ||||
#include <widget/Widget.hpp> | |||||
#include <app/Scene.hpp> | #include <app/Scene.hpp> | ||||
#include <keyboard.hpp> | #include <keyboard.hpp> | ||||
#include <gamepad.hpp> | #include <gamepad.hpp> | ||||
#include <event.hpp> | |||||
#include <context.hpp> | #include <context.hpp> | ||||
#include <patch.hpp> | #include <patch.hpp> | ||||
#include <settings.hpp> | #include <settings.hpp> | ||||
@@ -183,7 +183,7 @@ int main(int argc, char* argv[]) { | |||||
contextSet(new Context); | contextSet(new Context); | ||||
APP->engine = new engine::Engine; | APP->engine = new engine::Engine; | ||||
if (!settings::headless) { | if (!settings::headless) { | ||||
APP->event = new event::State; | |||||
APP->event = new widget::EventState; | |||||
APP->history = new history::State; | APP->history = new history::State; | ||||
APP->window = new Window; | APP->window = new Window; | ||||
APP->scene = new app::Scene; | APP->scene = new app::Scene; | ||||