mirror of
https://github.com/barry-ran/QtScrcpy.git
synced 2025-07-29 12:18:39 +00:00
Merge pull request #71 from yxtj/dev
1, translation debug, 2, optimize customized script related logic, 3, improve mouse handling logic
This commit is contained in:
commit
8d0b115967
27 changed files with 1017 additions and 765 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -9,5 +9,6 @@
|
|||
/server/gradlew
|
||||
/server/gradlew.bat
|
||||
/server/local.properties
|
||||
/build/
|
||||
build-*
|
||||
*.DS_Store
|
||||
|
|
|
@ -12,13 +12,7 @@ Controller::Controller(QString gameScript, QObject* parent) : QObject(parent)
|
|||
m_receiver = new Receiver(this);
|
||||
Q_ASSERT(m_receiver);
|
||||
|
||||
if (!gameScript.isEmpty()) {
|
||||
InputConvertGame* convertgame = new InputConvertGame(this);
|
||||
convertgame->loadKeyMap(gameScript);
|
||||
m_inputConvert = convertgame;
|
||||
} else {
|
||||
m_inputConvert = new InputConvertNormal(this);
|
||||
}
|
||||
updateScript(gameScript);
|
||||
Q_ASSERT(m_inputConvert);
|
||||
connect(m_inputConvert, &InputConvertBase::grabCursor, this, &Controller::grabCursor);
|
||||
}
|
||||
|
@ -51,6 +45,18 @@ void Controller::test(QRect rc)
|
|||
postControlMsg(controlMsg);
|
||||
}
|
||||
|
||||
void Controller::updateScript(QString gameScript)
|
||||
{
|
||||
if (!gameScript.isEmpty()) {
|
||||
InputConvertGame* convertgame = new InputConvertGame(this);
|
||||
convertgame->loadKeyMap(gameScript);
|
||||
m_inputConvert = convertgame;
|
||||
} else {
|
||||
m_inputConvert = new InputConvertNormal(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Controller::postTurnOn()
|
||||
{
|
||||
ControlMsg* controlMsg = new ControlMsg(ControlMsg::CMT_BACK_OR_SCREEN_ON);
|
||||
|
@ -161,6 +167,12 @@ void Controller::setScreenPowerMode(ControlMsg::ScreenPowerMode mode)
|
|||
postControlMsg(controlMsg);
|
||||
}
|
||||
|
||||
void Controller::screenShot()
|
||||
{
|
||||
// TODO:
|
||||
qDebug() << "screen shot";
|
||||
}
|
||||
|
||||
void Controller::mouseEvent(const QMouseEvent *from, const QSize &frameSize, const QSize &showSize)
|
||||
{
|
||||
if (m_inputConvert) {
|
||||
|
|
|
@ -20,6 +20,8 @@ public:
|
|||
void postControlMsg(ControlMsg* controlMsg);
|
||||
void test(QRect rc);
|
||||
|
||||
void updateScript(QString gameScript = "");
|
||||
|
||||
// turn the screen on if it was off, press BACK otherwise
|
||||
void postTurnOn();
|
||||
void postGoHome();
|
||||
|
@ -36,6 +38,7 @@ public:
|
|||
void clipboardPaste();
|
||||
void postTextInput(QString& text);
|
||||
void setScreenPowerMode(ControlMsg::ScreenPowerMode mode);
|
||||
void screenShot();
|
||||
|
||||
// for input convert
|
||||
void mouseEvent(const QMouseEvent* from, const QSize& frameSize, const QSize& showSize);
|
||||
|
|
|
@ -1,9 +1,38 @@
|
|||
#include <QDebug>
|
||||
#include <QDebug>
|
||||
#include <QCursor>
|
||||
#include <QGuiApplication>
|
||||
|
||||
#include "inputconvertgame.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <windef.h>
|
||||
// restrict mouse into a window
|
||||
static void restrictMouse(const int left, const int right,
|
||||
const int top, const int bottom)
|
||||
{
|
||||
RECT mainWinRect; // RECT is defined in <windef.h>
|
||||
mainWinRect.left = static_cast<LONG>(left);
|
||||
mainWinRect.right = static_cast<LONG>(right);
|
||||
mainWinRect.top = static_cast<LONG>(top);
|
||||
mainWinRect.bottom = static_cast<LONG>(bottom);
|
||||
ClipCursor(&mainWinRect); // Windows API
|
||||
}
|
||||
static void freeMouse()
|
||||
{
|
||||
ClipCursor(nullptr);
|
||||
}
|
||||
|
||||
#else // linux and macos
|
||||
static void restrictMouse(const int left, const int right,
|
||||
const int top, const int bottom)
|
||||
{}
|
||||
static void freeMouse()
|
||||
{}
|
||||
#endif
|
||||
|
||||
#define CURSOR_POS_CHECK 50
|
||||
|
||||
InputConvertGame::InputConvertGame(Controller* controller)
|
||||
|
@ -19,17 +48,25 @@ InputConvertGame::~InputConvertGame()
|
|||
|
||||
void InputConvertGame::mouseEvent(const QMouseEvent *from, const QSize &frameSize, const QSize &showSize)
|
||||
{
|
||||
// 处理开关按键
|
||||
if (m_keyMap.isSwitchOnKeyboard() == false &&
|
||||
from->type() == QEvent::MouseButtonPress &&
|
||||
m_keyMap.getSwitchKey() == from->button())
|
||||
{
|
||||
if (!switchGameMap()) {
|
||||
m_needSwitchGameAgain = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_gameMap) {
|
||||
updateSize(frameSize, showSize);
|
||||
|
||||
if (m_keyMap.enableMouseMoveMap()) {
|
||||
// mouse move
|
||||
// mouse move
|
||||
if (m_keyMap.isValidMouseMoveMap()) {
|
||||
if (processMouseMove(from)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// mouse click
|
||||
if (processMouseClick(from)) {
|
||||
return;
|
||||
|
@ -51,7 +88,7 @@ void InputConvertGame::wheelEvent(const QWheelEvent *from, const QSize &frameSiz
|
|||
void InputConvertGame::keyEvent(const QKeyEvent *from, const QSize& frameSize, const QSize& showSize)
|
||||
{
|
||||
// 处理开关按键
|
||||
if (m_keyMap.getSwitchKey() == from->key()) {
|
||||
if (m_keyMap.isSwitchOnKeyboard() && m_keyMap.getSwitchKey() == from->key()) {
|
||||
if (QEvent::KeyPress == from->type()) {
|
||||
if (!switchGameMap()) {
|
||||
m_needSwitchGameAgain = false;
|
||||
|
@ -60,15 +97,14 @@ void InputConvertGame::keyEvent(const QKeyEvent *from, const QSize& frameSize, c
|
|||
return;
|
||||
}
|
||||
|
||||
KeyMap::KeyMapNode& node = m_keyMap.getKeyMapNode(from->key());
|
||||
const KeyMap::KeyMapNode& node = m_keyMap.getKeyMapNodeKey(from->key());
|
||||
// 处理特殊按键:可以在按键映射和普通映射间切换的按键
|
||||
if (m_needSwitchGameAgain
|
||||
&& KeyMap::KMT_CLICK == node.type
|
||||
&& node.click.switchMap) {
|
||||
updateSize(frameSize, showSize);
|
||||
// Qt::Key_Tab Qt::Key_M
|
||||
processKeyClick(node.click.keyNode.pos, false,
|
||||
node.click.switchMap, from);
|
||||
// Qt::Key_Tab Qt::Key_M for PUBG mobile
|
||||
processKeyClick(node.click.keyNode.pos, false, node.click.switchMap, from);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -78,21 +114,23 @@ void InputConvertGame::keyEvent(const QKeyEvent *from, const QSize& frameSize, c
|
|||
return;
|
||||
}
|
||||
|
||||
switch (node.type) {
|
||||
// 处理方向盘
|
||||
if (KeyMap::KMT_STEER_WHEEL == node.type) {
|
||||
case KeyMap::KMT_STEER_WHEEL:
|
||||
processSteerWheel(node, from);
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理普通按键
|
||||
switch (node.type) {
|
||||
case KeyMap::KMT_CLICK:
|
||||
processKeyClick(node.click.keyNode.pos, false,
|
||||
node.click.switchMap, from);
|
||||
processKeyClick(node.click.keyNode.pos, false, node.click.switchMap, from);
|
||||
return;
|
||||
case KeyMap::KMT_CLICK_TWICE:
|
||||
processKeyClick(node.clickTwice.keyNode.pos, true, false, from);
|
||||
return;
|
||||
case KeyMap::KMT_DRAG:
|
||||
processKeyDrag(node.drag.startPos, node.drag.endPos, from);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
InputConvertNormal::keyEvent(from, frameSize, showSize);
|
||||
|
@ -102,8 +140,15 @@ void InputConvertGame::keyEvent(const QKeyEvent *from, const QSize& frameSize, c
|
|||
void InputConvertGame::loadKeyMap(const QString &json)
|
||||
{
|
||||
m_keyMap.loadKeyMap(json);
|
||||
if (m_keyMap.enableMouseMoveMap()) {
|
||||
m_mouseMoveLastConverPos = m_keyMap.getMouseMoveMap().startPos;
|
||||
if (m_keyMap.isValidMouseMoveMap()) {
|
||||
m_ctrlMouseMove.valid = true;
|
||||
m_ctrlMouseMove.touching = false;
|
||||
m_ctrlMouseMove.startPosRel = m_keyMap.getMouseMoveMap().startPos;
|
||||
m_ctrlMouseMove.startPosPixel = calcFrameAbsolutePos(m_ctrlMouseMove.startPosRel);
|
||||
}
|
||||
if(m_keyMap.isValidSteerWheelMap()){
|
||||
m_ctrlSteerWheel.valid = true;
|
||||
m_ctrlMouseMove.touching = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,6 +156,9 @@ void InputConvertGame::updateSize(const QSize &frameSize, const QSize &showSize)
|
|||
{
|
||||
m_frameSize = frameSize;
|
||||
m_showSize = showSize;
|
||||
if(m_ctrlMouseMove.valid){
|
||||
m_ctrlMouseMove.startPosPixel = calcScreenAbsolutePos(m_ctrlMouseMove.startPosRel);
|
||||
}
|
||||
}
|
||||
|
||||
void InputConvertGame::sendTouchDownEvent(int id, QPointF pos)
|
||||
|
@ -149,22 +197,35 @@ QPointF InputConvertGame::calcFrameAbsolutePos(QPointF relativePos)
|
|||
return absolutePos;
|
||||
}
|
||||
|
||||
QPointF InputConvertGame::calcScreenAbsolutePos(QPointF relativePos)
|
||||
{
|
||||
QPointF absolutePos;
|
||||
absolutePos.setX(m_showSize.width() * relativePos.x());
|
||||
absolutePos.setY(m_showSize.height() * relativePos.y());
|
||||
return absolutePos;
|
||||
}
|
||||
|
||||
int InputConvertGame::attachTouchID(int key)
|
||||
{
|
||||
//QMetaEnum map = QMetaEnum::fromType<Qt::Key>();
|
||||
for (int i = 0; i < MULTI_TOUCH_MAX_NUM; i++) {
|
||||
if (0 == multiTouchID[i]) {
|
||||
multiTouchID[i] = key;
|
||||
//qDebug() << "attach "<<key<<" ("<<map.valueToKey(key)<<") as "<<i;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
//qDebug() << "attach "<<key<<" ("<<map.valueToKey(key)<<") failed ";
|
||||
return -1;
|
||||
}
|
||||
|
||||
void InputConvertGame::detachTouchID(int key)
|
||||
{
|
||||
//QMetaEnum map = QMetaEnum::fromType<Qt::Key>();
|
||||
for (int i = 0; i < MULTI_TOUCH_MAX_NUM; i++) {
|
||||
if (key == multiTouchID[i]) {
|
||||
multiTouchID[i] = 0;
|
||||
//qDebug() << "detach "<<key<<" ("<<map.valueToKey(key)<<") from "<<i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -180,130 +241,65 @@ int InputConvertGame::getTouchID(int key)
|
|||
return -1;
|
||||
}
|
||||
|
||||
void InputConvertGame::processSteerWheel(KeyMap::KeyMapNode &node, const QKeyEvent *from)
|
||||
{
|
||||
int keyPress1 = Qt::Key_unknown;
|
||||
int keyPress2 = Qt::Key_unknown;
|
||||
int keysNum = updateSteerWheelKeysPress(node, from, keyPress1, keyPress2);
|
||||
bool needMove = false;
|
||||
if (QEvent::KeyPress == from->type()) {
|
||||
if (1 == keysNum) {
|
||||
node.steerWheel.firstPressKey = from->key();
|
||||
int id = attachTouchID(node.steerWheel.firstPressKey);
|
||||
if (-1 == id) {
|
||||
return;
|
||||
}
|
||||
// -------- steer wheel event --------
|
||||
|
||||
void InputConvertGame::processSteerWheel(const KeyMap::KeyMapNode &node, const QKeyEvent *from)
|
||||
{
|
||||
int key = from->key();
|
||||
bool flag = from->type() == QEvent::KeyPress;
|
||||
// identify keys
|
||||
if(key == node.steerWheel.up.key){
|
||||
m_ctrlSteerWheel.pressedUp = flag;
|
||||
}else if(key == node.steerWheel.right.key){
|
||||
m_ctrlSteerWheel.pressedRight = flag;
|
||||
}else if(key == node.steerWheel.down.key){
|
||||
m_ctrlSteerWheel.pressedDown = flag;
|
||||
}else{ // left
|
||||
m_ctrlSteerWheel.pressedLeft = flag;
|
||||
}
|
||||
QPointF offset(0.0, 0.0);
|
||||
int nPressed = 0;
|
||||
if(m_ctrlSteerWheel.pressedUp){
|
||||
++nPressed;
|
||||
offset.ry() -= node.steerWheel.up.offset;
|
||||
}
|
||||
if(m_ctrlSteerWheel.pressedRight){
|
||||
++nPressed;
|
||||
offset.rx() += node.steerWheel.right.offset;
|
||||
}
|
||||
if(m_ctrlSteerWheel.pressedDown){
|
||||
++nPressed;
|
||||
offset.ry() += node.steerWheel.down.offset;
|
||||
}
|
||||
if(m_ctrlSteerWheel.pressedLeft){
|
||||
++nPressed;
|
||||
offset.rx() -= node.steerWheel.left.offset;
|
||||
}
|
||||
// action
|
||||
//qDebug()<<nPressed<<"-"<<char(from->key())<<"-"<<from->type()<<"-"<<offset;
|
||||
if(nPressed == 0){ // release all
|
||||
int id = getTouchID(m_ctrlSteerWheel.touchKey);
|
||||
sendTouchUpEvent(id, node.steerWheel.centerPos + m_ctrlSteerWheel.lastOffset);
|
||||
detachTouchID(m_ctrlSteerWheel.touchKey);
|
||||
}else{
|
||||
int id;
|
||||
if(nPressed == 1 && flag){ // first press
|
||||
m_ctrlSteerWheel.touchKey = from->key();
|
||||
id = attachTouchID(m_ctrlSteerWheel.touchKey);
|
||||
sendTouchDownEvent(id, node.steerWheel.centerPos);
|
||||
needMove = true;
|
||||
} else if (2 == keysNum) {
|
||||
needMove = true;
|
||||
}
|
||||
} else if (QEvent::KeyRelease == from->type()){
|
||||
if (0 == keysNum) {
|
||||
int id = getTouchID(node.steerWheel.firstPressKey);
|
||||
sendTouchUpEvent(id, node.steerWheel.centerPos);
|
||||
detachTouchID(node.steerWheel.firstPressKey);
|
||||
node.steerWheel.firstPressKey = 0;
|
||||
} else if (1 == keysNum) {
|
||||
needMove = true;
|
||||
}else{
|
||||
id = getTouchID(m_ctrlSteerWheel.touchKey);
|
||||
}
|
||||
sendTouchMoveEvent(id, node.steerWheel.centerPos + offset);
|
||||
}
|
||||
if (needMove) {
|
||||
steerWheelMove(node, keysNum, keyPress1, keyPress2);
|
||||
}
|
||||
m_ctrlSteerWheel.lastOffset = offset;
|
||||
return;
|
||||
}
|
||||
|
||||
int InputConvertGame::updateSteerWheelKeysPress(KeyMap::KeyMapNode &node, const QKeyEvent *from, int& keyPress1, int& keyPress2)
|
||||
{
|
||||
bool keyPress = false;
|
||||
if (QEvent::KeyPress == from->type()) {
|
||||
keyPress = true;
|
||||
} else if (QEvent::KeyRelease == from->type()) {
|
||||
keyPress = false;
|
||||
}
|
||||
if (from->key() == node.steerWheel.upKey) {
|
||||
node.steerWheel.upKeyPressed = keyPress;
|
||||
} else if (from->key() == node.steerWheel.rightKey) {
|
||||
node.steerWheel.rightKeyPressed = keyPress;
|
||||
} else if (from->key() == node.steerWheel.downKey) {
|
||||
node.steerWheel.downKeyPressed = keyPress;
|
||||
} else if (from->key() == node.steerWheel.leftKey) {
|
||||
node.steerWheel.leftKeyPressed = keyPress;
|
||||
}
|
||||
// -------- key event --------
|
||||
|
||||
int count = 0;
|
||||
keyPress1 = Qt::Key_unknown;
|
||||
keyPress2 = Qt::Key_unknown;
|
||||
|
||||
// 上右下左的顺序统计按键数量,并记录前两个按键码
|
||||
if (node.steerWheel.upKeyPressed) {
|
||||
count++;
|
||||
if (Qt::Key_unknown == keyPress1) {
|
||||
keyPress1 = node.steerWheel.upKey;
|
||||
} else if (Qt::Key_unknown == keyPress2) {
|
||||
keyPress2 = node.steerWheel.upKey;
|
||||
}
|
||||
}
|
||||
if (node.steerWheel.rightKeyPressed) {
|
||||
count++;
|
||||
if (Qt::Key_unknown == keyPress1) {
|
||||
keyPress1 = node.steerWheel.rightKey;
|
||||
} else if (Qt::Key_unknown == keyPress2) {
|
||||
keyPress2 = node.steerWheel.rightKey;
|
||||
}
|
||||
}
|
||||
if (node.steerWheel.downKeyPressed) {
|
||||
count++;
|
||||
if (Qt::Key_unknown == keyPress1) {
|
||||
keyPress1 = node.steerWheel.downKey;
|
||||
} else if (Qt::Key_unknown == keyPress2) {
|
||||
keyPress2 = node.steerWheel.downKey;
|
||||
}
|
||||
}
|
||||
if (node.steerWheel.leftKeyPressed) {
|
||||
count++;
|
||||
if (Qt::Key_unknown == keyPress1) {
|
||||
keyPress1 = node.steerWheel.leftKey;
|
||||
} else if (Qt::Key_unknown == keyPress2) {
|
||||
keyPress2 = node.steerWheel.leftKey;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void InputConvertGame::steerWheelMove(KeyMap::KeyMapNode &node, int keysNum, int keyPress1, int keyPress2)
|
||||
{
|
||||
if (1 != keysNum && 2 != keysNum) {
|
||||
return;
|
||||
}
|
||||
QPointF movePos = node.steerWheel.centerPos;
|
||||
switch (keysNum) {
|
||||
case 2:
|
||||
if (keyPress2 == node.steerWheel.upKey) {
|
||||
movePos.setY(movePos.y() - node.steerWheel.upOffset);
|
||||
} else if (keyPress2 == node.steerWheel.rightKey) {
|
||||
movePos.setX(movePos.x() + node.steerWheel.rightOffset);
|
||||
} else if (keyPress2 == node.steerWheel.downKey) {
|
||||
movePos.setY(movePos.y() + node.steerWheel.downOffset);
|
||||
} else if (keyPress2 == node.steerWheel.leftKey) {
|
||||
movePos.setX(movePos.x() - node.steerWheel.leftOffset);
|
||||
}
|
||||
case 1:
|
||||
if (keyPress1 == node.steerWheel.upKey) {
|
||||
movePos.setY(movePos.y() - node.steerWheel.upOffset);
|
||||
} else if (keyPress1 == node.steerWheel.rightKey) {
|
||||
movePos.setX(movePos.x() + node.steerWheel.rightOffset);
|
||||
} else if (keyPress1 == node.steerWheel.downKey) {
|
||||
movePos.setY(movePos.y() + node.steerWheel.downOffset);
|
||||
} else if (keyPress1 == node.steerWheel.leftKey) {
|
||||
movePos.setX(movePos.x() - node.steerWheel.leftOffset);
|
||||
}
|
||||
break;
|
||||
}
|
||||
sendTouchMoveEvent(getTouchID(node.steerWheel.firstPressKey), movePos);
|
||||
}
|
||||
|
||||
void InputConvertGame::processKeyClick(QPointF clickPos, bool clickTwice, bool switchMap, const QKeyEvent *from)
|
||||
void InputConvertGame::processKeyClick(
|
||||
const QPointF& clickPos, bool clickTwice, bool switchMap, const QKeyEvent *from)
|
||||
{
|
||||
if (switchMap && QEvent::KeyRelease == from->type()) {
|
||||
m_needSwitchGameAgain = !m_needSwitchGameAgain;
|
||||
|
@ -327,9 +323,22 @@ void InputConvertGame::processKeyClick(QPointF clickPos, bool clickTwice, bool s
|
|||
}
|
||||
}
|
||||
|
||||
void InputConvertGame::processKeyDrag(const QPointF& startPos, QPointF endPos, const QKeyEvent* from)
|
||||
{
|
||||
if(QEvent::KeyPress == from->type()){
|
||||
int id = attachTouchID(from->key());
|
||||
sendTouchDownEvent(id, startPos);
|
||||
sendTouchMoveEvent(id, endPos);
|
||||
sendTouchUpEvent(id, endPos);
|
||||
detachTouchID(from->key());
|
||||
}
|
||||
}
|
||||
|
||||
// -------- mouse event --------
|
||||
|
||||
bool InputConvertGame::processMouseClick(const QMouseEvent *from)
|
||||
{
|
||||
KeyMap::KeyMapNode& node = m_keyMap.getKeyMapNode(from->button());
|
||||
const KeyMap::KeyMapNode& node = m_keyMap.getKeyMapNodeMouse(from->button());
|
||||
if (KeyMap::KMT_INVALID == node.type) {
|
||||
return false;
|
||||
}
|
||||
|
@ -350,55 +359,62 @@ bool InputConvertGame::processMouseMove(const QMouseEvent *from)
|
|||
{
|
||||
if (QEvent::MouseMove != from->type()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (checkCursorPos(from)) {
|
||||
m_mouseMoveLastPos = QPointF(0.0f, 0.0f);
|
||||
return true;
|
||||
}
|
||||
if(m_ctrlMouseMove.touching){
|
||||
QPointF mousePos = from->localPos();
|
||||
mousePos.rx() /= m_showSize.width();
|
||||
mousePos.ry() /= m_showSize.height();
|
||||
QPointF offset = mousePos - m_ctrlMouseMove.startPosRel;
|
||||
//qDebug()<<from->localPos()<<" - "<<m_mouseMoveLastConverPos<<" - "<<offset<<" - "<<offset.manhattanLength();
|
||||
|
||||
if (!m_mouseMoveLastPos.isNull()) {
|
||||
QPointF distance = from->localPos() - m_mouseMoveLastPos;
|
||||
distance /= m_keyMap.getMouseMoveMap().speedRatio;
|
||||
|
||||
mouseMoveStartTouch(from);
|
||||
startMouseMoveTimer();
|
||||
|
||||
m_mouseMoveLastConverPos.setX(m_mouseMoveLastConverPos.x() + distance.x() / m_showSize.width());
|
||||
m_mouseMoveLastConverPos.setY(m_mouseMoveLastConverPos.y() + distance.y() / m_showSize.height());
|
||||
|
||||
if (m_mouseMoveLastConverPos.x() < 0.1
|
||||
|| m_mouseMoveLastConverPos.x() > 0.8
|
||||
|| m_mouseMoveLastConverPos.y() < 0.1
|
||||
|| m_mouseMoveLastConverPos.y() > 0.8) {
|
||||
if(mousePos.x()<0.05 || mousePos.x()>0.95 || mousePos.y()<0.05 || mousePos.y()>0.95)
|
||||
{
|
||||
//qDebug()<<"reset";
|
||||
mouseMoveStopTouch();
|
||||
mouseMoveStartTouch(from);
|
||||
}
|
||||
|
||||
sendTouchMoveEvent(getTouchID(Qt::ExtraButton24), m_mouseMoveLastConverPos);
|
||||
offset /= m_keyMap.getMouseMoveMap().speedRatio;
|
||||
m_ctrlMouseMove.lastPosRel = m_ctrlMouseMove.startPosRel + offset;
|
||||
mouseMoveMovingTouch(m_ctrlMouseMove.lastPosRel);
|
||||
}else{
|
||||
m_ctrlMouseMove.touching = true;
|
||||
mouseMoveStartTouch(from);
|
||||
int left = from->globalX() - from->x();
|
||||
int top = from->globalY() - from->y();
|
||||
restrictMouse(left, left + m_showSize.width(), top, top+m_showSize.height());
|
||||
}
|
||||
m_mouseMoveLastPos = from->localPos();
|
||||
return true;
|
||||
}
|
||||
|
||||
void InputConvertGame::moveCursorToStart(const QMouseEvent *from)
|
||||
void InputConvertGame::moveCursorTo(const QMouseEvent *from, const QPoint &localPosPixel)
|
||||
{
|
||||
QPointF mouseMoveStartPos = m_keyMap.getMouseMoveMap().startPos;
|
||||
QPoint localPos = QPoint(m_showSize.width()*mouseMoveStartPos.x(), m_showSize.height()*mouseMoveStartPos.y());
|
||||
QPoint posOffset = from->localPos().toPoint() - localPos;
|
||||
QPoint posOffset = from->pos() - localPosPixel;
|
||||
QPoint globalPos = from->globalPos();
|
||||
|
||||
globalPos -= posOffset;
|
||||
//qDebug()<<"move cursor to "<<globalPos<<" offset "<<posOffset;
|
||||
QCursor::setPos(globalPos);
|
||||
}
|
||||
|
||||
void InputConvertGame::moveCursorTo(const QMouseEvent *from, const QPoint &pos)
|
||||
void InputConvertGame::mouseMoveStartTouch(const QMouseEvent* from)
|
||||
{
|
||||
QPoint posOffset = from->localPos().toPoint() - pos;
|
||||
QPoint globalPos = from->globalPos();
|
||||
moveCursorTo(from, m_ctrlMouseMove.startPosPixel.toPoint());
|
||||
int id = attachTouchID(m_ctrlMouseMove.touchKey);
|
||||
sendTouchDownEvent(id, m_ctrlMouseMove.startPosRel);
|
||||
m_ctrlMouseMove.lastPosRel = m_ctrlMouseMove.startPosRel;
|
||||
m_ctrlMouseMove.touching = true;
|
||||
}
|
||||
|
||||
globalPos -= posOffset;
|
||||
QCursor::setPos(globalPos);
|
||||
void InputConvertGame::mouseMoveMovingTouch(const QPointF& target)
|
||||
{
|
||||
sendTouchMoveEvent(getTouchID(m_ctrlMouseMove.touchKey), target);
|
||||
}
|
||||
|
||||
void InputConvertGame::mouseMoveStopTouch()
|
||||
{
|
||||
int id = getTouchID(m_ctrlMouseMove.touchKey);
|
||||
sendTouchUpEvent(id, m_ctrlMouseMove.lastPosRel);
|
||||
detachTouchID(m_ctrlMouseMove.touchKey);
|
||||
m_ctrlMouseMove.touching = false;
|
||||
}
|
||||
|
||||
void InputConvertGame::startMouseMoveTimer()
|
||||
|
@ -415,66 +431,26 @@ void InputConvertGame::stopMouseMoveTimer()
|
|||
}
|
||||
}
|
||||
|
||||
void InputConvertGame::mouseMoveStartTouch(const QMouseEvent* from)
|
||||
{
|
||||
Q_UNUSED(from);
|
||||
if (!m_mouseMovePress) {
|
||||
QPointF mouseMoveStartPos = m_keyMap.getMouseMoveMap().startPos;
|
||||
//moveCursorToStart(from);
|
||||
int id = attachTouchID(Qt::ExtraButton24);
|
||||
sendTouchDownEvent(id, mouseMoveStartPos);
|
||||
m_mouseMoveLastConverPos = mouseMoveStartPos;
|
||||
m_mouseMovePress = true;
|
||||
}
|
||||
}
|
||||
|
||||
void InputConvertGame::mouseMoveStopTouch()
|
||||
{
|
||||
if (m_mouseMovePress) {
|
||||
sendTouchUpEvent(getTouchID(Qt::ExtraButton24), m_mouseMoveLastConverPos);
|
||||
detachTouchID(Qt::ExtraButton24);
|
||||
m_mouseMovePress = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool InputConvertGame::switchGameMap()
|
||||
{
|
||||
m_gameMap = !m_gameMap;
|
||||
m_gameMap = !m_gameMap;
|
||||
emit grabCursor(m_gameMap);
|
||||
if (m_gameMap) {
|
||||
QGuiApplication::setOverrideCursor(QCursor(Qt::BlankCursor));
|
||||
#ifdef QT_NO_DEBUG
|
||||
QGuiApplication::setOverrideCursor(QCursor(Qt::BlankCursor));
|
||||
#else
|
||||
QGuiApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
|
||||
#endif
|
||||
//restrictMouse(); // called at the first run of processMouseMove()
|
||||
} else {
|
||||
mouseMoveStopTouch();
|
||||
if(m_ctrlMouseMove.touching)
|
||||
mouseMoveStopTouch();
|
||||
QGuiApplication::restoreOverrideCursor();
|
||||
freeMouse();
|
||||
}
|
||||
return m_gameMap;
|
||||
}
|
||||
|
||||
bool InputConvertGame::checkCursorPos(const QMouseEvent *from)
|
||||
{
|
||||
bool moveCursor = false;
|
||||
QPoint pos = from->pos();
|
||||
if (pos.x() < CURSOR_POS_CHECK) {
|
||||
pos.setX(m_showSize.width() - CURSOR_POS_CHECK);
|
||||
moveCursor = true;
|
||||
} else if (pos.x() > m_showSize.width() - CURSOR_POS_CHECK) {
|
||||
pos.setX(CURSOR_POS_CHECK);
|
||||
moveCursor = true;
|
||||
} else if (pos.y() < CURSOR_POS_CHECK) {
|
||||
pos.setY(m_showSize.height() - CURSOR_POS_CHECK);
|
||||
moveCursor = true;
|
||||
} else if (pos.y() > m_showSize.height() - CURSOR_POS_CHECK) {
|
||||
pos.setY(CURSOR_POS_CHECK);
|
||||
moveCursor = true;
|
||||
}
|
||||
|
||||
if (moveCursor) {
|
||||
moveCursorTo(from, pos);
|
||||
}
|
||||
|
||||
return moveCursor;
|
||||
}
|
||||
|
||||
void InputConvertGame::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
if (m_mouseMoveTimer == event->timerId()) {
|
||||
|
|
|
@ -27,6 +27,7 @@ protected:
|
|||
void sendTouchUpEvent(int id, QPointF pos);
|
||||
void sendTouchEvent(int id, QPointF pos, AndroidMotioneventAction action);
|
||||
QPointF calcFrameAbsolutePos(QPointF relativePos);
|
||||
QPointF calcScreenAbsolutePos(QPointF relativePos);
|
||||
|
||||
// multi touch id
|
||||
int attachTouchID(int key);
|
||||
|
@ -34,48 +35,60 @@ protected:
|
|||
int getTouchID(int key);
|
||||
|
||||
// steer wheel
|
||||
void processSteerWheel(KeyMap::KeyMapNode &node, const QKeyEvent* from);
|
||||
int updateSteerWheelKeysPress(KeyMap::KeyMapNode &node, const QKeyEvent* from, int& keyPress1, int& keyPress2);
|
||||
void steerWheelMove(KeyMap::KeyMapNode &node, int keysNum, int keyPress1, int keyPress2);
|
||||
void processSteerWheel(const KeyMap::KeyMapNode &node, const QKeyEvent* from);
|
||||
|
||||
// click
|
||||
void processKeyClick(QPointF clickPos, bool clickTwice, bool switchMap, const QKeyEvent* from);
|
||||
void processKeyClick(const QPointF& clickPos, bool clickTwice, bool switchMap, const QKeyEvent* from);
|
||||
|
||||
// drag
|
||||
void processKeyDrag(const QPointF& startPos, QPointF endPos, const QKeyEvent* from);
|
||||
|
||||
// mouse
|
||||
bool processMouseClick(const QMouseEvent* from);
|
||||
bool processMouseMove(const QMouseEvent* from);
|
||||
void moveCursorToStart(const QMouseEvent* from);
|
||||
void moveCursorTo(const QMouseEvent* from, const QPoint& pos);
|
||||
void startMouseMoveTimer();
|
||||
void stopMouseMoveTimer();
|
||||
void moveCursorTo(const QMouseEvent* from, const QPoint& localPosPixel);
|
||||
void mouseMoveStartTouch(const QMouseEvent* from);
|
||||
void mouseMoveMovingTouch(const QPointF& target);
|
||||
void mouseMoveStopTouch();
|
||||
|
||||
void startMouseMoveTimer();
|
||||
void stopMouseMoveTimer();
|
||||
|
||||
bool switchGameMap();
|
||||
bool checkCursorPos(const QMouseEvent* from);
|
||||
|
||||
protected:
|
||||
void timerEvent(QTimerEvent *event);
|
||||
|
||||
private:
|
||||
enum SteerWheelDirection {
|
||||
SWD_UP = 0,
|
||||
SWD_RIGHT,
|
||||
SWD_DOWN,
|
||||
SWD_LEFT,
|
||||
};
|
||||
|
||||
private:
|
||||
QSize m_frameSize;
|
||||
QSize m_showSize;
|
||||
bool m_gameMap = false;
|
||||
|
||||
int multiTouchID[MULTI_TOUCH_MAX_NUM] = { 0 };
|
||||
int multiTouchID[MULTI_TOUCH_MAX_NUM] = { 0 };
|
||||
|
||||
// steer wheel
|
||||
struct{
|
||||
bool valid = false;
|
||||
bool touching = false;
|
||||
int touchKey = Qt::Key_unknown; // the first key pressed
|
||||
int nKeyPressed = 0;
|
||||
bool pressedUp = false, pressedDown = false;
|
||||
bool pressedLeft = false, pressedRight = false;
|
||||
QPointF centerPos;
|
||||
QPointF lastOffset;
|
||||
} m_ctrlSteerWheel;
|
||||
|
||||
// mouse move
|
||||
struct{
|
||||
bool valid = false;
|
||||
bool touching = false;
|
||||
const int touchKey = Qt::ExtraButton24;
|
||||
QPointF startPosRel; // in [0, 1)
|
||||
QPointF startPosPixel; // in [0, size)
|
||||
QPointF lastPosRel;
|
||||
//QPointF lastPosPixel;
|
||||
} m_ctrlMouseMove;
|
||||
|
||||
// mouse move
|
||||
QPointF m_mouseMoveLastConverPos;
|
||||
QPointF m_mouseMoveLastPos = {0.0f, 0.0f};
|
||||
bool m_mouseMovePress = false;
|
||||
int m_mouseMoveTimer = 0;
|
||||
|
||||
bool m_needSwitchGameAgain = false;
|
||||
|
|
|
@ -41,10 +41,6 @@ void KeyMap::loadKeyMap(const QString &json)
|
|||
QJsonDocument jsonDoc;
|
||||
QJsonObject rootObj;
|
||||
|
||||
QMetaEnum metaEnumKey = QMetaEnum::fromType<Qt::Key>();
|
||||
QMetaEnum metaEnumMouseButtons = QMetaEnum::fromType<Qt::MouseButtons>();
|
||||
QMetaEnum metaEnumKeyMapType = QMetaEnum::fromType<KeyMap::KeyMapType>();
|
||||
|
||||
jsonDoc = QJsonDocument::fromJson(json.toUtf8(), &jsonError);
|
||||
|
||||
if(jsonError.error != QJsonParseError::NoError)
|
||||
|
@ -56,12 +52,13 @@ void KeyMap::loadKeyMap(const QString &json)
|
|||
// switchKey
|
||||
rootObj = jsonDoc.object();
|
||||
if (rootObj.contains("switchKey") && rootObj.value("switchKey").isString()) {
|
||||
Qt::Key key = (Qt::Key)metaEnumKey.keyToValue(rootObj.value("switchKey").toString().toStdString().c_str());
|
||||
if (-1 == key) {
|
||||
QPair<ActionType, int> p = getItemKey(rootObj, "switchKey");
|
||||
if(p.first == AT_INVALID){
|
||||
errorString = QString("json error: switchKey invalid");
|
||||
goto parseError;
|
||||
}
|
||||
m_switchKey = key;
|
||||
m_switchType = p.first;
|
||||
m_switchKey = p.second;
|
||||
} else {
|
||||
errorString = QString("json error: no find switchKey");
|
||||
goto parseError;
|
||||
|
@ -106,153 +103,124 @@ void KeyMap::loadKeyMap(const QString &json)
|
|||
goto parseError;
|
||||
}
|
||||
|
||||
KeyMap::KeyMapType type = (KeyMap::KeyMapType)metaEnumKeyMapType.keyToValue(node.value("type").toString().toStdString().c_str());
|
||||
KeyMap::KeyMapType type = getItemType(node, "type");
|
||||
switch (type) {
|
||||
case KeyMap::KMT_CLICK:
|
||||
{
|
||||
// safe check
|
||||
if (!node.contains("key") || !node.value("key").isString()
|
||||
|| !node.contains("pos") || !node.value("pos").isObject()
|
||||
|| !node.value("pos").toObject().contains("x") || !node.value("pos").toObject().value("x").isDouble()
|
||||
|| !node.value("pos").toObject().contains("y") || !node.value("pos").toObject().value("y").isDouble()
|
||||
|| !node.contains("switchMap") || !node.value("switchMap").isBool()
|
||||
) {
|
||||
if (!checkForClick(node)) {
|
||||
qWarning() << "json error: keyMapNodes node format error";
|
||||
break;
|
||||
}
|
||||
|
||||
Qt::Key key = (Qt::Key)metaEnumKey.keyToValue(node.value("key").toString().toStdString().c_str());
|
||||
Qt::MouseButtons btn = (Qt::MouseButtons)metaEnumMouseButtons.keyToValue(node.value("key").toString().toStdString().c_str());
|
||||
if (-1 == key && -1 == btn) {
|
||||
QPair<ActionType, int> key = getItemKey(node, "key");
|
||||
if(key.first == AT_INVALID){
|
||||
qWarning() << "json error: keyMapNodes node invalid key: " << node.value("key").toString();
|
||||
break;
|
||||
}
|
||||
|
||||
KeyMapNode keyMapNode;
|
||||
keyMapNode.type = type;
|
||||
if (key != -1) {
|
||||
keyMapNode.click.keyNode.key = key;
|
||||
} else {
|
||||
keyMapNode.click.keyNode.key = btn;
|
||||
}
|
||||
keyMapNode.click.keyNode.pos = QPointF(node.value("pos").toObject().value("x").toDouble(),
|
||||
node.value("pos").toObject().value("y").toDouble());
|
||||
keyMapNode.click.switchMap = node.value("switchMap").toBool();
|
||||
keyMapNode.click.keyNode.type = key.first;
|
||||
keyMapNode.click.keyNode.key = key.second;
|
||||
keyMapNode.click.keyNode.pos = getItemPos(node, "pos");
|
||||
keyMapNode.click.switchMap = getItemSwitchMap(node, "switchMap");
|
||||
m_keyMapNodes.push_back(keyMapNode);
|
||||
}
|
||||
break;
|
||||
case KeyMap::KMT_CLICK_TWICE:
|
||||
{
|
||||
// safe check
|
||||
if (!node.contains("key") || !node.value("key").isString()
|
||||
|| !node.contains("pos") || !node.value("pos").isObject()
|
||||
|| !node.value("pos").toObject().contains("x") || !node.value("pos").toObject().value("x").isDouble()
|
||||
|| !node.value("pos").toObject().contains("y") || !node.value("pos").toObject().value("y").isDouble()
|
||||
) {
|
||||
if (!checkForClickDouble(node)) {
|
||||
qWarning() << "json error: keyMapNodes node format error";
|
||||
break;
|
||||
}
|
||||
|
||||
Qt::Key key = (Qt::Key)metaEnumKey.keyToValue(node.value("key").toString().toStdString().c_str());
|
||||
Qt::MouseButtons btn = (Qt::MouseButtons)metaEnumMouseButtons.keyToValue(node.value("key").toString().toStdString().c_str());
|
||||
if (-1 == key && -1 == btn) {
|
||||
QPair<ActionType, int> key = getItemKey(node, "key");
|
||||
if(key.first == AT_INVALID){
|
||||
qWarning() << "json error: keyMapNodes node invalid key: " << node.value("key").toString();
|
||||
break;
|
||||
}
|
||||
|
||||
KeyMapNode keyMapNode;
|
||||
keyMapNode.type = type;
|
||||
if (key != -1) {
|
||||
keyMapNode.clickTwice.keyNode.key = key;
|
||||
} else {
|
||||
keyMapNode.clickTwice.keyNode.key = btn;
|
||||
}
|
||||
keyMapNode.clickTwice.keyNode.pos = QPointF(node.value("pos").toObject().value("x").toDouble(),
|
||||
node.value("pos").toObject().value("y").toDouble());
|
||||
keyMapNode.click.keyNode.type = key.first;
|
||||
keyMapNode.click.keyNode.key = key.second;
|
||||
keyMapNode.click.keyNode.pos = getItemPos(node, "pos");
|
||||
keyMapNode.click.switchMap = getItemSwitchMap(node, "switchMap");
|
||||
m_keyMapNodes.push_back(keyMapNode);
|
||||
}
|
||||
break;
|
||||
case KeyMap::KMT_STEER_WHEEL:
|
||||
{
|
||||
// safe check
|
||||
if (!node.contains("leftKey") || !node.value("leftKey").isString()
|
||||
|| !node.contains("rightKey") || !node.value("rightKey").isString()
|
||||
|| !node.contains("upKey") || !node.value("upKey").isString()
|
||||
|| !node.contains("downKey") || !node.value("downKey").isString()
|
||||
|| !node.contains("leftOffset") || !node.value("leftOffset").isDouble()
|
||||
|| !node.contains("rightOffset") || !node.value("rightOffset").isDouble()
|
||||
|| !node.contains("upOffset") || !node.value("upOffset").isDouble()
|
||||
|| !node.contains("downOffset") || !node.value("downOffset").isDouble()
|
||||
|| !node.contains("centerPos") || !node.value("centerPos").isObject()
|
||||
|| !node.value("centerPos").toObject().contains("x") || !node.value("centerPos").toObject().value("x").isDouble()
|
||||
|| !node.value("centerPos").toObject().contains("y") || !node.value("centerPos").toObject().value("y").isDouble()
|
||||
) {
|
||||
if(!checkForSteerWhell(node)){
|
||||
qWarning() << "json error: keyMapNodes node format error";
|
||||
break;
|
||||
}
|
||||
|
||||
Qt::Key leftKey = (Qt::Key)metaEnumKey.keyToValue(node.value("leftKey").toString().toStdString().c_str());
|
||||
Qt::MouseButtons leftBtn = (Qt::MouseButtons)metaEnumMouseButtons.keyToValue(node.value("leftKey").toString().toStdString().c_str());
|
||||
Qt::Key rightKey = (Qt::Key)metaEnumKey.keyToValue(node.value("rightKey").toString().toStdString().c_str());
|
||||
Qt::MouseButtons rightBtn = (Qt::MouseButtons)metaEnumMouseButtons.keyToValue(node.value("rightKey").toString().toStdString().c_str());
|
||||
Qt::Key upKey = (Qt::Key)metaEnumKey.keyToValue(node.value("upKey").toString().toStdString().c_str());
|
||||
Qt::MouseButtons upBtn = (Qt::MouseButtons)metaEnumMouseButtons.keyToValue(node.value("upKey").toString().toStdString().c_str());
|
||||
Qt::Key downKey = (Qt::Key)metaEnumKey.keyToValue(node.value("downKey").toString().toStdString().c_str());
|
||||
Qt::MouseButtons downBtn = (Qt::MouseButtons)metaEnumMouseButtons.keyToValue(node.value("downKey").toString().toStdString().c_str());
|
||||
|
||||
if ((-1 == leftKey && -1 == leftBtn)
|
||||
|| (-1 == rightKey && -1 == rightBtn)
|
||||
|| (-1 == upKey && -1 == upBtn)
|
||||
|| (-1 == downKey && -1 == downBtn)
|
||||
) {
|
||||
qWarning() << "json error: keyMapNodes node invalid key: " << node.value("key").toString();
|
||||
QPair<ActionType, int> leftKey = getItemKey(node, "leftKey");
|
||||
QPair<ActionType, int> rightKey = getItemKey(node, "rightKey");
|
||||
QPair<ActionType, int> upKey = getItemKey(node, "upKey");
|
||||
QPair<ActionType, int> downKey = getItemKey(node, "downKey");
|
||||
if(leftKey.first == AT_INVALID || rightKey.first == AT_INVALID
|
||||
|| upKey.first == AT_INVALID || downKey.first == AT_INVALID)
|
||||
{
|
||||
if(leftKey.first == AT_INVALID)
|
||||
qWarning() << "json error: keyMapNodes node invalid key: " << node.value("leftKey").toString();
|
||||
if(rightKey.first == AT_INVALID)
|
||||
qWarning() << "json error: keyMapNodes node invalid key: " << node.value("rightKey").toString();
|
||||
if(upKey.first == AT_INVALID)
|
||||
qWarning() << "json error: keyMapNodes node invalid key: " << node.value("upKey").toString();
|
||||
if(downKey.first == AT_INVALID)
|
||||
qWarning() << "json error: keyMapNodes node invalid key: " << node.value("downKey").toString();
|
||||
break;
|
||||
}
|
||||
|
||||
KeyMapNode keyMapNode;
|
||||
keyMapNode.type = type;
|
||||
keyMapNode.steerWheel.leftKeyPressed = false;
|
||||
keyMapNode.steerWheel.rightKeyPressed = false;
|
||||
keyMapNode.steerWheel.upKeyPressed = false;
|
||||
keyMapNode.steerWheel.downKeyPressed = false;
|
||||
keyMapNode.steerWheel.pressKeysNum = 0;
|
||||
keyMapNode.steerWheel.firstPressKey = 0;
|
||||
|
||||
if (leftKey != -1) {
|
||||
keyMapNode.steerWheel.leftKey = leftKey;
|
||||
} else {
|
||||
keyMapNode.steerWheel.leftKey = leftBtn;
|
||||
}
|
||||
if (rightKey != -1) {
|
||||
keyMapNode.steerWheel.rightKey = rightKey;
|
||||
} else {
|
||||
keyMapNode.steerWheel.rightKey = rightBtn;
|
||||
}
|
||||
if (upKey != -1) {
|
||||
keyMapNode.steerWheel.upKey = upKey;
|
||||
} else {
|
||||
keyMapNode.steerWheel.upKey = upBtn;
|
||||
}
|
||||
if (downKey != -1) {
|
||||
keyMapNode.steerWheel.downKey = downKey;
|
||||
} else {
|
||||
keyMapNode.steerWheel.downKey = downBtn;
|
||||
}
|
||||
keyMapNode.steerWheel.leftOffset = node.value("leftOffset").toDouble();
|
||||
keyMapNode.steerWheel.rightOffset = node.value("rightOffset").toDouble();
|
||||
keyMapNode.steerWheel.upOffset = node.value("upOffset").toDouble();
|
||||
keyMapNode.steerWheel.downOffset = node.value("downOffset").toDouble();
|
||||
keyMapNode.steerWheel.centerPos = QPointF(node.value("centerPos").toObject().value("x").toDouble(),
|
||||
node.value("centerPos").toObject().value("y").toDouble());
|
||||
keyMapNode.steerWheel.left = { leftKey.first, leftKey.second,
|
||||
getItemNumber(node, "leftOffset") };
|
||||
keyMapNode.steerWheel.right = { rightKey.first, rightKey.second,
|
||||
getItemNumber(node, "rightOffset") };
|
||||
keyMapNode.steerWheel.up = { upKey.first, upKey.second,
|
||||
getItemNumber(node, "upOffset") };
|
||||
keyMapNode.steerWheel.down = { downKey.first, downKey.second,
|
||||
getItemNumber(node, "downOffset") };
|
||||
|
||||
keyMapNode.steerWheel.centerPos = getItemPos(node, "centerPos");
|
||||
m_idxSteerWheel = m_keyMapNodes.size();
|
||||
m_keyMapNodes.push_back(keyMapNode);
|
||||
}
|
||||
break;
|
||||
case KeyMap::KMT_DRAG:
|
||||
{
|
||||
// safe check
|
||||
if(!checkForDrag(node)){
|
||||
qWarning() << "json error: keyMapNodes node format error";
|
||||
break;
|
||||
}
|
||||
|
||||
QPair<ActionType, int> key = getItemKey(node, "key");
|
||||
if(key.first == AT_INVALID){
|
||||
qWarning() << "json error: keyMapNodes node invalid key: " << node.value("key").toString();
|
||||
break;
|
||||
}
|
||||
KeyMapNode keyMapNode;
|
||||
keyMapNode.type = type;
|
||||
keyMapNode.drag.type = key.first;
|
||||
keyMapNode.drag.key = key.second;
|
||||
keyMapNode.drag.startPos = getItemPos(node, "startPos");
|
||||
keyMapNode.drag.endPos = getItemPos(node, "endPos");
|
||||
m_keyMapNodes.push_back(keyMapNode);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
qWarning() << "json error: keyMapNodes invalid node type:" << node.value("type").toString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// this must be called after m_keyMapNodes is stable
|
||||
makeReverseMap();
|
||||
qWarning() << "Script updated.";
|
||||
|
||||
parseError:
|
||||
if (!errorString.isEmpty()) {
|
||||
|
@ -261,35 +229,27 @@ parseError:
|
|||
return;
|
||||
}
|
||||
|
||||
KeyMap::KeyMapNode& KeyMap::getKeyMapNode(int key)
|
||||
const KeyMap::KeyMapNode& KeyMap::getKeyMapNode(int key)
|
||||
{
|
||||
for (auto& itemNode : m_keyMapNodes) {
|
||||
switch (itemNode.type) {
|
||||
case KMT_CLICK:
|
||||
if (itemNode.click.keyNode.key == key) {
|
||||
return itemNode;
|
||||
}
|
||||
break;
|
||||
case KMT_CLICK_TWICE:
|
||||
if (itemNode.clickTwice.keyNode.key == key) {
|
||||
return itemNode;
|
||||
}
|
||||
break;
|
||||
case KMT_STEER_WHEEL:
|
||||
if (itemNode.steerWheel.leftKey == key
|
||||
|| itemNode.steerWheel.rightKey == key
|
||||
|| itemNode.steerWheel.upKey == key
|
||||
|| itemNode.steerWheel.downKey == key
|
||||
) {
|
||||
return itemNode;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto p = rmapKey.value(key, &m_invalidNode);
|
||||
if(p == &m_invalidNode)
|
||||
return *rmapMouse.value(key, &m_invalidNode);
|
||||
return *p;
|
||||
}
|
||||
|
||||
return m_invalidNode;
|
||||
const KeyMap::KeyMapNode& KeyMap::getKeyMapNodeKey(int key)
|
||||
{
|
||||
return *rmapKey.value(key, &m_invalidNode);
|
||||
}
|
||||
|
||||
const KeyMap::KeyMapNode& KeyMap::getKeyMapNodeMouse(int key)
|
||||
{
|
||||
return *rmapMouse.value(key, &m_invalidNode);
|
||||
}
|
||||
|
||||
bool KeyMap::isSwitchOnKeyboard()
|
||||
{
|
||||
return m_switchType == AT_KEY;
|
||||
}
|
||||
|
||||
int KeyMap::getSwitchKey()
|
||||
|
@ -297,12 +257,159 @@ int KeyMap::getSwitchKey()
|
|||
return m_switchKey;
|
||||
}
|
||||
|
||||
KeyMap::MouseMoveMap KeyMap::getMouseMoveMap()
|
||||
const KeyMap::MouseMoveMap& KeyMap::getMouseMoveMap()
|
||||
{
|
||||
return m_mouseMoveMap;
|
||||
}
|
||||
|
||||
bool KeyMap::enableMouseMoveMap()
|
||||
const KeyMap::KeyMapNode& KeyMap::getSteerWheelMap()
|
||||
{
|
||||
return m_keyMapNodes[m_idxSteerWheel];
|
||||
}
|
||||
|
||||
bool KeyMap::isValidMouseMoveMap()
|
||||
{
|
||||
return !m_mouseMoveMap.startPos.isNull();
|
||||
}
|
||||
|
||||
bool KeyMap::isValidSteerWheelMap()
|
||||
{
|
||||
return m_idxSteerWheel != -1;
|
||||
}
|
||||
|
||||
void KeyMap::makeReverseMap()
|
||||
{
|
||||
rmapKey.clear();
|
||||
rmapMouse.clear();
|
||||
for(int i = 0 ;i < m_keyMapNodes.size(); ++i) {
|
||||
auto& node = m_keyMapNodes[i];
|
||||
switch (node.type) {
|
||||
case KMT_CLICK:
|
||||
{
|
||||
QMultiHash<int, KeyMapNode*>& m = node.click.keyNode.type == AT_KEY ? rmapKey : rmapMouse;
|
||||
m.insert(node.click.keyNode.key, &node);
|
||||
}
|
||||
break;
|
||||
case KMT_CLICK_TWICE:
|
||||
{
|
||||
QMultiHash<int, KeyMapNode*>& m = node.clickTwice.keyNode.type == AT_KEY ? rmapKey : rmapMouse;
|
||||
m.insert(node.clickTwice.keyNode.key, &node);
|
||||
}
|
||||
break;
|
||||
case KMT_STEER_WHEEL:
|
||||
{
|
||||
QMultiHash<int, KeyMapNode*>& ml = node.steerWheel.left.type == AT_KEY ? rmapKey : rmapMouse;
|
||||
ml.insert(node.steerWheel.left.key, &node);
|
||||
QMultiHash<int, KeyMapNode*>& mr = node.steerWheel.right.type == AT_KEY ? rmapKey : rmapMouse;
|
||||
mr.insert(node.steerWheel.right.key, &node);
|
||||
QMultiHash<int, KeyMapNode*>& mu = node.steerWheel.up.type == AT_KEY ? rmapKey : rmapMouse;
|
||||
mu.insert(node.steerWheel.up.key, &node);
|
||||
QMultiHash<int, KeyMapNode*>& md = node.steerWheel.down.type == AT_KEY ? rmapKey : rmapMouse;
|
||||
md.insert(node.steerWheel.down.key, &node);
|
||||
}
|
||||
break;
|
||||
case KMT_DRAG:
|
||||
{
|
||||
QMultiHash<int, KeyMapNode*>& m = node.drag.type == AT_KEY ? rmapKey : rmapMouse;
|
||||
m.insert(node.drag.key, &node);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---- check and get of json item ----
|
||||
|
||||
bool KeyMap::checkItemKey(const QJsonObject& node, const QString& name)
|
||||
{
|
||||
return node.contains(name) && node.value(name).isString();
|
||||
}
|
||||
|
||||
bool KeyMap::checkItemPos(const QJsonObject& node, const QString& name)
|
||||
{
|
||||
if(node.contains(name) && node.value(name).isObject()){
|
||||
QJsonObject pos = node.value(name).toObject();
|
||||
return pos.contains("x") && pos.value("x").isDouble()
|
||||
&& pos.contains("y") && pos.value("y").isDouble();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KeyMap::checkItemDouble(const QJsonObject& node, const QString& name)
|
||||
{
|
||||
return node.contains(name) && node.value(name).isDouble();
|
||||
}
|
||||
|
||||
bool KeyMap::checkItemSwitchMap(const QJsonObject& node, const QString& name)
|
||||
{
|
||||
return !node.contains(name) || node.value(name).isBool();
|
||||
}
|
||||
|
||||
KeyMap::KeyMapType KeyMap::getItemType(const QJsonObject& node, const QString& name)
|
||||
{
|
||||
QString value = node.value(name).toString();
|
||||
return static_cast<KeyMap::KeyMapType>(m_metaEnumKeyMapType.keyToValue(value.toStdString().c_str()));
|
||||
}
|
||||
|
||||
QPair<KeyMap::ActionType, int> KeyMap::getItemKey(const QJsonObject& node, const QString& name)
|
||||
{
|
||||
QString value = node.value(name).toString();
|
||||
int key = m_metaEnumKey.keyToValue(value.toStdString().c_str());
|
||||
int btn = m_metaEnumMouseButtons.keyToValue(value.toStdString().c_str());
|
||||
if(key == -1 && btn == -1){
|
||||
return {AT_INVALID, -1};
|
||||
}else if(key != -1){
|
||||
return {AT_KEY, key};
|
||||
}else{
|
||||
return {AT_MOUSE, btn};
|
||||
}
|
||||
}
|
||||
|
||||
QPointF KeyMap::getItemPos(const QJsonObject& node, const QString& name)
|
||||
{
|
||||
QJsonObject pos = node.value(name).toObject();
|
||||
return QPointF(pos.value("x").toDouble(), pos.value("y").toDouble());
|
||||
}
|
||||
|
||||
double KeyMap::getItemNumber(const QJsonObject& node, const QString& name)
|
||||
{
|
||||
return node.value(name).toDouble();
|
||||
}
|
||||
|
||||
bool KeyMap::getItemSwitchMap(const QJsonObject& node, const QString& name)
|
||||
{
|
||||
return node.value(name).toBool(false);
|
||||
}
|
||||
|
||||
|
||||
// ---- check for key-map node ----
|
||||
|
||||
bool KeyMap::checkForClick(const QJsonObject& node)
|
||||
{
|
||||
return checkItemKey(node, "key") && checkItemPos(node, "pos")
|
||||
&& checkItemSwitchMap(node, "switchMap");
|
||||
}
|
||||
|
||||
bool KeyMap::checkForClickDouble(const QJsonObject& node)
|
||||
{
|
||||
return checkForClick(node);
|
||||
}
|
||||
|
||||
bool KeyMap::checkForSteerWhell(const QJsonObject& node)
|
||||
{
|
||||
return checkItemKey(node, "leftKey") && checkItemKey(node, "rightKey")
|
||||
&& checkItemKey(node, "upKey") && checkItemKey(node, "downKey")
|
||||
&& checkItemDouble(node, "leftOffset") && checkItemDouble(node, "rightOffset")
|
||||
&& checkItemDouble(node, "upOffset") && checkItemDouble(node, "downOffset")
|
||||
&& checkItemPos(node, "centerPos");
|
||||
}
|
||||
|
||||
bool KeyMap::checkForDrag(const QJsonObject& node)
|
||||
{
|
||||
return checkItemKey(node, "key")
|
||||
&& checkItemPos(node, "startPos") && checkItemPos(node, "endPos")
|
||||
&& checkItemSwitchMap(node, "switchMap");
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,11 @@
|
|||
#include <QPointF>
|
||||
#include <QVector>
|
||||
#include <QRectF>
|
||||
#include <QPair>
|
||||
#include <QMetaEnum>
|
||||
#include <QMultiHash>
|
||||
|
||||
class QJsonObject;
|
||||
|
||||
class KeyMap : public QObject
|
||||
{
|
||||
|
@ -15,10 +19,19 @@ public:
|
|||
KMT_CLICK = 0,
|
||||
KMT_CLICK_TWICE,
|
||||
KMT_STEER_WHEEL,
|
||||
KMT_DRAG,
|
||||
};
|
||||
Q_ENUM(KeyMapType)
|
||||
|
||||
enum ActionType {
|
||||
AT_INVALID = -1,
|
||||
AT_KEY = 0,
|
||||
AT_MOUSE = 1,
|
||||
};
|
||||
Q_ENUM(ActionType)
|
||||
|
||||
struct KeyNode {
|
||||
ActionType type = AT_INVALID;
|
||||
int key = Qt::Key_unknown;
|
||||
QPointF pos = QPointF(0, 0);
|
||||
};
|
||||
|
@ -34,39 +47,27 @@ public:
|
|||
KeyNode keyNode;
|
||||
} clickTwice;
|
||||
struct {
|
||||
// 方向盘矩形中心位置
|
||||
QPointF centerPos = {0.0f, 0.0f};
|
||||
|
||||
// 方向盘矩形四个方向偏移量
|
||||
float leftOffset = 0.0f;
|
||||
float rightOffset = 0.0f;
|
||||
float upOffset = 0.0f;
|
||||
float downOffset = 0.0f;
|
||||
|
||||
// 方向盘矩形四个方向按键
|
||||
int leftKey = Qt::Key_unknown;
|
||||
int rightKey = Qt::Key_unknown;
|
||||
int upKey = Qt::Key_unknown;
|
||||
int downKey = Qt::Key_unknown;
|
||||
|
||||
// 辅助变量
|
||||
// 方向键的按下状态
|
||||
bool leftKeyPressed = false;
|
||||
bool rightKeyPressed = false;
|
||||
bool upKeyPressed = false;
|
||||
bool downKeyPressed = false;
|
||||
// 按下方向键的数量
|
||||
int pressKeysNum = 0;
|
||||
// 第一次按下的键
|
||||
int firstPressKey = 0;
|
||||
QPointF centerPos = {0.0, 0.0};
|
||||
struct DirInfo{
|
||||
ActionType type = AT_KEY; // keyboard/mouse
|
||||
int key = Qt::Key_unknown; // key/button
|
||||
double offset = 0.0;
|
||||
};
|
||||
DirInfo left, right, up, down;
|
||||
} steerWheel;
|
||||
struct {
|
||||
ActionType type = AT_KEY;
|
||||
int key = Qt::Key_unknown;
|
||||
QPointF startPos = QPointF(0, 0);
|
||||
QPointF endPos = QPointF(0, 0);
|
||||
} drag;
|
||||
};
|
||||
KeyMapNode() {}
|
||||
~KeyMapNode() {}
|
||||
};
|
||||
|
||||
struct MouseMoveMap {
|
||||
QPointF startPos = {0.0f, 0.0f};
|
||||
QPointF startPos = {0.0, 0.0};
|
||||
int speedRatio = 1;
|
||||
};
|
||||
|
||||
|
@ -74,19 +75,58 @@ public:
|
|||
virtual ~KeyMap();
|
||||
|
||||
void loadKeyMap(const QString &json);
|
||||
KeyMap::KeyMapNode& getKeyMapNode(int key);
|
||||
const KeyMap::KeyMapNode& getKeyMapNode(int key);
|
||||
const KeyMap::KeyMapNode& getKeyMapNodeKey(int key);
|
||||
const KeyMap::KeyMapNode& getKeyMapNodeMouse(int key);
|
||||
bool isSwitchOnKeyboard();
|
||||
int getSwitchKey();
|
||||
MouseMoveMap getMouseMoveMap();
|
||||
bool enableMouseMoveMap();
|
||||
|
||||
bool isValidMouseMoveMap();
|
||||
bool isValidSteerWheelMap();
|
||||
const MouseMoveMap& getMouseMoveMap();
|
||||
const KeyMapNode& getSteerWheelMap();
|
||||
|
||||
static const QString& getKeyMapPath();
|
||||
|
||||
private:
|
||||
// set up the reverse map from key/event event to keyMapNode
|
||||
void makeReverseMap();
|
||||
|
||||
// parse json of the mapping script
|
||||
bool checkItemKey(const QJsonObject& node, const QString& name="key");
|
||||
bool checkItemPos(const QJsonObject& node, const QString& name="pos");
|
||||
bool checkItemDouble(const QJsonObject& node, const QString& name);
|
||||
bool checkItemSwitchMap(const QJsonObject& node, const QString& name="switchMap");
|
||||
|
||||
KeyMapType getItemType(const QJsonObject& node, const QString& name="type");
|
||||
QPair<ActionType, int> getItemKey(const QJsonObject& node, const QString& name="key");
|
||||
QPointF getItemPos(const QJsonObject& node, const QString& name="pos");
|
||||
double getItemNumber(const QJsonObject& node, const QString& name);
|
||||
bool getItemSwitchMap(const QJsonObject& node, const QString& name="switchMap");
|
||||
|
||||
private:
|
||||
bool checkForClick(const QJsonObject& node);
|
||||
bool checkForClickDouble(const QJsonObject& node);
|
||||
bool checkForSteerWhell(const QJsonObject& node);
|
||||
bool checkForDrag(const QJsonObject& node);
|
||||
|
||||
private:
|
||||
QVector<KeyMapNode> m_keyMapNodes;
|
||||
KeyMapNode m_invalidNode;
|
||||
ActionType m_switchType = AT_KEY;
|
||||
int m_switchKey = Qt::Key_QuoteLeft;
|
||||
MouseMoveMap m_mouseMoveMap;
|
||||
static QString s_keyMapPath;
|
||||
|
||||
int m_idxSteerWheel = -1;
|
||||
|
||||
// mapping of key/mouse event name to index
|
||||
QMetaEnum m_metaEnumKey = QMetaEnum::fromType<Qt::Key>();
|
||||
QMetaEnum m_metaEnumMouseButtons = QMetaEnum::fromType<Qt::MouseButtons>();
|
||||
QMetaEnum m_metaEnumKeyMapType = QMetaEnum::fromType<KeyMap::KeyMapType>();
|
||||
// reverse map of key/mouse event
|
||||
QMultiHash<int, KeyMapNode*> rmapKey;
|
||||
QMultiHash<int, KeyMapNode*> rmapMouse;
|
||||
};
|
||||
|
||||
#endif // KEYMAP_H
|
||||
|
|
|
@ -90,6 +90,13 @@ Server *Device::getServer()
|
|||
return m_server;
|
||||
}
|
||||
|
||||
void Device::updateScript(QString script)
|
||||
{
|
||||
if(m_controller){
|
||||
m_controller->updateScript(script);
|
||||
}
|
||||
}
|
||||
|
||||
void Device::initSignals()
|
||||
{
|
||||
if (m_controller && m_videoForm) {
|
||||
|
|
|
@ -35,6 +35,8 @@ public:
|
|||
Controller *getController();
|
||||
Server *getServer();
|
||||
|
||||
void updateScript(QString script);
|
||||
|
||||
signals:
|
||||
void deviceDisconnect(QString serial);
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ void ToolForm::initStyle()
|
|||
IconHelper::Instance()->SetIcon(ui->closeScreenBtn, QChar(0xf070), 15);
|
||||
IconHelper::Instance()->SetIcon(ui->powerBtn, QChar(0xf011), 15);
|
||||
IconHelper::Instance()->SetIcon(ui->expandNotifyBtn, QChar(0xf103), 15);
|
||||
IconHelper::Instance()->SetIcon(ui->screenShotBtn, QChar(0xf05b), 15);
|
||||
}
|
||||
|
||||
void ToolForm::mousePressEvent(QMouseEvent *event)
|
||||
|
@ -115,6 +116,13 @@ void ToolForm::on_powerBtn_clicked()
|
|||
}
|
||||
}
|
||||
|
||||
void ToolForm::on_screenShotBtn_clicked()
|
||||
{
|
||||
if (m_videoForm && m_videoForm->getController()) {
|
||||
m_videoForm->getController()->screenShot();
|
||||
}
|
||||
}
|
||||
|
||||
void ToolForm::on_volumeUpBtn_clicked()
|
||||
{
|
||||
if (m_videoForm && m_videoForm->getController()) {
|
||||
|
|
|
@ -40,6 +40,8 @@ private slots:
|
|||
|
||||
void on_powerBtn_clicked();
|
||||
|
||||
void on_screenShotBtn_clicked();
|
||||
|
||||
void on_volumeUpBtn_clicked();
|
||||
|
||||
void on_volumeDownBtn_clicked();
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>63</width>
|
||||
<height>497</height>
|
||||
<height>537</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -133,6 +133,16 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="screenShotBtn">
|
||||
<property name="toolTip">
|
||||
<string>screen shot</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
|
|
@ -145,7 +145,8 @@ void VideoForm::updateShowSize(const QSize &newSize)
|
|||
showSize.setHeight(qMin(newSize.height(), screenRect.height() - 200));
|
||||
showSize.setWidth(showSize.height() * m_widthHeightRatio);
|
||||
} else {
|
||||
showSize.setWidth(qMin(newSize.width(), screenRect.width()/2));
|
||||
//showSize.setWidth(qMin(newSize.width(), screenRect.width()/2));
|
||||
showSize.setWidth(qMin(newSize.width(), screenRect.width() - 200));
|
||||
showSize.setHeight(showSize.width() * m_widthHeightRatio);
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,17 @@ bool DeviceManage::connectDevice(Device::DeviceParams params)
|
|||
return true;
|
||||
}
|
||||
|
||||
void DeviceManage::updateScript(QString script)
|
||||
{
|
||||
QMapIterator<QString, QPointer<Device>> i(m_devices);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
if (i.value()) {
|
||||
i.value()->updateScript(script);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DeviceManage::disconnectDevice(const QString &serial)
|
||||
{
|
||||
bool ret = false;
|
||||
|
|
|
@ -14,6 +14,8 @@ public:
|
|||
virtual ~DeviceManage();
|
||||
|
||||
bool connectDevice(Device::DeviceParams params);
|
||||
void updateScript(QString script);
|
||||
|
||||
bool disconnectDevice(const QString &serial);
|
||||
void disconnectAllDevice();
|
||||
|
||||
|
|
|
@ -81,11 +81,12 @@ void Dialog::initUI()
|
|||
ui->bitRateBox->setCurrentIndex(2);
|
||||
|
||||
ui->maxSizeBox->addItem("600");
|
||||
ui->maxSizeBox->addItem("800");
|
||||
ui->maxSizeBox->addItem("720");
|
||||
ui->maxSizeBox->addItem("1000");
|
||||
ui->maxSizeBox->addItem("1200");
|
||||
ui->maxSizeBox->addItem("1280");
|
||||
ui->maxSizeBox->addItem("1920");
|
||||
ui->maxSizeBox->addItem("native");
|
||||
ui->maxSizeBox->setCurrentIndex(2);
|
||||
ui->maxSizeBox->setCurrentIndex(3);
|
||||
|
||||
ui->formatBox->addItem("mp4");
|
||||
ui->formatBox->addItem("mkv");
|
||||
|
@ -316,7 +317,7 @@ void Dialog::on_stopAllServerBtn_clicked()
|
|||
m_deviceManage.disconnectAllDevice();
|
||||
}
|
||||
|
||||
void Dialog::on_updateGameScriptBtn_clicked()
|
||||
void Dialog::on_refreshGameScriptBtn_clicked()
|
||||
{
|
||||
ui->gameBox->clear();
|
||||
QDir dir(KeyMap::getKeyMapPath());
|
||||
|
@ -334,9 +335,14 @@ void Dialog::on_updateGameScriptBtn_clicked()
|
|||
}
|
||||
}
|
||||
|
||||
void Dialog::on_applyScriptBtn_clicked()
|
||||
{
|
||||
m_deviceManage.updateScript(getGameScript(ui->gameBox->currentText()));
|
||||
}
|
||||
|
||||
void Dialog::on_gameCheck_clicked(bool checked)
|
||||
{
|
||||
if (checked) {
|
||||
on_updateGameScriptBtn_clicked();
|
||||
on_refreshGameScriptBtn_clicked();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,8 @@ private slots:
|
|||
|
||||
void on_stopAllServerBtn_clicked();
|
||||
|
||||
void on_updateGameScriptBtn_clicked();
|
||||
void on_refreshGameScriptBtn_clicked();
|
||||
void on_applyScriptBtn_clicked();
|
||||
void on_gameCheck_clicked(bool checked);
|
||||
|
||||
private:
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>513</width>
|
||||
<height>637</height>
|
||||
<width>600</width>
|
||||
<height>700</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>16777215</height>
|
||||
<height>2160</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -26,20 +26,20 @@
|
|||
<string>USB line</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="3" column="2">
|
||||
<widget class="QPushButton" name="getIPBtn">
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="serialBox"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>get device ip</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
<string>device serial:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QPushButton" name="stopServerBtn">
|
||||
<item row="3" column="2">
|
||||
<widget class="QPushButton" name="getIPBtn">
|
||||
<property name="text">
|
||||
<string>stop server</string>
|
||||
<string>get device IP</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
|
@ -49,33 +49,13 @@
|
|||
<item row="3" column="1">
|
||||
<widget class="QPushButton" name="updateDevice">
|
||||
<property name="text">
|
||||
<string>update device</string>
|
||||
<string>refresh devices</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QPushButton" name="startAdbdBtn">
|
||||
<property name="text">
|
||||
<string>start adbd</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>device serial:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="serialBox"/>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="startServerBtn">
|
||||
<property name="text">
|
||||
|
@ -93,6 +73,26 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QPushButton" name="stopServerBtn">
|
||||
<property name="text">
|
||||
<string>stop server</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QPushButton" name="startAdbdBtn">
|
||||
<property name="text">
|
||||
<string>start adbd</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -101,8 +101,37 @@
|
|||
<property name="title">
|
||||
<string>Wireless</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4" columnstretch="2,0,0,1,2">
|
||||
<item row="3" column="2">
|
||||
<layout class="QGridLayout" name="gridLayout_4" columnstretch="2,0,0,1,2,0">
|
||||
<item row="4" column="4">
|
||||
<widget class="QPushButton" name="wirelessConnectBtn">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>wireless connect</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLineEdit" name="deviceIpEdt">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>128</number>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string notr="true">192.168.0.1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
|
@ -121,38 +150,27 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<item row="4" column="3">
|
||||
<widget class="QLineEdit" name="devicePortEdt">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string notr="true">5555</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLineEdit" name="deviceIpEdt">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string notr="true">192.168.0.1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QPushButton" name="wirelessConnectBtn">
|
||||
<property name="text">
|
||||
<string>wireless connect</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="4">
|
||||
<item row="4" column="5">
|
||||
<widget class="QPushButton" name="wirelessDisConnectBtn">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>wireless disconnect</string>
|
||||
</property>
|
||||
|
@ -169,7 +187,7 @@
|
|||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>200</height>
|
||||
<height>240</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
|
@ -243,49 +261,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3" colspan="2">
|
||||
<widget class="QCheckBox" name="notDisplayCheck">
|
||||
<item row="0" column="9" colspan="2">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>not display</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
<string>record format:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3" colspan="2">
|
||||
<widget class="QComboBox" name="bitRateBox">
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="currentText">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="6" colspan="2">
|
||||
<widget class="QCheckBox" name="alwaysTopCheck">
|
||||
<property name="text">
|
||||
<string>always top</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="11" colspan="2">
|
||||
<widget class="QCheckBox" name="useReverseCheck">
|
||||
<property name="text">
|
||||
<string>use reverse</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="12">
|
||||
<widget class="QComboBox" name="formatBox"/>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
|
@ -296,35 +278,85 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="6">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<item row="0" column="11">
|
||||
<widget class="QComboBox" name="formatBox"/>
|
||||
</item>
|
||||
<item row="3" column="6" colspan="2">
|
||||
<widget class="QPushButton" name="refreshGameScriptBtn">
|
||||
<property name="text">
|
||||
<string>max size:</string>
|
||||
<string>refresh script</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="9" colspan="2">
|
||||
<widget class="QCheckBox" name="closeScreenCheck">
|
||||
<property name="text">
|
||||
<string>close screen</string>
|
||||
<item row="2" column="9" colspan="3">
|
||||
<widget class="QCheckBox" name="useReverseCheck">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3" colspan="8">
|
||||
<widget class="QLineEdit" name="recordPathEdt">
|
||||
<property name="readOnly">
|
||||
<property name="text">
|
||||
<string>reverse connection</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="7">
|
||||
<widget class="QComboBox" name="maxSizeBox">
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
<item row="3" column="10" colspan="2">
|
||||
<widget class="QCheckBox" name="gameCheck">
|
||||
<property name="text">
|
||||
<string>auto enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="11" colspan="2">
|
||||
<item row="2" column="3" colspan="2">
|
||||
<widget class="QCheckBox" name="alwaysTopCheck">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>always on top</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="3">
|
||||
<widget class="QCheckBox" name="notDisplayCheck">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>background record</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="6" colspan="3">
|
||||
<widget class="QCheckBox" name="closeScreenCheck">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>screen-off</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="10" colspan="2">
|
||||
<widget class="QPushButton" name="selectRecordPathBtn">
|
||||
<property name="text">
|
||||
<string>select path</string>
|
||||
|
@ -334,40 +366,44 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="10">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>record format:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="8" colspan="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="5">
|
||||
<item row="3" column="0" colspan="6">
|
||||
<widget class="QComboBox" name="gameBox"/>
|
||||
</item>
|
||||
<item row="3" column="6" colspan="2">
|
||||
<widget class="QPushButton" name="updateGameScriptBtn">
|
||||
<property name="text">
|
||||
<string>update script</string>
|
||||
<item row="1" column="3" colspan="7">
|
||||
<widget class="QLineEdit" name="recordPathEdt">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="9" colspan="4">
|
||||
<widget class="QCheckBox" name="gameCheck">
|
||||
<item row="0" column="2" colspan="2">
|
||||
<widget class="QComboBox" name="bitRateBox">
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="currentText">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="8" colspan="2">
|
||||
<widget class="QPushButton" name="applyScriptBtn">
|
||||
<property name="text">
|
||||
<string>custom map</string>
|
||||
<string>apply</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="7" colspan="2">
|
||||
<widget class="QComboBox" name="maxSizeBox">
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4" colspan="3">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>max size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -378,6 +414,16 @@
|
|||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<tabstops>
|
||||
<tabstop>bitRateBox</tabstop>
|
||||
<tabstop>formatBox</tabstop>
|
||||
<tabstop>recordPathEdt</tabstop>
|
||||
<tabstop>selectRecordPathBtn</tabstop>
|
||||
<tabstop>gameBox</tabstop>
|
||||
<tabstop>refreshGameScriptBtn</tabstop>
|
||||
<tabstop>serialBox</tabstop>
|
||||
<tabstop>startServerBtn</tabstop>
|
||||
<tabstop>stopServerBtn</tabstop>
|
||||
<tabstop>stopAllServerBtn</tabstop>
|
||||
<tabstop>updateDevice</tabstop>
|
||||
<tabstop>getIPBtn</tabstop>
|
||||
<tabstop>startAdbdBtn</tabstop>
|
||||
|
@ -387,13 +433,8 @@
|
|||
<tabstop>wirelessDisConnectBtn</tabstop>
|
||||
<tabstop>adbCommandEdt</tabstop>
|
||||
<tabstop>adbCommandBtn</tabstop>
|
||||
<tabstop>formatBox</tabstop>
|
||||
<tabstop>recordPathEdt</tabstop>
|
||||
<tabstop>selectRecordPathBtn</tabstop>
|
||||
<tabstop>serialBox</tabstop>
|
||||
<tabstop>startServerBtn</tabstop>
|
||||
<tabstop>stopServerBtn</tabstop>
|
||||
<tabstop>outEdit</tabstop>
|
||||
<tabstop>stopAdbBtn</tabstop>
|
||||
<tabstop>clearOut</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
|
Binary file not shown.
|
@ -16,22 +16,22 @@
|
|||
<translation type="vanished">file transfer failed</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/device.cpp" line="108"/>
|
||||
<location filename="../../device/device.cpp" line="115"/>
|
||||
<source>install apk</source>
|
||||
<translation>install apk</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/device.cpp" line="110"/>
|
||||
<location filename="../../device/device.cpp" line="117"/>
|
||||
<source>file transfer</source>
|
||||
<translation>file transfer</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/device.cpp" line="113"/>
|
||||
<location filename="../../device/device.cpp" line="120"/>
|
||||
<source>wait current %1 to complete</source>
|
||||
<translation>wait current %1 to complete</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/device.cpp" line="116"/>
|
||||
<location filename="../../device/device.cpp" line="123"/>
|
||||
<source>%1 complete, save in %2</source>
|
||||
<translation>%1 complete, save in %2</translation>
|
||||
</message>
|
||||
|
@ -41,7 +41,7 @@
|
|||
<translation type="vanished">%1 complete\n save in %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/device.cpp" line="119"/>
|
||||
<location filename="../../device/device.cpp" line="126"/>
|
||||
<source>%1 failed</source>
|
||||
<translation>%1 failed</translation>
|
||||
</message>
|
||||
|
@ -54,99 +54,105 @@
|
|||
<translation>Wireless</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="147"/>
|
||||
<location filename="../../dialog.ui" line="114"/>
|
||||
<source>wireless connect</source>
|
||||
<translation>wireless connect</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="157"/>
|
||||
<location filename="../../dialog.ui" line="175"/>
|
||||
<source>wireless disconnect</source>
|
||||
<translation>wireless disconnect</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="236"/>
|
||||
<location filename="../../dialog.ui" line="254"/>
|
||||
<source>Start Config</source>
|
||||
<translation>Start Config</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="292"/>
|
||||
<location filename="../../dialog.ui" line="274"/>
|
||||
<source>record save path:</source>
|
||||
<translation>record save path:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="330"/>
|
||||
<location filename="../../dialog.cpp" line="286"/>
|
||||
<location filename="../../dialog.ui" line="362"/>
|
||||
<location filename="../../dialog.cpp" line="287"/>
|
||||
<source>select path</source>
|
||||
<translation>select path</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="340"/>
|
||||
<location filename="../../dialog.ui" line="267"/>
|
||||
<source>record format:</source>
|
||||
<translation>record format:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Game for Peace</source>
|
||||
<translation type="vanished">Game for Peace</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="249"/>
|
||||
<source>not display</source>
|
||||
<translation>not display</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="92"/>
|
||||
<location filename="../../dialog.ui" line="72"/>
|
||||
<source>stop all server</source>
|
||||
<translation>stop all server</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="195"/>
|
||||
<location filename="../../dialog.ui" line="213"/>
|
||||
<source>adb command:</source>
|
||||
<translation>adb command:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="205"/>
|
||||
<location filename="../../dialog.ui" line="223"/>
|
||||
<source>terminate</source>
|
||||
<translation>terminate</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="212"/>
|
||||
<location filename="../../dialog.ui" line="230"/>
|
||||
<source>execute</source>
|
||||
<translation>execute</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="226"/>
|
||||
<location filename="../../dialog.ui" line="244"/>
|
||||
<source>clear</source>
|
||||
<translation>clear</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="269"/>
|
||||
<source>always top</source>
|
||||
<translation>always top</translation>
|
||||
<location filename="../../dialog.ui" line="300"/>
|
||||
<source>reverse connection</source>
|
||||
<translation>reverse connection</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="279"/>
|
||||
<source>use reverse</source>
|
||||
<translation>use reverse</translation>
|
||||
<location filename="../../dialog.ui" line="310"/>
|
||||
<source>auto enable</source>
|
||||
<translation>auto enable</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="302"/>
|
||||
<location filename="../../dialog.ui" line="339"/>
|
||||
<source>background record</source>
|
||||
<translation>background record</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="355"/>
|
||||
<source>screen-off</source>
|
||||
<translation>screen-off</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="392"/>
|
||||
<source>apply</source>
|
||||
<translation>apply</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="406"/>
|
||||
<source>max size:</source>
|
||||
<translation>max size</translation>
|
||||
<translation>max size:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="309"/>
|
||||
<source>close screen</source>
|
||||
<translation>close screen</translation>
|
||||
<location filename="../../dialog.ui" line="323"/>
|
||||
<source>always on top</source>
|
||||
<translation>always on top</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="363"/>
|
||||
<source>update script</source>
|
||||
<translation>update script</translation>
|
||||
<location filename="../../dialog.ui" line="287"/>
|
||||
<source>refresh script</source>
|
||||
<translation>refresh script</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="370"/>
|
||||
<source>custom map</source>
|
||||
<translation>custom map</translation>
|
||||
<location filename="../../dialog.ui" line="42"/>
|
||||
<source>get device IP</source>
|
||||
<translation>get device IP</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="26"/>
|
||||
|
@ -154,17 +160,17 @@
|
|||
<translation>USB line</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="42"/>
|
||||
<location filename="../../dialog.ui" line="79"/>
|
||||
<source>stop server</source>
|
||||
<translation>stop server</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="82"/>
|
||||
<location filename="../../dialog.ui" line="62"/>
|
||||
<source>start server</source>
|
||||
<translation>start server</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="72"/>
|
||||
<location filename="../../dialog.ui" line="35"/>
|
||||
<source>device serial:</source>
|
||||
<translation>device serial:</translation>
|
||||
</message>
|
||||
|
@ -173,28 +179,19 @@
|
|||
<translation type="vanished">Config</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="242"/>
|
||||
<location filename="../../dialog.ui" line="260"/>
|
||||
<source>bit rate:</source>
|
||||
<translation>bit rate:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>video size:</source>
|
||||
<translation type="vanished">video size:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="62"/>
|
||||
<location filename="../../dialog.ui" line="89"/>
|
||||
<source>start adbd</source>
|
||||
<translation>start adbd</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="32"/>
|
||||
<source>get device ip</source>
|
||||
<translation>get device ip</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="52"/>
|
||||
<source>update device</source>
|
||||
<translation>update device</translation>
|
||||
<source>refresh devices</source>
|
||||
<translation>refresh devices</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -262,6 +259,11 @@
|
|||
<source>return</source>
|
||||
<translation>return</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="139"/>
|
||||
<source>screen shot</source>
|
||||
<translation>screen shot</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>VideoForm</name>
|
||||
|
@ -278,7 +280,7 @@
|
|||
<translation type="vanished">file transfer failed</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/videoform.cpp" line="407"/>
|
||||
<location filename="../../device/ui/videoform.cpp" line="408"/>
|
||||
<source>file does not exist</source>
|
||||
<translation>file does not exist</translation>
|
||||
</message>
|
||||
|
|
Binary file not shown.
|
@ -16,22 +16,22 @@
|
|||
<translation type="vanished">文件传输失败</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/device.cpp" line="108"/>
|
||||
<location filename="../../device/device.cpp" line="115"/>
|
||||
<source>install apk</source>
|
||||
<translation>安装apk</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/device.cpp" line="110"/>
|
||||
<location filename="../../device/device.cpp" line="117"/>
|
||||
<source>file transfer</source>
|
||||
<translation>文件传输</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/device.cpp" line="113"/>
|
||||
<location filename="../../device/device.cpp" line="120"/>
|
||||
<source>wait current %1 to complete</source>
|
||||
<translation>等待当前%1完成</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/device.cpp" line="116"/>
|
||||
<location filename="../../device/device.cpp" line="123"/>
|
||||
<source>%1 complete, save in %2</source>
|
||||
<translation>%1完成,保存在%2</translation>
|
||||
</message>
|
||||
|
@ -41,7 +41,7 @@
|
|||
<translation type="vanished">%1完成\n 保存在 %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/device.cpp" line="119"/>
|
||||
<location filename="../../device/device.cpp" line="126"/>
|
||||
<source>%1 failed</source>
|
||||
<translation>%1 失败</translation>
|
||||
</message>
|
||||
|
@ -54,99 +54,105 @@
|
|||
<translation>无线</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="147"/>
|
||||
<location filename="../../dialog.ui" line="114"/>
|
||||
<source>wireless connect</source>
|
||||
<translation>无线连接</translation>
|
||||
<translation>wireless connect</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="157"/>
|
||||
<location filename="../../dialog.ui" line="175"/>
|
||||
<source>wireless disconnect</source>
|
||||
<translation>无线断开</translation>
|
||||
<translation>wireless disconnect</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="236"/>
|
||||
<location filename="../../dialog.ui" line="254"/>
|
||||
<source>Start Config</source>
|
||||
<translation>启动配置</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="292"/>
|
||||
<location filename="../../dialog.ui" line="274"/>
|
||||
<source>record save path:</source>
|
||||
<translation>录像保存路径:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="330"/>
|
||||
<location filename="../../dialog.cpp" line="286"/>
|
||||
<location filename="../../dialog.ui" line="362"/>
|
||||
<location filename="../../dialog.cpp" line="287"/>
|
||||
<source>select path</source>
|
||||
<translation>选择路径</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="340"/>
|
||||
<location filename="../../dialog.ui" line="267"/>
|
||||
<source>record format:</source>
|
||||
<translation>录制格式:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Game for Peace</source>
|
||||
<translation type="vanished">和平精英</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="249"/>
|
||||
<source>not display</source>
|
||||
<translation>仅后台录制</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="92"/>
|
||||
<location filename="../../dialog.ui" line="72"/>
|
||||
<source>stop all server</source>
|
||||
<translation>停止所有服务</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="195"/>
|
||||
<location filename="../../dialog.ui" line="213"/>
|
||||
<source>adb command:</source>
|
||||
<translation>adb命令行:</translation>
|
||||
<translation>adb命令:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="205"/>
|
||||
<location filename="../../dialog.ui" line="223"/>
|
||||
<source>terminate</source>
|
||||
<translation>终止</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="212"/>
|
||||
<location filename="../../dialog.ui" line="230"/>
|
||||
<source>execute</source>
|
||||
<translation>执行</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="226"/>
|
||||
<location filename="../../dialog.ui" line="244"/>
|
||||
<source>clear</source>
|
||||
<translation>清理</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="269"/>
|
||||
<source>always top</source>
|
||||
<translation>窗口置顶</translation>
|
||||
<location filename="../../dialog.ui" line="300"/>
|
||||
<source>reverse connection</source>
|
||||
<translation>反向连接</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="279"/>
|
||||
<source>use reverse</source>
|
||||
<translation>使用reverse</translation>
|
||||
<location filename="../../dialog.ui" line="310"/>
|
||||
<source>auto enable</source>
|
||||
<translation>自动启用脚本</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="302"/>
|
||||
<source>max size:</source>
|
||||
<translation>最大尺寸</translation>
|
||||
<location filename="../../dialog.ui" line="339"/>
|
||||
<source>background record</source>
|
||||
<translation>后台录制</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="309"/>
|
||||
<source>close screen</source>
|
||||
<location filename="../../dialog.ui" line="355"/>
|
||||
<source>screen-off</source>
|
||||
<translation>自动息屏</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="363"/>
|
||||
<source>update script</source>
|
||||
<translation>更新脚本</translation>
|
||||
<location filename="../../dialog.ui" line="392"/>
|
||||
<source>apply</source>
|
||||
<translation>应用脚本</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="370"/>
|
||||
<source>custom map</source>
|
||||
<translation>自定义映射</translation>
|
||||
<location filename="../../dialog.ui" line="406"/>
|
||||
<source>max size:</source>
|
||||
<translation>最大尺寸:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="323"/>
|
||||
<source>always on top</source>
|
||||
<translation>窗口置顶</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="287"/>
|
||||
<source>refresh script</source>
|
||||
<translation>刷新脚本</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="42"/>
|
||||
<source>get device IP</source>
|
||||
<translation>获取设备IP</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="26"/>
|
||||
|
@ -154,17 +160,17 @@
|
|||
<translation>USB线</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="42"/>
|
||||
<location filename="../../dialog.ui" line="79"/>
|
||||
<source>stop server</source>
|
||||
<translation>停止服务</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="82"/>
|
||||
<location filename="../../dialog.ui" line="62"/>
|
||||
<source>start server</source>
|
||||
<translation>启动服务</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="72"/>
|
||||
<location filename="../../dialog.ui" line="35"/>
|
||||
<source>device serial:</source>
|
||||
<translation>设备序列号:</translation>
|
||||
</message>
|
||||
|
@ -173,27 +179,18 @@
|
|||
<translation type="vanished">配置</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="242"/>
|
||||
<location filename="../../dialog.ui" line="260"/>
|
||||
<source>bit rate:</source>
|
||||
<translation>比特率:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>video size:</source>
|
||||
<translation type="vanished">视频尺寸:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="62"/>
|
||||
<location filename="../../dialog.ui" line="89"/>
|
||||
<source>start adbd</source>
|
||||
<translation>启动adbd</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="32"/>
|
||||
<source>get device ip</source>
|
||||
<translation>获取设备IP</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="52"/>
|
||||
<source>update device</source>
|
||||
<source>refresh devices</source>
|
||||
<translation>刷新设备列表</translation>
|
||||
</message>
|
||||
</context>
|
||||
|
@ -262,6 +259,11 @@
|
|||
<source>return</source>
|
||||
<translation>返回</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="139"/>
|
||||
<source>screen shot</source>
|
||||
<translation>截图</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>VideoForm</name>
|
||||
|
@ -278,7 +280,7 @@
|
|||
<translation type="vanished">文件传输失败</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/videoform.cpp" line="407"/>
|
||||
<location filename="../../device/ui/videoform.cpp" line="408"/>
|
||||
<source>file does not exist</source>
|
||||
<translation>文件不存在</translation>
|
||||
</message>
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 301 KiB After Width: | Height: | Size: 314 KiB |
Binary file not shown.
Before Width: | Height: | Size: 293 KiB After Width: | Height: | Size: 306 KiB |
128
README.md
128
README.md
|
@ -2,15 +2,15 @@
|
|||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
[中文介绍](README_zh.md)
|
||||
|
||||
QtScrcpy can connect to Android devices via USB (or via TCP/IP) for display and control. No root privileges are required.
|
||||
QtScrcpy connects to Android devices via USB (or via TCP/IP) for display and control. It does NOT require the root privileges.
|
||||
|
||||
A single application can support up to 16 Android devices to connect at the same time.
|
||||
A single instance supports up to 16 Android device connections at the same time.
|
||||
|
||||
Supports three major desktop platforms, GNU/Linux, Windows and MacOS.
|
||||
It supports three major platforms: GNU/Linux, Windows and MacOS.
|
||||
|
||||
It focuses on:
|
||||
|
||||
|
@ -29,59 +29,61 @@ It focuses on:
|
|||
|
||||

|
||||
|
||||
## Custom keymap(only windows enable)
|
||||
You can write your own script to map the PC keyboard keys to the touch and click of the mobile phone according to your needs. [Here](docs/按键映射说明.md) are the rules.
|
||||
## Customized key mapping (Windows only)
|
||||
You can write your own script to map keyboard and mouse actions to touches and clicks of the mobile phone according to your needs. [Here](docs/按键映射说明.md) are the rules.
|
||||
|
||||
By default, it has its own mapping script for key and mouse mapping of "Game for peace" mobile games. When enabled, you can use key and mouse to play "Game for peace" mobile games like PC games. You can also write mapping files of other games according to [writing rules](docs/按键映射说明.md). The default key mapping is as follows:
|
||||
A script for "PUBG mobile" mapping is provided by default. Once enabled, you can play the game with your keyboard and mouse as the PC version. You can also write your own mapping files for other games according to [writing rules](docs/按键映射说明.md). The default key mapping is as follows:
|
||||
|
||||

|
||||
|
||||
[Here is a video demonstration of playing "Game for peace"](http://mp.weixin.qq.com/mp/video?__biz=MzU1NTg5MjYyNw==&mid=100000015&sn=3e301fdc5a364bd16d6207fa674bc8b3&vid=wxv_968792362971430913&idx=1&vidsn=eec329cc13c3e24c187dc9b4d5eb8760&fromid=1&scene=20&xtrack=1&clicktime=1567346543&sessionid=1567346375&subscene=92&ascene=0&fasttmpl_type=0&fasttmpl_fullversion=4730859-zh_CN-zip&fasttmpl_flag=0&realreporttime=1567346543910#wechat_redirect)
|
||||
[Here is a video demonstration of playing "PUBG mobile"](http://mp.weixin.qq.com/mp/video?__biz=MzU1NTg5MjYyNw==&mid=100000015&sn=3e301fdc5a364bd16d6207fa674bc8b3&vid=wxv_968792362971430913&idx=1&vidsn=eec329cc13c3e24c187dc9b4d5eb8760&fromid=1&scene=20&xtrack=1&clicktime=1567346543&sessionid=1567346375&subscene=92&ascene=0&fasttmpl_type=0&fasttmpl_fullversion=4730859-zh_CN-zip&fasttmpl_flag=0&realreporttime=1567346543910#wechat_redirect)
|
||||
|
||||
The operation method of custom key mapping is as follows:
|
||||
- Write a custom script and put it in the keymap directory
|
||||
- Check the custom mapping option and select the custom mapping script before starting the service
|
||||
- Enter the game scene after connecting the mobile phone
|
||||
- Press the ~ key (left side of the number key 1) to switch to the game mapping mode to experience (what key to press depends on the switchkey defined by your key script)
|
||||
- Press the ~ key again to switch to normal control mode
|
||||
- To start the WASD control car, remember to set it to single rocker mode in vehicle settings.
|
||||
Here is the instruction of adding new customized mapping files.
|
||||
|
||||
- Write a customized script and put it in the `keymap` directory
|
||||
- Click `refresh script` to check whether it can be found
|
||||
- Connect your phone, start service and click `apply`
|
||||
- Start the game and press `~` key (left side of the number key 1) to switch to the mapping mode (It can be changed in the script as `switchkey`)
|
||||
- Press the ~ key again to switch back to normal mode
|
||||
- (For PUBG and similar games) If you want to drive cars with WASD, you need to check the `single rocker mode` in the game setting.
|
||||
|
||||
## Thanks
|
||||
|
||||
QtScrcpy is based on [Genymobile's](https://github.com/Genymobile) [scrcpy](https://github.com/Genymobile/scrcpy) project and is very grateful to him.
|
||||
QtScrcpy is based on [Genymobile's](https://github.com/Genymobile) [scrcpy](https://github.com/Genymobile/scrcpy) project. Thanks
|
||||
|
||||
The difference between QtScrcpy and the original scrcpy is as follows:
|
||||
|
||||
keys|scrcpy|QtScrcpy
|
||||
--|:--:|:--:
|
||||
ui|sdl|qt
|
||||
video decode|ffmpeg|ffmpeg
|
||||
video encode|ffmpeg|ffmpeg
|
||||
video render|sdl|opengl
|
||||
base tool|c++|Qt
|
||||
cross-platform|self implemented|provided by Qt
|
||||
language|C|C++
|
||||
style|sync|asyn
|
||||
style|sync|async
|
||||
control|single touch|single/multi touch
|
||||
build|meson+gradle|Qt Creator
|
||||
|
||||
- It's very easy to customize your interface with Qt
|
||||
- It's very easy to customize your GUI with Qt
|
||||
- Asynchronous programming of Qt-based signal slot mechanism improves performance
|
||||
- Easy for novices to learn
|
||||
- Add multi touch support
|
||||
- Easy to learn
|
||||
- Add support for multi-touch
|
||||
|
||||
|
||||
## Learn
|
||||
|
||||
If you are interested in it and want to learn how it works and feel that you can't get started, you can choose to purchase my recorded video lessons.
|
||||
It details the development architecture and development process of the entire software, and takes you to develop QtScrcpy from scratch.:
|
||||
If you are interested in it and want to learn how it works but do not know how to get started, you can choose to purchase my recorded video lessons.
|
||||
It details the development architecture and the development process of the entire software, and help you develop QtScrcpy from scratch.
|
||||
|
||||
course introduction:[https://blog.csdn.net/rankun1/article/details/87970523](https://blog.csdn.net/rankun1/article/details/87970523)
|
||||
Course introduction:[https://blog.csdn.net/rankun1/article/details/87970523](https://blog.csdn.net/rankun1/article/details/87970523)
|
||||
|
||||
Or you can join my QtScrcpy qq group and exchange ideas with like-minded friends.:
|
||||
You can join my QQ group for QtScrcpy and exchange ideas with like-minded friends.:
|
||||
|
||||
QQ Group number:901736468
|
||||
|
||||
|
||||
## Requirements
|
||||
The Android part requires at least API 21 (Android 5.0).
|
||||
Android API >= 21 (Android 5.0).
|
||||
|
||||
Make sure you enabled [adb debugging][enable-adb] on your device(s).
|
||||
|
||||
|
@ -117,47 +119,50 @@ Connect to your Android device on your computer, then run the program and click
|
|||
|
||||

|
||||
|
||||
### Wireless connection steps (ensure that the mobile phone and computer are in the same LAN):
|
||||
1. Enable USB debugging in developer options on Android mobile terminal
|
||||
2. Connect Android phone to computer via USB
|
||||
3. Click update device, and you will see that the device number is updated.
|
||||
4. Click get ip
|
||||
### Wireless connection steps (ensure that the mobile phone and PC are in the same LAN):
|
||||
1. Enable USB debugging in developer options on the Android device
|
||||
2. Connect the Android device to computer via USB
|
||||
3. Click update device, and you will see that the device number is updated
|
||||
4. Click get device IP
|
||||
5. Click start adbd
|
||||
6. Click wireless connect
|
||||
7. Click update device again, and another device with IP address beginning is found. Select this device.
|
||||
7. Click update device again, and another device with IP address will be found. Select this device.
|
||||
8. Click start service
|
||||
|
||||
|
||||
|
||||
Note: it is not necessary to keep you Android device connected via USB after you start adbd.
|
||||
|
||||
## Interface button introduction:
|
||||
|
||||
- Startup configuration: function parameter settings before starting the service
|
||||
- Start config: function parameter settings before starting the service
|
||||
|
||||
You can set the bit rate, resolution, recording format, and video save path of the local recorded video.
|
||||
|
||||
- Recording only in the background: Starting the service is not realistic, just recording the Android device screen
|
||||
- Window Top: Android device video window top display
|
||||
- Background record: the Android device screen is not displayed after starting the service. It is recorded in background.
|
||||
- Always on top: the video window for Android device will be kept on the top
|
||||
- Close screen: automatically turn off the Android device screen to save power after starting the service
|
||||
- Use reverse: service startup mode, service startup failure error more than one device can remove this check to try to connect
|
||||
- Reverse connection: service startup mode. You can uncheck it if you experience connection failure with message `more than one device`
|
||||
|
||||
|
||||
- Refresh device list: Refresh the currently connected device
|
||||
- Start the service: connect to the Android device
|
||||
- Refresh devices: Refresh the currently connected device
|
||||
- Start service: connect to the Android device
|
||||
- Stop service: disconnect from Android device
|
||||
- Stop all services: disconnect all connected Android devices
|
||||
- Get device ip: Get the IP address of the Android device and update it to the "Wireless" area for easy wireless connection.
|
||||
- Start adbd: Start the adbd service of the Android device, you must start it before the wireless connection.
|
||||
- Wireless connection: Connect to Android devices wirelessly
|
||||
- Get device IP: Get the IP address of the Android device and update it to the "Wireless" area for the ease of wireless connection setting.
|
||||
- Start adbd: Start the adbd service of the Android device. You must start it before the wireless connection.
|
||||
- Wireless connect: Connect to Android devices wirelessly
|
||||
- Wireless disconnect: Disconnect wirelessly connected Android devices
|
||||
- adb command line: convenient to execute custom adb commands (currently does not support blocking commands, such as shell)
|
||||
- adb command: execute customized adb commands (blocking commands are not supported now, such as shell)
|
||||
|
||||
|
||||
## The main function
|
||||
- Display Android device screens in real time
|
||||
Real-time mouse and keyboard control Android device
|
||||
- Real-time mouse and keyboard control of Android devices
|
||||
- Screen recording
|
||||
- Wireless connections
|
||||
- Supports up to 16 device connections (can be added if PC performance allows, you need to compile it yourself)
|
||||
- full-screen display
|
||||
- Window topping
|
||||
- Wireless connection
|
||||
- Supports up to 16 device connections (the number can be higher if your PC performance allows. You need to compile it by yourself)
|
||||
- Full-screen display
|
||||
- Display on the top
|
||||
- Install apk: drag and drop apk to the video window to install
|
||||
- Transfer files: Drag files to the video window to send files to Android devices
|
||||
- Background recording: record only, no display interface
|
||||
|
@ -181,23 +186,24 @@ Real-time mouse and keyboard control Android device
|
|||
[DEVELOP](docs/DEVELOP.md)
|
||||
|
||||
## Why develop QtScrcpy?
|
||||
There are several reasons for this, and the proportions are arranged from large to small:
|
||||
1. In the process of learning Qt, you need a project to combat
|
||||
2. It has audio and video related skills and is very interested in audio and video.
|
||||
3. It has Android development skills, it’s a bit rusty for a long time, you need to consolidate it.
|
||||
4. Found scrcpy, decided to re-entamrate with the new technology stack (C++ + Qt + Opengl + ffmpeg)
|
||||
There are several reasons listed as below according to importance (high to low).
|
||||
1. In the process of learning Qt, I need a real project to try
|
||||
2. I have some background skill about audio and video and I am interested at them
|
||||
3. I have some Android development skills. But I have used it for a long time. I want to consolidate it.
|
||||
4. I found scrcpy and decided to re-make it with the new technology stack (C++ + Qt + Opengl + ffmpeg)
|
||||
|
||||
|
||||
## Build
|
||||
Try to provide all the dependencies and make it easy to compile.
|
||||
## How to build
|
||||
All the dependencies are provided and it is easy to compile.
|
||||
|
||||
### PC client
|
||||
1. Set up the Qt development environment on the target platform (Qt >= 5.9.7, vs >= 2015 (not support mingw))
|
||||
1. Set up the Qt development environment on the target platform (Qt >= 5.9.7, vs >= 2015 (mingw not supported))
|
||||
2. Clone the project
|
||||
3. Open the project root directory all.pro with QtCreator
|
||||
4. Compile and run
|
||||
|
||||
### Android (If you do not need to modify the requirements, you can use the built-in scrcpy-server directly)
|
||||
### Android (If you do not have special requirements, you can directly use the built-in scrcpy-server.jar)
|
||||
|
||||
1. Set up an Android development environment on the target platform
|
||||
2. Open server project in project root with Android Studio
|
||||
3. The first time you open it, if you do not have the corresponding version of gradle, you will be prompted to find gradle, whether to upgrade gradle and create it. Select Cancel. After canceling, you will be prompted to select the location of the existing gradle. You can also cancel it (it will download automatically).
|
||||
|
@ -208,13 +214,13 @@ Try to provide all the dependencies and make it easy to compile.
|
|||
Since it is based on scrcpy, respect its Licence
|
||||
|
||||
Copyright (C) 2018 Genymobile
|
||||
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
|
27
README_zh.md
27
README_zh.md
|
@ -2,9 +2,9 @@
|
|||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
[English introduction (from Google Translate)](README.md)
|
||||
[English introduction](README.md)
|
||||
|
||||
QtScrcpy可以通过USB(或通过TCP/IP)连接Android设备,并进行显示和控制。不需要root权限。
|
||||
|
||||
|
@ -41,15 +41,15 @@ QtScrcpy可以通过USB(或通过TCP/IP)连接Android设备,并进行显示和
|
|||
|
||||
自定义按键映射操作方法如下:
|
||||
- 编写自定义脚本放入keymap目录
|
||||
- 启动服务之前记得勾选自定义映射选项,并选择自定义映射脚本
|
||||
- 连接手机以后进入游戏场景
|
||||
- 按~键(数字键1左边)切换为游戏映射模式即可体验(具体按什么键要看你按键脚本定义的switchKey)
|
||||
- 点击刷新脚本,确保脚本可以被检测到
|
||||
- 连接手机并启动服务之后,点击应用脚本
|
||||
- 进入游戏场景,按~键(数字键1左边)切换为游戏映射模式即可体验(具体按什么键要看你按键脚本定义的switchKey)
|
||||
- 再次按~键切换为正常控制模式
|
||||
- 要想wasd控制开车记得在载具设置中设置为单摇杆模式
|
||||
|
||||
## 感谢
|
||||
|
||||
基于[Genymobile](https://github.com/Genymobile)的[scrcpy](https://github.com/Genymobile/scrcpy)项目进行复刻,重构,非常感谢他。QtScrcpy和原版scrcpy区别如下:
|
||||
基于[Genymobile](https://github.com/Genymobile)的[scrcpy](https://github.com/Genymobile/scrcpy)项目进行复刻,重构,非常感谢。QtScrcpy和原版scrcpy区别如下:
|
||||
|
||||
关键点|scrcpy|QtScrcpy
|
||||
--|:--:|:--:
|
||||
|
@ -94,7 +94,7 @@ Android部分至少需要API 21(Android 5.0)。
|
|||
|
||||
### Windows
|
||||
|
||||
windows平台,你可以直接使用我编译好的可执行程序:
|
||||
Windows平台,你可以直接使用我编译好的可执行程序:
|
||||
|
||||
- [国内下载][gitee-download]
|
||||
- [国外下载][github-download]
|
||||
|
@ -128,13 +128,13 @@ Mac OS平台,你可以直接使用我编译好的可执行程序:
|
|||
1. 安卓手机端在开发者选项中打开usb调试
|
||||
2. 通过usb连接安卓手机到电脑
|
||||
3. 点击刷新设备,会看到有设备号更新出来
|
||||
4. 点击获取设备ip
|
||||
4. 点击获取设备IP
|
||||
5. 点击启动adbd
|
||||
6. 无线连接
|
||||
7. 再次点击刷新设备,发现多出了一个ip地址开头的设备,选择这个设备
|
||||
7. 再次点击刷新设备,发现多出了一个IP地址开头的设备,选择这个设备
|
||||
8. 启动服务
|
||||
|
||||
备注:启动adbd以后不用再usb线了,以后连接断开都不再需要,除非安卓adbd停了需要重新启动
|
||||
备注:启动adbd以后不用再连着usb线了,以后连接断开都不再需要,除非安卓adbd停了需要重新启动
|
||||
|
||||
## 界面按钮介绍:
|
||||
|
||||
|
@ -147,7 +147,6 @@ Mac OS平台,你可以直接使用我编译好的可执行程序:
|
|||
- 自动息屏:启动服务以后,自动关闭Android设备屏幕节省电量
|
||||
- 使用reverse:服务启动模式,出现服务启动失败报错more than one device可以去掉这个勾选尝试连接
|
||||
|
||||
|
||||
- 刷新设备列表:刷新当前连接的设备
|
||||
- 启动服务:连接到Android设备
|
||||
- 停止服务:断开与Android设备的连接
|
||||
|
@ -214,13 +213,13 @@ Mac OS平台,你可以直接使用我编译好的可执行程序:
|
|||
由于是复刻的scrcpy,尊重它的Licence
|
||||
|
||||
Copyright (C) 2018 Genymobile
|
||||
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
- 按键映射中的坐标位置都是用相对位置表示的,屏幕的宽高都用1表示,例如屏幕的像素为1920x1080,那么坐标(0.5,0.5)则表示的是
|
||||
以屏幕左上角为原点,像素坐标(1920,1080)*(0.5,0.5)=(960,540)的位置。
|
||||
- 按键映射中的按键码是用Qt的枚举表示的,详细说明可以[参考Qt文档](https://doc-snapshots.qt.io/4.8/qt.html)(搜索 The key names used by Qt. 可以快速定位)。
|
||||
- 按键映射中的按键码是用Qt的枚举表示的,详细说明可以[参考Qt文档]( https://doc.qt.io/qt-5/qt.html )(搜索 The key names used by Qt. 可以快速定位)。
|
||||
|
||||
### 映射类型说明
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue