Skip to content

Commit

Permalink
Scrolling with middle mouse button (#423)
Browse files Browse the repository at this point in the history
  • Loading branch information
igorsegallafa committed Mar 7, 2023
1 parent 73a15bf commit d129fb8
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 7 deletions.
8 changes: 7 additions & 1 deletion Backends/RmlUi_Platform_GLFW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ void SystemInterface_GLFW::SetMouseCursor(const Rml::String& cursor_name)
cursor = cursor_cross;
else if (cursor_name == "text")
cursor = cursor_text;
else if (cursor_name == "rmlui-scroll-idle")
cursor = cursor_pointer;
else if (cursor_name == "rmlui-scroll-up")
cursor = cursor_pointer;
else if (cursor_name == "rmlui-scroll-down")
cursor = cursor_pointer;
else if (cursor_name == "unavailable")
cursor = nullptr;

Expand Down Expand Up @@ -331,4 +337,4 @@ Rml::Input::KeyIdentifier RmlGLFW::ConvertKey(int glfw_key)
// clang-format on

return Rml::Input::KI_UNKNOWN;
}
}
6 changes: 6 additions & 0 deletions Backends/RmlUi_Platform_SDL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ void SystemInterface_SDL::SetMouseCursor(const Rml::String& cursor_name)
cursor = cursor_cross;
else if (cursor_name == "text")
cursor = cursor_text;
else if (cursor_name == "rmlui-scroll-idle")
cursor = cursor_move;
else if (cursor_name == "rmlui-scroll-up")
cursor = cursor_move;
else if (cursor_name == "rmlui-scroll-down")
cursor = cursor_move;
else if (cursor_name == "unavailable")
cursor = cursor_unavailable;

Expand Down
6 changes: 6 additions & 0 deletions Backends/RmlUi_Platform_SFML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ void SystemInterface_SFML::SetMouseCursor(const Rml::String& cursor_name)
cursor = &cursor_cross;
else if (cursor_name == "text")
cursor = &cursor_text;
else if (cursor_name == "rmlui-scroll-idle")
cursor = &cursor_move;
else if (cursor_name == "rmlui-scroll-up")
cursor = &cursor_move;
else if (cursor_name == "rmlui-scroll-down")
cursor = &cursor_move;
else if (cursor_name == "unavailable")
cursor = &cursor_unavailable;

Expand Down
6 changes: 6 additions & 0 deletions Backends/RmlUi_Platform_Win32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ void SystemInterface_Win32::SetMouseCursor(const Rml::String& cursor_name)
cursor_handle = cursor_cross;
else if (cursor_name == "text")
cursor_handle = cursor_text;
else if (cursor_name == "rmlui-scroll-idle")
cursor_handle = cursor_move;
else if (cursor_name == "rmlui-scroll-up")
cursor_handle = cursor_move;
else if (cursor_name == "rmlui-scroll-down")
cursor_handle = cursor_move;
else if (cursor_name == "unavailable")
cursor_handle = cursor_unavailable;

Expand Down
6 changes: 6 additions & 0 deletions Backends/RmlUi_Platform_X11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ void SystemInterface_X11::SetMouseCursor(const Rml::String& cursor_name)
cursor_handle = cursor_cross;
else if (cursor_name == "text")
cursor_handle = cursor_text;
else if (cursor_name == "rmlui-scroll-idle")
cursor_handle = cursor_move;
else if (cursor_name == "rmlui-scroll-up")
cursor_handle = cursor_move;
else if (cursor_name == "rmlui-scroll-down")
cursor_handle = cursor_move;
else if (cursor_name == "unavailable")
cursor_handle = cursor_unavailable;

