Exemplo n.º 1
0
/* key_dinput_acquire: [window thread]
 *  Acquires the keyboard device. This must be called after a
 *  window switch for example if the device is in foreground
 *  cooperative level.
 */
int key_dinput_acquire(void)
{
   HRESULT hr;
   BYTE keystate[256];

   if (key_dinput_device) {
      /* Read the current Windows keyboard state */
      GetKeyboardState(keystate);
      update_shifts(keystate);

      hr = IDirectInputDevice_Acquire(key_dinput_device);

      if (FAILED(hr)) {
         _TRACE(PREFIX_E "acquire keyboard failed: %s\n", dinput_err_str(hr));
         return -1;
      }

      /* Initialize keyboard state */
      SetEvent(key_input_event);

      return 0;
   }
   else
      return -1;
}
Exemplo n.º 2
0
/* handle_key_release: [input thread]
 *  Does stuff when a key is released.  The keyboard event source
 *  should be locked.
 */
static void handle_key_release(unsigned char scancode)
{
   int mycode = hw_to_mycode[scancode];
   if (mycode == 0)
      return;

   {
      BYTE keystate[256];
      GetKeyboardState(keystate);
      update_shifts(keystate);
   }

   _handle_key_release(mycode);
}
Exemplo n.º 3
0
/* _al_xwin_keyboard_handler:
 *  Keyboard "interrupt" handler.
 */
void _al_xwin_keyboard_handler(XKeyEvent *event, ALLEGRO_DISPLAY *display)
{
    int keycode;

    if (!xkeyboard_installed)
        return;

    keycode = keycode_to_scancode[event->keycode];
    if (keycode == -1)
        keycode = find_unknown_key_assignment(event->keycode);

    update_shifts(event);

    /* Special case the pause key. */
    if (keycode == ALLEGRO_KEY_PAUSE) {
        /* Allegro ignore's releasing of the pause key. */
        if (event->type == KeyRelease)
            return;
        if (pause_key) {
            event->type = KeyRelease;
            pause_key = 0;
        }
        else {
            pause_key = 1;
        }
    }

    if (event->type == KeyPress) { /* Key pressed.  */
        int len;
        char buffer[16];
        int unicode = 0;
        int filtered = 0;

#if defined (ALLEGRO_XWINDOWS_WITH_XIM) && defined(X_HAVE_UTF8_STRING)
        if (xic) {
            len = Xutf8LookupString(xic, event, buffer, sizeof buffer, NULL, NULL);
        }
        else
#endif
        {
            /* XLookupString is supposed to only use ASCII. */
            len = XLookupString(event, buffer, sizeof buffer, NULL, NULL);
        }
        buffer[len] = '\0';
        ALLEGRO_USTR_INFO info;
        const ALLEGRO_USTR *ustr = al_ref_cstr(&info, buffer);
        unicode = al_ustr_get(ustr, 0);
        if (unicode < 0)
            unicode = 0;

#ifdef ALLEGRO_XWINDOWS_WITH_XIM
        ALLEGRO_DISPLAY_XGLX *glx = (void *)display;
        filtered = XFilterEvent((XEvent *)event, glx->window);
#endif
        if (keycode || unicode) {
            handle_key_press(keycode, unicode, filtered, _key_shifts, display);
        }
    }
    else { /* Key release. */
        /* HACK:
         * Detect key repeat by looking forward to see if this release is
         * followed by a press event, in which case we assume that this release
         * event was generated in response to that key press event. Events are
         * simultaneous if they are separated by less than 4 ms (a value that
         * worked well on one machine where this hack was needed).
         *
         * This is unnecessary on systems where XkbSetDetectableAutorepeat works.
         */
        if (XPending(event->display) > 0) {
            ALLEGRO_KEY_REPEAT_DATA d;
            XEvent dummy;
            d.event = event;
            d.found = false;
            XCheckIfEvent(event->display, &dummy, check_for_repeat, (XPointer)&d);
            if (d.found) {
                return;
            }
        }
        handle_key_release(keycode, display);
    }
}
Exemplo n.º 4
0
/* _xwin_keyboard_handler:
 *  Keyboard "interrupt" handler.
 */
