Пример #1
0
static void
flushKeyEvents (KeyboardInstanceObject *kio) {
  const KeyEventEntry *event = kio->events.buffer;

  while (kio->events.count) {
    logKeyEvent("flushing", event->code, event->press);
    forwardKeyEvent(kio, event->code, event->press);

    event += 1;
    kio->events.count -= 1;
  }

  memset(kio->deferred.mask, 0, kio->deferred.size);
  kio->deferred.modifiersOnly = 0;
}
Пример #2
0
LRESULT CALLBACK keyevent(int code, WPARAM wparam, LPARAM lparam)
{
	static bool shiftPressed = false;
	static bool mod3Pressed = false;
	static bool mod4Pressed = false;

	KBDLLHOOKSTRUCT keyInfo;
	if (code == HC_ACTION
	    && (wparam == WM_SYSKEYUP || wparam == WM_KEYUP || wparam == WM_SYSKEYDOWN
		|| wparam == WM_KEYDOWN)) {
		keyInfo = *((KBDLLHOOKSTRUCT *) lparam);

		if (keyInfo.flags & LLKHF_INJECTED) {	// process injected events like normal, because most probably we are injecting them
			logKeyEvent("injected", keyInfo);
			return CallNextHookEx(NULL, code, wparam, lparam);
		}
	}

	if (bypassMode)
		return CallNextHookEx(NULL, code, wparam, lparam);

	if (code == HC_ACTION && (wparam == WM_SYSKEYUP || wparam == WM_KEYUP)) {
		logKeyEvent("key up", keyInfo);

		if (isShift(keyInfo)) {
			shiftPressed = false;
			keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
			return -1;
		} else if (isMod3(keyInfo)) {
			mod3Pressed = false;
			return -1;
		} else if (isMod4(keyInfo)) {
			mod4Pressed = false;
			return -1;
		}
	}

	else if (code == HC_ACTION && (wparam == WM_SYSKEYDOWN || wparam == WM_KEYDOWN)) {
		logKeyEvent("key down", keyInfo);

		unsigned level = 1;
		if (shiftPressed)
			level = 2;
		if (mod3Pressed)
			level = 3;
		if (mod4Pressed)
			level = 4;

		if (isShift(keyInfo)) {
			shiftPressed = true;
			keybd_event(VK_SHIFT, 0, 0, 0);
			return -1;
		} else if (isMod3(keyInfo)) {
			mod3Pressed = true;
			return -1;
		} else if (isMod4(keyInfo)) {
			/* ALTGR triggers two keys: LCONTROL and RMENU
			   we don't want to have any of those two here effective but return -1 seems 
			   to change nothing, so we simply send keyup here.  */
			keybd_event(VK_RMENU, 0, KEYEVENTF_KEYUP, 0);	
			mod4Pressed = true;
			return -1;
		} else if (level == 1 && handleLayer1SpecialCases(keyInfo)) {
			return -1;
		} else if (level == 4 && handleLayer4SpecialCases(keyInfo)) {
			return -1;
		} else {
			TCHAR key = mapScanCodeToChar(level, keyInfo.scanCode);
			if (key != 0 && (keyInfo.flags & LLKHF_INJECTED) == 0) {
				// if key must be mapped
				printf("Mapped %d->%c (level %u)\n", keyInfo.scanCode, key, level);
				//BYTE state[256];
				//GetKeyboardState(state);
				sendChar(key, keyInfo);
				//SetKeyboardState(state);
				return -1;
			}
		}
	}
	return CallNextHookEx(NULL, code, wparam, lparam);
}
Пример #3
0
void
handleKeyEvent (KeyboardInstanceObject *kio, int code, int press) {
  KeyTableState state = KTS_UNBOUND;

  logKeyEvent("received", code, press);

  if (kio->kmo->isActive) {
    if ((code >= 0) && (code < keyCodeCount)) {
      const KeyValue *kv = &keyCodeMap[code];

      if ((kv->group != KBD_GROUP(SPECIAL)) || (kv->number != KBD_KEY(SPECIAL, Unmapped))) {
        if ((kv->group == KBD_GROUP(SPECIAL)) && (kv->number == KBD_KEY(SPECIAL, Ignore))) return;
        state = kio->kmo->handleKeyEvent(kv->group, kv->number, press);
      }
    }
  }

  if (state == KTS_HOTKEY) {
    logKeyEvent("ignoring", code, press);
  } else {
    typedef enum {
      WKA_NONE,
      WKA_CURRENT,
      WKA_ALL
    } WriteKeysAction;
    WriteKeysAction action = WKA_NONE;

    if (press) {
      kio->deferred.modifiersOnly = state == KTS_MODIFIERS;

      if (state == KTS_UNBOUND) {
        action = WKA_ALL;
      } else {
        if (kio->events.count == kio->events.size) {
          unsigned int newSize = kio->events.size? kio->events.size<<1: 0X1;
          KeyEventEntry *newBuffer = realloc(kio->events.buffer, (newSize * sizeof(*newBuffer)));

          if (newBuffer) {
            kio->events.buffer = newBuffer;
            kio->events.size = newSize;
          } else {
            logMallocError();
          }
        }

        if (kio->events.count < kio->events.size) {
          KeyEventEntry *event = &kio->events.buffer[kio->events.count++];

          event->code = code;
          event->press = press;
          BITMASK_SET(kio->deferred.mask, code);

          logKeyEvent("deferring", code, press);
        } else {
          logKeyEvent("discarding", code, press);
        }
      }
    } else if (kio->deferred.modifiersOnly) {
      kio->deferred.modifiersOnly = 0;
      action = WKA_ALL;
    } else if (BITMASK_TEST(kio->deferred.mask, code)) {
      KeyEventEntry *to = kio->events.buffer;
      const KeyEventEntry *from = to;
      unsigned int count = kio->events.count;

      while (count) {
        if (from->code == code) {
          logKeyEvent("dropping", from->code, from->press);
        } else if (to != from) {
          *to++ = *from;
        } else {
          to += 1;
        }

        from += 1, count -= 1;
      }

      kio->events.count = to - kio->events.buffer;
      BITMASK_CLEAR(kio->deferred.mask, code);
    } else {
      action = WKA_CURRENT;
    }

    switch (action) {
      case WKA_ALL:
        flushKeyEvents(kio);

      case WKA_CURRENT:
        logKeyEvent("forwarding", code, press);
        forwardKeyEvent(kio, code, press);

      case WKA_NONE:
        break;
    }
  }
}