Wrecked Games

Please login or register.

Login with username, password and session length
Advanced search  

News:

We're just that awesome.

Author Topic: keyReleased not called on alt-tab  (Read 1353 times)

Rakkar

  • Newbie
  • *
  • Karma: +0/-0
  • Posts: 7
    • View Profile
keyReleased not called on alt-tab
« on: March 07, 2007, 08:23:26 PM »

If I press a key, hit alt-tab with the key held down, release the key, and then switch back, the event callback keyReleased is not called.

What should I do?

Code: [Select]

void InputManager::Startup(void *customStartupData)
{
HWND     hWnd = (HWND) customStartupData;
OIS::ParamList pl;
std::ostringstream wnd;
wnd << (size_t)hWnd;
pl.insert(std::make_pair( std::string("WINDOW"), wnd.str() ));

im = OIS::InputManager::createInputSystem(pl);
keyboard = (OIS::Keyboard*)im->createInputObject( OIS::OISKeyboard, true );
if (keyboard)
keyboard->setEventCallback(this);

...
Logged

pjcast

  • Administrator
  • Veteran
  • *****
  • Karma: +1/-0
  • Posts: 2661
    • View Profile
    • http://www.wreckedgames.com
keyReleased not called on alt-tab
« Reply #1 on: March 07, 2007, 08:46:04 PM »

OIS does not currently handle that very elegently. So, I would imagine a 'stuck' key would of course be the result.

I think, all that needs to be done, is in the DirectInput Keyboard class, simply set a flag variable when the capture() method fails to acquire the keyboard the first time... and when an acquire is successful, after all events are processed, grab the exact keyboard state, and compare with percieved state, and fire off events for items that differ. Of course, this would require that applications are calling caputre() even when not focused (to cause acquire to fail). And, if the app does not call capture(), this trick wouldn't work. Maybe a new method is needed instead... something like verifyState() which could be called by the application when it knows it returned from a lost focus.

Anyway, I can't make any promises on when I can implement this.. I have real life work priorities right now, as well as some prior wiimote obligations. A patch is welcome if you think you can solve it, and have the time. Besides that, your app can also reset its own percieved states - reset any thing the app thought was held down, and just wait for another keydown event. Anyway, alt-tab problems are best solved by not alt-tabbing  :lol: (if only it was that easy)
Logged

Rakkar

  • Newbie
  • *
  • Karma: +0/-0
  • Posts: 7
    • View Profile
keyReleased not called on alt-tab
« Reply #2 on: March 07, 2007, 09:43:39 PM »

This seems to work

Code: [Select]

void Win32Keyboard::_readBuffered()
{
DIDEVICEOBJECTDATA diBuff[KEYBOARD_DX_BUFFERSIZE];
DWORD entries = KEYBOARD_DX_BUFFERSIZE;
HRESULT hr;

// KevinJ - Set to true after we alt-tab
static bool verifyAfterAltTab=false;

hr = mKeyboard->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
if( hr != DI_OK )
{
hr = mKeyboard->Acquire();
// KevinJ - E_ACCESSDENIED is returned when I alt-tab.  Maybe other stuff is returned too?
if (hr==E_ACCESSDENIED)
verifyAfterAltTab=true;
while( hr == DIERR_INPUTLOST )
hr = mKeyboard->Acquire();
return;
}

if( FAILED(hr) )
OIS_EXCEPT( E_General, "Win32Keyboard::_readBuffered() >> Problem with Device!" );

//Update keyboard and modifier states.. And, if listener, fire events
for(unsigned int i = 0; i < entries; ++i )
{
//If the listener returns false, that means that we are probably deleted...
//send no more events and just leave as the this pointer is invalid now...
bool ret = true;
KeyCode kc = (KeyCode)diBuff[ i ].dwOfs;

//Store result in our keyBuffer too
KeyBuffer[kc] = static_cast<unsigned char>(diBuff[ i ].dwData);

if( diBuff[ i ].dwData & 0x80 )
{
//Turn on modifier
if( kc == KC_LCONTROL || kc == KC_RCONTROL )
mModifiers |= Ctrl;
else if( kc == KC_LSHIFT || kc == KC_RSHIFT )
mModifiers |= Shift;
else if( kc == KC_LMENU || kc == KC_RMENU )
mModifiers |= Alt;

if( listener )
ret = listener->keyPressed( KeyEvent( this, diBuff[i].dwTimeStamp, kc, _translateText(kc) ) );
}
else
{
//Turn off modifier
if( kc == KC_LCONTROL || kc == KC_RCONTROL )
mModifiers &= ~Ctrl;
else if( kc == KC_LSHIFT || kc == KC_RSHIFT )
mModifiers &= ~Shift;
else if( kc == KC_LMENU || kc == KC_RMENU )
mModifiers &= ~Alt;

//Fire off event
if( listener )
ret = listener->keyReleased( KeyEvent( this, diBuff[i].dwTimeStamp, kc, 0 ) );
}

if(ret == false)
break;
}

// KevinJ - Check the buffer against the current keystate, and send events where it is wrong
if (verifyAfterAltTab==true)
{
bool ret = true;
unsigned char keyBufferCopy[256];
memcpy(keyBufferCopy, KeyBuffer, 256);
_read();
unsigned i;
for (i=0; i < 256; i++)
{
if (keyBufferCopy[i]!=KeyBuffer[i])
{
if (listener)
{
if (KeyBuffer[i])
ret = listener->keyPressed( KeyEvent( this, 0, (KeyCode)i, _translateText((KeyCode)i) ) );
else
ret = listener->keyReleased( KeyEvent( this, 0, (KeyCode)i, 0 ) );

}
}

if(ret == false)
break;
}
verifyAfterAltTab=false;
}
}
Logged

pjcast

  • Administrator
  • Veteran
  • *****
  • Karma: +1/-0
  • Posts: 2661
    • View Profile
    • http://www.wreckedgames.com
keyReleased not called on alt-tab
« Reply #3 on: March 07, 2007, 11:35:02 PM »

Cool, looks ok to me. And since you say it works ok for you, I don't have a problem adding it in.. since it only causes an extra copy(s) when device lost/restored, so not a big deal. I'll add it in when I get back to OIS next week or so. Thanks.
Logged

Rakkar

  • Newbie
  • *
  • Karma: +0/-0
  • Posts: 7
    • View Profile
keyReleased not called on alt-tab
« Reply #4 on: March 08, 2007, 12:32:41 AM »

Great.  The only thing you might want to look at is

Code: [Select]

ret = listener->keyPressed( KeyEvent( this, 0, (KeyCode)i, _translateText((KeyCode)i) ) );


I passed 0 for the timer, because it wasn't worth the bother to look up the current time.  But that ought to be done for correctness.  I'm also not sure if it will work for all languages for (KeyCode)i - there must be a reason they did that, and I'm guessing language translation is it.  It works for me though, and since I'm only supporting English until after I launch it's good enough.
Logged

pjcast

  • Administrator
  • Veteran
  • *****
  • Karma: +1/-0
  • Posts: 2661
    • View Profile
    • http://www.wreckedgames.com
keyReleased not called on alt-tab
« Reply #5 on: March 08, 2007, 06:53:39 AM »

I'll look into it. As for the timer, it is not used in OIS anymore, and no longer exposed. In fact, it was 0 on some systems, since its was rarely even used by most people.
Logged

CaseyB

  • Regular
  • *
  • Karma: +0/-0
  • Posts: 31
    • View Profile
keyReleased not called on alt-tab
« Reply #6 on: May 04, 2007, 08:18:34 AM »

We are having a similar issue with ctrl-alt-delete.  We never get the keyReleased so we never clear our modifier list.  Has this fix been added to OIS and should testing for E_ACCESSDENIED also work for ctrl-alt-delete?
Logged

pjcast

  • Administrator
  • Veteran
  • *****
  • Karma: +1/-0
  • Posts: 2661
    • View Profile
    • http://www.wreckedgames.com
keyReleased not called on alt-tab
« Reply #7 on: May 04, 2007, 09:55:01 AM »

Ah, forgot about this :(

I will be adding this as well as some other things tonight/this weekend. Not sure what E_ACCESSDENIED is for.

Edit - nm, I see where the access denied thingy is :) I'll be adding this to 1.0 branch right now.. not sure how it would work with ctrl-alt-delete.
« Last Edit: May 20, 2007, 05:34:07 PM by pjcast »
Logged

pjcast

  • Administrator
  • Veteran
  • *****
  • Karma: +1/-0
  • Posts: 2661
    • View Profile
    • http://www.wreckedgames.com
Re: keyReleased not called on alt-tab
« Reply #8 on: May 20, 2007, 05:49:00 PM »

Ok, this is fixed in 1.0 branch of CVS... I will be preparing an official 1.0 release this week!!!  :o :)
Logged