wgois / OIS

Official OIS repository. Object oriented Input System
https://wgois.github.io/OIS/
zlib License
254 stars 86 forks source link

No Keyboard Input on Cocoa OSX. #51

Closed VENTDEV closed 5 years ago

VENTDEV commented 5 years ago

Describe the bug I'm converting my Ogre3D based Carbon program over to a Cocoa program. My program is ran via a single thread main while() loop. OIS Mouse and Keyboard capture is in this loop. The mouse inputs work fine, but there is no keyboard input.

Seeing how Cocoa uses an event system, I took it that I needed to run the loop as a timer. My attempts at setting up a timer failed because Objective-C and me disagree. However I was able to get the event system to work in a do-while loop. Similar to how SDL, firefox, qt,wx etc do it with nextEventMatchingMask/sendEvent. The Main loop calls the input loop, the input loop nextEventMatchingMask/sendEvent's and loops while there is events. If there is an event, I call OIS mouse and keyboard capture.

The mouse works great. But once again, OIS fails to get any keyboard input. I can check the Cocoa event to see that there is a keydown. It dumps to log. But if I uncomment OIS's logging in CocoaKeyboard.mm KeyDown(NSEvent*)theEvent it does get that far with the proper characters.

To Reproduce Eaisest way to duplicate my issue is to run http://wiki.ogre3d.org/Advanced+Ogre+Framework in Ogre 1.10.12 using Cocoa. Add the following function to the AppStateManager::Start function, just inside the while loop and remove the existing ois captures and call this function.

void  AppStateManager::osxLoop()
{
    @autoreleasepool
    {
        NSEvent* ev;
        do
        {
            ev = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES];

            if(ev)
            {
               if([ev type] == NSKeyDown)
                {

                       OF::getSingletonPtr()->m_pLog->logMessage("Cocoa Key Down");
                }

                OF::getSingletonPtr()->m_pMouse->capture();
                OF::getSingletonPtr()->m_pKeyboard->capture();
                [NSApp sendEvent: ev];
            }
        }
        while(ev);
    }
}

Alternatively, if you just want to look at the stock driving code, you can find that here: http://wiki.ogre3d.org/Advanced+Ogre+Framework#AppStateManager.cpp

The main loop is in Start().

Expected behavior OSX to read the keydowns.

Platform (please complete the following information):

Additional context If there is a way to directly inject osx keyup and keydown events. That'd be a temporary work around. I may end up doing that in leu of a solution. Also if there is a way I must run my main loop in cocoa, that would be helpful information too.

VENTDEV commented 5 years ago

Upon additional testing, it seems that OIS keyboard works when it is only stuck in my do/while loop but not when it's in my main while loop. So most likely this is all cocoa thread locking silliness. I will see if I can get a timer dependent loop working.

VENTDEV commented 5 years ago

Just an update, I finally got a working NStimer system going. But it did not help. Mouse input still worked, keyboard did not. I returned to manual do/while loop. On occasion, OIS would work with this, but sometimes it would not. At all times, my nextEventMatchingMask was able to get input, with proper virtual keys.

So I made a hackish work around to directly inject these NSEvent's into OIS, inside OIS it sends it to [keyUp] or [keyDown] respectively. And now everything is working fine again. Except when occasionally OIS works properly, then I get two keys for every key press. I will hack out OIS's ability to work properly to fix that.

Anyway, my work around is fine for what I need it for. I am still interested in a proper solution though, so if you get one working, I am all ears. And if I come across one later, I will let you know.

VENTDEV commented 5 years ago

Update on progress for this issue.

Unfortunately for me, SDL2 conflicted with CEF on OS X. So I switched window handling to GLFW. GLFW uses a CVDisplayLinkStart loop if I am not mistaken. In any case, you have to use their polling event to drive the cocoa window and this conflicted with the above manual loop I created. However, all OIS function work perfectly fine from this type of loop. The only issue I am having now is mouse drag does not work unless you alt-tab out and then back in, but I am not sure if that is an OIS or an issue with my "app" start up.

Anyway, I am marking this issue as closed. Moral of the story, use the CVDisplayLink system to drive Cocoa and OIS will work fine. :)