/* Shift, Ctrl, Alt and Sym key press and release handlers */ void Tohkbd::handleShiftChanged() { checkDoWeNeedBacklight(); if (keymap->shiftPressed && capsLockSeq == 0) /* Shift pressed first time */ capsLockSeq = 1; else if (!keymap->shiftPressed && capsLockSeq == 1) /* Shift released */ capsLockSeq = 2; else if (keymap->shiftPressed && capsLockSeq == 2) /* Shift pressed 2nd time */ { capsLockSeq = 3; uinputif->sendUinputKeyPress(KEY_CAPSLOCK, 1); QThread::msleep(KEYREPEAT_RATE); uinputif->sendUinputKeyPress(KEY_CAPSLOCK, 0); uinputif->synUinputDevice(); tca8424->setLeds(LED_CAPSLOCK_ON); printf("CapsLock on\n"); } else if (keymap->shiftPressed && capsLockSeq == 3) /* Shift pressed 3rd time */ { capsLockSeq = 0; uinputif->sendUinputKeyPress(KEY_CAPSLOCK, 1); QThread::msleep(KEYREPEAT_RATE); uinputif->sendUinputKeyPress(KEY_CAPSLOCK, 0); uinputif->synUinputDevice(); tca8424->setLeds(LED_CAPSLOCK_OFF); printf("CapsLock off\n"); } }
void Tohkbd::handleCtrlChanged() { controlLeds(true); checkDoWeNeedBacklight(); uinputif->sendUinputKeyPress(KEY_LEFTCTRL, keymap->ctrl->pressed ? 1 : 0); QThread::msleep(KEYREPEAT_RATE); uinputif->synUinputDevice(); }
void Tohkbd::handleSymChanged() { checkDoWeNeedBacklight(); if ((capsLockSeq == 1 || capsLockSeq == 2)) /* Abort caps-lock if other key pressed */ capsLockSeq = 0; if (keymap->stickySymEnabled) { tca8424->setLeds(keymap->symPressed ? LED_SYMLOCK_ON : LED_SYMLOCK_OFF); /* TODO: Fix correct led when such is in HW */ } }
/* Shift, Ctrl, Alt and Sym key press and release handlers */ void Tohkbd::handleShiftChanged() { /* Release capslock if shift is pressed, to aVOID tHIS */ if (capsLock && keymap->shift->pressed) toggleCapsLock(); controlLeds(true); checkDoWeNeedBacklight(); uinputif->sendUinputKeyPress(KEY_LEFTSHIFT, keymap->shift->pressed ? 1 : 0); QThread::msleep(KEYREPEAT_RATE); uinputif->synUinputDevice(); }
void Tohkbd::handleCtrlChanged() { checkDoWeNeedBacklight(); if ((capsLockSeq == 1 || capsLockSeq == 2)) /* Abort caps-lock if other key pressed */ capsLockSeq = 0; printf("ctrl changed %s\n", keymap->ctrlPressed ? "down" : "up"); if (keymap->stickyCtrlEnabled) { tca8424->setLeds(keymap->ctrlPressed ? LED_SYMLOCK_ON : LED_SYMLOCK_OFF); /* TODO: Fix correct led when such is in HW */ } }
void Tohkbd::handleAltChanged() { controlLeds(true); checkDoWeNeedBacklight(); uinputif->sendUinputKeyPress(KEY_LEFTALT, keymap->alt->pressed ? 1 : 0); QThread::msleep(KEYREPEAT_RATE); uinputif->synUinputDevice(); if (!keymap->alt->pressed && taskSwitcherVisible) { /* hide taskswitcher when alt is released * this will also activate selected application */ tohkbd2user->hideTaskSwitcher(); taskSwitcherVisible = false; } }
/* Handle state change of phone display * Turn keyboard backlight on and off */ void Tohkbd::handleDisplayStatus(const QDBusMessage& msg) { QList<QVariant> args = msg.arguments(); const char *turn = qPrintable(args.at(0).toString()); printf("Display status changed to \"%s\"\n", turn); if (strcmp(turn, "on") == 0) { controlLeds(true); checkDoWeNeedBacklight(); displayIsOn = true; slideEventEmitted = false; } else if (strcmp(turn, "off") == 0) { displayIsOn = false; backlightTimer->stop(); controlLeds(false); } }
void Tohkbd::handleAltChanged() { checkDoWeNeedBacklight(); if ((capsLockSeq == 1 || capsLockSeq == 2)) /* Abort caps-lock if other key pressed */ capsLockSeq = 0; printf("alt changed %s\n", keymap->altPressed ? "down" : "up"); if (keymap->stickyAltEnabled) { tca8424->setLeds(keymap->altPressed ? LED_SYMLOCK_ON : LED_SYMLOCK_OFF); /* TODO: Fix correct led when such is in HW */ } if (!keymap->altPressed && taskSwitcherVisible) { /* hide taskswitcher when alt is released * this will also activate selected application */ tohkbd2user->call(QDBus::AutoDetect, "hideTaskSwitcher"); taskSwitcherVisible = false; } }
/* Handle state change of phone display * Turn keyboard backlight on and off */ void Tohkbd::handleDisplayStatus(const QDBusMessage& msg) { QList<QVariant> args = msg.arguments(); const char *turn = qPrintable(args.at(0).toString()); printf("Display status changed to \"%s\"\n", turn); if (strcmp(turn, "on") == 0) { checkDoWeNeedBacklight(); displayIsOn = true; slideEventEmitted = false; } else if (strcmp(turn, "off") == 0) { displayIsOn = false; if (backlightTimer->isActive() || forceBacklightOn) { backlightTimer->stop(); tca8424->setLeds(LED_BACKLIGHT_OFF); } } }
/* Set integer setting and save it to settings */ void Tohkbd::setSettingInt(const QString &key, const int &value) { QSettings settings(QSettings::SystemScope, "harbour-tohkbd2", "tohkbd2"); if (key == "backlightTimeout" && value >= 100 && value <= 5000) { backlightTimer->setInterval(value); settings.beginGroup("generalsettings"); settings.setValue("backlightTimeout", value); settings.endGroup(); } else if (key == "backlightLuxThreshold" && value >= 1 && value <= 50) { backlightLuxThreshold = value; settings.beginGroup("generalsettings"); settings.setValue("backlightLuxThreshold", value); settings.endGroup(); } else if (key == "keyRepeatDelay" && value >= 50 && value <= 500) { keyRepeatDelay = value; settings.beginGroup("generalsettings"); settings.setValue("keyRepeatDelay", value); settings.endGroup(); } else if (key == "keyRepeatRate" && value >= 25 && value <= 100) { keyRepeatRate = value; settings.beginGroup("generalsettings"); settings.setValue("keyRepeatRate", value); settings.endGroup(); } else if (key == "backlightEnabled" && (value == 0 || value == 1)) { backlightEnabled = (value == 1); settings.beginGroup("generalsettings"); settings.setValue("backlightEnabled", (value == 1)); settings.endGroup(); checkDoWeNeedBacklight(); } else if (key == "forceBacklightOn" && (value == 0 || value == 1)) { forceBacklightOn = (value == 1); settings.beginGroup("generalsettings"); settings.setValue("forceBacklightOn", (value == 1)); settings.endGroup(); checkDoWeNeedBacklight(); } else if (key == "forceLandscapeOrientation" && (value == 0 || value == 1)) { forceLandscapeOrientation = (value == 1); settings.beginGroup("generalsettings"); settings.setValue("forceLandscapeOrientation", (value == 1)); settings.endGroup(); if (value == 0 && !currentOrientationLock.isEmpty()) { QList<QVariant> args; args.append(currentOrientationLock); tohkbd2user->callWithArgumentList(QDBus::AutoDetect, "setOrientationLock", args); } else if (value == 1 && keypadIsPresent) { QList<QVariant> args; args.append("landscape"); tohkbd2user->callWithArgumentList(QDBus::AutoDetect, "setOrientationLock", args); } } else if (key == "stickyCtrlEnabled" && (value == 0 || value == 1)) { keymap->stickyCtrlEnabled = (value == 1); settings.beginGroup("generalsettings"); settings.setValue("stickyCtrlEnabled", (value == 1)); settings.endGroup(); } else if (key == "stickyAltEnabled" && (value == 0 || value == 1)) { keymap->stickyAltEnabled = (value == 1); settings.beginGroup("generalsettings"); settings.setValue("stickyAltEnabled", (value == 1)); settings.endGroup(); } else if (key == "stickySymEnabled" && (value == 0 || value == 1)) { keymap->stickySymEnabled = (value == 1); settings.beginGroup("generalsettings"); settings.setValue("stickySymEnabled", (value == 1)); settings.endGroup(); } }
/* Key press handler. Called from keymap->process() if actual key was pressed */ void Tohkbd::handleKeyPressed(QList< QPair<int, int> > keyCode) { bool processAllKeys = true; presenceTimer->start(); if (!displayIsOn && !slideEventEmitted) { emitKeypadSlideEvent(true); /* slideEventEmitted is used to limit events to just one * emitted once when key pressed while display is off * it is reset when display turns on. */ slideEventEmitted = true; } if ((capsLockSeq == 1 || capsLockSeq == 2)) /* Abort caps-lock if other key pressed */ capsLockSeq = 0; checkDoWeNeedBacklight(); /* alt+TAB is the task-switcher */ if (keymap->altPressed && keyCode.at(0).first == KEY_TAB) { if (!taskSwitcherVisible) { /* show taskswitcher and advance one app */ taskSwitcherVisible = true; tohkbd2user->call(QDBus::AutoDetect, "nextAppTaskSwitcher"); tohkbd2user->call(QDBus::AutoDetect, "showTaskSwitcher"); } else { /* Toggle to next app */ tohkbd2user->call(QDBus::AutoDetect, "nextAppTaskSwitcher"); } /* Don't process further */ keyIsPressed = true; return; } /* Alt-p takes a screenshot */ if (keymap->altPressed && keyCode.at(0).first == KEY_P) { screenShot(); /* Don't process further */ keyIsPressed = true; return; } /* if F1...F12 key is pressed then launch detached process */ if (FKEYS.contains(keyCode.at(0).first)) { QString cmd = applicationShortcuts[keyCode.at(0).first]; if (!cmd.isEmpty()) { printf("Requesting user daemon to start %s\n", qPrintable(cmd)); QList<QVariant> args; args.append(cmd); tohkbd2user->callWithArgumentList(QDBus::AutoDetect, "launchApplication", args); /* Don't process further */ keyIsPressed = true; return; } } if (processAllKeys) { for (int i=0; i<keyCode.count(); i++) { /* Some of the keys require shift pressed to get correct symbol */ if (keyCode.at(i).second & FORCE_COMPOSE) uinputif->sendUinputKeyPress(KEY_COMPOSE, 1); if ((keyCode.at(i).second & FORCE_RIGHTALT)) uinputif->sendUinputKeyPress(KEY_RIGHTALT, 1); if ((keyCode.at(i).second & FORCE_SHIFT) || keymap->shiftPressed) uinputif->sendUinputKeyPress(KEY_LEFTSHIFT, 1); if ((keyCode.at(i).second & FORCE_ALT) || keymap->altPressed) uinputif->sendUinputKeyPress(KEY_LEFTALT, 1); if ((keyCode.at(i).second & FORCE_CTRL) || keymap->ctrlPressed) uinputif->sendUinputKeyPress(KEY_LEFTCTRL, 1); /* Mimic key pressing */ uinputif->sendUinputKeyPress(keyCode.at(i).first, 1); QThread::msleep(KEYREPEAT_RATE); uinputif->sendUinputKeyPress(keyCode.at(i).first, 0); if ((keyCode.at(i).second & FORCE_CTRL) || keymap->ctrlPressed) uinputif->sendUinputKeyPress(KEY_LEFTCTRL, 0); if ((keyCode.at(i).second & FORCE_ALT) || keymap->altPressed) uinputif->sendUinputKeyPress(KEY_LEFTALT, 0); if ((keyCode.at(i).second & FORCE_SHIFT) || keymap->shiftPressed) uinputif->sendUinputKeyPress(KEY_LEFTSHIFT, 0); if ((keyCode.at(i).second & FORCE_RIGHTALT)) uinputif->sendUinputKeyPress(KEY_RIGHTALT, 0); if (keyCode.at(i).second & FORCE_COMPOSE) uinputif->sendUinputKeyPress(KEY_COMPOSE, 0); } } uinputif->synUinputDevice(); /* store keycode for repeat */ lastKeyCode = keyCode; /* Repeat delay first, then repeat rate */ repeatTimer->start(keyRepeat ? (keyRepeatRate-(KEYREPEAT_RATE-1)) : keyRepeatDelay); keyIsPressed = true; }
void Tohkbd::handleSymChanged() { controlLeds(true); checkDoWeNeedBacklight(); }
/* Key press handler. Called from keymap->process() if actual key was pressed */ void Tohkbd::handleKeyPressed(QList< QPair<int, int> > keyCode) { bool processAllKeys = true; /* No need to do this all if we are repeating */ if (!keyRepeat) { if (!displayIsOn && !slideEventEmitted) { emitKeypadSlideEvent(true); /* slideEventEmitted is used to limit events to just one * emitted once when key pressed while display is off * it is reset when display turns on. */ slideEventEmitted = true; } checkDoWeNeedBacklight(); /* alt+TAB is the task-switcher */ if (keymap->alt->pressed && keyCode.at(0).first == KEY_TAB) { if (!taskSwitcherVisible) { /* show taskswitcher and advance one app */ taskSwitcherVisible = true; tohkbd2user->nextAppTaskSwitcher(); tohkbd2user->showTaskSwitcher(); } else { /* Toggle to next app */ tohkbd2user->nextAppTaskSwitcher(); } /* Don't process further */ keyIsPressed = true; return; } /* Check custom key mappings */ if (keyCode.at(0).first > KEY_MAX) { switch (keyCode.at(0).first) { /* Sym-Int takes a screenshot */ case KEY_TOH_SCREENSHOT: tohkbd2user->takeScreenShot(); break; /* Sym-Del toggles "selfie" led */ case KEY_TOH_SELFIE: selfieLedOn = !selfieLedOn; tca8424->setLeds(selfieLedOn ? LED_SELFIE_ON : LED_SELFIE_OFF); break; case KEY_TOH_BACKLIGHT: forceBacklightOn = !forceBacklightOn; checkDoWeNeedBacklight(); break; case KEY_TOH_NEWEMAIL: { QDBusMessage m = QDBusMessage::createMethodCall("com.jolla.email.ui", "/com/jolla/email/ui", "", "mailto" ); QList<QVariant> args; args.append(QStringList() << "mailto:"); m.setArguments(args); QDBusConnection::sessionBus().send(m); } break; default: break; } /* Don't process further */ keyIsPressed = true; return; } /* if F1...F12 key is pressed then launch detached process */ if (FKEYS.contains(keyCode.at(0).first)) { QString cmd = applicationShortcuts[keyCode.at(0).first]; if (!cmd.isEmpty()) { printf("Requesting user daemon to start %s\n", qPrintable(cmd)); tohkbd2user->launchApplication(cmd); /* Don't process further */ keyIsPressed = true; return; } } /* Catch ctrl-alt-del (Works only from left ctrl or stickies) */ if (keymap->alt->pressed && keymap->ctrl->pressed && keyCode.at(0).first == KEY_DELETE) { printf("Requesting user daemon to reboot with remorse.\n"); tohkbd2user->actionWithRemorse(ACTION_REBOOT_REMORSE); keyIsPressed = true; return; } /* Catch ctrl-alt-backspace to restart lipstick (Works only from left ctrl or stickies) */ if (keymap->alt->pressed && keymap->ctrl->pressed && keyCode.at(0).first == KEY_BACKSPACE) { printf("Requesting user daemon to restart lipstick with remorse.\n"); tohkbd2user->actionWithRemorse(ACTION_RESTART_LIPSTICK_REMORSE); keyIsPressed = true; return; } } if (processAllKeys) { for (int i=0; i<keyCode.count(); i++) { bool tweakCapsLock = false; if (fix_CapsLock) tweakCapsLock = (capsLock == 3 && ((keyCode.at(i).first >= KEY_Q && keyCode.at(i).first <= KEY_P) || (keyCode.at(i).first >= KEY_A && keyCode.at(i).first <= KEY_L) || (keyCode.at(i).first >= KEY_Z && keyCode.at(i).first <= KEY_M) )); /* Some of the keys require shift pressed to get correct symbol */ if (keyCode.at(i).second & FORCE_COMPOSE) uinputif->sendUinputKeyPress(KEY_COMPOSE, 1); if ((keyCode.at(i).second & FORCE_RIGHTALT)) uinputif->sendUinputKeyPress(KEY_RIGHTALT, 1); if ((keyCode.at(i).second & FORCE_SHIFT) || tweakCapsLock) uinputif->sendUinputKeyPress(KEY_LEFTSHIFT, 1); if ((keyCode.at(i).second & FORCE_ALT)) uinputif->sendUinputKeyPress(KEY_LEFTALT, 1); if ((keyCode.at(i).second & FORCE_CTRL)) uinputif->sendUinputKeyPress(KEY_LEFTCTRL, 1); /* Mimic key pressing */ uinputif->sendUinputKeyPress(keyCode.at(i).first, 1); QThread::msleep(KEYREPEAT_RATE); uinputif->sendUinputKeyPress(keyCode.at(i).first, 0); if ((keyCode.at(i).second & FORCE_CTRL)) uinputif->sendUinputKeyPress(KEY_LEFTCTRL, 0); if ((keyCode.at(i).second & FORCE_ALT)) uinputif->sendUinputKeyPress(KEY_LEFTALT, 0); if ((keyCode.at(i).second & FORCE_SHIFT) || tweakCapsLock) uinputif->sendUinputKeyPress(KEY_LEFTSHIFT, 0); if ((keyCode.at(i).second & FORCE_RIGHTALT)) uinputif->sendUinputKeyPress(KEY_RIGHTALT, 0); if (keyCode.at(i).second & FORCE_COMPOSE) uinputif->sendUinputKeyPress(KEY_COMPOSE, 0); } } uinputif->synUinputDevice(); /* store keycode for repeat */ lastKeyCode = keyCode; /* Repeat delay first, then repeat rate */ repeatTimer->start(keyRepeat ? (keyRepeatRate-(KEYREPEAT_RATE-1)) : keyRepeatDelay); keyIsPressed = true; }
bool Tohkbd::checkKeypadPresence() { bool __prev_keypadPresence = keypadIsPresent; if (!vddEnabled) { /* keyboard is being connected to base */ /* TODO: how to detect keyboard is removed ??? */ printf("Presence detected, turning power on\n"); QThread::msleep(150); setVddState(true); QThread::msleep(150); tca8424->reset(); QThread::msleep(150); } tca8424driver::PresenceResult res = tca8424->testComms(); if (res == tca8424driver::DetectFail) { printf("keypad not present, turning power off\n"); setVddState(false); if (keypadIsPresent) { keyboardConnectedNotification(false); presenceTimer->stop(); handleKeyReleased(); } keypadIsPresent = false; } else { if (!keypadIsPresent) { keyboardConnectedNotification(true); controlLeds(true); checkDoWeNeedBacklight(); checkEEPROM(); } else if (res == tca8424driver::NoKeyPressedSinceReset && displayIsOn) { /* Keyboard power interrupt shortly? refresh leds just in case */ controlLeds(true); } presenceTimer->start(); keypadIsPresent = true; } if (__prev_keypadPresence != keypadIsPresent) { emit keyboardConnectedChanged(keypadIsPresent); emitKeypadSlideEvent(keypadIsPresent); vkbLayoutIsTohkbd = keypadIsPresent; changeActiveLayout(); if (forceLandscapeOrientation) changeOrientationLock(); } return keypadIsPresent; }
/* Set integer setting and save it to settings */ void Tohkbd::setSettingInt(const QString &key, const int &value) { QSettings settings(QSettings::SystemScope, "harbour-tohkbd2", "tohkbd2"); if (key == "backlightTimeout" && value >= 100 && value <= 5000) { settings.beginGroup("generalsettings"); settings.setValue("backlightTimeout", value); backlightTimer->setInterval(value); settings.endGroup(); } else if (key == "backlightLuxThreshold" && value >= 1 && value <= 50) { settings.beginGroup("generalsettings"); settings.setValue("backlightLuxThreshold", value); backlightLuxThreshold = value; settings.endGroup(); } else if (key == "keyRepeatDelay" && value >= 50 && value <= 500) { settings.beginGroup("generalsettings"); settings.setValue("keyRepeatDelay", value); keyRepeatDelay = value; settings.endGroup(); } else if (key == "keyRepeatRate" && value >= 25 && value <= 100) { settings.beginGroup("generalsettings"); settings.setValue("keyRepeatRate", value); keyRepeatRate = value; settings.endGroup(); } else if (key == "backlightEnabled" && (value == 0 || value == 1)) { settings.beginGroup("generalsettings"); settings.setValue("backlightEnabled", (value == 1)); backlightEnabled = (value == 1); settings.endGroup(); checkDoWeNeedBacklight(); } else if (key == "forceBacklightOn" && (value == 0 || value == 1)) { settings.beginGroup("generalsettings"); settings.setValue("forceBacklightOn", (value == 1)); forceBacklightOn = (value == 1); settings.endGroup(); checkDoWeNeedBacklight(); } else if (key == "forceLandscapeOrientation" && (value == 0 || value == 1)) { settings.beginGroup("generalsettings"); settings.setValue("forceLandscapeOrientation", (value == 1)); forceLandscapeOrientation = (value == 1); settings.endGroup(); if (value == 0 && !currentOrientationLock.isEmpty()) { tohkbd2user->setOrientationLock(currentOrientationLock); } else if (value == 1 && keypadIsPresent) { tohkbd2user->setOrientationLock("landscape"); } } else if (key == "stickyShiftEnabled" && (value == 0 || value == 1)) { settings.beginGroup("generalsettings"); settings.setValue("stickyShiftEnabled", (value == 1)); keymap->shift->setMode((value == 1) ? modifierHandler::Sticky : modifierHandler::Normal); settings.endGroup(); } else if (key == "stickyCtrlEnabled" && (value == 0 || value == 1)) { settings.beginGroup("generalsettings"); settings.setValue("stickyCtrlEnabled", (value == 1)); keymap->ctrl->setMode((value == 1) ? modifierHandler::Sticky : modifierHandler::Normal); settings.endGroup(); } else if (key == "stickyAltEnabled" && (value == 0 || value == 1)) { settings.beginGroup("generalsettings"); settings.setValue("stickyAltEnabled", (value == 1)); keymap->alt->setMode((value == 1) ? modifierHandler::Sticky : modifierHandler::Normal); settings.endGroup(); } else if (key == "stickySymEnabled" && (value == 0 || value == 1)) { settings.beginGroup("generalsettings"); settings.setValue("stickySymEnabled", (value == 1)); keymap->sym->setMode((value == 1) ? modifierHandler::Sticky : modifierHandler::Normal); settings.endGroup(); } else if (key == "lockingShiftEnabled" && (value == 0 || value == 1)) { settings.beginGroup("generalsettings"); settings.setValue("lockingShiftEnabled", (value == 1)); keymap->shift->setMode((value == 1) ? modifierHandler::Lock : modifierHandler::Normal); settings.endGroup(); } else if (key == "lockingCtrlEnabled" && (value == 0 || value == 1)) { settings.beginGroup("generalsettings"); settings.setValue("lockingCtrlEnabled", (value == 1)); keymap->ctrl->setMode((value == 1) ? modifierHandler::Lock : modifierHandler::Normal); settings.endGroup(); } else if (key == "lockingAltEnabled" && (value == 0 || value == 1)) { settings.beginGroup("generalsettings"); settings.setValue("lockingAltEnabled", (value == 1)); keymap->alt->setMode((value == 1) ? modifierHandler::Lock : modifierHandler::Normal); settings.endGroup(); } else if (key == "lockingSymEnabled" && (value == 0 || value == 1)) { settings.beginGroup("generalsettings"); settings.setValue("lockingSymEnabled", (value == 1)); keymap->sym->setMode((value == 1) ? modifierHandler::Lock : modifierHandler::Normal); settings.endGroup(); } keymap->releaseStickyModifiers(true); }