diff --git a/dgl/Base.hpp b/dgl/Base.hpp index 292831ad..0229512c 100644 --- a/dgl/Base.hpp +++ b/dgl/Base.hpp @@ -40,10 +40,10 @@ START_NAMESPACE_DGL Keyboard modifier flags. */ enum Modifier { - kModifierShift = 1u << 0u, /**< Shift key */ - kModifierControl = 1u << 1u, /**< Control key */ - kModifierAlt = 1u << 2u, /**< Alt/Option key */ - kModifierSuper = 1u << 3u /**< Mod4/Command/Windows key */ + kModifierShift = 1u << 0u, ///< Shift key + kModifierControl = 1u << 1u, ///< Control key + kModifierAlt = 1u << 2u, ///< Alt/Option key + kModifierSuper = 1u << 3u ///< Mod4/Command/Windows key }; /** @@ -113,6 +113,23 @@ enum Key { kKeyPause }; +/** + Common flags for all events. + */ +enum Flag { + kFlagSendEvent = 1, ///< Event is synthetic + kFlagIsHint = 2 ///< Event is a hint (not direct user input) +}; + +/** + Reason for a crossing event. + */ +enum CrossingMode { + kCrossingNormal, ///< Crossing due to pointer motion + kCrossingGrab, ///< Crossing due to a grab + kCrossingUngrab ///< Crossing due to a grab release +}; + // -------------------------------------------------------------------------------------------------------------------- // Base DGL classes diff --git a/dgl/ImageWidgets.hpp b/dgl/ImageWidgets.hpp index ac8a3abb..a88bc3ac 100644 --- a/dgl/ImageWidgets.hpp +++ b/dgl/ImageWidgets.hpp @@ -227,7 +227,7 @@ private: Point fStartPos; Point fEndPos; - Rectangle fSliderArea; + Rectangle fSliderArea; void _recheckArea() noexcept; diff --git a/dgl/Widget.hpp b/dgl/Widget.hpp index a54c3de0..dc4cea56 100644 --- a/dgl/Widget.hpp +++ b/dgl/Widget.hpp @@ -63,38 +63,61 @@ class Widget public: /** Base event data. - @a mod The currently active keyboard modifiers, @see Modifier. - @a time The timestamp (if any). + These are the fields present on all Widget events. + + @a mod Currently active keyboard modifiers, @see Modifier. + @a mod Event flags, @see Flag. + @a time Event timestamp (if any). */ struct BaseEvent { - uint mod; - uint32_t time; + uint mod; + uint flags; + uint time; /** Constuctor */ - BaseEvent() noexcept : mod(0x0), time(0) {} + BaseEvent() noexcept : mod(0x0), flags(0x0), time(0) {} /** Destuctor */ virtual ~BaseEvent() noexcept {} }; /** Keyboard event. - @a press True if the key was pressed, false if released. - @a key Unicode point of the key pressed. + + This event represents low-level key presses and releases. + This can be used for "direct" keyboard handing like key bindings, but must not be interpreted as text input. + + Keys are represented portably as Unicode code points, using the "natural" code point for the key. + The @a key field is the code for the pressed key, without any modifiers applied. + For example, a press or release of the 'A' key will have `key` 97 ('a') + regardless of whether shift or control are being held. + + Alternatively, the raw @a keycode can be used to work directly with physical keys, + but note that this value is not portable and differs between platforms and hardware. + + @a press True if the key was pressed, false if released. + @a key Unicode point of the key pressed. + @a keycode Raw keycode. @see onKeyboard */ struct KeyboardEvent : BaseEvent { bool press; uint key; + uint keycode; /** Constuctor */ KeyboardEvent() noexcept : BaseEvent(), press(false), - key(0) {} + key(0), + keycode(0) {} }; /** Special keyboard event. + + This event allows the use of keys that do not have unicode points. + Note that some are non-printable keys. + @a press True if the key was pressed, false if released. @a key The key pressed. @see onSpecial @@ -111,54 +134,91 @@ public: }; /** - Mouse event. - @a button The button number (1 = left, 2 = middle, 3 = right). + Character input event. + + This event represents text input, usually as the result of a key press. + The text is given both as a Unicode character code and a UTF-8 string. + + Note that this event is generated by the platform's input system, + so there is not necessarily a direct correspondence between text events and physical key presses. + For example, with some input methods a sequence of several key presses will generate a single character. + + @a keycode Raw key code. + @a character Unicode character code. + @a string UTF-8 string. + @see onCharacterInput + */ + struct CharacterInputEvent : BaseEvent { + uint keycode; + uint character; + char string[8]; + + /** Constuctor */ + CharacterInputEvent() noexcept + : BaseEvent(), + keycode(0), + character(0), + string{'\0','\0','\0','\0','\0','\0','\0','\0'} {} + }; + + /** + Mouse press or release event. + + @a button The button number starting from 1 (1 = left, 2 = middle, 3 = right). @a press True if the button was pressed, false if released. @a pos The widget-relative coordinates of the pointer. @see onMouse */ struct MouseEvent : BaseEvent { - int button; + uint button; bool press; - Point pos; + Point pos; /** Constuctor */ MouseEvent() noexcept : BaseEvent(), button(0), press(false), - pos(0, 0) {} + pos(0.0, 0.0) {} }; /** Mouse motion event. + @a pos The widget-relative coordinates of the pointer. @see onMotion */ struct MotionEvent : BaseEvent { - Point pos; + Point pos; /** Constuctor */ MotionEvent() noexcept : BaseEvent(), - pos(0, 0) {} + pos(0.0, 0.0) {} }; /** Mouse scroll event. + + The scroll distance is expressed in "lines", + an arbitrary unit that corresponds to a single tick of a detented mouse wheel. + For example, `delta.y` = 1.0 scrolls 1 line up. + Some systems and devices support finer resolution and/or higher values for fast scrolls, + so programs should handle any value gracefully. + @a pos The widget-relative coordinates of the pointer. @a delta The scroll distance. @see onScroll */ struct ScrollEvent : BaseEvent { - Point pos; - Point delta; + Point pos; + Point delta; /** Constuctor */ ScrollEvent() noexcept : BaseEvent(), - pos(0, 0), - delta(0.0f, 0.0f) {} + pos(0.0, 0.0), + delta(0.0, 0.0) {} }; /** @@ -318,12 +378,14 @@ public: /** Check if this widget contains the point defined by @a x and @a y. */ - bool contains(int x, int y) const noexcept; + template + bool contains(T x, T y) const noexcept; /** Check if this widget contains the point @a pos. */ - bool contains(const Point& pos) const noexcept; + template + bool contains(const Point& pos) const noexcept; /** Tell this widget's window to repaint itself. diff --git a/dgl/Window.hpp b/dgl/Window.hpp index 1fa7f819..44eda0c6 100644 --- a/dgl/Window.hpp +++ b/dgl/Window.hpp @@ -34,6 +34,11 @@ class Application; class Widget; class StandaloneWindow; +/* TODO + * add focusEvent with CrossingMode arg + * add eventcrossing/enter-leave event + */ + class Window { public: diff --git a/dgl/src/ImageWidgets.cpp b/dgl/src/ImageWidgets.cpp index f42f066d..48b85dc2 100644 --- a/dgl/src/ImageWidgets.cpp +++ b/dgl/src/ImageWidgets.cpp @@ -991,18 +991,18 @@ void ImageSlider::_recheckArea() noexcept if (fStartPos.getY() == fEndPos.getY()) { // horizontal - fSliderArea = Rectangle(fStartPos.getX(), - fStartPos.getY(), - fEndPos.getX() + static_cast(fImage.getWidth()) - fStartPos.getX(), - static_cast(fImage.getHeight())); + fSliderArea = Rectangle(fStartPos.getX(), + fStartPos.getY(), + fEndPos.getX() + static_cast(fImage.getWidth()) - fStartPos.getX(), + static_cast(fImage.getHeight())); } else { // vertical - fSliderArea = Rectangle(fStartPos.getX(), - fStartPos.getY(), - static_cast(fImage.getWidth()), - fEndPos.getY() + static_cast(fImage.getHeight()) - fStartPos.getY()); + fSliderArea = Rectangle(fStartPos.getX(), + fStartPos.getY(), + static_cast(fImage.getWidth()), + fEndPos.getY() + static_cast(fImage.getHeight()) - fStartPos.getY()); } } diff --git a/dgl/src/Widget.cpp b/dgl/src/Widget.cpp index 89083cab..ec6db8c5 100644 --- a/dgl/src/Widget.cpp +++ b/dgl/src/Widget.cpp @@ -191,12 +191,14 @@ Window& Widget::getParentWindow() const noexcept return pData->parent; } -bool Widget::contains(int x, int y) const noexcept +template +bool Widget::contains(T x, T y) const noexcept { return (x >= 0 && y >= 0 && static_cast(x) < pData->size.getWidth() && static_cast(y) < pData->size.getHeight()); } -bool Widget::contains(const Point& pos) const noexcept +template +bool Widget::contains(const Point& pos) const noexcept { return contains(pos.getX(), pos.getY()); } diff --git a/examples/Parameters/ExampleUIParameters.cpp b/examples/Parameters/ExampleUIParameters.cpp index aa0a0b3a..8e69e2c4 100644 --- a/examples/Parameters/ExampleUIParameters.cpp +++ b/examples/Parameters/ExampleUIParameters.cpp @@ -107,7 +107,7 @@ protected: const uint minwh = std::min(width, height); const uint bgColor = getBackgroundColor(); - Rectangle r; + Rectangle r; // if host doesn't respect aspect-ratio but supports ui background, draw out-of-bounds color from it if (width != height && bgColor != 0) @@ -185,7 +185,7 @@ protected: const uint height = getHeight(); const uint minwh = std::min(width, height); - Rectangle r; + Rectangle r; r.setWidth(minwh/3 - 6); r.setHeight(minwh/3 - 6); diff --git a/examples/States/ExampleUIStates.cpp b/examples/States/ExampleUIStates.cpp index 1f197f75..2e0ae031 100644 --- a/examples/States/ExampleUIStates.cpp +++ b/examples/States/ExampleUIStates.cpp @@ -149,7 +149,7 @@ protected: const uint width = getWidth(); const uint height = getHeight(); - Rectangle r; + Rectangle r; r.setWidth(width/3 - 6); r.setHeight(height/3 - 6); @@ -204,7 +204,7 @@ protected: const uint width = getWidth(); const uint height = getHeight(); - Rectangle r; + Rectangle r; r.setWidth(width/3 - 6); r.setHeight(height/3 - 6);