When testing my plugin in Linux (both Ubuntu and Mint), I noticed the horizontal scrolling didn’t work at all. Looking into JUCE’s source code, it becomes obvious why:
void XWindowSystem::handleWheelEvent (LinuxComponentPeer* peer, const XButtonPressedEvent& buttonPressEvent, float amount) const
{
MouseWheelDetails wheel;
wheel.deltaX = 0.0f;
wheel.deltaY = amount;
wheel.isReversed = false;
wheel.isSmooth = false;
wheel.isInertial = false;
peer->handleMouseWheel (MouseInputSource::InputSourceType::mouse, getLogicalMousePos (buttonPressEvent, peer->getPlatformScaleFactor()),
getEventTime (buttonPressEvent), wheel);
}
After digging into the source code a bit more, I was able to come up with the following solution, so I figured I’d share it so anyone else can implement it into their JUCE Linux program
In juce_XWindowSystem_linux.h :
- Change line 308 in the source to
void handleWheelEvent (LinuxComponentPeer*, const XButtonPressedEvent&, float, float) const;
- Change line 346 in the source to
int pointerMap[7] = {};
In juce_XWindowSystem_linux.cpp :
- Change the enum MouseButtons (found at line 398 in the source) to
enum MouseButtons
{
NoButton = 0,
LeftButton = 1,
MiddleButton = 2,
RightButton = 3,
WheelUp = 4,
WheelDown = 5,
WheelLeft = 6,
WheelRight = 7
};
- Change the function initialisePointerMap (found at line 3063 in the source) to
void XWindowSystem::initialisePointerMap()
{
auto numButtons = X11Symbols::getInstance()->xGetPointerMapping (display, nullptr, 0);
pointerMap[2] = pointerMap[3] = pointerMap[4] = pointerMap[5] = pointerMap[6] = Keys::NoButton;
if (numButtons == 2)
{
pointerMap[0] = Keys::LeftButton;
pointerMap[1] = Keys::RightButton;
}
else if (numButtons >= 3)
{
pointerMap[0] = Keys::LeftButton;
pointerMap[1] = Keys::MiddleButton;
pointerMap[2] = Keys::RightButton;
if (numButtons >= 5)
{
pointerMap[3] = Keys::WheelUp;
pointerMap[4] = Keys::WheelDown;
if (numButtons >= 7)
{
pointerMap[5] = Keys::WheelLeft;
pointerMap[6] = Keys::WheelRight;
}
}
}
}
- Change the function handleWheelEvent (found at line 3571 in the source) to
void XWindowSystem::handleWheelEvent (LinuxComponentPeer* peer, const XButtonPressedEvent& buttonPressEvent, float amount, float h_amount) const
{
MouseWheelDetails wheel;
wheel.deltaX = h_amount;
wheel.deltaY = amount;
wheel.isReversed = false;
wheel.isSmooth = false;
wheel.isInertial = false;
peer->handleMouseWheel (MouseInputSource::InputSourceType::mouse, getLogicalMousePos (buttonPressEvent, peer->getPlatformScaleFactor()),
getEventTime (buttonPressEvent), wheel);
}
- And finally, change the function handleButtonPressEvent (found at line 3593 in the source) to
void XWindowSystem::handleButtonPressEvent (LinuxComponentPeer* peer, const XButtonPressedEvent& buttonPressEvent) const
{
updateKeyModifiers ((int) buttonPressEvent.state);
auto mapIndex = (uint32) (buttonPressEvent.button - Button1);
if (mapIndex < (uint32) numElementsInArray (pointerMap))
{
switch (pointerMap[mapIndex])
{
case Keys::WheelLeft: handleWheelEvent (peer, buttonPressEvent, 0.0f, 100.0f / 256.0f); break;
case Keys::WheelRight: handleWheelEvent (peer, buttonPressEvent, 0.0f, -100.0f / 256.0f); break;
case Keys::WheelUp: handleWheelEvent (peer, buttonPressEvent, 50.0f / 256.0f, 0.0f); break;
case Keys::WheelDown: handleWheelEvent (peer, buttonPressEvent, -50.0f / 256.0f, 0.0f); break;
case Keys::LeftButton: handleButtonPressEvent (peer, buttonPressEvent, ModifierKeys::leftButtonModifier); break;
case Keys::RightButton: handleButtonPressEvent (peer, buttonPressEvent, ModifierKeys::rightButtonModifier); break;
case Keys::MiddleButton: handleButtonPressEvent (peer, buttonPressEvent, ModifierKeys::middleButtonModifier); break;
default: break;
}
}
}
And that should be it! I only have the one laptop to test this on, so it may need some more fine-tuning. using 50.0f/256.0f in the horizontal scrolling felt too slow and not fluid enough for me so I doubled it, but these values could also be changed depending on what feels more natural
Hope this helps!