Page 1 of 1

[SOLVED] love.window.setMode() "releases" all keys?

Posted: Tue Nov 06, 2018 2:02 pm
by LuaIsLife
Hi there,

Just a quick question.. is it a known behaviour that love.window.setMode()
resets the state of the keys of the keyboard, aka love.keyboard.isDown() returns false and love.keyreleased()
gets fired for all keys?

I have some code where I reset some window properties via love.window.setMode() and this "window reset" is triggered
via a keycombo.

I noticed that after the setMode() call every key is "released" (they are definitely not, they are still pressed down),
the callback "keyreleased" was fired as my debug code showed to me and isDown() resulted in "false" for the key in question.

It's not a big deal, but I was scratching my head for some minutes what has been triggering this.. so, is this intended behaviour?

(No example code yet because my code is bad for copy&paste.. but could provide one if needed.)

Re: love.window.setMode() "releases" all keys?

Posted: Tue Nov 06, 2018 2:07 pm
by pgimeno
I've had a similar problem, especially annoying when toggling fullscreen mode because it causes double keypresses.

Edit: Simple repro:

Code: Select all

local full

function love.keypressed(k)
  if k == "space" then
    full = not full
    love.window.setMode(800, 600, {fullscreen=full})
  end
  if k == "escape" then return love.event.quit() end
end

function love.draw()
  love.graphics.print("Press space to toggle fullscreen mode")
end
It will keep going while space is pressed.

Re: love.window.setMode() "releases" all keys?

Posted: Tue Nov 06, 2018 2:32 pm
by LuaIsLife
Thanks.. so now easy fix at the time being?

Re: love.window.setMode() "releases" all keys?

Posted: Tue Nov 06, 2018 3:50 pm
by slime
There's no easy complete fix, but a really simple workaround is to only call setMode in keyreleased instead of keypressed.

Re: love.window.setMode() "releases" all keys?

Posted: Tue Nov 06, 2018 4:06 pm
by pgimeno
I presume it's a consequence of destroying and recreating the window, as the keypresses are associated to a window.

Here's a workaround I could think of:

Code: Select all

local function setMode(...)
  love.window.setMode(...)
  love.event.pump()
  local f = love.event.poll()
  local evs = {}
  local nevs = 0
  repeat
    nevs = nevs + 1
    evs[nevs] = {f()}
  until evs[nevs][1] == nil
  nevs = nevs - 1
  local keyevs = {}
  local i = 1
  while i <= nevs do
    if evs[i][1] == 'keyreleased' and not keyevs[evs[i][3]] then
      keyevs[evs[i][3]] = i
      i = i + 1
    elseif evs[i][1] == 'keypressed' and keyevs[evs[i][3]] then
      local k = evs[i][3]
      table.remove(evs, i)
      table.remove(evs, keyevs[k])
      keyevs[k] = nil
      nevs = nevs - 2
      i = i - 1
    else
      i = i + 1
    end
  end
  for i = 1, nevs do
    love.event.push(unpack(evs[i]))
  end
end
The idea is to gather all events into a table immediately after calling love.window.setMode, and if a pair keyreleased/keypressed with the same scancode is found, remove both from the list of events. When done, push all remaining events back into the queue.

Edit: Fixed a little bug above. Note that it still generates textinput events, though, but I don't think it's likely that your program changes mode while processing textinput events.

Re: love.window.setMode() "releases" all keys?

Posted: Tue Nov 06, 2018 5:13 pm
by zorg
Another solution would be to "stage" changes into variables, and only apply screen changes when you're not expecting any more input... like pressing/clicking on an "apply" button in an options menu like most games do it.

Re: love.window.setMode() "releases" all keys?

Posted: Wed Nov 07, 2018 7:10 am
by LuaIsLife
pgimeno wrote: Tue Nov 06, 2018 4:06 pm I presume it's a consequence of destroying and recreating the window, as the keypresses are associated to a window.
That has been my guess too... it's not too important to me, just something I noticed that MAY become important later on..

Thanks a ton for the support!

I am surprised how helpful this community is.. it's like löve and lua itself, small but "no bullshit" and "to the point" in a way.