Expand Down
20 changes: 17 additions & 3 deletions Include/RmlUi/Core/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,12 @@ class RMLUICORE_API Context : public ScriptInterface
/// @return True if the mouse is not interacting with any elements in the context (see 'IsMouseInteracting'), otherwise false.
bool ProcessMouseMove(int x, int y, int key_modifier_state);
/// Sends a mouse-button down event into this context.
/// @param[in] button_index The index of the button that was pressed; 0 for the left button, 1 for right, and any others from 2 onwards.
/// @param[in] button_index The index of the button that was pressed; 0 for the left button, 1 for right, and 2 for middle button.
/// @param[in] key_modifier_state The state of key modifiers (shift, control, caps-lock, etc) keys; this should be generated by ORing together members of the Input::KeyModifier enumeration.
/// @return True if the mouse is not interacting with any elements in the context (see 'IsMouseInteracting'), otherwise false.
bool ProcessMouseButtonDown(int button_index, int key_modifier_state);
/// Sends a mouse-button up event into this context.
/// @param[in] button_index The index of the button that was release; 0 for the left button, 1 for right, and any others from 2 onwards.
/// @param[in] button_index The index of the button that was release; 0 for the left button, 1 for right, and 2 for middle button.
/// @param[in] key_modifier_state The state of key modifiers (shift, control, caps-lock, etc) keys; this should be generated by ORing together members of the Input::KeyModifier enumeration.
/// @return True if the mouse is not interacting with any elements in the context (see 'IsMouseInteracting'), otherwise false.
bool ProcessMouseButtonUp(int button_index, int key_modifier_state);
Expand Down Expand Up @@ -308,7 +308,7 @@ class RMLUICORE_API Context : public ScriptInterface

// The element that was clicked on last.
Element* last_click_element;
// The time the last click occured.
// The time the last click occurred.
double last_click_time;
// Mouse position during the last mouse_down event.
Vector2i last_click_mouse_position;
Expand All @@ -317,6 +317,14 @@ class RMLUICORE_API Context : public ScriptInterface
Vector2i mouse_position;
bool mouse_active;

// Scrolling element with scroll button controller.
Vector2i started_scroll_position;
Element* scroll_hover;
bool holding_scroll;

// The time the last update occurred.
double last_update_time;

// Enables cursor handling.
bool enable_cursor;
String cursor_name;
Expand Down Expand Up @@ -369,6 +377,12 @@ class RMLUICORE_API Context : public ScriptInterface
// Returns the data model with the provided name, or nullptr if it does not exist.
DataModel* GetDataModelPtr(const String& name) const;

// Returns the scrolling cursor based on scroll direction.
String GetScrollCursor() const;

// Reset mouse scrolling parameters.
void ResetScrollParameters();

