#include "UtilitiesTabController.h" #include #include "../overlaycontroller.h" #include #include // application namespace namespace advsettings { const char* steamDesktopOverlaykey = "valve.steam.desktop"; void UtilitiesTabController::initStage1() { auto settings = OverlayController::appSettings(); settings->beginGroup("utilitiesSettings"); auto qAlarmEnabled = settings->value("alarmEnabled", m_alarmEnabled); auto qAlarmIsModal = settings->value("alarmIsModal", m_alarmIsModal); auto qAlarmHour = settings->value("alarmHour", 0); auto qAlarmMinute = settings->value("alarmMinute", 0); settings->endGroup(); m_alarmEnabled = qAlarmEnabled.toBool(); m_alarmIsModal = qAlarmIsModal.toBool(); m_alarmTime = QTime(qAlarmHour.toInt(), qAlarmMinute.toInt()); vr::VROverlayHandle_t pOverlayHandle; auto error = vr::VROverlay()->FindOverlay(steamDesktopOverlaykey, &pOverlayHandle); if (error != vr::VROverlayError_None) { m_steamDesktopOverlayAvailable = false; LOG(INFO) << "Could not find overlay \"" << steamDesktopOverlaykey << "\": " << vr::VROverlay()->GetOverlayErrorNameFromEnum(error); } else { m_steamDesktopOverlayAvailable = true; float width; error = vr::VROverlay()->GetOverlayWidthInMeters(pOverlayHandle, &width); if (error != vr::VROverlayError_None) { LOG(ERROR) << "Could not read overlay width of \"" << steamDesktopOverlaykey << "\": " << vr::VROverlay()->GetOverlayErrorNameFromEnum(error); } else { m_steamDesktopOverlayWidth = width; } } } void UtilitiesTabController::initStage2(OverlayController * parent, QQuickWindow * widget) { this->parent = parent; this->widget = widget; } void fillKiStruct(INPUT& ip, WORD scanCode, bool keyup) { ip.type = INPUT_KEYBOARD; ip.ki.wVk = scanCode; if (keyup) { ip.ki.dwFlags = KEYEVENTF_KEYUP; } else { ip.ki.dwFlags = 0; } ip.ki.wScan = 0; ip.ki.dwExtraInfo = 0; ip.ki.time = 0; }; void UtilitiesTabController::sendKeyboardInput(QString input) { int len = input.length(); if (len > 0) { LPINPUT ips = new INPUT[len * 5 + 3]; unsigned ii = 0; bool shiftPressed = false; bool ctrlPressed = false; bool altPressed = false; for (int i = 0; i < len; i++) { short tmp = VkKeyScan(input.at(i).toLatin1()); WORD c = tmp & 0xFF; short shiftState = tmp >> 8; bool isShift = shiftState & 1; bool isCtrl = shiftState & 2; bool isAlt = shiftState & 4; if (isShift && !shiftPressed) { fillKiStruct(ips[ii++], VK_SHIFT, false); shiftPressed = true; } else if (!isShift && shiftPressed) { fillKiStruct(ips[ii++], VK_SHIFT, true); shiftPressed = false; } if (isCtrl && !ctrlPressed) { fillKiStruct(ips[ii++], VK_CONTROL, false); ctrlPressed = true; } else if (!isCtrl && ctrlPressed) { fillKiStruct(ips[ii++], VK_CONTROL, true); ctrlPressed = false; } if (isAlt && !altPressed) { fillKiStruct(ips[ii++], VK_MENU, false); altPressed = true; } else if (!isAlt && altPressed) { fillKiStruct(ips[ii++], VK_MENU, true); altPressed = false; } fillKiStruct(ips[ii++], c, false); fillKiStruct(ips[ii++], c, true); } if (shiftPressed) { fillKiStruct(ips[ii++], VK_SHIFT, true); shiftPressed = false; } if (ctrlPressed) { fillKiStruct(ips[ii++], VK_CONTROL, true); ctrlPressed = false; } if (altPressed) { fillKiStruct(ips[ii++], VK_MENU, true); altPressed = false; } if (!SendInput(ii, ips, sizeof(INPUT))) { char *err; auto errCode = GetLastError(); if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language (LPTSTR)&err, 0, NULL)){ LOG(ERROR) << "Error calling SendInput(): Could not get error message (" << errCode << ")"; } else { LOG(ERROR) << "Error calling SendInput(): " << err; } } delete ips; } } void UtilitiesTabController::sendKeyboardEnter() { LPINPUT ips = new INPUT[2]; fillKiStruct(ips[0], VK_RETURN, false); fillKiStruct(ips[1], VK_RETURN, true); if (!SendInput(2, ips, sizeof(INPUT))) { char *err; auto errCode = GetLastError(); if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language (LPTSTR)&err, 0, NULL)) { LOG(ERROR) << "Error calling SendInput(): Could not get error message (" << errCode << ")"; } else { LOG(ERROR) << "Error calling SendInput(): " << err; } } delete ips; } void UtilitiesTabController::sendKeyboardBackspace(int count) { if (count > 0) { LPINPUT ips = new INPUT[count * 2]; for (int i = 0; i < count; i++) { fillKiStruct(ips[2 * i], VK_BACK, false); fillKiStruct(ips[2 * i + 1], VK_BACK, true); } if (!SendInput(2 * count, ips, sizeof(INPUT))) { char *err; auto errCode = GetLastError(); if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language (LPTSTR)&err, 0, NULL)) { LOG(ERROR) << "Error calling SendInput(): Could not get error message (" << errCode << ")"; } else { LOG(ERROR) << "Error calling SendInput(): " << err; } } delete ips; } } bool UtilitiesTabController::alarmEnabled() const { return m_alarmEnabled; } bool UtilitiesTabController::alarmIsModal() const { return m_alarmIsModal; } int UtilitiesTabController::alarmTimeHour() const { return m_alarmTime.hour(); } int UtilitiesTabController::alarmTimeMinute() const { return m_alarmTime.minute(); } void UtilitiesTabController::setAlarmEnabled(bool enabled, bool notify) { if (m_alarmEnabled != enabled) { m_alarmEnabled = enabled; auto settings = OverlayController::appSettings(); settings->beginGroup("utilitiesSettings"); settings->setValue("alarmEnabled", m_alarmEnabled); settings->endGroup(); settings->sync(); m_alarmLastCheckTime = QTime(); if (notify) { emit alarmEnabledChanged(m_alarmEnabled); } } } void UtilitiesTabController::setAlarmIsModal(bool modal, bool notify) { if (m_alarmIsModal != modal) { m_alarmIsModal = modal; auto settings = OverlayController::appSettings(); settings->beginGroup("utilitiesSettings"); settings->setValue("alarmIsModal", m_alarmIsModal); settings->endGroup(); settings->sync(); if (notify) { emit alarmIsModalChanged(m_alarmIsModal); } } } void UtilitiesTabController::setAlarmTimeHour(int hour, bool notify) { if (m_alarmTime.hour() != hour) { if (m_alarmTime.isValid()) { m_alarmTime = QTime(hour, m_alarmTime.minute()); } else { m_alarmTime = QTime(hour, 0); } auto settings = OverlayController::appSettings(); settings->beginGroup("utilitiesSettings"); settings->setValue("alarmHour", m_alarmTime.hour()); settings->setValue("alarmMinute", m_alarmTime.minute()); settings->endGroup(); settings->sync(); m_alarmLastCheckTime = QTime(); if (notify) { emit alarmTimeHourChanged(hour); } } } void UtilitiesTabController::setAlarmTimeMinute(int min, bool notify) { if (m_alarmTime.minute() != min) { if (m_alarmTime.isValid()) { m_alarmTime = QTime(m_alarmTime.hour(), min); } else { m_alarmTime = QTime(0, min); } auto settings = OverlayController::appSettings(); settings->beginGroup("utilitiesSettings"); settings->setValue("alarmHour", m_alarmTime.hour()); settings->setValue("alarmMinute", m_alarmTime.minute()); settings->endGroup(); settings->sync(); m_alarmLastCheckTime = QTime(); if (notify) { emit alarmTimeMinuteChanged(min); } } } void UtilitiesTabController::setAlarmTimeToCurrentTime() { auto now = QTime::currentTime(); setAlarmTimeHour(now.hour()); setAlarmTimeMinute(now.minute()); } void UtilitiesTabController::modAlarmTimeHour(int value, bool notify) { auto h = m_alarmTime.hour(); m_alarmTime = m_alarmTime.addSecs(value * 60 * 60); auto settings = OverlayController::appSettings(); settings->beginGroup("utilitiesSettings"); settings->setValue("alarmHour", m_alarmTime.hour()); settings->setValue("alarmMinute", m_alarmTime.minute()); settings->endGroup(); settings->sync(); if (h != m_alarmTime.hour()) { m_alarmLastCheckTime = QTime(); if (notify) { emit alarmTimeHourChanged(m_alarmTime.hour()); } } } void UtilitiesTabController::modAlarmTimeMinute(int value, bool notify) { auto h = m_alarmTime.hour(); auto m = m_alarmTime.minute(); m_alarmTime = m_alarmTime.addSecs(value * 60); auto settings = OverlayController::appSettings(); settings->beginGroup("utilitiesSettings"); settings->setValue("alarmHour", m_alarmTime.hour()); settings->setValue("alarmMinute", m_alarmTime.minute()); settings->endGroup(); settings->sync(); if (m != m_alarmTime.minute() || h != m_alarmTime.hour()) { m_alarmLastCheckTime = QTime(); if (notify) { if (h != m_alarmTime.hour()) { emit alarmTimeHourChanged(m_alarmTime.hour()); } if (m != m_alarmTime.minute()) { emit alarmTimeMinuteChanged(m_alarmTime.minute()); } } } } void UtilitiesTabController::eventLoopTick() { if (settingsUpdateCounter >= 10) { vr::VROverlayHandle_t pOverlayHandle; auto error = vr::VROverlay()->FindOverlay(steamDesktopOverlaykey, &pOverlayHandle); if (error == vr::VROverlayError_None) { if (!m_steamDesktopOverlayAvailable) { m_steamDesktopOverlayAvailable = true; emit steamDesktopOverlayAvailableChanged(m_steamDesktopOverlayAvailable); } float width; error = vr::VROverlay()->GetOverlayWidthInMeters(pOverlayHandle, &width); if (error != vr::VROverlayError_None) { LOG(ERROR) << "Could not read overlay width of \"" << steamDesktopOverlaykey << "\": " << vr::VROverlay()->GetOverlayErrorNameFromEnum(error); } else { setSteamDesktopOverlayWidth(width, true, false); } } else { if (m_steamDesktopOverlayAvailable) { m_steamDesktopOverlayAvailable = false; emit steamDesktopOverlayAvailableChanged(m_steamDesktopOverlayAvailable); } } if (m_alarmEnabled && m_alarmTime.isValid()) { auto now = QTime::currentTime(); if (m_alarmLastCheckTime.isValid() && m_alarmLastCheckTime <= m_alarmTime && m_alarmTime <= now) { setAlarmEnabled(false); char alarmMessageBuffer[1024]; std::snprintf(alarmMessageBuffer, 1024, "The alarm at %02i:%02i went off.", alarmTimeHour(), alarmTimeMinute()); if (m_alarmIsModal) { std::thread messageThread([](UtilitiesTabController* parent, std::string message) { auto res = vr::VROverlay()->ShowMessageOverlay(message.c_str(), "Alarm Clock", "Ok", "+15 min"); if (res == vr::VRMessageOverlayResponse_ButtonPress_1) { parent->setAlarmTimeToCurrentTime(); parent->modAlarmTimeMinute(15); parent->setAlarmEnabled(true); } else if (res >= vr::VRMessageOverlayResponse_CouldntFindSystemOverlay) { static const char* errorMessages[] = { "CouldntFindSystemOverlay", "CouldntFindOrCreateClientOverlay", "ApplicationQuit" }; int errorCode = res - vr::VRMessageOverlayResponse_CouldntFindSystemOverlay; if (res < 3) { LOG(ERROR) << "Could not create Alarm Overlay: " << errorMessages[errorCode]; } else { LOG(ERROR) << "Could not create Alarm Overlay: Unknown Error"; } } }, this, std::string(alarmMessageBuffer)); messageThread.detach(); } else { vr::VRNotificationId notificationId; vr::EVRInitError eError; vr::IVRNotifications* vrnotification = (vr::IVRNotifications*)vr::VR_GetGenericInterface(vr::IVRNotifications_Version, &eError); if (eError != vr::VRInitError_None) { LOG(ERROR) << "Error while getting IVRNotifications interface" << vr::VR_GetVRInitErrorAsEnglishDescription(eError); vrnotification = nullptr; } else { vr::NotificationBitmap_t* messageIconPtr = nullptr; /* // Can i even create this object on the stack, who takes ownership? vr::NotificationBitmap_t messageIcon; // First get image width and height vr::VROverlay()->GetOverlayImageData(parent->overlayThumbnailHandle(), nullptr, 0, (uint32_t*)&messageIcon.m_nWidth, (uint32_t*)&messageIcon.m_nHeight); messageIcon.m_nBytesPerPixel = 4; unsigned bufferSize = messageIcon.m_nWidth*messageIcon.m_nHeight*messageIcon.m_nBytesPerPixel; // Can I delete this buffer after this section? Who takes ownership? std::unique_ptr imageBuffer; imageBuffer.reset(new char[bufferSize]); messageIcon.m_pImageData = imageBuffer.get(); // Get image data auto iconError = vr::VROverlay()->GetOverlayImageData(parent->overlayThumbnailHandle(), messageIcon.m_pImageData, bufferSize, (uint32_t*)&messageIcon.m_nWidth, (uint32_t*)&messageIcon.m_nHeight); if (iconError != vr::VROverlayError_None) { LOG(ERROR) << "Error while getting message overlay icon: " << vr::VROverlay()->GetOverlayErrorNameFromEnum(iconError); } else { messageIconPtr = &messageIcon; } */ auto nError = vrnotification->CreateNotification( parent->overlayHandle(), 666, vr::EVRNotificationType_Transient, alarmMessageBuffer, vr::EVRNotificationStyle_Application, messageIconPtr, ¬ificationId ); if (nError != vr::VRNotificationError_OK) { LOG(ERROR) << "Error while creating notification: " << nError; vrnotification = nullptr; } } } } m_alarmLastCheckTime = now; } settingsUpdateCounter = 0; } else { settingsUpdateCounter++; } } bool UtilitiesTabController::steamDesktopOverlayAvailable() const { return m_steamDesktopOverlayAvailable; } float UtilitiesTabController::steamDesktopOverlayWidth() const { return m_steamDesktopOverlayWidth; } void UtilitiesTabController::setSteamDesktopOverlayWidth(float width, bool notify, bool notifyOpenVr) { if (std::abs(m_steamDesktopOverlayWidth - width) > 0.01) { m_steamDesktopOverlayWidth = width; if (notifyOpenVr) { vr::VROverlayHandle_t pOverlayHandle; auto error = vr::VROverlay()->FindOverlay(steamDesktopOverlaykey, &pOverlayHandle); if (error != vr::VROverlayError_None) { LOG(ERROR) << "Could not find overlay \"" << steamDesktopOverlaykey << "\": " << vr::VROverlay()->GetOverlayErrorNameFromEnum(error); } else { error = vr::VROverlay()->SetOverlayWidthInMeters(pOverlayHandle, m_steamDesktopOverlayWidth); if (error != vr::VROverlayError_None) { LOG(ERROR) << "Could not modify overlay width of \"" << steamDesktopOverlaykey << "\": " << vr::VROverlay()->GetOverlayErrorNameFromEnum(error); } } } if (notify) { emit steamDesktopOverlayWidthChanged(m_steamDesktopOverlayWidth); } } } } // namespace advconfig