void _xwin_keyboard_handler(XKeyEvent *event, int dga2_hack)
{
   int keycode;

   if (!xkeyboard_installed)
      return;

   if (_xwin_keyboard_callback)
      (*_xwin_keyboard_callback)(event->type == KeyPress ? 1 : 0, event->keycode);

   keycode = _xwin.keycode_to_scancode[event->keycode];
   if (keycode == -1)
      keycode = find_unknown_key_assignment(event->keycode);

   if (dga2_hack)
      dga2_update_shifts(event);
   else
      update_shifts(event);

   /* Special case the pause key. */
   if (keycode == KEY_PAUSE) {
      /* Allegro ignore's releasing of the pause key. */
      if (event->type == KeyRelease)
         return;
      if (pause_key) {
         event->type = KeyRelease;
         pause_key = 0;
      }
      else {
         pause_key = 1;
      }
   }

   if (event->type == KeyPress) { /* Key pressed.  */
      int len;
      char buffer[16];
      char buffer2[16];
      int unicode = 0, r = 0;

#if defined (ALLEGRO_XWINDOWS_WITH_XIM) && defined(X_HAVE_UTF8_STRING)
      if (xic) {
	 len = Xutf8LookupString(xic, event, buffer, sizeof buffer, NULL, NULL);
      }
      else
#endif
      {
         /* XLookupString is supposed to only use ASCII. */
	 len = XLookupString(event, buffer, sizeof buffer, NULL, NULL);
      }
      buffer[len] = '\0';
      uconvert(buffer, U_UTF8, buffer2, U_UNICODE, sizeof buffer2);
      unicode = *(unsigned short *)buffer2;

#ifdef ALLEGRO_XWINDOWS_WITH_XIM
      r = XFilterEvent((XEvent *)event, _xwin.window);
#endif
      if (keycode || unicode) {
	 /* If we have a keycode, we want it to go to Allegro immediately, so the
	  * key[] array is updated, and the user callbacks are called. OTOH, a key
	  * should not be added to the keyboard buffer (parameter -1) if it was
          * filtered out as a compose key, or if it is a modifier key.
	  */
	 if (r || keycode >= KEY_MODIFIERS)
	    unicode = -1;
	 else {
	    /* Historically, Allegro expects to get only the scancode when Alt is
	     * held down.
	     */
	    if (_key_shifts & KB_ALT_FLAG)
	       unicode = 0;
         }

	 _handle_key_press(unicode, keycode);

         /* Detect Ctrl-Alt-End. */
         if (keycode == KEY_END && (_key_shifts & KB_CTRL_FLAG) &&
            (_key_shifts & KB_ALT_FLAG) && (three_finger_flag))
         {
         #ifndef ALLEGRO_HAVE_LIBPTHREAD
            if (_unix_bg_man == &_bg_man_sigalrm) {
               _sigalrm_request_abort();
            }
            else
         #endif
            {
               TRACE(PREFIX_W "Three finger combo detected. SIGTERMing "
                     "pid %d\n", main_pid);
               kill(main_pid, SIGTERM);
            }
         }
      }
   }
   else { /* Key release. */
      _handle_key_release(keycode);
   }
}
Exemplo n.º 5
0
/* handle_key_press: [input thread]
 *  Does stuff when a key is pressed.
 */
static void handle_key_press(unsigned char scancode)
{
   int mycode;
   int unicode;
   int n;
   UINT vkey;
   BYTE keystate[256];
   WCHAR chars[16];

   vkey = MapVirtualKey(scancode, 1);

   GetKeyboardState(keystate);
   update_shifts(keystate);

   /* TODO: shouldn't we base the mapping on vkey? */
   mycode = hw_to_mycode[scancode];
   if (mycode == 0)
      return;

   /* MapVirtualKey always returns the arrow key VKEY, so adjust
      it if num lock is on */
   if (keystate[VK_NUMLOCK]) {
      switch (scancode) {
         case DIK_NUMPAD0:
            vkey = VK_NUMPAD0;
            break;
         case DIK_NUMPAD1:
            vkey = VK_NUMPAD1;
            break;
         case DIK_NUMPAD2:
            vkey = VK_NUMPAD2;
            break;
         case DIK_NUMPAD3:
            vkey = VK_NUMPAD3;
            break;
         case DIK_NUMPAD4:
            vkey = VK_NUMPAD4;
            break;
         case DIK_NUMPAD5:
            vkey = VK_NUMPAD5;
            break;
         case DIK_NUMPAD6:
            vkey = VK_NUMPAD6;
            break;
         case DIK_NUMPAD7:
            vkey = VK_NUMPAD7;
            break;
         case DIK_NUMPAD8:
            vkey = VK_NUMPAD8;
            break;
         case DIK_NUMPAD9:
            vkey = VK_NUMPAD9;
            break;
         case DIK_DECIMAL:
            vkey = VK_DECIMAL;
            break;
     }
   }

   /* what's life without a few special cases */
   switch (scancode) {
      case DIK_DIVIDE:
         vkey = VK_DIVIDE;
         break;
      case DIK_MULTIPLY:
         vkey = VK_MULTIPLY;
         break;
      case DIK_SUBTRACT:
         vkey = VK_SUBTRACT;
         break;
      case DIK_ADD:
         vkey = VK_ADD;
         break;
      case DIK_NUMPADENTER:
         vkey = VK_RETURN;
   }

   /* TODO: is there an advantage using ToUnicode? maybe it would allow
    * Chinese and so on characters? For now, always ToAscii is used. */
   //n = ToUnicode(vkey, scancode, keystate, chars, 16, 0);
   n = ToAscii(vkey, scancode, keystate, (WORD *)chars, 0);
   if (n == 1)
   {
      WCHAR wstr[2];
      MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPCSTR)chars, n, wstr, 2);
      unicode = wstr[0];
   }
   else
   {
      /* Don't generate key presses for modifier keys or dead keys */
      if (mycode >= KEY_MODIFIERS || n != 0)
	 unicode = -1;
      else
	 unicode = 0;
   }

   /* When alt key is pressed, any key always must return ASCII 0 in Allegro. */
   if (unicode > 0 && (keystate[VK_LMENU] & 0x80)) {
      unicode = 0;
   }

   _handle_key_press(unicode, mycode);
}