// Builds the parameters for a generic key event.
void GenerateKeyEventParameters(Dictionary& parameters, Input::KeyIdentifier key_identifier);
// Builds the parameters for a generic mouse event.
Expand Down
68 changes: 65 additions & 3 deletions Source/Core/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ namespace Rml {

static constexpr float DOUBLE_CLICK_TIME = 0.5f; // [s]
static constexpr float DOUBLE_CLICK_MAX_DIST = 3.f; // [dp]
static constexpr float SCROLL_MIDDLE_MOUSE_SPEED_FACTOR = 0.5f;

Context::Context(const String& name) : name(name), dimensions(0, 0), density_independent_pixel_ratio(1.0f), mouse_position(0, 0), clip_origin(-1, -1), clip_dimensions(-1, -1)
Context::Context(const String& name) : name(name), dimensions(0, 0), density_independent_pixel_ratio(1.0f), mouse_position(0, 0), started_scroll_position(0, 0), clip_origin(-1, -1), clip_dimensions(-1, -1)
{
instancer = nullptr;

Expand Down Expand Up @@ -86,6 +87,7 @@ Context::Context(const String& name) : name(name), dimensions(0, 0), density_ind
hover = nullptr;
active = nullptr;
drag = nullptr;
scroll_hover = nullptr;

drag_started = false;
drag_verbose = false;
Expand All @@ -94,7 +96,9 @@ Context::Context(const String& name) : name(name), dimensions(0, 0), density_ind

last_click_element = nullptr;
last_click_time = 0;
last_update_time = 0;

holding_scroll = false;
mouse_active = false;

enable_cursor = true;
Expand Down Expand Up @@ -182,7 +186,24 @@ float Context::GetDensityIndependentPixelRatio() const
bool Context::Update()
{
RMLUI_ZoneScoped;


double current_time = GetSystemInterface()->GetElapsedTime();

if (scroll_hover)
{
const Vector2i scroll_delta = mouse_position - started_scroll_position;
const float delta_time = float(current_time - last_update_time);
const float scroll_speed = scroll_delta.y * SCROLL_MIDDLE_MOUSE_SPEED_FACTOR * delta_time;

Dictionary scroll_parameters;
GenerateMouseEventParameters(scroll_parameters);
scroll_parameters["wheel_delta"] = scroll_speed;

// Scroll event was not handled by any element, it means that we don't have anything to scroll.
if (scroll_hover->DispatchEvent(EventId::Mousescroll, scroll_parameters))
ResetScrollParameters();
}

// Update the hover chain to detect any new or moved elements under the mouse.
if (mouse_active)
UpdateHoverChain(mouse_position);
Expand All @@ -209,6 +230,9 @@ bool Context::Update()
// Release any documents that were unloaded during the update.
ReleaseUnloadedDocuments();

// Last update time used to calculate delta time posteriorly.
last_update_time = current_time;

return true;
}

Expand Down Expand Up @@ -620,6 +644,9 @@ bool Context::ProcessMouseMove(int x, int y, int key_modifier_state)
if (drag_hover && drag_verbose)
drag_hover->DispatchEvent(EventId::Dragmove, drag_parameters);
}

if (scroll_hover)
holding_scroll = true;
}

return !IsMouseInteracting();
Expand Down Expand Up @@ -726,6 +753,17 @@ bool Context::ProcessMouseButtonDown(int button_index, int key_modifier_state)
hover->DispatchEvent(EventId::Mousedown, parameters);
}

if (scroll_hover)
{
ResetScrollParameters();
}
else if (button_index == 2)
{
scroll_hover = hover;
holding_scroll = false;
started_scroll_position = mouse_position;
}

return !IsMouseInteracting();
}

Expand Down Expand Up @@ -801,6 +839,9 @@ bool Context::ProcessMouseButtonUp(int button_index, int key_modifier_state)
hover->DispatchEvent(EventId::Mouseup, parameters);
}

if (scroll_hover && holding_scroll)
ResetScrollParameters();

return result;
}

Expand Down Expand Up @@ -1092,7 +1133,9 @@ void Context::UpdateHoverChain(Vector2i old_mouse_position, int key_modifier_sta
{
String new_cursor_name;

if(drag)
if (scroll_hover)
new_cursor_name = GetScrollCursor();
else if(drag)
new_cursor_name = drag->GetComputedValues().cursor();
else if (hover)
new_cursor_name = hover->GetComputedValues().cursor();
Expand Down Expand Up @@ -1290,6 +1333,25 @@ DataModel* Context::GetDataModelPtr(const String& name) const
return nullptr;
}

// Returns the scrolling cursor based on scroll direction.
String Context::GetScrollCursor() const
{
const int scroll_direction = started_scroll_position.y - mouse_position.y;

if (scroll_direction == 0)
return "rmlui-scroll-idle";

return scroll_direction > 0 ? "rmlui-scroll-up" : "rmlui-scroll-down";
}

// Reset mouse scrolling parameters.
void Context::ResetScrollParameters()
{
scroll_hover = nullptr;
holding_scroll = false;
started_scroll_position = Vector2i(0, 0);
}

// Builds the parameters for a generic key event.
void Context::GenerateKeyEventParameters(Dictionary& parameters, Input::KeyIdentifier key_identifier)
{
Expand Down

0 comments on commit d129fb8

Please sign in to comment.