Apple Mouse wheel not picked up

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
DaedalusYoung
Party member
Posts: 407
Joined: Sun Jul 14, 2013 8:04 pm

Apple Mouse wheel not picked up

Post by DaedalusYoung »

I've got a fairly new Apple Mouse. It doesn't have a traditional scroll wheel, instead, it works like a touch device. I can swipe and tap, and swiping works as a regular mouse wheel would. If I swipe it up or down, it acts like I'd keep the wheel spinning. Tap it acts like I stop the spinning wheel. It's fairly sensitive, so not very easy to use in all applications, but it works.

I was trying to get the mouse wheel to work in LÖVE, but there's a slight problem. In my tests, I have determined that when using the mouse wheel, mousepressed() and mousereleased() are triggered at the exact same time, while mouse.isDown() doesn't pick up the action at all. So I cannot get the wheel to work using isDown(), but I also can't get it to work with the callbacks, because it doesn't even see the mouse as being activated for even one frame. I can see the wheel is activated, but I can't see when it's not in use anymore, so assigning a 'wu' variable in mousepressed() and then setting that variable back to nil in mousereleased() tells me that the wheel is not activated at all.

I don't think there's any way around this, but I'm just wondering, seeing as the wheel works as normal in other applications, what does LÖVE do differently that only makes it appear to work as a superfast spike?
User avatar
Boolsheet
Inner party member
Posts: 780
Joined: Wed Dec 29, 2010 4:57 am
Location: Switzerland

Re: Apple Mouse wheel not picked up

Post by Boolsheet »

Since the Apple mouse is a multi-touch device, the simple scroll wheel API can not represent all the information that the mouse sends. SDL 1.2 just does the minimum with scroll wheel events and all you get are impulses.

I'm guessing the drivers goes into some sort of legacy mode and just emulates a simple scroll wheel. The more impulses you get, the faster it scrolls. Set up a variable that has the actual count of these impulses and a variable that slowly approaches this value over time. That should get you the swiping effect.

Code: Select all

function love.load()
	target_position = 0
	display_position = 0

	-- Adjust this if scrolls too slow or fast.
	scroll_speed = 25
end

function love.mousepressed(x, y, b)
	if b == "wu" then
		target_position = target_position + scroll_speed
	elseif b == "wd" then
		target_position = target_position - scroll_speed
	end
end

function love.update(dt)
	local diff = target_position - display_position
	if diff ~= 0 then
		if math.abs(diff) < 0.01 then
			display_position = target_position
		else
			display_position = display_position + diff * scroll_speed * dt
		end
	end
end

function love.draw()
	local num_lines = 16
	local line_distance = 40
	local wrap_around = num_lines * line_distance
	for i = 1, num_lines, 2 do
		local p = (i * line_distance + display_position) % wrap_around - line_distance
		love.graphics.rectangle("fill", 0, p, 800, line_distance)
	end
end
I do hope your driver does handle it like that anyway and I understood your problem correctly.

You can also try out a development build for LÖVE. If the callbacks were already adjusted for SDL 2, then you even get horizontal movement (not exposed). Still no multi-touch stuff, though. :P
Last edited by Boolsheet on Tue Nov 12, 2013 8:31 am, edited 1 time in total.
Shallow indentations.
User avatar
slime
Solid Snayke
Posts: 3133
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: Apple Mouse wheel not picked up

Post by slime »

Boolsheet wrote:You can also try out a development build for LÖVE. If the callbacks were already adjusted for SDL 2, then you even get horizontal movement. Still no multi-touch stuff, though. :P
That's one thing I haven't changed (or rather, I preserved backwards compatibility for it) actually - LÖVE's mousewheel events are still part of the mousepressed event, only wheel-up and wheel-down are sent, and there's no way to get the amount scrolled.

Maybe I'll see if I can add SDL's new functionality nicely.
User avatar
DaedalusYoung
Party member
Posts: 407
Joined: Sun Jul 14, 2013 8:04 pm

Re: Apple Mouse wheel not picked up

Post by DaedalusYoung »

Thanks, I'll look into it. Can mousepressed() get called more than once per frame? Likely the mouse is sending quick pulses, as you said, that other apps are able to pick up. If it gets 500 pulses per second, it moves fast, if it gets 120 pulses per second, it is slow (or something like that). If mousepressed() is able to pick that up, then that might work just fine after all.

[edit]
Well, I tested that and it's indeed not the case. I can get the scrolling to work by adding and subtracting in the mousepressed() function, and that looks alright, but it indeed doesn't use the proper velocity. But at least it scrolls, so that's a good thing, too bad mouse.isDown() doesn't see it.

