"Right click" on iOS

This is rather embarrassing to ask since it’s such a basic feature, but how are “right clicks” (= touch and hold) handled in iOS?

I have a desktop app that has some context menus on right click that I’d like to show in the iOS version, but I am too simple-minded to figure out which callbacks I need to use (or if I need to roll my own solution with a timer, which I hardly believe).

Well, it’s not a “right click”, it’s a “long press”, but yes, you of course need to use a timer yourself if you want that behaviour, because how else could JUCE or iOS know whether your component considers a long press to be a special event? Many (most?) components wouldn’t want anything different to happen just because you’ve held a touch down for a couple of seconds.

2 Likes

Alright, just wanted to confirm this before I reinvent the wheel. Thanks for clearing that up.

Since this thread was started a few years ago, I just wanted to follow up and check whether there have been any subsequent additions to JUCE to handle “right clicks” for iOS?

It’s pretty simple to do this yourself, here is my shot at it:

class TouchAndHoldComponent
{
public:

	TouchAndHoldComponent():
		updateTimer(this)
	{

	}
	
	virtual ~TouchAndHoldComponent()
	{
		abortTouch();
	}
	
	virtual void touchAndHold(Point<int> downPosition) = 0;
	
	void startTouch(Point<int> downPosition)
	{
		if (isTouchEnabled())
		{
			updateTimer.startTouch(downPosition);
		}
	}

	void setDragDistance(float newDistance)
	{
		updateTimer.setDragDistance(newDistance);
	}

	void abortTouch()
	{
		updateTimer.stopTimer();
	}

	bool isTouchEnabled() const
	{
		return touchEnabled;
	}

	void setTouchEnabled(bool shouldBeEnabled)
	{
		touchEnabled = shouldBeEnabled;
	}

private:

	struct UpdateTimer : public Timer
	{
		UpdateTimer(TouchAndHoldComponent* parent_):
			parent(parent_),
			dragDistance(0.0f)
		{}

		void startTouch(Point<int>& newDownPosition)
		{
			downPosition = newDownPosition;
			startTimer(1000);
		}

		void setDragDistance(float newDistance)
		{
			dragDistance = newDistance;
		}

		void timerCallback()
		{
			stopTimer();

			if (dragDistance < 8.0f)
			{
				parent->touchAndHold(downPosition);
			}
		}

	private:

		Point<int> downPosition;

		float dragDistance;

		TouchAndHoldComponent* parent;
	};

	bool touchEnabled = true;

	UpdateTimer updateTimer;
};