/*
* This file is part of openauto project.
* Copyright (C) 2018 f1x.studio (Michal Szwaj)
*
* openauto is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
* openauto is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with openauto. If not, see .
*/
#include
#include
#include
namespace f1x
{
namespace openauto
{
namespace autoapp
{
namespace projection
{
InputDevice::InputDevice(QObject& parent, configuration::IConfiguration::Pointer configuration, const QRect& touchscreenGeometry, const QRect& displayGeometry)
: parent_(parent)
, configuration_(std::move(configuration))
, touchscreenGeometry_(touchscreenGeometry)
, displayGeometry_(displayGeometry)
, eventHandler_(nullptr)
{
this->moveToThread(parent.thread());
}
void InputDevice::start(IInputDeviceEventHandler& eventHandler)
{
std::lock_guard lock(mutex_);
OPENAUTO_LOG(info) << "[InputDevice] start.";
eventHandler_ = &eventHandler;
parent_.installEventFilter(this);
}
void InputDevice::stop()
{
std::lock_guard lock(mutex_);
OPENAUTO_LOG(info) << "[InputDevice] stop.";
parent_.removeEventFilter(this);
eventHandler_ = nullptr;
}
bool InputDevice::eventFilter(QObject* obj, QEvent* event)
{
std::lock_guard lock(mutex_);
if(eventHandler_ != nullptr)
{
if(event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease)
{
QKeyEvent* key = static_cast(event);
if(!key->isAutoRepeat())
{
return this->handleKeyEvent(event, key);
}
}
else if(event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseMove)
{
return this->handleTouchEvent(event);
}
}
return QObject::eventFilter(obj, event);
}
bool InputDevice::handleKeyEvent(QEvent* event, QKeyEvent* key)
{
auto eventType = event->type() == QEvent::KeyPress ? ButtonEventType::PRESS : ButtonEventType::RELEASE;
aasdk::proto::enums::ButtonCode::Enum buttonCode;
WheelDirection wheelDirection = WheelDirection::NONE;
switch(key->key())
{
case Qt::Key_Return:
case Qt::Key_Enter:
buttonCode = aasdk::proto::enums::ButtonCode::ENTER;
break;
case Qt::Key_Left:
buttonCode = aasdk::proto::enums::ButtonCode::LEFT;
break;
case Qt::Key_Right:
buttonCode = aasdk::proto::enums::ButtonCode::RIGHT;
break;
case Qt::Key_Up:
buttonCode = aasdk::proto::enums::ButtonCode::UP;
break;
case Qt::Key_Down:
buttonCode = aasdk::proto::enums::ButtonCode::DOWN;
break;
case Qt::Key_Escape:
buttonCode = aasdk::proto::enums::ButtonCode::BACK;
break;
case Qt::Key_H:
buttonCode = aasdk::proto::enums::ButtonCode::HOME;
break;
case Qt::Key_P:
buttonCode = aasdk::proto::enums::ButtonCode::PHONE;
break;
case Qt::Key_O:
buttonCode = aasdk::proto::enums::ButtonCode::CALL_END;
break;
case Qt::Key_X:
buttonCode = aasdk::proto::enums::ButtonCode::PLAY;
break;
case Qt::Key_C:
buttonCode = aasdk::proto::enums::ButtonCode::PAUSE;
break;
case Qt::Key_MediaPrevious:
case Qt::Key_V:
buttonCode = aasdk::proto::enums::ButtonCode::PREV;
break;
case Qt::Key_MediaPlay:
case Qt::Key_B:
buttonCode = aasdk::proto::enums::ButtonCode::TOGGLE_PLAY;
break;
case Qt::Key_MediaNext:
case Qt::Key_N:
buttonCode = aasdk::proto::enums::ButtonCode::NEXT;
break;
case Qt::Key_M:
buttonCode = aasdk::proto::enums::ButtonCode::MICROPHONE_1;
break;
case Qt::Key_1:
wheelDirection = WheelDirection::LEFT;
eventType = ButtonEventType::NONE;
buttonCode = aasdk::proto::enums::ButtonCode::SCROLL_WHEEL;
break;
case Qt::Key_2:
wheelDirection = WheelDirection::RIGHT;
eventType = ButtonEventType::NONE;
buttonCode = aasdk::proto::enums::ButtonCode::SCROLL_WHEEL;
break;
default:
return true;
}
const auto& buttonCodes = this->getSupportedButtonCodes();
if(std::find(buttonCodes.begin(), buttonCodes.end(), buttonCode) != buttonCodes.end())
{
if(buttonCode != aasdk::proto::enums::ButtonCode::SCROLL_WHEEL || event->type() == QEvent::KeyRelease)
{
eventHandler_->onButtonEvent({eventType, wheelDirection, buttonCode});
}
}
return true;
}
bool InputDevice::handleTouchEvent(QEvent* event)
{
if(!configuration_->getTouchscreenEnabled())
{
return true;
}
aasdk::proto::enums::TouchAction::Enum type;
switch(event->type())
{
case QEvent::MouseButtonPress:
type = aasdk::proto::enums::TouchAction::PRESS;
break;
case QEvent::MouseButtonRelease:
type = aasdk::proto::enums::TouchAction::RELEASE;
break;
case QEvent::MouseMove:
type = aasdk::proto::enums::TouchAction::DRAG;
break;
default:
return true;
};
QMouseEvent* mouse = static_cast(event);
if(event->type() == QEvent::MouseButtonRelease || mouse->buttons().testFlag(Qt::LeftButton))
{
const uint32_t x = (static_cast(mouse->pos().x()) / touchscreenGeometry_.width()) * displayGeometry_.width();
const uint32_t y = (static_cast(mouse->pos().y()) / touchscreenGeometry_.height()) * displayGeometry_.height();
eventHandler_->onTouchEvent({type, x, y, 0});
}
return true;
}
bool InputDevice::hasTouchscreen() const
{
return configuration_->getTouchscreenEnabled();
}
QRect InputDevice::getTouchscreenGeometry() const
{
return touchscreenGeometry_;
}
void InputDevice::setTouchscreenGeometry(QRect& touchscreenGeometry)
{
touchscreenGeometry_ = touchscreenGeometry;
}
IInputDevice::ButtonCodes InputDevice::getSupportedButtonCodes() const
{
return configuration_->getButtonCodes();
}
}
}
}
}