Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: OSX Mavericks - isKeyPressed is broken.  (Read 2602 times)

0 Members and 1 Guest are viewing this topic.

escher

  • Newbie
  • *
  • Posts: 8
    • View Profile
OSX Mavericks - isKeyPressed is broken.
« on: December 09, 2013, 08:28:15 pm »
I've seen this mentioned a couple places, but nowhere with a resolution, or even more information.

I have a fairly basic framework that I just started putting together. At this point, it has sprite rendering and some input recognition and that's about it. Out of the blue, it will start segfaulting as soon as it's run, even without changing any code from a functional build. However, once it segfaults once, ANY program that I build with SFML using isKeyPressed will segfault until a reboot. The error log is at http://pastebin.com/6BM96ULt.

I'd paste the whole framework, but the problem is I have a hard time trimming everything out and finding the truly minimal case, since it requires a reboot each time. If we're at a standstill otherwise, I'll spend a couple hours going through that, though.

And, for the record, when I say any program, I truly mean any program. The following causes an isKeyPressed segfault upon launching:

Code: [Select]
#include <SFML/Graphics.hpp>

int main(int argc, char const** argv)
{
    sf::RenderWindow __window;
    __window.create(sf::VideoMode(800, 600), "Crash Test");

    while (__window.isOpen())
    {
        sf::Event event;
        while (__window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed) __window.close();
        }

        if ( sf::Keyboard::isKeyPressed(sf::Keyboard::Q) ) {
            // CRASH
        }
    }
   
    return EXIT_SUCCESS;
}

Any help or information would be greatly appreciated. I haven't found any frameworks I like as much as SFML, but I'm quite close to dropping it and trying another option at this point.

EDIT: Oh, and for what it's worth, I'm using clang from the command line. Also, I've tried it with both the frameworks and the dylibs.

EDIT 2: Not sure why I didn't think of it before, but just to be sure I tested building with gcc, and the same thing occurs.

EDIT 3: Just rebuilt SFML from the latest on github, thinking I might have had an outdated copy without the fix at https://github.com/SFML/SFML/commit/d77f2419383619506fba36b7d6ab93f96e86127f (even though I'm on a laptop with a connected keyboard and mouse). However, it still occurs in the exact same way.
« Last Edit: December 10, 2013, 06:41:43 pm by escher »

escher

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: OSX Mavericks segfault on isKeyPressed
« Reply #1 on: December 10, 2013, 04:00:03 pm »
I think I may have hit upon the solution.

When I rebuilt from the latest, I didn't realize that it wasn't making the dylibs. I thought that the SFML_BUILD_FRAMEWORKS would do both the frameworks AND the dylibs, but that was apparently wrong. So, when I was doing the make and make install, it wasn't actually updating what I was building against. I noticed this and switched my build script back over to frameworks, and it looks like the latest patch works.

Because it was randomly dying in the past, I'm not 100% certain that it's cleared up, but it was in a broken state and now isn't, so that's a pretty good indication.

escher

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: OSX Mavericks segfault on isKeyPressed
« Reply #2 on: December 10, 2013, 08:00:52 pm »
Sadly, it looks like my hope was premature. It wasn't crashing, but I didn't actually test any of the keyboard functionality. It turns out it's still completely broken and not reading any keypresses.

After some debugging, I've determined that the relevant code is from /src/SFML/Window/OSX/HIDInputManager.mm:

Code: [Select]
bool HIDInputManager::isPressed(IOHIDElements& elements)
{
    if (!m_isValid) {
        sf::err() << "HIDInputManager is invalid." << std::endl;
        return false;
    }

    // state = true if at least one corresponding HID button is pressed
    bool state = false;

    for (IOHIDElements::iterator it = elements.begin(); it != elements.end();) {

        IOHIDValueRef value = 0;

        IOHIDDeviceRef device = IOHIDElementGetDevice(*it);
        IOHIDDeviceGetValue(device, *it, &value);

        if (!value) {

            sf::err() << "here." << std::endl;

            // This means some kind of error / disconnection so we remove this
            // element from our buttons

            CFRelease(*it);
            it = elements.erase(it);

        } else if (IOHIDValueGetIntegerValue(value) == 1) {

            sf::err() << "there." << std::endl;

            // This means the button is pressed
            state = true;
            break; // Stop here

        } else {

            sf::err() << "else." << std::endl;

            // This means the button is released
            ++it;
        }

    }

    return state;
}

As you can see, I'm just throwing some debugging lines, since the documentation on Apple's side of this seems to be all but non-existent (or I'm just inept at finding it), which makes it really hard for me to come in completely fresh and get any useful information.

However, with this setup, on the first run (and any subsequent ones that work), I get hundreds of "else" printouts on startup (as expected, since it's in the main loop). Once it enters the broken state, the keyboard no longer works at all until a reboot, and upon startup I get exactly seven "here" printouts.

EDIT: Well, the seven "here" printouts corresponds to the 7 places I call sf::Keyboard::isKeyPressed() in my main loop. Each one corresponds to the first time I call isKeyPressed for a given key. If I have if ( sf::Keyboard::isKeyPressed(sf::Keyboard::Q) ) {} twice, for example, it'll only give me the error printout once. I was thinking the IOHIDDeviceRef was a keyboard, so I was a little confused about why there were a bunch of them, but it looks like it's actually a key.

Also, for the record, the mouse seems to behave just fine. sf::Mouse::isButtonPressed() hasn't ever acted up.
« Last Edit: December 11, 2013, 09:36:01 pm by escher »

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
Re: OSX Mavericks - isKeyPressed is broken.
« Reply #3 on: December 24, 2013, 09:25:45 am »
I answer your PM here so that (hopefully) more people can get involved since I've got nearly zero free time these days.

Some documentation with Xcode, under OS X 10.9 doc set > Drivers, Kernel, & Hardware > User-Space Device Access > Reference > IOHID* Reference.

There is also https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Intro/AH_Intro.html and https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Device_Access_IOKit/AH_Device_Access_IOKit.html

Unfortunately, this is so low level that there is barely any example on the web. I think SDL2 doesn't use it at all (and is less precise regarding the keyboard state).
« Last Edit: December 24, 2013, 09:27:48 am by Hiura »
SFML / OS X developer

escher

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: OSX Mavericks - isKeyPressed is broken.
« Reply #4 on: December 27, 2013, 05:41:06 am »
I actually looked into SDL2 (and other frameworks) to see if I could figure out what was different in the keyboard access. I couldn't find anywhere else that used this ultra low level stuff, which is a double-edged sword. I think you're right that it'll result in more precision, but it also means some uncharted territory.

Anyway, using some sample code from https://developer.apple.com/library/Mac/samplecode/HID_Dumper/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008869, I was able to get a bunch of dumped information for each IOHIDElement inside the device. I ran it in both states and compared the output, but I wasn't able to see anything different other than memory addresses (which vary between every run). There still might be something that I'm missing, though.

Dumping the information on the IOHIDDevice requires a bit more work to get it put into SFML, but I'm going to see what (if anything) I can figure out on that front over the next few days.

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
Re: OSX Mavericks - isKeyPressed is broken.
« Reply #5 on: December 28, 2013, 07:08:53 pm »
I quickly installed 10.9 on an external drive (don't have time yet to update my working environment) to see what's going on but was not able to reproduce the problem. :-/

For reference, ~4 years ago I wrote this small project to understand how HID works. You can have a look if you want here: http://sdrv.ms/1hM94k5
SFML / OS X developer