More mouse events

Hello,

is there a way to send a mouse event for each pixels when we moving the mouse ? I need it to draw in a component ^^

mouseMove perhaps?

https://docs.juce.com/master/classMouseListener.html#a34327ec666304f0660d818db8281d2fd

Thank you for your answer !

My problem is there is not enough call to mouseMove. Juce seems to trigger a mouse event each 10ms or something like that. But with fast moves there is gaps. I need an event for each pixels or an equivalent

Even in Photoshop when you move the mouse really quickly it is just interpolating with lines between the events.
I doubt you’ll get an event per pixel in JUCE or any other framework tbh, my guess is this is something from the OS level.

I’m fairly sure that that’s not controlled by applications (or plugins), but by the system and mouse driver. For example, on the Mac, my System Preferences panel for the Mouse has a “tracking speed” control, which causes larger mouse position changes to be reported for given physical movement distances of the mouse. I think there is a timer (in the mouse driver?) that polls the mouse in most cases, but there a many types of pointer devices, and I don’t know how universal that is. But in short, I think the answer is “you can’t”.

I asked because there could have been an option to generate interpolated mouse events in juce. I tought there is such option in the SDL framework

Coming from a game development background, I can totally see how this can be done. What you need in this case is raw input from the OS.

Windows (and possibly Linux) support this feature:

macOS unfortunately doesn’t provide this - it interpolates mouse input for you with mouse acceleration. There are workarounds of course, it’s just that it’s not out of the box where users will have this off by default (and it’s a bit cumbersome to disable from the POV of users).

JUCE is not presently set up with this feature. Meanwhile, SDL2 is (search for WM_INPUT).

To help people that have the same problem, I share my solution. It’s not complete, but I think it’s a decent base.

In the members of your component class add ScopedPointer<MouseEvent> _lastMouseEvent;
In first line of mouseDown add _lastMouseEvent = new MouseEvent(e);
In the last line of mouseUp add _lastMouseEvent.reset();
In mouseDrag use :

		MouseEventWrapper mouseEventWrapper(mouseEvent, _lastMouseEvent.get());
		while(mouseEventWrapper) {
			//use the mouseEventWrapper like a normal mouseEvent
			mouseEventWrapper++;
		}

The mouse event wrapper should be used like a normal mouseEvent. I only wrote the wrapper for things I needed, but you can easily understand how it works and extend it.

.h

	class MouseEventWrapper {
	public:
		const ModifierKeys& mods;

		MouseEventWrapper(const MouseEvent& e, const MouseEvent* last = nullptr);

		Point<int> getMouseDownPosition() const;
		int getDistanceFromDragStartX() const;
		Point<int> getOffsetFromDragStart() const;
		int getMouseDownY() const;

		operator bool() const;
		void operator++(int);

	private:
		int getDeltaX() const;
		int getDeltaY() const;
		int getStepSize() const;
		int getTotalNumIter() const;
		int getOffsetX() const;
		int getOffsetY() const;

		const MouseEvent& _e;
		const MouseEvent* _last;
		int _iterNum;
		int _totalNumIter;
	};

.cpp

MouseEventWrapper::MouseEventWrapper(const MouseEvent& e, const MouseEvent* last)
: mods(e.mods)
, _e(e)
, _last(last)
, _iterNum(0)
, _totalNumIter(1) {
	if (!last)
		return;

	_totalNumIter = getTotalNumIter();
}

int MouseEventWrapper::getDeltaX() const {
	return _last ? _e.getDistanceFromDragStartX() - _last->getDistanceFromDragStartX() : 0;
}

int MouseEventWrapper::getDeltaY() const {
	return _last ? _e.getDistanceFromDragStartY() - _last->getDistanceFromDragStartY() : 0;
}

int MouseEventWrapper::getStepSize() const {
	return 1;
}

int MouseEventWrapper::getTotalNumIter() const {
	const double delta = getDeltaX();
	const double stepSize = getStepSize();
	return static_cast<int>(abs(delta / stepSize));
}

int MouseEventWrapper::getOffsetX() const {
	const double delta = getDeltaX();
	const double total = jmax(1, getTotalNumIter());
	return static_cast<int>(delta / total * (_iterNum + 1));
}

int MouseEventWrapper::getOffsetY() const {
	const double delta = getDeltaY();
	const double total = jmax(1, getTotalNumIter());
	return static_cast<int>(delta / total * (_iterNum + 1));
}

Point<int> MouseEventWrapper::getMouseDownPosition() const {
	return _e.getMouseDownPosition();
}

int MouseEventWrapper::getDistanceFromDragStartX() const {
	return _last ? _last->getDistanceFromDragStartX() + getOffsetX() : _e.getDistanceFromDragStartX();
}

Point<int> MouseEventWrapper::getOffsetFromDragStart() const {
	auto p = _e.getOffsetFromDragStart();
	p.addXY(getOffsetX(), getOffsetY());
	return p;
}

int MouseEventWrapper::getMouseDownY() const {
	return _e.getMouseDownY();
}

MouseEventWrapper::operator bool() const {
	return _iterNum < _totalNumIter;
}

void MouseEventWrapper::operator++(int) {
	_iterNum++;
}

Note 1 : there is a function getStepSize() that return 1. It’s the size between to interpolated mouse events. 1 mean you want an event by pixel.
Note 2 : The number of iterations is processed using the x axis.