If you want to play with this yourself, I used this testcode:

Code: Select all

function love.load()
	posy = 300
	prevy = { 300, 300 }
	wheelcolour = {
		line = { 192, 192, 192 },
		fill = { 255, 255, 255 }
		}
	love.graphics.setLineWidth(4)
end

function love.update(dt)
	if love.mouse.isDown('l') then
		mousedown = 'l'
	elseif love.mouse.isDown('r') then
		mousedown = 'r'
	elseif love.mouse.isDown('wu') then
		mousedown = 'wu'
	elseif love.mouse.isDown('wd') then
		mousedown = 'wd'
	end
	if prevy[1] == posy and prevy[2] == posy then
		wheelcolour.line = { 192, 192, 192 }
		wheelcolour.fill = { 255, 255, 255 }
	elseif prevy[1] ~= prevy[2] and prevy[1] == posy then
		wheelcolour.line = { 192, 192, 0 }
		wheelcolour.fill = { 255, 255, 0 }
	end
	prevy[2] = prevy[1]
	prevy[1] = posy
end

function love.draw()
	love.graphics.setColor(255, 255, 255)
	love.graphics.print("mousedown: " .. tostring(mousedown), 32, 32)
	love.graphics.print("mousepressed: " .. tostring(mousepressed), 32, 48)
	love.graphics.print("mousereleased: " .. tostring(mousereleased), 32, 64)
	love.graphics.setColor(wheelcolour.fill)
	love.graphics.circle('fill', 400, posy, 16, 18)
	love.graphics.setColor(wheelcolour.line)
	love.graphics.circle('line', 400, posy, 16, 18)
end

function love.mousepressed(x, y, button)
	mousepressed = button
	if button == "wu" then
		posy = posy - 1
		wheelcolour.line = { 192, 0, 0 }
		wheelcolour.fill = { 255, 0, 0 }
	elseif button == "wd" then
		posy = posy + 1
		wheelcolour.line = { 0, 192, 0 }
		wheelcolour.fill = { 0, 255, 0 }
	end
	if posy < 0 then posy = 0 elseif posy > 599 then posy = 599 end
end

function love.mousereleased(x, y, button)
	mousereleased = button
end
It shows when the wheel is activated by colour and flickers when it is slowing down.
User avatar
Boolsheet
Inner party member
Posts: 780
Joined: Wed Dec 29, 2010 4:57 am
Location: Switzerland

Re: Apple Mouse wheel not picked up

Post by Boolsheet »

Is my example code also not producing a satisfactory result? Since all you get are impulses and you have no idea what the user settings are, you kind of have to fiddle with it. Or give the user an option to change the speed.

There is no concept of "holding the scroll wheel down". SDL 1.2 jammed the scroll wheel into the mouse button event and LÖVE follows this behaviour. This is somewhat wrong and it indeed seems to confuse people. SDL 2.0 has its own separate wheel motion event for this so it's a bit cleaner.

Because the concept of holding down a scroll wheel is invalid, SDL 1.2 just fires a release event immediately after the press to make it consistent with the rest of the button events. love.mouse.isDown can never give you true for a scroll wheel because it doesn't exist.
Shallow indentations.
User avatar
DaedalusYoung
Party member
Posts: 407
Joined: Sun Jul 14, 2013 8:04 pm

Re: Apple Mouse wheel not picked up

Post by DaedalusYoung »

Your code feels a bit better while scrolling, but it doesn't handle tapping to hold very well; it always slows down gradually instead of instant stopping.

On further experimentation, it also seems to work the wrong way round, increasing speed the longer the mousewheel is spinning, while the Apple Mouse sort of works like giving it an impulse, letting the wheel spin and letting it slow down naturally. How fast this spinning starts depends on how fast you swipe the mouse. Think of it literally like moving a free spinning wheel, give it an impulse and it will spin fast and gradually slow down. Put your hand on it while it's spinning and it will stop instantly.

Of course, there is no way of knowing the initial swipe speed, unless you can accurately count the number of pulses per frame.

I'm thinking the mouse emulates this by giving a high frequency of mouse wheel pulses at first, which slows down over time until it reaches 0 (like fading LEDs is done by pulse width modulation). And especially these first pulses are not all picked up, as LÖVE only counts 1 pulse per frame (while in reality, the mouse may be giving off 10 pulses per frame). In my code, it is obvious the frequency decreases as the spinning slows down, because it flickers the colours. This is not visible for high speed spins, because there are more pulses than frames.
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 67 guests