mirror of
https://github.com/barry-ran/QtScrcpy.git
synced 2025-04-21 03:55:04 +00:00
commit
8e76585997
38 changed files with 1167 additions and 374 deletions
17
.github/workflows/macos.yml
vendored
17
.github/workflows/macos.yml
vendored
|
@ -46,15 +46,18 @@ jobs:
|
|||
- uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 1
|
||||
# 编译
|
||||
- name: Build MacOS
|
||||
run: |
|
||||
export ENV_QT_CLANG=$(pwd)/${{env.Qt5_Dir}}
|
||||
ci/mac/build_for_mac.sh release
|
||||
# 发布
|
||||
- name: Publish
|
||||
if: startsWith(github.event.ref, 'refs/tags/')
|
||||
run: |
|
||||
export ENV_QT_CLANG=$(pwd)/${{env.Qt5_Dir}}
|
||||
ci/mac/publish_for_mac.sh ../build
|
||||
ci/mac/package_for_mac.sh
|
||||
# tag 打包
|
||||
- name: Package
|
||||
if: startsWith(github.event.ref, 'refs/tags/')
|
||||
|
@ -65,7 +68,7 @@ jobs:
|
|||
[string]$tag = ${env:ref}.Substring(${env:ref}.LastIndexOf('/') + 1)
|
||||
[string]$name = 'QtScrcpy-mac-x64-' + ${tag}
|
||||
# 打包zip
|
||||
Compress-Archive -Path ci\build\QtScrcpy.app ci\build\${name}.zip
|
||||
Compress-Archive -Path ci\build\QtScrcpy.dmg ci\build\${name}.zip
|
||||
# 查询Release
|
||||
- name: Query Release
|
||||
if: startsWith(github.event.ref, 'refs/tags/')
|
||||
|
@ -73,12 +76,20 @@ jobs:
|
|||
env:
|
||||
githubFullName: ${{ github.event.repository.full_name }}
|
||||
ref: ${{ github.event.ref }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
[string]$tag = ${env:ref}.Substring(${env:ref}.LastIndexOf('/') + 1)
|
||||
[string]$url = 'https://api.github.com/repos/' + ${env:githubFullName} + '/releases/tags/' + ${tag}
|
||||
|
||||
$token = ${env:github_token}
|
||||
$authInfo = ("{0}" -f $token)
|
||||
$authInfo = [System.Text.Encoding]::UTF8.GetBytes($authInfo)
|
||||
$authInfo = [System.Convert]::ToBase64String($authInfo)
|
||||
$headers = @{Authorization=("barry-ran {0}" -f $authInfo)}
|
||||
|
||||
$response={}
|
||||
try {
|
||||
$response = Invoke-RestMethod -Uri $url -Method Get
|
||||
$response = Invoke-RestMethod -Uri $url -Headers $headers -Method Get
|
||||
} catch {
|
||||
Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__
|
||||
Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription
|
||||
|
@ -102,12 +113,14 @@ jobs:
|
|||
run: |
|
||||
[string]$tag = ${env:ref}.Substring(${env:ref}.LastIndexOf('/') + 1)
|
||||
[string]$url = 'https://api.github.com/repos/' + ${env:githubFullName} + '/releases/tags/' + ${tag}
|
||||
|
||||
# github token防止api rate limite,否则一个小时只能60个api请求
|
||||
$token = ${env:github_token}
|
||||
$authInfo = ("{0}" -f $token)
|
||||
$authInfo = [System.Text.Encoding]::UTF8.GetBytes($authInfo)
|
||||
$authInfo = [System.Convert]::ToBase64String($authInfo)
|
||||
$headers = @{Authorization=("barry-ran {0}" -f $authInfo)}
|
||||
|
||||
$response = Invoke-RestMethod -Uri $url -ContentType 'text/json' -Headers $headers -Method Get
|
||||
[string]$latestUpUrl = $response.upload_url
|
||||
Write-Host 'latestUpUrl:'$latestUpUrl
|
||||
|
|
10
.github/workflows/windows.yml
vendored
10
.github/workflows/windows.yml
vendored
|
@ -103,12 +103,20 @@ jobs:
|
|||
env:
|
||||
githubFullName: ${{ github.event.repository.full_name }}
|
||||
ref: ${{ github.event.ref }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
[string]$tag = ${env:ref}.Substring(${env:ref}.LastIndexOf('/') + 1)
|
||||
[string]$url = 'https://api.github.com/repos/' + ${env:githubFullName} + '/releases/tags/' + ${tag}
|
||||
|
||||
$token = ${env:github_token}
|
||||
$authInfo = ("{0}" -f $token)
|
||||
$authInfo = [System.Text.Encoding]::UTF8.GetBytes($authInfo)
|
||||
$authInfo = [System.Convert]::ToBase64String($authInfo)
|
||||
$headers = @{Authorization=("barry-ran {0}" -f $authInfo)}
|
||||
|
||||
$response={}
|
||||
try {
|
||||
$response = Invoke-RestMethod -Uri $url -Method Get
|
||||
$response = Invoke-RestMethod -Uri $url -Headers $headers -Method Get
|
||||
} catch {
|
||||
Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__
|
||||
Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription
|
||||
|
|
|
@ -62,7 +62,7 @@ void Controller::updateScript(QString gameScript)
|
|||
connect(m_inputConvert, &InputConvertBase::grabCursor, this, &Controller::grabCursor);
|
||||
}
|
||||
|
||||
void Controller::postTurnOn()
|
||||
void Controller::onPostBackOrScreenOn()
|
||||
{
|
||||
ControlMsg* controlMsg = new ControlMsg(ControlMsg::CMT_BACK_OR_SCREEN_ON);
|
||||
if (!controlMsg) {
|
||||
|
@ -71,42 +71,42 @@ void Controller::postTurnOn()
|
|||
postControlMsg(controlMsg);
|
||||
}
|
||||
|
||||
void Controller::postGoHome()
|
||||
void Controller::onPostGoHome()
|
||||
{
|
||||
postKeyCodeClick(AKEYCODE_HOME);
|
||||
}
|
||||
|
||||
void Controller::postGoMenu()
|
||||
void Controller::onPostGoMenu()
|
||||
{
|
||||
postKeyCodeClick(AKEYCODE_MENU);
|
||||
}
|
||||
|
||||
void Controller::postGoBack()
|
||||
void Controller::onPostGoBack()
|
||||
{
|
||||
postKeyCodeClick(AKEYCODE_BACK);
|
||||
}
|
||||
|
||||
void Controller::postAppSwitch()
|
||||
void Controller::onPostAppSwitch()
|
||||
{
|
||||
postKeyCodeClick(AKEYCODE_APP_SWITCH);
|
||||
}
|
||||
|
||||
void Controller::postPower()
|
||||
void Controller::onPostPower()
|
||||
{
|
||||
postKeyCodeClick(AKEYCODE_POWER);
|
||||
}
|
||||
|
||||
void Controller::postVolumeUp()
|
||||
void Controller::onPostVolumeUp()
|
||||
{
|
||||
postKeyCodeClick(AKEYCODE_VOLUME_UP);
|
||||
}
|
||||
|
||||
void Controller::postVolumeDown()
|
||||
void Controller::onPostVolumeDown()
|
||||
{
|
||||
postKeyCodeClick(AKEYCODE_VOLUME_DOWN);
|
||||
}
|
||||
|
||||
void Controller::expandNotificationPanel()
|
||||
void Controller::onExpandNotificationPanel()
|
||||
{
|
||||
ControlMsg* controlMsg = new ControlMsg(ControlMsg::CMT_EXPAND_NOTIFICATION_PANEL);
|
||||
if (!controlMsg) {
|
||||
|
@ -115,7 +115,7 @@ void Controller::expandNotificationPanel()
|
|||
postControlMsg(controlMsg);
|
||||
}
|
||||
|
||||
void Controller::collapseNotificationPanel()
|
||||
void Controller::onCollapseNotificationPanel()
|
||||
{
|
||||
ControlMsg* controlMsg = new ControlMsg(ControlMsg::CMT_COLLAPSE_NOTIFICATION_PANEL);
|
||||
if (!controlMsg) {
|
||||
|
@ -124,7 +124,7 @@ void Controller::collapseNotificationPanel()
|
|||
postControlMsg(controlMsg);
|
||||
}
|
||||
|
||||
void Controller::requestDeviceClipboard()
|
||||
void Controller::onRequestDeviceClipboard()
|
||||
{
|
||||
ControlMsg* controlMsg = new ControlMsg(ControlMsg::CMT_GET_CLIPBOARD);
|
||||
if (!controlMsg) {
|
||||
|
@ -133,7 +133,7 @@ void Controller::requestDeviceClipboard()
|
|||
postControlMsg(controlMsg);
|
||||
}
|
||||
|
||||
void Controller::setDeviceClipboard()
|
||||
void Controller::onSetDeviceClipboard()
|
||||
{
|
||||
QClipboard *board = QApplication::clipboard();
|
||||
QString text = board->text();
|
||||
|
@ -145,14 +145,14 @@ void Controller::setDeviceClipboard()
|
|||
postControlMsg(controlMsg);
|
||||
}
|
||||
|
||||
void Controller::clipboardPaste()
|
||||
void Controller::onClipboardPaste()
|
||||
{
|
||||
QClipboard *board = QApplication::clipboard();
|
||||
QString text = board->text();
|
||||
postTextInput(text);
|
||||
onPostTextInput(text);
|
||||
}
|
||||
|
||||
void Controller::postTextInput(QString& text)
|
||||
void Controller::onPostTextInput(QString& text)
|
||||
{
|
||||
ControlMsg* controlMsg = new ControlMsg(ControlMsg::CMT_INJECT_TEXT);
|
||||
if (!controlMsg) {
|
||||
|
@ -162,7 +162,7 @@ void Controller::postTextInput(QString& text)
|
|||
postControlMsg(controlMsg);
|
||||
}
|
||||
|
||||
void Controller::setScreenPowerMode(ControlMsg::ScreenPowerMode mode)
|
||||
void Controller::onSetScreenPowerMode(ControlMsg::ScreenPowerMode mode)
|
||||
{
|
||||
ControlMsg* controlMsg = new ControlMsg(ControlMsg::CMT_SET_SCREEN_POWER_MODE);
|
||||
if (!controlMsg) {
|
||||
|
@ -172,21 +172,21 @@ void Controller::setScreenPowerMode(ControlMsg::ScreenPowerMode mode)
|
|||
postControlMsg(controlMsg);
|
||||
}
|
||||
|
||||
void Controller::mouseEvent(const QMouseEvent *from, const QSize &frameSize, const QSize &showSize)
|
||||
void Controller::onMouseEvent(const QMouseEvent *from, const QSize &frameSize, const QSize &showSize)
|
||||
{
|
||||
if (m_inputConvert) {
|
||||
m_inputConvert->mouseEvent(from, frameSize, showSize);
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::wheelEvent(const QWheelEvent *from, const QSize &frameSize, const QSize &showSize)
|
||||
void Controller::onWheelEvent(const QWheelEvent *from, const QSize &frameSize, const QSize &showSize)
|
||||
{
|
||||
if (m_inputConvert) {
|
||||
m_inputConvert->wheelEvent(from, frameSize, showSize);
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::keyEvent(const QKeyEvent *from, const QSize &frameSize, const QSize &showSize)
|
||||
void Controller::onKeyEvent(const QKeyEvent *from, const QSize &frameSize, const QSize &showSize)
|
||||
{
|
||||
if (m_inputConvert) {
|
||||
m_inputConvert->keyEvent(from, frameSize, showSize);
|
||||
|
|
|
@ -22,27 +22,29 @@ public:
|
|||
|
||||
void updateScript(QString gameScript = "");
|
||||
|
||||
// turn the screen on if it was off, press BACK otherwise
|
||||
void postTurnOn();
|
||||
void postGoHome();
|
||||
void postGoMenu();
|
||||
void postGoBack();
|
||||
void postAppSwitch();
|
||||
void postPower();
|
||||
void postVolumeUp();
|
||||
void postVolumeDown();
|
||||
void expandNotificationPanel();
|
||||
void collapseNotificationPanel();
|
||||
void requestDeviceClipboard();
|
||||
void setDeviceClipboard();
|
||||
void clipboardPaste();
|
||||
void postTextInput(QString& text);
|
||||
void setScreenPowerMode(ControlMsg::ScreenPowerMode mode);
|
||||
public slots:
|
||||
void onPostGoBack();
|
||||
void onPostGoHome();
|
||||
void onPostGoMenu();
|
||||
void onPostAppSwitch();
|
||||
void onPostPower();
|
||||
void onPostVolumeUp();
|
||||
void onPostVolumeDown();
|
||||
void onExpandNotificationPanel();
|
||||
void onCollapseNotificationPanel();
|
||||
void onSetScreenPowerMode(ControlMsg::ScreenPowerMode mode);
|
||||
|
||||
// for input convert
|
||||
void mouseEvent(const QMouseEvent* from, const QSize& frameSize, const QSize& showSize);
|
||||
void wheelEvent(const QWheelEvent* from, const QSize& frameSize, const QSize& showSize);
|
||||
void keyEvent(const QKeyEvent* from, const QSize& frameSize, const QSize& showSize);
|
||||
void onMouseEvent(const QMouseEvent* from, const QSize& frameSize, const QSize& showSize);
|
||||
void onWheelEvent(const QWheelEvent* from, const QSize& frameSize, const QSize& showSize);
|
||||
void onKeyEvent(const QKeyEvent* from, const QSize& frameSize, const QSize& showSize);
|
||||
|
||||
// turn the screen on if it was off, press BACK otherwise
|
||||
void onPostBackOrScreenOn();
|
||||
void onRequestDeviceClipboard();
|
||||
void onSetDeviceClipboard();
|
||||
void onClipboardPaste();
|
||||
void onPostTextInput(QString& text);
|
||||
|
||||
signals:
|
||||
void grabCursor(bool grab);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include <cmath>
|
||||
|
||||
#include "inputconvertnormal.h"
|
||||
|
||||
InputConvertNormal::InputConvertNormal(Controller* controller)
|
||||
|
@ -63,10 +65,10 @@ void InputConvertNormal::wheelEvent(const QWheelEvent *from, const QSize& frameS
|
|||
qint32 vScroll = 0;
|
||||
switch (from->orientation()) {
|
||||
case Qt::Horizontal:
|
||||
hScroll = from->delta();
|
||||
hScroll = from->delta() / abs(from->delta()) * 2;
|
||||
break;
|
||||
case Qt::Vertical:
|
||||
vScroll = from->delta();
|
||||
vScroll = from->delta() / abs(from->delta()) * 2;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "controller.h"
|
||||
#include "config.h"
|
||||
#include "avframeconvert.h"
|
||||
#include "mousetap/mousetap.h"
|
||||
extern "C"
|
||||
{
|
||||
#include "libavutil/imgutils.h"
|
||||
|
@ -34,15 +35,8 @@ Device::Device(DeviceParams params, QObject *parent)
|
|||
m_decoder = new Decoder(m_vb, this);
|
||||
m_fileHandler = new FileHandler(this);
|
||||
m_controller = new Controller(params.gameScript, this);
|
||||
m_videoForm = new VideoForm(Config::getInstance().getSkin());
|
||||
m_videoForm->setSerial(m_params.serial);
|
||||
if (m_controller) {
|
||||
m_videoForm->setController(m_controller);
|
||||
}
|
||||
if (m_fileHandler) {
|
||||
m_videoForm->setFileHandler(m_fileHandler);
|
||||
}
|
||||
m_videoForm->show();
|
||||
m_videoForm = new VideoForm(Config::getInstance().getFramelessWindow(), Config::getInstance().getSkin());
|
||||
m_videoForm->setDevice(this);
|
||||
}
|
||||
|
||||
m_stream = new Stream(this);
|
||||
|
@ -76,6 +70,7 @@ Device::~Device()
|
|||
delete m_vb;
|
||||
}
|
||||
if (m_videoForm) {
|
||||
m_videoForm->close();
|
||||
delete m_videoForm;
|
||||
}
|
||||
emit deviceDisconnect(m_params.serial);
|
||||
|
@ -86,16 +81,25 @@ VideoForm *Device::getVideoForm()
|
|||
return m_videoForm;
|
||||
}
|
||||
|
||||
Controller *Device::getController()
|
||||
{
|
||||
return m_controller;
|
||||
}
|
||||
|
||||
Server *Device::getServer()
|
||||
{
|
||||
return m_server;
|
||||
}
|
||||
|
||||
const QString &Device::getSerial()
|
||||
{
|
||||
return m_params.serial;
|
||||
}
|
||||
|
||||
const QSize Device::frameSize()
|
||||
{
|
||||
QSize size;
|
||||
if (!m_videoForm) {
|
||||
return size;
|
||||
}
|
||||
return m_videoForm->frameSize();
|
||||
}
|
||||
|
||||
void Device::updateScript(QString script)
|
||||
{
|
||||
if(m_controller){
|
||||
|
@ -115,35 +119,86 @@ void Device::onScreenshot()
|
|||
m_vb->unLock();
|
||||
}
|
||||
|
||||
void Device::onShowTouch(bool show)
|
||||
{
|
||||
AdbProcess* adb = new AdbProcess();
|
||||
if (!adb) {
|
||||
return;
|
||||
}
|
||||
connect(adb, &AdbProcess::adbProcessResult, this, [this](AdbProcess::ADB_EXEC_RESULT processResult){
|
||||
if (AdbProcess::AER_SUCCESS_START != processResult) {
|
||||
sender()->deleteLater();
|
||||
}
|
||||
});
|
||||
adb->setShowTouchesEnabled(getSerial(), show);
|
||||
|
||||
qInfo() << getSerial() << " show touch " << (show ? "enable" : "disable");
|
||||
}
|
||||
|
||||
void Device::initSignals()
|
||||
{
|
||||
if (m_controller && m_videoForm) {
|
||||
connect(m_controller, &Controller::grabCursor, m_videoForm, &VideoForm::onGrabCursor);
|
||||
connect(m_videoForm, &VideoForm::screenshot, this, &Device::onScreenshot);
|
||||
connect(this, &Device::screenshot, this, &Device::onScreenshot);
|
||||
connect(this, &Device::showTouch, this, &Device::onShowTouch);
|
||||
connect(this, &Device::setControlState, this, &Device::onSetControlState);
|
||||
connect(this, &Device::grabCursor, this, &Device::onGrabCursor);
|
||||
|
||||
if (m_controller) {
|
||||
connect(m_controller, &Controller::grabCursor, this, &Device::grabCursor);
|
||||
}
|
||||
if (m_controller) {
|
||||
connect(this, &Device::postGoBack, m_controller, &Controller::onPostGoBack);
|
||||
connect(this, &Device::postGoHome, m_controller, &Controller::onPostGoHome);
|
||||
connect(this, &Device::postGoMenu, m_controller, &Controller::onPostGoMenu);
|
||||
connect(this, &Device::postAppSwitch, m_controller, &Controller::onPostAppSwitch);
|
||||
connect(this, &Device::postPower, m_controller, &Controller::onPostPower);
|
||||
connect(this, &Device::postVolumeUp, m_controller, &Controller::onPostVolumeUp);
|
||||
connect(this, &Device::postVolumeDown, m_controller, &Controller::onPostVolumeDown);
|
||||
connect(this, &Device::setScreenPowerMode, m_controller, &Controller::onSetScreenPowerMode);
|
||||
connect(this, &Device::expandNotificationPanel, m_controller, &Controller::onExpandNotificationPanel);
|
||||
connect(this, &Device::collapseNotificationPanel, m_controller, &Controller::onCollapseNotificationPanel);
|
||||
connect(this, &Device::mouseEvent, m_controller, &Controller::onMouseEvent);
|
||||
connect(this, &Device::wheelEvent, m_controller, &Controller::onWheelEvent);
|
||||
connect(this, &Device::keyEvent, m_controller, &Controller::onKeyEvent);
|
||||
|
||||
connect(this, &Device::postBackOrScreenOn, m_controller, &Controller::onPostBackOrScreenOn);
|
||||
connect(this, &Device::requestDeviceClipboard, m_controller, &Controller::onRequestDeviceClipboard);
|
||||
connect(this, &Device::setDeviceClipboard, m_controller, &Controller::onSetDeviceClipboard);
|
||||
connect(this, &Device::clipboardPaste, m_controller, &Controller::onClipboardPaste);
|
||||
connect(this, &Device::postTextInput, m_controller, &Controller::onPostTextInput);
|
||||
}
|
||||
if (m_videoForm) {
|
||||
connect(m_videoForm, &VideoForm::destroyed, this, [this](QObject *obj){
|
||||
Q_UNUSED(obj)
|
||||
deleteLater();
|
||||
});
|
||||
|
||||
connect(this, &Device::switchFullScreen, m_videoForm, &VideoForm::onSwitchFullScreen);
|
||||
}
|
||||
if (m_fileHandler) {
|
||||
connect(this, &Device::pushFileRequest, m_fileHandler, &FileHandler::onPushFileRequest);
|
||||
connect(this, &Device::installApkRequest, m_fileHandler, &FileHandler::onInstallApkRequest);
|
||||
connect(m_fileHandler, &FileHandler::fileHandlerResult, this, [this](FileHandler::FILE_HANDLER_RESULT processResult, bool isApk){
|
||||
QString tips = "";
|
||||
QString tipsType = "";
|
||||
if (isApk) {
|
||||
tips = tr("install apk");
|
||||
tipsType = tr("install apk");
|
||||
} else {
|
||||
tips = tr("file transfer");
|
||||
tipsType = tr("file transfer");
|
||||
}
|
||||
QString tips;
|
||||
if (FileHandler::FAR_IS_RUNNING == processResult && m_videoForm) {
|
||||
QMessageBox::warning(m_videoForm, "QtScrcpy", tr("wait current %1 to complete").arg(tips), QMessageBox::Ok);
|
||||
tips = tr("wait current %1 to complete").arg(tipsType);
|
||||
}
|
||||
if (FileHandler::FAR_SUCCESS_EXEC == processResult && m_videoForm) {
|
||||
QMessageBox::information(m_videoForm, "QtScrcpy", tr("%1 complete, save in %2").arg(tips).arg(Config::getInstance().getPushFilePath()), QMessageBox::Ok);
|
||||
tips = tr("%1 complete, save in %2").arg(tipsType).arg(Config::getInstance().getPushFilePath());
|
||||
}
|
||||
if (FileHandler::FAR_ERROR_EXEC == processResult && m_videoForm) {
|
||||
QMessageBox::information(m_videoForm, "QtScrcpy", tr("%1 failed").arg(tips), QMessageBox::Ok);
|
||||
tips = tr("%1 failed").arg(tipsType);
|
||||
}
|
||||
qInfo() << tips;
|
||||
if (m_controlState == GCS_CLIENT) {
|
||||
return;
|
||||
}
|
||||
QMessageBox::information(m_videoForm, "QtScrcpy", tips, QMessageBox::Ok);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -164,6 +219,16 @@ void Device::initSignals()
|
|||
if (m_videoForm) {
|
||||
m_videoForm->setWindowTitle(deviceName);
|
||||
m_videoForm->updateShowSize(size);
|
||||
|
||||
QRect rc = Config::getInstance().getRect(getSerial());
|
||||
if (rc.isValid()) {
|
||||
m_videoForm->move(rc.topLeft());
|
||||
m_videoForm->resize(rc.size());
|
||||
// TODO: setGeometry magneticwidget bug
|
||||
//m_videoForm->setGeometry(rc);
|
||||
}
|
||||
// videoForm delay show
|
||||
m_videoForm->show();
|
||||
}
|
||||
|
||||
// init recorder
|
||||
|
@ -182,7 +247,7 @@ void Device::initSignals()
|
|||
|
||||
// 显示界面时才自动息屏(m_params.display)
|
||||
if (m_params.closeScreen && m_params.display && m_controller) {
|
||||
m_controller->setScreenPowerMode(ControlMsg::SPM_OFF);
|
||||
emit m_controller->onSetScreenPowerMode(ControlMsg::SPM_OFF);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -235,6 +300,34 @@ void Device::startServer()
|
|||
});
|
||||
}
|
||||
|
||||
void Device::onSetControlState(Device* device, Device::GroupControlState state)
|
||||
{
|
||||
Q_UNUSED(device)
|
||||
if (m_controlState == state) {
|
||||
return;
|
||||
}
|
||||
GroupControlState oldState = m_controlState;
|
||||
m_controlState = state;
|
||||
emit controlStateChange(this, oldState, m_controlState);
|
||||
}
|
||||
|
||||
void Device::onGrabCursor(bool grab)
|
||||
{
|
||||
if (!m_videoForm) {
|
||||
return;
|
||||
}
|
||||
if (m_controlState == GCS_CLIENT) {
|
||||
return;
|
||||
}
|
||||
QRect rc = m_videoForm->getGrabCursorRect();
|
||||
MouseTap::getInstance()->enableMouseEventTap(rc, grab);
|
||||
}
|
||||
|
||||
Device::GroupControlState Device::controlState()
|
||||
{
|
||||
return m_controlState;
|
||||
}
|
||||
|
||||
bool Device::saveFrame(const AVFrame* frame)
|
||||
{
|
||||
if (!frame) {
|
||||
|
@ -276,10 +369,10 @@ bool Device::saveFrame(const AVFrame* frame)
|
|||
}
|
||||
QDateTime dateTime = QDateTime::currentDateTime();
|
||||
QString fileName = dateTime.toString("_yyyyMMdd_hhmmss_zzz");
|
||||
fileName = Config::getInstance().getTitle() + fileName + ".jpg";
|
||||
fileName = Config::getInstance().getTitle() + fileName + ".png";
|
||||
QDir dir(fileDir);
|
||||
absFilePath = dir.absoluteFilePath(fileName);
|
||||
ret = rgbImage.save(absFilePath);
|
||||
ret = rgbImage.save(absFilePath, "PNG", 100);
|
||||
if (!ret) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
#include <QPointer>
|
||||
#include <QTime>
|
||||
|
||||
#include "controlmsg.h"
|
||||
|
||||
class QMouseEvent;
|
||||
class QWheelEvent;
|
||||
class QKeyEvent;
|
||||
class Recorder;
|
||||
class Server;
|
||||
class VideoBuffer;
|
||||
|
@ -30,20 +35,64 @@ public:
|
|||
QString gameScript = ""; // 游戏映射脚本
|
||||
bool renderExpiredFrames = false; // 是否渲染延迟视频帧
|
||||
};
|
||||
enum GroupControlState {
|
||||
GCS_FREE = 0,
|
||||
GCS_HOST,
|
||||
GCS_CLIENT,
|
||||
};
|
||||
explicit Device(DeviceParams params, QObject *parent = nullptr);
|
||||
virtual ~Device();
|
||||
|
||||
VideoForm *getVideoForm();
|
||||
Controller *getController();
|
||||
Server *getServer();
|
||||
const QString &getSerial();
|
||||
const QSize frameSize();
|
||||
|
||||
void updateScript(QString script);
|
||||
Device::GroupControlState controlState();
|
||||
|
||||
signals:
|
||||
void deviceDisconnect(QString serial);
|
||||
|
||||
// tool bar
|
||||
void switchFullScreen();
|
||||
void postGoBack();
|
||||
void postGoHome();
|
||||
void postGoMenu();
|
||||
void postAppSwitch();
|
||||
void postPower();
|
||||
void postVolumeUp();
|
||||
void postVolumeDown();
|
||||
void setScreenPowerMode(ControlMsg::ScreenPowerMode mode);
|
||||
void expandNotificationPanel();
|
||||
void collapseNotificationPanel();
|
||||
void postBackOrScreenOn();
|
||||
void postTextInput(QString& text);
|
||||
void requestDeviceClipboard();
|
||||
void setDeviceClipboard();
|
||||
void clipboardPaste();
|
||||
void pushFileRequest(const QString& serial, const QString& file, const QString& devicePath = "");
|
||||
void installApkRequest(const QString& serial, const QString& apkFile);
|
||||
|
||||
// key map
|
||||
void mouseEvent(const QMouseEvent* from, const QSize& frameSize, const QSize& showSize);
|
||||
void wheelEvent(const QWheelEvent* from, const QSize& frameSize, const QSize& showSize);
|
||||
void keyEvent(const QKeyEvent* from, const QSize& frameSize, const QSize& showSize);
|
||||
|
||||
// self connect signal and slots
|
||||
void screenshot();
|
||||
void showTouch(bool show);
|
||||
void setControlState(Device* device, Device::GroupControlState state);
|
||||
void grabCursor(bool grab);
|
||||
|
||||
// for notify
|
||||
void controlStateChange(Device* device, Device::GroupControlState oldState, Device::GroupControlState newState);
|
||||
|
||||
public slots:
|
||||
void onScreenshot();
|
||||
void onShowTouch(bool show);
|
||||
void onSetControlState(Device* device, Device::GroupControlState state);
|
||||
void onGrabCursor(bool grab);
|
||||
|
||||
private:
|
||||
void initSignals();
|
||||
|
@ -65,6 +114,8 @@ private:
|
|||
|
||||
QTime m_startTimeCount;
|
||||
DeviceParams m_params;
|
||||
|
||||
GroupControlState m_controlState = GCS_FREE;
|
||||
};
|
||||
|
||||
#endif // DEVICE_H
|
||||
|
|
|
@ -24,7 +24,7 @@ FileHandler::~FileHandler()
|
|||
|
||||
}
|
||||
|
||||
void FileHandler::pushFileRequest(const QString &serial, const QString &file, const QString& devicePath)
|
||||
void FileHandler::onPushFileRequest(const QString &serial, const QString &file, const QString& devicePath)
|
||||
{
|
||||
if (m_adb.isRuning()) {
|
||||
emit fileHandlerResult(FAR_IS_RUNNING, false);
|
||||
|
@ -35,7 +35,7 @@ void FileHandler::pushFileRequest(const QString &serial, const QString &file, co
|
|||
m_adb.push(serial, file, devicePath);
|
||||
}
|
||||
|
||||
void FileHandler::installApkRequest(const QString &serial, const QString &apkFile)
|
||||
void FileHandler::onInstallApkRequest(const QString &serial, const QString &apkFile)
|
||||
{
|
||||
if (m_adb.isRuning()) {
|
||||
emit fileHandlerResult(FAR_IS_RUNNING, true);
|
||||
|
|
|
@ -17,10 +17,12 @@ public:
|
|||
FileHandler(QObject *parent = nullptr);
|
||||
virtual ~FileHandler();
|
||||
|
||||
void pushFileRequest(const QString& serial, const QString& file, const QString& devicePath = "");
|
||||
void installApkRequest(const QString& serial, const QString& apkFile);
|
||||
const QString &getDevicePath();
|
||||
|
||||
public slots:
|
||||
void onPushFileRequest(const QString& serial, const QString& file, const QString& devicePath = "");
|
||||
void onInstallApkRequest(const QString& serial, const QString& apkFile);
|
||||
|
||||
signals:
|
||||
void fileHandlerResult(FILE_HANDLER_RESULT processResult, bool isApk = false);
|
||||
|
||||
|
|
|
@ -6,9 +6,7 @@
|
|||
#include "toolform.h"
|
||||
#include "ui_toolform.h"
|
||||
#include "iconhelper.h"
|
||||
#include "videoform.h"
|
||||
#include "controller.h"
|
||||
#include "adbprocess.h"
|
||||
#include "device.h"
|
||||
|
||||
ToolForm::ToolForm(QWidget* adsorbWidget, AdsorbPositions adsorbPos)
|
||||
: MagneticWidget(adsorbWidget, adsorbPos)
|
||||
|
@ -18,8 +16,6 @@ ToolForm::ToolForm(QWidget* adsorbWidget, AdsorbPositions adsorbPos)
|
|||
setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
|
||||
//setWindowFlags(windowFlags() & ~Qt::WindowMinMaxButtonsHint);
|
||||
|
||||
m_videoForm = dynamic_cast<VideoForm*>(adsorbWidget);
|
||||
|
||||
initStyle();
|
||||
}
|
||||
|
||||
|
@ -28,6 +24,15 @@ ToolForm::~ToolForm()
|
|||
delete ui;
|
||||
}
|
||||
|
||||
void ToolForm::setDevice(Device *device)
|
||||
{
|
||||
if (!device) {
|
||||
return;
|
||||
}
|
||||
m_device = device;
|
||||
connect(m_device, &Device::controlStateChange, this, &ToolForm::onControlStateChange);
|
||||
}
|
||||
|
||||
void ToolForm::initStyle()
|
||||
{
|
||||
IconHelper::Instance()->SetIcon(ui->fullScreenBtn, QChar(0xf0b2), 15);
|
||||
|
@ -43,6 +48,25 @@ void ToolForm::initStyle()
|
|||
IconHelper::Instance()->SetIcon(ui->expandNotifyBtn, QChar(0xf103), 15);
|
||||
IconHelper::Instance()->SetIcon(ui->screenShotBtn, QChar(0xf0c4), 15);
|
||||
IconHelper::Instance()->SetIcon(ui->touchBtn, QChar(0xf111), 15);
|
||||
IconHelper::Instance()->SetIcon(ui->groupControlBtn, QChar(0xf0c0), 15);
|
||||
}
|
||||
|
||||
void ToolForm::updateGroupControl()
|
||||
{
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
switch (m_device->controlState()) {
|
||||
case Device::GroupControlState::GCS_FREE:
|
||||
ui->groupControlBtn->setStyleSheet("color: #DCDCDC");
|
||||
break;
|
||||
case Device::GroupControlState::GCS_HOST:
|
||||
ui->groupControlBtn->setStyleSheet("color: red");
|
||||
break;
|
||||
case Device::GroupControlState::GCS_CLIENT:
|
||||
ui->groupControlBtn->setStyleSheet("color: green");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ToolForm::mousePressEvent(QMouseEvent *event)
|
||||
|
@ -80,97 +104,121 @@ void ToolForm::hideEvent(QHideEvent *event)
|
|||
|
||||
void ToolForm::on_fullScreenBtn_clicked()
|
||||
{
|
||||
if (m_videoForm) {
|
||||
m_videoForm->switchFullScreen();
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
|
||||
emit m_device->switchFullScreen();
|
||||
}
|
||||
|
||||
void ToolForm::on_returnBtn_clicked()
|
||||
{
|
||||
if (m_videoForm && m_videoForm->getController()) {
|
||||
m_videoForm->getController()->postGoBack();
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->postGoBack();
|
||||
}
|
||||
|
||||
void ToolForm::on_homeBtn_clicked()
|
||||
{
|
||||
if (m_videoForm && m_videoForm->getController()) {
|
||||
m_videoForm->getController()->postGoHome();
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->postGoHome();
|
||||
}
|
||||
|
||||
void ToolForm::on_menuBtn_clicked()
|
||||
{
|
||||
if (m_videoForm && m_videoForm->getController()) {
|
||||
m_videoForm->getController()->postGoMenu();
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->postGoMenu();
|
||||
}
|
||||
|
||||
void ToolForm::on_appSwitchBtn_clicked()
|
||||
{
|
||||
if (m_videoForm && m_videoForm->getController()) {
|
||||
m_videoForm->getController()->postAppSwitch();
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->postAppSwitch();
|
||||
}
|
||||
|
||||
void ToolForm::on_powerBtn_clicked()
|
||||
{
|
||||
if (m_videoForm && m_videoForm->getController()) {
|
||||
m_videoForm->getController()->postPower();
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->postPower();
|
||||
}
|
||||
|
||||
void ToolForm::on_screenShotBtn_clicked()
|
||||
{
|
||||
emit screenshot();
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->screenshot();
|
||||
}
|
||||
|
||||
void ToolForm::on_volumeUpBtn_clicked()
|
||||
{
|
||||
if (m_videoForm && m_videoForm->getController()) {
|
||||
m_videoForm->getController()->postVolumeUp();
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->postVolumeUp();
|
||||
}
|
||||
|
||||
void ToolForm::on_volumeDownBtn_clicked()
|
||||
{
|
||||
if (m_videoForm && m_videoForm->getController()) {
|
||||
m_videoForm->getController()->postVolumeDown();
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->postVolumeDown();
|
||||
}
|
||||
|
||||
void ToolForm::on_closeScreenBtn_clicked()
|
||||
{
|
||||
if (m_videoForm && m_videoForm->getController()) {
|
||||
m_videoForm->getController()->setScreenPowerMode(ControlMsg::SPM_OFF);
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->setScreenPowerMode(ControlMsg::SPM_OFF);
|
||||
}
|
||||
|
||||
void ToolForm::on_expandNotifyBtn_clicked()
|
||||
{
|
||||
if (m_videoForm && m_videoForm->getController()) {
|
||||
m_videoForm->getController()->expandNotificationPanel();
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->expandNotificationPanel();
|
||||
}
|
||||
|
||||
void ToolForm::on_touchBtn_clicked()
|
||||
{
|
||||
if (!m_videoForm) {
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_showTouch = !m_showTouch;
|
||||
emit m_device->showTouch(m_showTouch);
|
||||
}
|
||||
|
||||
AdbProcess* adb = new AdbProcess();
|
||||
if (!adb) {
|
||||
void ToolForm::on_groupControlBtn_clicked()
|
||||
{
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
connect(adb, &AdbProcess::adbProcessResult, this, [this](AdbProcess::ADB_EXEC_RESULT processResult){
|
||||
if (AdbProcess::AER_SUCCESS_START != processResult) {
|
||||
sender()->deleteLater();
|
||||
}
|
||||
});
|
||||
adb->setShowTouchesEnabled(m_videoForm->getSerial(), m_showTouch);
|
||||
|
||||
qInfo() << "show touch " << (m_showTouch ? "enable" : "disable");
|
||||
Device::GroupControlState state = m_device->controlState();
|
||||
if (state == Device::GroupControlState::GCS_FREE) {
|
||||
emit m_device->setControlState(m_device, Device::GroupControlState::GCS_HOST);
|
||||
}
|
||||
if (state == Device::GroupControlState::GCS_HOST) {
|
||||
emit m_device->setControlState(m_device, Device::GroupControlState::GCS_FREE);
|
||||
}
|
||||
}
|
||||
|
||||
void ToolForm::onControlStateChange(Device *device, Device::GroupControlState oldState, Device::GroupControlState newState)
|
||||
{
|
||||
Q_UNUSED(device)
|
||||
Q_UNUSED(oldState)
|
||||
Q_UNUSED(newState)
|
||||
updateGroupControl();
|
||||
}
|
||||
|
|
|
@ -5,12 +5,13 @@
|
|||
#include <QPointer>
|
||||
|
||||
#include "magneticwidget.h"
|
||||
#include "device.h"
|
||||
|
||||
namespace Ui {
|
||||
class ToolForm;
|
||||
}
|
||||
|
||||
class VideoForm;
|
||||
class Device;
|
||||
class ToolForm : public MagneticWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -19,6 +20,8 @@ public:
|
|||
explicit ToolForm(QWidget* adsorbWidget, AdsorbPositions adsorbPos);
|
||||
~ToolForm();
|
||||
|
||||
void setDevice(Device *device);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
void mouseReleaseEvent(QMouseEvent *event);
|
||||
|
@ -27,41 +30,31 @@ protected:
|
|||
void showEvent(QShowEvent *event);
|
||||
void hideEvent(QHideEvent *event);
|
||||
|
||||
signals:
|
||||
void screenshot();
|
||||
|
||||
private slots:
|
||||
void on_fullScreenBtn_clicked();
|
||||
|
||||
void on_returnBtn_clicked();
|
||||
|
||||
void on_homeBtn_clicked();
|
||||
|
||||
void on_menuBtn_clicked();
|
||||
|
||||
void on_appSwitchBtn_clicked();
|
||||
|
||||
void on_powerBtn_clicked();
|
||||
|
||||
void on_screenShotBtn_clicked();
|
||||
|
||||
void on_volumeUpBtn_clicked();
|
||||
|
||||
void on_volumeDownBtn_clicked();
|
||||
|
||||
void on_closeScreenBtn_clicked();
|
||||
|
||||
void on_expandNotifyBtn_clicked();
|
||||
|
||||
void on_touchBtn_clicked();
|
||||
void on_groupControlBtn_clicked();
|
||||
|
||||
void onControlStateChange(Device* device, Device::GroupControlState oldState, Device::GroupControlState newState);
|
||||
|
||||
private:
|
||||
void initStyle();
|
||||
void updateGroupControl();
|
||||
|
||||
private:
|
||||
Ui::ToolForm *ui;
|
||||
QPoint m_dragPosition;
|
||||
QPointer<VideoForm> m_videoForm;
|
||||
QPointer<Device> m_device;
|
||||
bool m_showTouch = false;
|
||||
};
|
||||
|
||||
|
|
|
@ -20,6 +20,13 @@
|
|||
<property name="topMargin">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="groupControlBtn">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="fullScreenBtn">
|
||||
<property name="toolTip">
|
||||
|
|
|
@ -8,33 +8,39 @@
|
|||
#include <QMimeData>
|
||||
#include <QFileInfo>
|
||||
#include <QMessageBox>
|
||||
#include <QShortcut>
|
||||
#include <QWindow>
|
||||
#include <QScreen>
|
||||
|
||||
#include "videoform.h"
|
||||
#include "qyuvopenglwidget.h"
|
||||
#include "mousetap/mousetap.h"
|
||||
#include "ui_videoform.h"
|
||||
#include "iconhelper.h"
|
||||
#include "toolform.h"
|
||||
#include "device.h"
|
||||
#include "controller.h"
|
||||
#include "filehandler.h"
|
||||
#include "config.h"
|
||||
extern "C"
|
||||
{
|
||||
#include "libavutil/frame.h"
|
||||
}
|
||||
|
||||
VideoForm::VideoForm(bool skin, QWidget *parent)
|
||||
VideoForm::VideoForm(bool framelessWindow, bool skin, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, ui(new Ui::videoForm)
|
||||
, m_skin(skin)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
initUI();
|
||||
installShortcut();
|
||||
updateShowSize(size());
|
||||
bool vertical = size().height() > size().width();
|
||||
if (m_skin) {
|
||||
updateStyleSheet(vertical);
|
||||
}
|
||||
if (framelessWindow) {
|
||||
setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
|
||||
}
|
||||
}
|
||||
|
||||
VideoForm::~VideoForm()
|
||||
|
@ -70,13 +76,47 @@ void VideoForm::initUI()
|
|||
ui->keepRadioWidget->setMouseTracking(true);
|
||||
}
|
||||
|
||||
void VideoForm::onGrabCursor(bool grab)
|
||||
QRect VideoForm::getGrabCursorRect()
|
||||
{
|
||||
#if defined(Q_OS_WIN32) || defined(Q_OS_OSX)
|
||||
MouseTap::getInstance()->enableMouseEventTap(m_videoWidget, grab);
|
||||
QRect rc;
|
||||
#if defined(Q_OS_WIN32)
|
||||
rc = QRect(m_videoWidget->mapToGlobal(m_videoWidget->pos())
|
||||
, m_videoWidget->size());
|
||||
// high dpi support
|
||||
rc.setTopLeft(rc.topLeft() * m_videoWidget->devicePixelRatio());
|
||||
rc.setBottomRight(rc.bottomRight() * m_videoWidget->devicePixelRatio());
|
||||
#elif defined(Q_OS_OSX)
|
||||
rc = m_videoWidget->geometry();
|
||||
rc.setTopLeft(m_videoWidget->mapToGlobal(rc.topLeft()));
|
||||
rc.setBottomRight(m_videoWidget->mapToGlobal(rc.bottomRight()));
|
||||
rc.setX(rc.x() + 100);
|
||||
rc.setY(rc.y() + 30);
|
||||
rc.setWidth(rc.width() - 180);
|
||||
rc.setHeight(rc.height() - 60);
|
||||
#else
|
||||
Q_UNUSED(grab)
|
||||
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
const QSize &VideoForm::frameSize()
|
||||
{
|
||||
return m_frameSize;
|
||||
}
|
||||
|
||||
void VideoForm::resizeSquare()
|
||||
{
|
||||
QRect screenRect = getScreenRect();
|
||||
if (screenRect.isEmpty()) {
|
||||
qWarning() << "getScreenRect is empty";
|
||||
return;
|
||||
}
|
||||
resize(screenRect.height(), screenRect.height());
|
||||
}
|
||||
|
||||
void VideoForm::removeBlackRect()
|
||||
{
|
||||
resize(ui->keepRadioWidget->goodSize());
|
||||
}
|
||||
|
||||
void VideoForm::updateRender(const AVFrame *frame)
|
||||
|
@ -98,7 +138,7 @@ void VideoForm::showToolForm(bool show)
|
|||
{
|
||||
if (!m_toolForm) {
|
||||
m_toolForm = new ToolForm(this, ToolForm::AP_OUTSIDE_RIGHT);
|
||||
connect(m_toolForm, &ToolForm::screenshot, this, &VideoForm::screenshot);
|
||||
m_toolForm->setDevice(m_device);
|
||||
}
|
||||
m_toolForm->move(pos().x() + geometry().width(), pos().y() + 30);
|
||||
m_toolForm->setVisible(show);
|
||||
|
@ -106,16 +146,178 @@ void VideoForm::showToolForm(bool show)
|
|||
|
||||
void VideoForm::moveCenter()
|
||||
{
|
||||
QDesktopWidget* desktop = QApplication::desktop();
|
||||
if (!desktop) {
|
||||
qWarning() << "QApplication::desktop() is nullptr";
|
||||
QRect screenRect = getScreenRect();
|
||||
if (screenRect.isEmpty()) {
|
||||
qWarning() << "getScreenRect is empty";
|
||||
return;
|
||||
}
|
||||
QRect screenRect = desktop->availableGeometry();
|
||||
// 窗口居中
|
||||
move(screenRect.center() - QRect(0, 0, size().width(), size().height()).center());
|
||||
}
|
||||
|
||||
void VideoForm::installShortcut()
|
||||
{
|
||||
QShortcut *shortcut = nullptr;
|
||||
|
||||
// switchFullScreen
|
||||
shortcut = new QShortcut(QKeySequence("Ctrl+f"), this);
|
||||
connect(shortcut, &QShortcut::activated, this, [this](){
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->switchFullScreen();
|
||||
});
|
||||
|
||||
// resizeSquare
|
||||
shortcut = new QShortcut(QKeySequence("Ctrl+g"), this);
|
||||
connect(shortcut, &QShortcut::activated, this, [this](){
|
||||
resizeSquare();
|
||||
});
|
||||
|
||||
// removeBlackRect
|
||||
shortcut = new QShortcut(QKeySequence("Ctrl+x"), this);
|
||||
connect(shortcut, &QShortcut::activated, this, [this](){
|
||||
removeBlackRect();
|
||||
});
|
||||
|
||||
|
||||
// postGoHome
|
||||
shortcut = new QShortcut(QKeySequence("Ctrl+h"), this);
|
||||
connect(shortcut, &QShortcut::activated, this, [this](){
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->postGoHome();
|
||||
});
|
||||
|
||||
// postGoBack
|
||||
shortcut = new QShortcut(QKeySequence("Ctrl+b"), this);
|
||||
connect(shortcut, &QShortcut::activated, this, [this](){
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->postGoBack();
|
||||
});
|
||||
|
||||
// postAppSwitch
|
||||
shortcut = new QShortcut(QKeySequence("Ctrl+s"), this);
|
||||
connect(shortcut, &QShortcut::activated, this, [this](){
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->postAppSwitch();
|
||||
});
|
||||
|
||||
// postGoMenu
|
||||
shortcut = new QShortcut(QKeySequence("Ctrl+m"), this);
|
||||
connect(shortcut, &QShortcut::activated, this, [this](){
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->postGoMenu();
|
||||
});
|
||||
|
||||
// postVolumeUp
|
||||
shortcut = new QShortcut(QKeySequence("Ctrl+up"), this);
|
||||
connect(shortcut, &QShortcut::activated, this, [this](){
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->postVolumeUp();
|
||||
});
|
||||
|
||||
// postVolumeDown
|
||||
shortcut = new QShortcut(QKeySequence("Ctrl+down"), this);
|
||||
connect(shortcut, &QShortcut::activated, this, [this](){
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->postVolumeDown();
|
||||
});
|
||||
|
||||
// postPower
|
||||
shortcut = new QShortcut(QKeySequence("Ctrl+p"), this);
|
||||
connect(shortcut, &QShortcut::activated, this, [this](){
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->postPower();
|
||||
});
|
||||
|
||||
// setScreenPowerMode(ControlMsg::SPM_OFF)
|
||||
shortcut = new QShortcut(QKeySequence("Ctrl+o"), this);
|
||||
connect(shortcut, &QShortcut::activated, this, [this](){
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->setScreenPowerMode(ControlMsg::SPM_OFF);
|
||||
});
|
||||
|
||||
// expandNotificationPanel
|
||||
shortcut = new QShortcut(QKeySequence("Ctrl+n"), this);
|
||||
connect(shortcut, &QShortcut::activated, this, [this](){
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->expandNotificationPanel();
|
||||
});
|
||||
|
||||
// collapseNotificationPanel
|
||||
shortcut = new QShortcut(QKeySequence("Ctrl+Shift+n"), this);
|
||||
connect(shortcut, &QShortcut::activated, this, [this](){
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->collapseNotificationPanel();
|
||||
});
|
||||
|
||||
// requestDeviceClipboard
|
||||
shortcut = new QShortcut(QKeySequence("Ctrl+c"), this);
|
||||
connect(shortcut, &QShortcut::activated, this, [this](){
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->requestDeviceClipboard();
|
||||
});
|
||||
|
||||
// clipboardPaste
|
||||
shortcut = new QShortcut(QKeySequence("Ctrl+v"), this);
|
||||
connect(shortcut, &QShortcut::activated, this, [this](){
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->clipboardPaste();
|
||||
});
|
||||
|
||||
// setDeviceClipboard
|
||||
shortcut = new QShortcut(QKeySequence("Ctrl+Shift+v"), this);
|
||||
connect(shortcut, &QShortcut::activated, this, [this](){
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
emit m_device->setDeviceClipboard();
|
||||
});
|
||||
}
|
||||
|
||||
QRect VideoForm::getScreenRect()
|
||||
{
|
||||
QRect screenRect;
|
||||
QWidget *win = window();
|
||||
if (!win) {
|
||||
return screenRect;
|
||||
}
|
||||
QWindow *winHandle = win->windowHandle();
|
||||
if (!winHandle) {
|
||||
return screenRect;
|
||||
}
|
||||
QScreen *screen = winHandle->screen();
|
||||
if (!screen) {
|
||||
return screenRect;
|
||||
}
|
||||
screenRect = screen->availableGeometry();
|
||||
return screenRect;
|
||||
}
|
||||
|
||||
void VideoForm::updateStyleSheet(bool vertical)
|
||||
{
|
||||
if (vertical) {
|
||||
|
@ -157,12 +359,11 @@ void VideoForm::updateShowSize(const QSize &newSize)
|
|||
|
||||
bool vertical = m_widthHeightRatio < 1.0f ? true : false;
|
||||
QSize showSize = newSize;
|
||||
QDesktopWidget* desktop = QApplication::desktop();
|
||||
if (!desktop) {
|
||||
qWarning() << "QApplication::desktop() is nullptr";
|
||||
QRect screenRect = getScreenRect();
|
||||
if (screenRect.isEmpty()) {
|
||||
qWarning() << "getScreenRect is empty";
|
||||
return;
|
||||
}
|
||||
QRect screenRect = desktop->availableGeometry();
|
||||
if (vertical) {
|
||||
showSize.setHeight(qMin(newSize.height(), screenRect.height() - 200));
|
||||
showSize.setWidth(showSize.height() * m_widthHeightRatio);
|
||||
|
@ -171,8 +372,8 @@ void VideoForm::updateShowSize(const QSize &newSize)
|
|||
showSize.setHeight(showSize.width() / m_widthHeightRatio);
|
||||
}
|
||||
|
||||
if (isFullScreen()) {
|
||||
switchFullScreen();
|
||||
if (isFullScreen() && m_device) {
|
||||
emit m_device->switchFullScreen();
|
||||
}
|
||||
if (m_skin) {
|
||||
QMargins m = getMargins(vertical);
|
||||
|
@ -190,7 +391,7 @@ void VideoForm::updateShowSize(const QSize &newSize)
|
|||
}
|
||||
}
|
||||
|
||||
void VideoForm::switchFullScreen()
|
||||
void VideoForm::onSwitchFullScreen()
|
||||
{
|
||||
if (isFullScreen()) {
|
||||
// 横屏全屏铺满全屏,恢复时,恢复保持宽高比
|
||||
|
@ -253,39 +454,25 @@ void VideoForm::staysOnTop(bool top)
|
|||
}
|
||||
}
|
||||
|
||||
Controller *VideoForm::getController()
|
||||
void VideoForm::setDevice(Device *device)
|
||||
{
|
||||
return m_controller;
|
||||
}
|
||||
|
||||
void VideoForm::setFileHandler(FileHandler *fileHandler)
|
||||
{
|
||||
m_fileHandler = fileHandler;
|
||||
}
|
||||
|
||||
void VideoForm::setSerial(const QString &serial)
|
||||
{
|
||||
m_serial = serial;
|
||||
}
|
||||
|
||||
const QString &VideoForm::getSerial()
|
||||
{
|
||||
return m_serial;
|
||||
}
|
||||
|
||||
void VideoForm::setController(Controller *controller)
|
||||
{
|
||||
m_controller = controller;
|
||||
m_device = device;
|
||||
}
|
||||
|
||||
void VideoForm::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::MiddleButton) {
|
||||
if (m_device) {
|
||||
emit m_device->postGoHome();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_videoWidget->geometry().contains(event->pos())) {
|
||||
if (!m_controller) {
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
event->setLocalPos(m_videoWidget->mapFrom(this, event->localPos().toPoint()));
|
||||
m_controller->mouseEvent(event, m_videoWidget->frameSize(), m_videoWidget->size());
|
||||
emit m_device->mouseEvent(event, m_videoWidget->frameSize(), m_videoWidget->size());
|
||||
} else {
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
m_dragPosition = event->globalPos() - frameGeometry().topLeft();
|
||||
|
@ -297,7 +484,7 @@ void VideoForm::mousePressEvent(QMouseEvent *event)
|
|||
void VideoForm::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
if (m_dragPosition.isNull()) {
|
||||
if (!m_controller) {
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
event->setLocalPos(m_videoWidget->mapFrom(this, event->localPos().toPoint()));
|
||||
|
@ -316,7 +503,7 @@ void VideoForm::mouseReleaseEvent(QMouseEvent *event)
|
|||
local.setY(m_videoWidget->height());
|
||||
}
|
||||
event->setLocalPos(local);
|
||||
m_controller->mouseEvent(event, m_videoWidget->frameSize(), m_videoWidget->size());
|
||||
emit m_device->mouseEvent(event, m_videoWidget->frameSize(), m_videoWidget->size());
|
||||
} else {
|
||||
m_dragPosition = QPoint(0, 0);
|
||||
}
|
||||
|
@ -325,11 +512,11 @@ void VideoForm::mouseReleaseEvent(QMouseEvent *event)
|
|||
void VideoForm::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
if (m_videoWidget->geometry().contains(event->pos())) {
|
||||
if (!m_controller) {
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
event->setLocalPos(m_videoWidget->mapFrom(this, event->localPos().toPoint()));
|
||||
m_controller->mouseEvent(event, m_videoWidget->frameSize(), m_videoWidget->size());
|
||||
emit m_device->mouseEvent(event, m_videoWidget->frameSize(), m_videoWidget->size());
|
||||
} else if (!m_dragPosition.isNull()){
|
||||
if (event->buttons() & Qt::LeftButton) {
|
||||
move(event->globalPos() - m_dragPosition);
|
||||
|
@ -338,10 +525,22 @@ void VideoForm::mouseMoveEvent(QMouseEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
void VideoForm::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton
|
||||
&& !m_videoWidget->geometry().contains(event->pos())) {
|
||||
removeBlackRect();
|
||||
}
|
||||
|
||||
if (event->button() == Qt::RightButton && m_device) {
|
||||
emit m_device->postBackOrScreenOn();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoForm::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
if (m_videoWidget->geometry().contains(event->pos())) {
|
||||
if (!m_controller) {
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
QPointF pos = m_videoWidget->mapFrom(this, event->pos());
|
||||
|
@ -352,41 +551,30 @@ void VideoForm::wheelEvent(QWheelEvent *event)
|
|||
*/
|
||||
QWheelEvent wheelEvent(pos, event->globalPosF(), event->delta(),
|
||||
event->buttons(), event->modifiers(), event->orientation());
|
||||
m_controller->wheelEvent(&wheelEvent, m_videoWidget->frameSize(), m_videoWidget->size());
|
||||
emit m_device->wheelEvent(&wheelEvent, m_videoWidget->frameSize(), m_videoWidget->size());
|
||||
}
|
||||
}
|
||||
|
||||
void VideoForm::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
if (Qt::Key_Escape == event->key()
|
||||
&& !event->isAutoRepeat()
|
||||
&& isFullScreen()) {
|
||||
switchFullScreen();
|
||||
}
|
||||
if (!m_controller) {
|
||||
return;
|
||||
}
|
||||
if (event->key() == Qt::Key_C && (event->modifiers() & Qt::ControlModifier)) {
|
||||
m_controller->requestDeviceClipboard();
|
||||
}
|
||||
if (event->key() == Qt::Key_V && (event->modifiers() & Qt::ControlModifier)) {
|
||||
if (event->modifiers() & Qt::ShiftModifier) {
|
||||
m_controller->setDeviceClipboard();
|
||||
} else {
|
||||
m_controller->clipboardPaste();
|
||||
}
|
||||
return;
|
||||
emit m_device->switchFullScreen();
|
||||
}
|
||||
|
||||
m_controller->keyEvent(event, m_videoWidget->frameSize(), m_videoWidget->size());
|
||||
emit m_device->keyEvent(event, m_videoWidget->frameSize(), m_videoWidget->size());
|
||||
}
|
||||
|
||||
void VideoForm::keyReleaseEvent(QKeyEvent *event)
|
||||
{
|
||||
if (!m_controller) {
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
m_controller->keyEvent(event, m_videoWidget->frameSize(), m_videoWidget->size());
|
||||
emit m_device->keyEvent(event, m_videoWidget->frameSize(), m_videoWidget->size());
|
||||
}
|
||||
|
||||
void VideoForm::paintEvent(QPaintEvent *paint)
|
||||
|
@ -432,6 +620,15 @@ void VideoForm::resizeEvent(QResizeEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
void VideoForm::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
Config::getInstance().setRect(m_device->getSerial(), geometry());
|
||||
}
|
||||
|
||||
void VideoForm::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
event->acceptProposedAction();
|
||||
|
@ -449,7 +646,7 @@ void VideoForm::dragLeaveEvent(QDragLeaveEvent *event)
|
|||
|
||||
void VideoForm::dropEvent(QDropEvent *event)
|
||||
{
|
||||
if (!m_fileHandler) {
|
||||
if (!m_device) {
|
||||
return;
|
||||
}
|
||||
const QMimeData* qm = event->mimeData();
|
||||
|
@ -462,8 +659,8 @@ void VideoForm::dropEvent(QDropEvent *event)
|
|||
}
|
||||
|
||||
if (fileInfo.isFile() && fileInfo.suffix() == "apk") {
|
||||
m_fileHandler->installApkRequest(m_serial, file);
|
||||
emit m_device->installApkRequest(m_device->getSerial(), file);
|
||||
return;
|
||||
}
|
||||
m_fileHandler->pushFileRequest(m_serial, file, Config::getInstance().getPushFilePath() + fileInfo.fileName());
|
||||
emit m_device->pushFileRequest(m_device->getSerial(), file, Config::getInstance().getPushFilePath() + fileInfo.fileName());
|
||||
}
|
||||
|
|
|
@ -10,31 +10,27 @@ class videoForm;
|
|||
|
||||
struct AVFrame;
|
||||
class ToolForm;
|
||||
class Controller;
|
||||
class Device;
|
||||
class FileHandler;
|
||||
class QYUVOpenGLWidget;
|
||||
class VideoForm : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit VideoForm(bool skin = true, QWidget *parent = 0);
|
||||
explicit VideoForm(bool framelessWindow = false, bool skin = true, QWidget *parent = 0);
|
||||
~VideoForm();
|
||||
|
||||
void switchFullScreen();
|
||||
void staysOnTop(bool top = true);
|
||||
void updateShowSize(const QSize &newSize);
|
||||
void updateRender(const AVFrame *frame);
|
||||
void setController(Controller *controller);
|
||||
Controller* getController();
|
||||
void setFileHandler(FileHandler *fileHandler);
|
||||
void setSerial(const QString &serial);
|
||||
const QString& getSerial();
|
||||
|
||||
signals:
|
||||
void screenshot();
|
||||
void setDevice(Device *device);
|
||||
QRect getGrabCursorRect();
|
||||
const QSize &frameSize();
|
||||
void resizeSquare();
|
||||
void removeBlackRect();
|
||||
|
||||
public slots:
|
||||
void onGrabCursor(bool grab);
|
||||
void onSwitchFullScreen();
|
||||
|
||||
private:
|
||||
void updateStyleSheet(bool vertical);
|
||||
|
@ -43,11 +39,14 @@ private:
|
|||
|
||||
void showToolForm(bool show = true);
|
||||
void moveCenter();
|
||||
void installShortcut();
|
||||
QRect getScreenRect();
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
void mouseReleaseEvent(QMouseEvent *event);
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
void mouseDoubleClickEvent(QMouseEvent *event);
|
||||
void wheelEvent(QWheelEvent *event);
|
||||
void keyPressEvent(QKeyEvent *event);
|
||||
void keyReleaseEvent(QKeyEvent *event);
|
||||
|
@ -55,6 +54,7 @@ protected:
|
|||
void paintEvent(QPaintEvent *);
|
||||
void showEvent(QShowEvent *event);
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
void closeEvent(QCloseEvent *event);
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent *event);
|
||||
void dragMoveEvent(QDragMoveEvent *event);
|
||||
|
@ -76,9 +76,7 @@ private:
|
|||
QPoint m_fullScreenBeforePos;
|
||||
|
||||
//outside member
|
||||
QString m_serial = "";
|
||||
QPointer<Controller> m_controller;
|
||||
QPointer<FileHandler> m_fileHandler;
|
||||
QPointer<Device> m_device;
|
||||
};
|
||||
|
||||
#endif // VIDEOFORM_H
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
#include <QDebug>
|
||||
#include <QMouseEvent>
|
||||
#include <QWheelEvent>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "devicemanage.h"
|
||||
#include "server.h"
|
||||
|
@ -44,6 +47,7 @@ bool DeviceManage::connectDevice(Device::DeviceParams params)
|
|||
*/
|
||||
Device *device = new Device(params);
|
||||
connect(device, &Device::deviceDisconnect, this, &DeviceManage::onDeviceDisconnect);
|
||||
connect(device, &Device::controlStateChange, this, &DeviceManage::onControlStateChange);
|
||||
m_devices[params.serial] = device;
|
||||
return true;
|
||||
}
|
||||
|
@ -102,13 +106,166 @@ void DeviceManage::disconnectAllDevice()
|
|||
}
|
||||
}
|
||||
|
||||
void DeviceManage::setGroupControlSignals(Device *host, Device *client, bool install)
|
||||
{
|
||||
if (!host || !client) {
|
||||
return;
|
||||
}
|
||||
if (install) {
|
||||
connect(host, &Device::postGoBack, client, &Device::postGoBack);
|
||||
connect(host, &Device::postGoHome, client, &Device::postGoHome);
|
||||
connect(host, &Device::postGoMenu, client, &Device::postGoMenu);
|
||||
connect(host, &Device::postAppSwitch, client, &Device::postAppSwitch);
|
||||
connect(host, &Device::postPower, client, &Device::postPower);
|
||||
connect(host, &Device::postVolumeUp, client, &Device::postVolumeUp);
|
||||
connect(host, &Device::postVolumeDown, client, &Device::postVolumeDown);
|
||||
connect(host, &Device::setScreenPowerMode, client, &Device::setScreenPowerMode);
|
||||
connect(host, &Device::expandNotificationPanel, client, &Device::expandNotificationPanel);
|
||||
connect(host, &Device::collapseNotificationPanel, client, &Device::collapseNotificationPanel);
|
||||
connect(host, &Device::postBackOrScreenOn, client, &Device::postBackOrScreenOn);
|
||||
connect(host, &Device::postTextInput, client, &Device::postTextInput);
|
||||
connect(host, &Device::setDeviceClipboard, client, &Device::setDeviceClipboard);
|
||||
connect(host, &Device::clipboardPaste, client, &Device::clipboardPaste);
|
||||
connect(host, &Device::pushFileRequest, client, &Device::pushFileRequest);
|
||||
connect(host, &Device::installApkRequest, client, &Device::installApkRequest);
|
||||
connect(host, &Device::screenshot, client, &Device::screenshot);
|
||||
connect(host, &Device::showTouch, client, &Device::showTouch);
|
||||
// dont connect requestDeviceClipboard
|
||||
//connect(host, &Device::requestDeviceClipboard, client, &Device::requestDeviceClipboard);
|
||||
} else {
|
||||
disconnect(host, &Device::postGoBack, client, &Device::postGoBack);
|
||||
disconnect(host, &Device::postGoHome, client, &Device::postGoHome);
|
||||
disconnect(host, &Device::postGoMenu, client, &Device::postGoMenu);
|
||||
disconnect(host, &Device::postAppSwitch, client, &Device::postAppSwitch);
|
||||
disconnect(host, &Device::postPower, client, &Device::postPower);
|
||||
disconnect(host, &Device::postVolumeUp, client, &Device::postVolumeUp);
|
||||
disconnect(host, &Device::postVolumeDown, client, &Device::postVolumeDown);
|
||||
disconnect(host, &Device::setScreenPowerMode, client, &Device::setScreenPowerMode);
|
||||
disconnect(host, &Device::expandNotificationPanel, client, &Device::expandNotificationPanel);
|
||||
disconnect(host, &Device::collapseNotificationPanel, client, &Device::collapseNotificationPanel);
|
||||
disconnect(host, &Device::postBackOrScreenOn, client, &Device::postBackOrScreenOn);
|
||||
disconnect(host, &Device::postTextInput, client, &Device::postTextInput);
|
||||
disconnect(host, &Device::setDeviceClipboard, client, &Device::setDeviceClipboard);
|
||||
disconnect(host, &Device::clipboardPaste, client, &Device::clipboardPaste);
|
||||
disconnect(host, &Device::pushFileRequest, client, &Device::pushFileRequest);
|
||||
disconnect(host, &Device::installApkRequest, client, &Device::installApkRequest);
|
||||
disconnect(host, &Device::screenshot, client, &Device::screenshot);
|
||||
disconnect(host, &Device::showTouch, client, &Device::showTouch);
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceManage::setGroupControlHost(Device *host, bool install)
|
||||
{
|
||||
QMapIterator<QString, QPointer<Device>> i(m_devices);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
if (!i.value()) {
|
||||
continue;
|
||||
}
|
||||
if (i.value() == host) {
|
||||
continue;
|
||||
}
|
||||
if (install) {
|
||||
if (host) {
|
||||
setGroupControlSignals(host, i.value(), true);
|
||||
}
|
||||
emit i.value()->setControlState(i.value(), Device::GroupControlState::GCS_CLIENT);
|
||||
} else {
|
||||
if (host) {
|
||||
setGroupControlSignals(host, i.value(), false);
|
||||
}
|
||||
emit i.value()->setControlState(i.value(), Device::GroupControlState::GCS_FREE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceManage::onDeviceDisconnect(QString serial)
|
||||
{
|
||||
if (!serial.isEmpty() && m_devices.contains(serial)) {
|
||||
if (m_devices[serial]->controlState() == Device::GroupControlState::GCS_HOST) {
|
||||
setGroupControlHost(nullptr, false);
|
||||
}
|
||||
m_devices.remove(serial);
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceManage::onControlStateChange(Device *device, Device::GroupControlState oldState, Device::GroupControlState newState)
|
||||
{
|
||||
if (!device) {
|
||||
return;
|
||||
}
|
||||
// free to host
|
||||
if (oldState == Device::GroupControlState::GCS_FREE
|
||||
&& newState == Device::GroupControlState::GCS_HOST) {
|
||||
// install direct control signals
|
||||
setGroupControlHost(device, true);
|
||||
// install convert control signals(frameSize need convert)
|
||||
connect(device, &Device::mouseEvent, this, &DeviceManage::onMouseEvent, Qt::UniqueConnection);
|
||||
connect(device, &Device::wheelEvent, this, &DeviceManage::onWheelEvent, Qt::UniqueConnection);
|
||||
connect(device, &Device::keyEvent, this, &DeviceManage::onKeyEvent, Qt::UniqueConnection);
|
||||
return;
|
||||
}
|
||||
// host to free
|
||||
if (oldState == Device::GroupControlState::GCS_HOST
|
||||
&& newState == Device::GroupControlState::GCS_FREE) {
|
||||
// uninstall direct control signals
|
||||
setGroupControlHost(device, false);
|
||||
// uninstall convert control signals(frameSize need convert)
|
||||
disconnect(device, &Device::mouseEvent, this, &DeviceManage::onMouseEvent);
|
||||
disconnect(device, &Device::wheelEvent, this, &DeviceManage::onWheelEvent);
|
||||
disconnect(device, &Device::keyEvent, this, &DeviceManage::onKeyEvent);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceManage::onMouseEvent(const QMouseEvent *from, const QSize &frameSize, const QSize &showSize)
|
||||
{
|
||||
QMapIterator<QString, QPointer<Device>> i(m_devices);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
if (!i.value()) {
|
||||
continue;
|
||||
}
|
||||
if (i.value() == sender()) {
|
||||
continue;
|
||||
}
|
||||
// neend convert frameSize to its frameSize
|
||||
emit i.value()->mouseEvent(from, i.value()->frameSize(), showSize);
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceManage::onWheelEvent(const QWheelEvent *from, const QSize &frameSize, const QSize &showSize)
|
||||
{
|
||||
QMapIterator<QString, QPointer<Device>> i(m_devices);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
if (!i.value()) {
|
||||
continue;
|
||||
}
|
||||
if (i.value() == sender()) {
|
||||
continue;
|
||||
}
|
||||
// neend convert frameSize to its frameSize
|
||||
emit i.value()->wheelEvent(from, i.value()->frameSize(), showSize);
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceManage::onKeyEvent(const QKeyEvent *from, const QSize &frameSize, const QSize &showSize)
|
||||
{
|
||||
QMapIterator<QString, QPointer<Device>> i(m_devices);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
if (!i.value()) {
|
||||
continue;
|
||||
}
|
||||
if (i.value() == sender()) {
|
||||
continue;
|
||||
}
|
||||
// neend convert frameSize to its frameSize
|
||||
emit i.value()->keyEvent(from, i.value()->frameSize(), showSize);
|
||||
}
|
||||
}
|
||||
|
||||
quint16 DeviceManage::getFreePort()
|
||||
{
|
||||
quint16 port = m_localPortStart;
|
||||
|
|
|
@ -20,8 +20,18 @@ public:
|
|||
bool disconnectDevice(const QString &serial);
|
||||
void disconnectAllDevice();
|
||||
|
||||
protected:
|
||||
void setGroupControlSignals(Device *host, Device *client, bool install);
|
||||
void setGroupControlHost(Device *host, bool install);
|
||||
|
||||
protected slots:
|
||||
void onDeviceDisconnect(QString serial);
|
||||
void onControlStateChange(Device* device, Device::GroupControlState oldState, Device::GroupControlState newState);
|
||||
|
||||
// neend convert frameSize to its frameSize
|
||||
void onMouseEvent(const QMouseEvent* from, const QSize& frameSize, const QSize& showSize);
|
||||
void onWheelEvent(const QWheelEvent* from, const QSize& frameSize, const QSize& showSize);
|
||||
void onKeyEvent(const QKeyEvent* from, const QSize& frameSize, const QSize& showSize);
|
||||
|
||||
private:
|
||||
quint16 getFreePort();
|
||||
|
|
|
@ -98,6 +98,7 @@ void Dialog::initUI()
|
|||
ui->formatBox->setCurrentIndex(Config::getInstance().getRecordFormatIndex());
|
||||
|
||||
ui->recordPathEdt->setText(Config::getInstance().getRecordPath());
|
||||
ui->framelessCheck->setChecked(Config::getInstance().getFramelessWindow());
|
||||
|
||||
#ifdef Q_OS_OSX
|
||||
// mac need more width
|
||||
|
@ -384,3 +385,9 @@ void Dialog::on_formatBox_activated(int index)
|
|||
{
|
||||
Config::getInstance().setRecordFormatIndex(index);
|
||||
}
|
||||
|
||||
void Dialog::on_framelessCheck_stateChanged(int arg1)
|
||||
{
|
||||
Q_UNUSED(arg1)
|
||||
Config::getInstance().setFramelessWindow(ui->framelessCheck->isChecked());
|
||||
}
|
||||
|
|
|
@ -62,6 +62,8 @@ private slots:
|
|||
|
||||
void on_formatBox_activated(int index);
|
||||
|
||||
void on_framelessCheck_stateChanged(int arg1);
|
||||
|
||||
private:
|
||||
bool checkAdbRun();
|
||||
void initUI();
|
||||
|
|
|
@ -215,6 +215,22 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<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="1" column="1">
|
||||
<widget class="QCheckBox" name="closeScreenCheck">
|
||||
<property name="sizePolicy">
|
||||
|
@ -228,22 +244,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<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="0" column="3">
|
||||
<widget class="QCheckBox" name="useReverseCheck">
|
||||
<property name="sizePolicy">
|
||||
|
@ -260,8 +260,8 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="alwaysTopCheck">
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="notDisplayCheck">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
|
@ -269,13 +269,20 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>always on top</string>
|
||||
<string>background record</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QCheckBox" name="framelessCheck">
|
||||
<property name="text">
|
||||
<string>frameless</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
Binary file not shown.
|
@ -16,22 +16,22 @@
|
|||
<translation type="vanished">file transfer failed</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/device.cpp" line="134"/>
|
||||
<location filename="../../device/device.cpp" line="183"/>
|
||||
<source>install apk</source>
|
||||
<translation>install apk</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/device.cpp" line="136"/>
|
||||
<location filename="../../device/device.cpp" line="185"/>
|
||||
<source>file transfer</source>
|
||||
<translation>file transfer</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/device.cpp" line="139"/>
|
||||
<location filename="../../device/device.cpp" line="189"/>
|
||||
<source>wait current %1 to complete</source>
|
||||
<translation>wait current %1 to complete</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/device.cpp" line="142"/>
|
||||
<location filename="../../device/device.cpp" line="192"/>
|
||||
<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="145"/>
|
||||
<location filename="../../device/device.cpp" line="195"/>
|
||||
<source>%1 failed</source>
|
||||
<translation>%1 failed</translation>
|
||||
</message>
|
||||
|
@ -49,17 +49,17 @@
|
|||
<context>
|
||||
<name>Dialog</name>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="415"/>
|
||||
<location filename="../../dialog.ui" line="422"/>
|
||||
<source>Wireless</source>
|
||||
<translation>Wireless</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="499"/>
|
||||
<location filename="../../dialog.ui" line="506"/>
|
||||
<source>wireless connect</source>
|
||||
<translation>wireless connect</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="515"/>
|
||||
<location filename="../../dialog.ui" line="522"/>
|
||||
<source>wireless disconnect</source>
|
||||
<translation>wireless disconnect</translation>
|
||||
</message>
|
||||
|
@ -75,7 +75,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="144"/>
|
||||
<location filename="../../dialog.cpp" line="294"/>
|
||||
<location filename="../../dialog.cpp" line="305"/>
|
||||
<source>select path</source>
|
||||
<translation>select path</translation>
|
||||
</message>
|
||||
|
@ -90,27 +90,32 @@
|
|||
<translation>record screen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="372"/>
|
||||
<location filename="../../dialog.ui" line="282"/>
|
||||
<source>frameless</source>
|
||||
<translation>frameless</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="379"/>
|
||||
<source>stop all server</source>
|
||||
<translation>stop all server</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="549"/>
|
||||
<location filename="../../dialog.ui" line="556"/>
|
||||
<source>adb command:</source>
|
||||
<translation>adb command:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="585"/>
|
||||
<location filename="../../dialog.ui" line="592"/>
|
||||
<source>terminate</source>
|
||||
<translation>terminate</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="572"/>
|
||||
<location filename="../../dialog.ui" line="579"/>
|
||||
<source>execute</source>
|
||||
<translation>execute</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="598"/>
|
||||
<location filename="../../dialog.ui" line="605"/>
|
||||
<source>clear</source>
|
||||
<translation>clear</translation>
|
||||
</message>
|
||||
|
@ -124,12 +129,12 @@
|
|||
<translation type="vanished">auto enable</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="240"/>
|
||||
<location filename="../../dialog.ui" line="272"/>
|
||||
<source>background record</source>
|
||||
<translation>background record</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="227"/>
|
||||
<location filename="../../dialog.ui" line="243"/>
|
||||
<source>screen-off</source>
|
||||
<translation>screen-off</translation>
|
||||
</message>
|
||||
|
@ -144,7 +149,7 @@
|
|||
<translation>max size:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="272"/>
|
||||
<location filename="../../dialog.ui" line="227"/>
|
||||
<source>always on top</source>
|
||||
<translation>always on top</translation>
|
||||
</message>
|
||||
|
@ -154,27 +159,27 @@
|
|||
<translation>refresh script</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="389"/>
|
||||
<location filename="../../dialog.ui" line="396"/>
|
||||
<source>get device IP</source>
|
||||
<translation>get device IP</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="288"/>
|
||||
<location filename="../../dialog.ui" line="295"/>
|
||||
<source>USB line</source>
|
||||
<translation>USB line</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="344"/>
|
||||
<location filename="../../dialog.ui" line="351"/>
|
||||
<source>stop server</source>
|
||||
<translation>stop server</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="334"/>
|
||||
<location filename="../../dialog.ui" line="341"/>
|
||||
<source>start server</source>
|
||||
<translation>start server</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="324"/>
|
||||
<location filename="../../dialog.ui" line="331"/>
|
||||
<source>device serial:</source>
|
||||
<translation>device serial:</translation>
|
||||
</message>
|
||||
|
@ -188,12 +193,12 @@
|
|||
<translation>bit rate:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="399"/>
|
||||
<location filename="../../dialog.ui" line="406"/>
|
||||
<source>start adbd</source>
|
||||
<translation>start adbd</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="379"/>
|
||||
<location filename="../../dialog.ui" line="386"/>
|
||||
<source>refresh devices</source>
|
||||
<translation>refresh devices</translation>
|
||||
</message>
|
||||
|
@ -206,7 +211,7 @@
|
|||
<context>
|
||||
<name>QObject</name>
|
||||
<message>
|
||||
<location filename="../../main.cpp" line="80"/>
|
||||
<location filename="../../main.cpp" line="101"/>
|
||||
<source>This software is completely open source and free, you can download it at the following address:</source>
|
||||
<translation>This software is completely open source and free, you can download it at the following address:</translation>
|
||||
</message>
|
||||
|
@ -219,12 +224,12 @@
|
|||
<translation>Tool</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="26"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="33"/>
|
||||
<source>full screen</source>
|
||||
<translation>full screen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="49"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="56"/>
|
||||
<source>expand notify</source>
|
||||
<translation>expand notify</translation>
|
||||
</message>
|
||||
|
@ -237,52 +242,52 @@
|
|||
<translation type="vanished">turn on</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="59"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="66"/>
|
||||
<source>touch switch</source>
|
||||
<translation>touch switch</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="69"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="76"/>
|
||||
<source>close screen</source>
|
||||
<translation>close screen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="79"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="86"/>
|
||||
<source>power</source>
|
||||
<translation>power</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="89"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="96"/>
|
||||
<source>volume up</source>
|
||||
<translation>volume up</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="99"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="106"/>
|
||||
<source>volume down</source>
|
||||
<translation>volume down</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="109"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="116"/>
|
||||
<source>app switch</source>
|
||||
<translation>app switch</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="119"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="126"/>
|
||||
<source>menu</source>
|
||||
<translation>menu</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="129"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="136"/>
|
||||
<source>home</source>
|
||||
<translation>home</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="139"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="146"/>
|
||||
<source>return</source>
|
||||
<translation>return</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="149"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="156"/>
|
||||
<source>screen shot</source>
|
||||
<translation>screen shot</translation>
|
||||
</message>
|
||||
|
@ -302,7 +307,7 @@
|
|||
<translation type="vanished">file transfer failed</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/videoform.cpp" line="415"/>
|
||||
<location filename="../../device/ui/videoform.cpp" line="657"/>
|
||||
<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="134"/>
|
||||
<location filename="../../device/device.cpp" line="183"/>
|
||||
<source>install apk</source>
|
||||
<translation>安装apk</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/device.cpp" line="136"/>
|
||||
<location filename="../../device/device.cpp" line="185"/>
|
||||
<source>file transfer</source>
|
||||
<translation>文件传输</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/device.cpp" line="139"/>
|
||||
<location filename="../../device/device.cpp" line="189"/>
|
||||
<source>wait current %1 to complete</source>
|
||||
<translation>等待当前%1完成</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/device.cpp" line="142"/>
|
||||
<location filename="../../device/device.cpp" line="192"/>
|
||||
<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="145"/>
|
||||
<location filename="../../device/device.cpp" line="195"/>
|
||||
<source>%1 failed</source>
|
||||
<translation>%1 失败</translation>
|
||||
</message>
|
||||
|
@ -49,17 +49,17 @@
|
|||
<context>
|
||||
<name>Dialog</name>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="415"/>
|
||||
<location filename="../../dialog.ui" line="422"/>
|
||||
<source>Wireless</source>
|
||||
<translation>无线</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="499"/>
|
||||
<location filename="../../dialog.ui" line="506"/>
|
||||
<source>wireless connect</source>
|
||||
<translation>无线连接</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="515"/>
|
||||
<location filename="../../dialog.ui" line="522"/>
|
||||
<source>wireless disconnect</source>
|
||||
<translation>无线断开</translation>
|
||||
</message>
|
||||
|
@ -75,7 +75,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="144"/>
|
||||
<location filename="../../dialog.cpp" line="294"/>
|
||||
<location filename="../../dialog.cpp" line="305"/>
|
||||
<source>select path</source>
|
||||
<translation>选择路径</translation>
|
||||
</message>
|
||||
|
@ -90,27 +90,32 @@
|
|||
<translation>录制屏幕</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="372"/>
|
||||
<location filename="../../dialog.ui" line="282"/>
|
||||
<source>frameless</source>
|
||||
<translation>无边框</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="379"/>
|
||||
<source>stop all server</source>
|
||||
<translation>停止所有服务</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="549"/>
|
||||
<location filename="../../dialog.ui" line="556"/>
|
||||
<source>adb command:</source>
|
||||
<translation>adb命令:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="585"/>
|
||||
<location filename="../../dialog.ui" line="592"/>
|
||||
<source>terminate</source>
|
||||
<translation>终止</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="572"/>
|
||||
<location filename="../../dialog.ui" line="579"/>
|
||||
<source>execute</source>
|
||||
<translation>执行</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="598"/>
|
||||
<location filename="../../dialog.ui" line="605"/>
|
||||
<source>clear</source>
|
||||
<translation>清理</translation>
|
||||
</message>
|
||||
|
@ -124,12 +129,12 @@
|
|||
<translation type="vanished">自动启用脚本</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="240"/>
|
||||
<location filename="../../dialog.ui" line="272"/>
|
||||
<source>background record</source>
|
||||
<translation>后台录制</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="227"/>
|
||||
<location filename="../../dialog.ui" line="243"/>
|
||||
<source>screen-off</source>
|
||||
<translation>自动息屏</translation>
|
||||
</message>
|
||||
|
@ -144,7 +149,7 @@
|
|||
<translation>最大尺寸:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="272"/>
|
||||
<location filename="../../dialog.ui" line="227"/>
|
||||
<source>always on top</source>
|
||||
<translation>窗口置顶</translation>
|
||||
</message>
|
||||
|
@ -154,27 +159,27 @@
|
|||
<translation>刷新脚本</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="389"/>
|
||||
<location filename="../../dialog.ui" line="396"/>
|
||||
<source>get device IP</source>
|
||||
<translation>获取设备IP</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="288"/>
|
||||
<location filename="../../dialog.ui" line="295"/>
|
||||
<source>USB line</source>
|
||||
<translation>USB线</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="344"/>
|
||||
<location filename="../../dialog.ui" line="351"/>
|
||||
<source>stop server</source>
|
||||
<translation>停止服务</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="334"/>
|
||||
<location filename="../../dialog.ui" line="341"/>
|
||||
<source>start server</source>
|
||||
<translation>启动服务</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="324"/>
|
||||
<location filename="../../dialog.ui" line="331"/>
|
||||
<source>device serial:</source>
|
||||
<translation>设备序列号:</translation>
|
||||
</message>
|
||||
|
@ -188,12 +193,12 @@
|
|||
<translation>比特率:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="399"/>
|
||||
<location filename="../../dialog.ui" line="406"/>
|
||||
<source>start adbd</source>
|
||||
<translation>启动adbd</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../dialog.ui" line="379"/>
|
||||
<location filename="../../dialog.ui" line="386"/>
|
||||
<source>refresh devices</source>
|
||||
<translation>刷新设备列表</translation>
|
||||
</message>
|
||||
|
@ -206,7 +211,7 @@
|
|||
<context>
|
||||
<name>QObject</name>
|
||||
<message>
|
||||
<location filename="../../main.cpp" line="80"/>
|
||||
<location filename="../../main.cpp" line="101"/>
|
||||
<source>This software is completely open source and free, you can download it at the following address:</source>
|
||||
<translation>本软件完全开源免费,你可以在下面的地址下载:</translation>
|
||||
</message>
|
||||
|
@ -219,12 +224,12 @@
|
|||
<translation>工具</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="26"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="33"/>
|
||||
<source>full screen</source>
|
||||
<translation>全屏</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="49"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="56"/>
|
||||
<source>expand notify</source>
|
||||
<translation>下拉通知</translation>
|
||||
</message>
|
||||
|
@ -237,52 +242,52 @@
|
|||
<translation type="vanished">解锁</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="59"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="66"/>
|
||||
<source>touch switch</source>
|
||||
<translation>触摸显示开关</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="69"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="76"/>
|
||||
<source>close screen</source>
|
||||
<translation>关闭屏幕</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="79"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="86"/>
|
||||
<source>power</source>
|
||||
<translation>电源</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="89"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="96"/>
|
||||
<source>volume up</source>
|
||||
<translation>音量加</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="99"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="106"/>
|
||||
<source>volume down</source>
|
||||
<translation>音量减</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="109"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="116"/>
|
||||
<source>app switch</source>
|
||||
<translation>切换应用</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="119"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="126"/>
|
||||
<source>menu</source>
|
||||
<translation>菜单</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="129"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="136"/>
|
||||
<source>home</source>
|
||||
<translation>主界面</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="139"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="146"/>
|
||||
<source>return</source>
|
||||
<translation>返回</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/toolform.ui" line="149"/>
|
||||
<location filename="../../device/ui/toolform.ui" line="156"/>
|
||||
<source>screen shot</source>
|
||||
<translation>截图</translation>
|
||||
</message>
|
||||
|
@ -302,7 +307,7 @@
|
|||
<translation type="vanished">文件传输失败</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../device/ui/videoform.cpp" line="415"/>
|
||||
<location filename="../../device/ui/videoform.cpp" line="657"/>
|
||||
<source>file does not exist</source>
|
||||
<translation>文件不存在</translation>
|
||||
</message>
|
||||
|
|
|
@ -44,6 +44,15 @@
|
|||
#define COMMON_RECORD_FORMAT_INDEX_KEY "RecordFormatIndex"
|
||||
#define COMMON_RECORD_FORMAT_INDEX_DEF 0
|
||||
|
||||
#define SERIAL_WINDOW_RECT_KEY_X "WindowRectX"
|
||||
#define SERIAL_WINDOW_RECT_KEY_Y "WindowRectY"
|
||||
#define SERIAL_WINDOW_RECT_KEY_W "WindowRectW"
|
||||
#define SERIAL_WINDOW_RECT_KEY_H "WindowRectH"
|
||||
#define SERIAL_WINDOW_RECT_KEY_DEF -1
|
||||
|
||||
#define COMMON_FRAMELESS_WINDOW_KEY "FramelessWindow"
|
||||
#define COMMON_FRAMELESS_WINDOW_DEF false
|
||||
|
||||
// 最大尺寸 录制格式
|
||||
|
||||
QString Config::s_configPath = "";
|
||||
|
@ -140,6 +149,45 @@ void Config::setRecordFormatIndex(int recordFormatIndex)
|
|||
m_userData->endGroup();
|
||||
}
|
||||
|
||||
void Config::setRect(const QString &serial, const QRect &rc)
|
||||
{
|
||||
m_userData->beginGroup(serial);
|
||||
m_userData->setValue(SERIAL_WINDOW_RECT_KEY_X, rc.left());
|
||||
m_userData->setValue(SERIAL_WINDOW_RECT_KEY_Y, rc.top());
|
||||
m_userData->setValue(SERIAL_WINDOW_RECT_KEY_W, rc.width());
|
||||
m_userData->setValue(SERIAL_WINDOW_RECT_KEY_H, rc.height());
|
||||
m_userData->endGroup();
|
||||
m_userData->sync();
|
||||
}
|
||||
|
||||
QRect Config::getRect(const QString &serial)
|
||||
{
|
||||
QRect rc;
|
||||
m_userData->beginGroup(serial);
|
||||
rc.setX(m_userData->value(SERIAL_WINDOW_RECT_KEY_X, SERIAL_WINDOW_RECT_KEY_DEF).toInt());
|
||||
rc.setY(m_userData->value(SERIAL_WINDOW_RECT_KEY_Y, SERIAL_WINDOW_RECT_KEY_DEF).toInt());
|
||||
rc.setWidth(m_userData->value(SERIAL_WINDOW_RECT_KEY_W, SERIAL_WINDOW_RECT_KEY_DEF).toInt());
|
||||
rc.setHeight(m_userData->value(SERIAL_WINDOW_RECT_KEY_H, SERIAL_WINDOW_RECT_KEY_DEF).toInt());
|
||||
m_userData->endGroup();
|
||||
return rc;
|
||||
}
|
||||
|
||||
void Config::setFramelessWindow(bool frameless)
|
||||
{
|
||||
m_userData->beginGroup(GROUP_COMMON);
|
||||
m_userData->setValue(COMMON_FRAMELESS_WINDOW_KEY, frameless);
|
||||
m_userData->endGroup();
|
||||
}
|
||||
|
||||
bool Config::getFramelessWindow()
|
||||
{
|
||||
bool framelessWindow = false;
|
||||
m_userData->beginGroup(GROUP_COMMON);
|
||||
framelessWindow = m_userData->value(COMMON_FRAMELESS_WINDOW_KEY, COMMON_FRAMELESS_WINDOW_DEF).toBool();
|
||||
m_userData->endGroup();
|
||||
return framelessWindow;
|
||||
}
|
||||
|
||||
QString Config::getServerVersion()
|
||||
{
|
||||
QString server;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
#include <QRect>
|
||||
|
||||
class QSettings;
|
||||
class Config : public QObject
|
||||
|
@ -29,6 +30,10 @@ public:
|
|||
void setMaxSizeIndex(int maxSizeIndex);
|
||||
int getRecordFormatIndex();
|
||||
void setRecordFormatIndex(int recordFormatIndex);
|
||||
void setRect(const QString &serial, const QRect &rc);
|
||||
QRect getRect(const QString &serial);
|
||||
bool getFramelessWindow();
|
||||
void setFramelessWindow(bool frameless);
|
||||
|
||||
private:
|
||||
explicit Config(QObject *parent = nullptr);
|
||||
|
|
|
@ -15,7 +15,7 @@ public:
|
|||
|
||||
void initMouseEventTap() override;
|
||||
void quitMouseEventTap() override;
|
||||
void enableMouseEventTap(QWidget* widget, bool enabled) override;
|
||||
void enableMouseEventTap(QRect rc, bool enabled) override;
|
||||
|
||||
protected:
|
||||
void run() override;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
#include <QDebug>
|
||||
#include <QWidget>
|
||||
|
||||
#include "cocoamousetap.h"
|
||||
|
||||
|
@ -20,77 +19,55 @@ typedef struct MouseEventTapData{
|
|||
CFMachPortRef tap = Q_NULLPTR;
|
||||
CFRunLoopRef runloop = Q_NULLPTR;
|
||||
CFRunLoopSourceRef runloopSource = Q_NULLPTR;
|
||||
QWidget* widget = Q_NULLPTR;
|
||||
QRect rc;
|
||||
} MouseEventTapData;
|
||||
|
||||
static CGEventRef Cocoa_MouseTapCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon)
|
||||
{
|
||||
Q_UNUSED(proxy);
|
||||
MouseEventTapData *tapdata = (MouseEventTapData*)refcon;
|
||||
|
||||
NSView *nsview;
|
||||
NSWindow *nswindow;
|
||||
NSRect windowRect;
|
||||
NSRect newWindowRect;
|
||||
CGPoint eventLocation;
|
||||
|
||||
switch (type) {
|
||||
case kCGEventTapDisabledByTimeout:
|
||||
{
|
||||
CGEventTapEnable(tapdata->tap, true);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
case kCGEventTapDisabledByUserInput:
|
||||
{
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (!tapdata->widget) {
|
||||
if (tapdata->rc.isEmpty()) {
|
||||
return event;
|
||||
}
|
||||
// get nswindow from qt widget
|
||||
nsview = (NSView *)tapdata->widget->window()->winId();
|
||||
if (!nsview) {
|
||||
return event;
|
||||
}
|
||||
nswindow = [nsview window];
|
||||
|
||||
eventLocation = CGEventGetUnflippedLocation(event);
|
||||
windowRect = [nswindow contentRectForFrameRect:[nswindow frame]];
|
||||
|
||||
windowRect.origin.x += 100;
|
||||
windowRect.origin.y += 30;
|
||||
windowRect.size.width -= 180;
|
||||
windowRect.size.height -= 60;
|
||||
|
||||
newWindowRect = NSMakeRect(windowRect.origin.x, windowRect.origin.y,
|
||||
windowRect.size.width - 10, windowRect.size.height - 10);
|
||||
//qDebug() << newWindowRect.origin.x << newWindowRect.origin.y << newWindowRect.size.width << newWindowRect.size.height;
|
||||
|
||||
if (!NSMouseInRect(NSPointFromCGPoint(eventLocation), newWindowRect, NO)) {
|
||||
|
||||
/* This is in CGs global screenspace coordinate system, which has a
|
||||
* flipped Y.
|
||||
*/
|
||||
CGPoint newLocation = CGEventGetLocation(event);
|
||||
|
||||
if (eventLocation.x < NSMinX(windowRect)) {
|
||||
newLocation.x = NSMinX(windowRect);
|
||||
} else if (eventLocation.x >= NSMaxX(windowRect)) {
|
||||
newLocation.x = NSMaxX(windowRect) - 1.0;
|
||||
NSRect limitWindowRect = NSMakeRect(tapdata->rc.left(), tapdata->rc.top(),
|
||||
tapdata->rc.width(), tapdata->rc.height());
|
||||
// check rect samll than limit rect
|
||||
NSRect checkWindowRect = NSMakeRect(limitWindowRect.origin.x + 10, limitWindowRect.origin.y + 10,
|
||||
limitWindowRect.size.width - 10, limitWindowRect.size.height - 10);
|
||||
/* This is in CGs global screenspace coordinate system, which has a
|
||||
* flipped Y.
|
||||
*/
|
||||
CGPoint eventLocation = CGEventGetLocation(event);
|
||||
if (!NSMouseInRect(NSPointFromCGPoint(eventLocation), checkWindowRect, NO)) {
|
||||
if (eventLocation.x <= NSMinX(limitWindowRect)) {
|
||||
eventLocation.x = NSMinX(limitWindowRect) + 1.0;
|
||||
} else if (eventLocation.x >= NSMaxX(limitWindowRect)) {
|
||||
eventLocation.x = NSMaxX(limitWindowRect) - 1.0;
|
||||
}
|
||||
|
||||
if (eventLocation.y <= NSMinY(windowRect)) {
|
||||
newLocation.y -= (NSMinY(windowRect) - eventLocation.y + 1);
|
||||
} else if (eventLocation.y > NSMaxY(windowRect)) {
|
||||
newLocation.y += (eventLocation.y - NSMaxY(windowRect));
|
||||
if (eventLocation.y <= NSMinY(limitWindowRect)) {
|
||||
eventLocation.y = NSMinY(limitWindowRect) + 1.0;
|
||||
} else if (eventLocation.y >= NSMaxY(limitWindowRect)) {
|
||||
eventLocation.y = NSMaxY(limitWindowRect) - 1.0;
|
||||
}
|
||||
|
||||
CGWarpMouseCursorPosition(newLocation);
|
||||
CGWarpMouseCursorPosition(eventLocation);
|
||||
CGAssociateMouseAndMouseCursorPosition(YES);
|
||||
|
||||
if ((CGEventMaskBit(type) & movementEventsMask) == 0) {
|
||||
|
@ -99,7 +76,7 @@ static CGEventRef Cocoa_MouseTapCallback(CGEventTapProxy proxy, CGEventType type
|
|||
* movement events, since they mean that our warp cursor above
|
||||
* behaves strangely.
|
||||
*/
|
||||
CGEventSetLocation(event, newLocation);
|
||||
CGEventSetLocation(event, eventLocation);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,11 +148,11 @@ void CocoaMouseTap::quitMouseEventTap()
|
|||
}
|
||||
}
|
||||
|
||||
void CocoaMouseTap::enableMouseEventTap(QWidget* widget, bool enabled)
|
||||
void CocoaMouseTap::enableMouseEventTap(QRect rc, bool enabled)
|
||||
{
|
||||
if (m_tapData && m_tapData->tap)
|
||||
{
|
||||
enabled ? m_tapData->widget = widget : m_tapData->widget = Q_NULLPTR;
|
||||
enabled ? m_tapData->rc = rc : m_tapData->rc = QRect();
|
||||
CGEventTapEnable(m_tapData->tap, enabled);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
#ifndef MOUSETAP_H
|
||||
#define MOUSETAP_H
|
||||
#include <QRect>
|
||||
|
||||
class QWidget;
|
||||
class MouseTap {
|
||||
public:
|
||||
static MouseTap* getInstance();
|
||||
virtual void initMouseEventTap() = 0;
|
||||
virtual void quitMouseEventTap() = 0;
|
||||
virtual void enableMouseEventTap(QWidget* widget, bool enabled) = 0;
|
||||
// rc base global screenspace coordinate system, which has a flipped Y.
|
||||
virtual void enableMouseEventTap(QRect rc, bool enabled) = 0;
|
||||
|
||||
private:
|
||||
static MouseTap *s_instance;
|
||||
|
|
|
@ -24,17 +24,12 @@ void WinMouseTap::quitMouseEventTap()
|
|||
|
||||
}
|
||||
|
||||
void WinMouseTap::enableMouseEventTap(QWidget *widget, bool enabled)
|
||||
void WinMouseTap::enableMouseEventTap(QRect rc, bool enabled)
|
||||
{
|
||||
if (!widget) {
|
||||
if (enabled && rc.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if(enabled) {
|
||||
QRect rc(widget->parentWidget()->mapToGlobal(widget->pos())
|
||||
, widget->size());
|
||||
// high dpi support
|
||||
rc.setTopLeft(rc.topLeft() * widget->devicePixelRatio());
|
||||
rc.setBottomRight(rc.bottomRight() * widget->devicePixelRatio());
|
||||
RECT mainRect;
|
||||
mainRect.left = (LONG)rc.left();
|
||||
mainRect.right = (LONG)rc.right();
|
||||
|
|
|
@ -11,7 +11,7 @@ public:
|
|||
|
||||
void initMouseEventTap() override;
|
||||
void quitMouseEventTap() override;
|
||||
void enableMouseEventTap(QWidget* widget, bool enabled) override;
|
||||
void enableMouseEventTap(QRect rc, bool enabled) override;
|
||||
};
|
||||
|
||||
#endif // WINMOUSETAP_H
|
||||
|
|
30
README.md
30
README.md
|
@ -160,6 +160,7 @@ Note: it is not necessary to keep you Android device connected via USB after you
|
|||
- Display Android device screens in real time
|
||||
- Real-time mouse and keyboard control of Android devices
|
||||
- Screen recording
|
||||
- Screenshot to png
|
||||
- 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
|
||||
|
@ -176,6 +177,33 @@ Note: it is not necessary to keep you Android device connected via USB after you
|
|||
- `Ctrl`+`Shift`+`v` copies the computer clipboard to the device clipboard;
|
||||
- `Ctrl`+`v` _pastes_ the computer clipboard as a sequence of text events (but
|
||||
breaks non-ASCII characters).
|
||||
- Group control
|
||||
|
||||
## Shortcuts
|
||||
|
||||
| Action | Shortcut (Windows) | Shortcut (macOS)
|
||||
| -------------------------------------- |:----------------------------- |:-----------------------------
|
||||
| Switch fullscreen mode | `Ctrl`+`f` | `Cmd`+`f`
|
||||
| Resize window to 1:1 (pixel-perfect) | `Ctrl`+`g` | `Cmd`+`g`
|
||||
| Resize window to remove black borders | `Ctrl`+`x` \| _Double-click¹_ | `Cmd`+`x` \| _Double-click¹_
|
||||
| Click on `HOME` | `Ctrl`+`h` \| _Middle-click_ | `Ctrl`+`h` \| _Middle-click_
|
||||
| Click on `BACK` | `Ctrl`+`b` \| _Right-click²_ | `Cmd`+`b` \| _Right-click²_
|
||||
| Click on `APP_SWITCH` | `Ctrl`+`s` | `Cmd`+`s`
|
||||
| Click on `MENU` | `Ctrl`+`m` | `Ctrl`+`m`
|
||||
| Click on `VOLUME_UP` | `Ctrl`+`↑` _(up)_ | `Cmd`+`↑` _(up)_
|
||||
| Click on `VOLUME_DOWN` | `Ctrl`+`↓` _(down)_ | `Cmd`+`↓` _(down)_
|
||||
| Click on `POWER` | `Ctrl`+`p` | `Cmd`+`p`
|
||||
| Power on | _Right-click²_ | _Right-click²_
|
||||
| Turn device screen off (keep mirroring)| `Ctrl`+`o` | `Cmd`+`o`
|
||||
| Expand notification panel | `Ctrl`+`n` | `Cmd`+`n`
|
||||
| Collapse notification panel | `Ctrl`+`Shift`+`n` | `Cmd`+`Shift`+`n`
|
||||
| Copy device clipboard to computer | `Ctrl`+`c` | `Cmd`+`c`
|
||||
| Paste computer clipboard to device | `Ctrl`+`v` | `Cmd`+`v`
|
||||
| Copy computer clipboard to device | `Ctrl`+`Shift`+`v` | `Cmd`+`Shift`+`v`
|
||||
|
||||
_¹Double-click on black borders to remove them._
|
||||
|
||||
_²Right-click turns the screen on if it was off, presses BACK otherwise._
|
||||
|
||||
## TODO
|
||||
[TODO](docs/TODO.md)
|
||||
|
@ -198,7 +226,7 @@ There are several reasons listed as below according to importance (high to low).
|
|||
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 (mingw not supported))
|
||||
1. Set up the Qt development environment on the target platform (Qt >= 5.12.0, vs >= 2017 (mingw not supported))
|
||||
2. Clone the project
|
||||
3. Open the project root directory all.pro with QtCreator
|
||||
4. Compile and run
|
||||
|
|
30
README_zh.md
30
README_zh.md
|
@ -163,6 +163,7 @@ Mac OS平台,你可以直接使用我编译好的可执行程序:
|
|||
- 实时显示Android设备屏幕
|
||||
- 实时键鼠控制Android设备
|
||||
- 屏幕录制
|
||||
- 截图为png
|
||||
- 无线连接
|
||||
- 最多支持16台设备连接(PC性能允许的情况下可以增加,需要自己编译)
|
||||
- 全屏显示
|
||||
|
@ -176,6 +177,33 @@ Mac OS平台,你可以直接使用我编译好的可执行程序:
|
|||
- `Ctrl` + `c`将设备剪贴板复制到计算机剪贴板;
|
||||
- `Ctrl` + `Shift` + `v`将计算机剪贴板复制到设备剪贴板;
|
||||
- `Ctrl` +`v` 将计算机剪贴板作为一系列文本事件发送到设备(不支持非ASCII字符)。
|
||||
- 群控
|
||||
|
||||
## 快捷键
|
||||
|
||||
| 功能 | 快捷键(Windows) | 快捷键 (macOS)
|
||||
| -------------------------------------- |:----------------------------- |:-----------------------------
|
||||
| 切换全屏 | `Ctrl`+`f` | `Cmd`+`f`
|
||||
| 调整窗口大小为 1:1 | `Ctrl`+`g` | `Cmd`+`g`
|
||||
| 调整窗口大小去除黑边 | `Ctrl`+`x` \| _左键双击_ | `Cmd`+`x` \| _左键双击_
|
||||
| 点击 `主页` | `Ctrl`+`h` \| _点击鼠标中键_ | `Ctrl`+`h` \| _点击鼠标中键_
|
||||
| 点击 `BACK` | `Ctrl`+`b` \| _右键双击_ | `Cmd`+`b` \| _右键双击_
|
||||
| 点击 `APP_SWITCH` | `Ctrl`+`s` | `Cmd`+`s`
|
||||
| 点击 `MENU` | `Ctrl`+`m` | `Ctrl`+`m`
|
||||
| 点击 `VOLUME_UP` | `Ctrl`+`↑` _(上)_ | `Cmd`+`↑` _(上)_
|
||||
| 点击 `VOLUME_DOWN` | `Ctrl`+`↓` _(下)_ | `Cmd`+`↓` _(下)_
|
||||
| 点击 `POWER` | `Ctrl`+`p` | `Cmd`+`p`
|
||||
| 打开电源 | _右键双击_ | _右键双击_
|
||||
| 关闭屏幕 (保持投屏) | `Ctrl`+`o` | `Cmd`+`o`
|
||||
| 打开下拉菜单 | `Ctrl`+`n` | `Cmd`+`n`
|
||||
| 关闭下拉菜单 | `Ctrl`+`Shift`+`n` | `Cmd`+`Shift`+`n`
|
||||
| 复制设备剪切板到电脑 | `Ctrl`+`c` | `Cmd`+`c`
|
||||
| 粘贴电脑剪切板到设备 | `Ctrl`+`v` | `Cmd`+`v`
|
||||
| 复制电脑剪切板到设备 | `Ctrl`+`Shift`+`v` | `Cmd`+`Shift`+`v`
|
||||
|
||||
鼠标左键双击黑色区域可以去除黑色区域
|
||||
|
||||
如果电源关闭,鼠标右键双击打开电源;如果电源开启,鼠标右键双击相当于返回
|
||||
|
||||
## TODO
|
||||
[后期计划](docs/TODO.md)
|
||||
|
@ -198,7 +226,7 @@ Mac OS平台,你可以直接使用我编译好的可执行程序:
|
|||
尽量提供了所有依赖资源,方便傻瓜式编译。
|
||||
|
||||
### PC端
|
||||
1. 目标平台上搭建Qt开发环境(Qt >= 5.9.7, vs >= 2015 (**不支持mingw**))
|
||||
1. 目标平台上搭建Qt开发环境(Qt >= 5.12.0, vs >= 2017 (**不支持mingw**))
|
||||
2. 克隆该项目
|
||||
3. 使用QtCreator打开项目根目录all.pro
|
||||
4. 编译,运行即可
|
||||
|
|
BIN
ci/mac/package/dmg-background.jpg
Normal file
BIN
ci/mac/package/dmg-background.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 41 KiB |
55
ci/mac/package/package.py
Normal file
55
ci/mac/package/package.py
Normal file
|
@ -0,0 +1,55 @@
|
|||
import dmgbuild
|
||||
import os
|
||||
import json
|
||||
import sys
|
||||
|
||||
current_file_path = os.path.dirname(os.path.realpath(__file__))
|
||||
dmg_settings_path = '%s/dmg-settings.json' % current_file_path
|
||||
dmg_background_img = '%s/dmg-background.jpg' % current_file_path
|
||||
app_path = '%s/../../build/QtScrcpy.app' % current_file_path
|
||||
dmg_path = '%s/../../build/QtScrcpy.dmg' % current_file_path
|
||||
app_name = 'QtScrcpy'
|
||||
|
||||
def console_print(msg):
|
||||
print(msg)
|
||||
sys.stdout.flush()
|
||||
|
||||
def generate_dmg_info():
|
||||
with open(dmg_settings_path, 'w') as file:
|
||||
info = {
|
||||
'title': app_name,
|
||||
'icon-size': 120,
|
||||
'background': dmg_background_img,
|
||||
'format': 'UDZO',
|
||||
'compression-level': 9,
|
||||
'window': {
|
||||
'position': {'x': 400, 'y': 200},
|
||||
'size': {'width': 780, 'height': 480}
|
||||
},
|
||||
'contents': [
|
||||
{
|
||||
'x': 223,
|
||||
'y': 227,
|
||||
'type': 'file',
|
||||
'path': app_path
|
||||
},
|
||||
{
|
||||
'x': 550,
|
||||
'y': 227,
|
||||
'type': 'link',
|
||||
'path': '/Applications'
|
||||
}
|
||||
]
|
||||
}
|
||||
json.dump(info, file)
|
||||
|
||||
if __name__ == '__main__':
|
||||
console_print('generate dmg info')
|
||||
generate_dmg_info()
|
||||
console_print('build dmg: %s' % dmg_path)
|
||||
dmgbuild.build_dmg(dmg_path, app_name, dmg_settings_path)
|
||||
if not os.path.exists(dmg_path):
|
||||
console_print('fail to create %s' % dmg_path)
|
||||
sys.exit(1)
|
||||
|
||||
sys.exit(0)
|
1
ci/mac/package/requirements.txt
Normal file
1
ci/mac/package/requirements.txt
Normal file
|
@ -0,0 +1 @@
|
|||
dmgbuild==1.3.3
|
37
ci/mac/package_for_mac.sh
Executable file
37
ci/mac/package_for_mac.sh
Executable file
|
@ -0,0 +1,37 @@
|
|||
# 获取绝对路径,保证其他目录执行此脚本依然正确
|
||||
{
|
||||
cd $(dirname "$0")
|
||||
script_path=$(pwd)
|
||||
cd -
|
||||
} &> /dev/null # disable output
|
||||
# 设置当前目录,cd的目录影响接下来执行程序的工作目录
|
||||
old_cd=$(pwd)
|
||||
cd $(dirname "$0")
|
||||
|
||||
echo
|
||||
echo
|
||||
echo ---------------------------------------------------------------
|
||||
echo pip install requirements
|
||||
echo ---------------------------------------------------------------
|
||||
|
||||
pip install -r $script_path/package/requirements.txt
|
||||
if [ $? -ne 0 ] ;then
|
||||
echo "pip install requirements failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo
|
||||
echo
|
||||
echo ---------------------------------------------------------------
|
||||
echo create package
|
||||
echo ---------------------------------------------------------------
|
||||
|
||||
python $script_path/package/package.py
|
||||
if [ $? -ne 0 ] ;then
|
||||
echo "create package failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 恢复当前目录
|
||||
cd $old_cd
|
||||
exit 0
|
18
docs/FAQ.md
18
docs/FAQ.md
|
@ -3,16 +3,26 @@
|
|||
|
||||
如果在此文档没有解决你的问题,描述你的问题,截图软件控制台中打印的日志,一起发到QQ群里提问。
|
||||
|
||||
## 支持声音(软件不做支持)
|
||||
[关于转发安卓声音到PC的讨论](https://github.com/Genymobile/scrcpy/issues/14#issuecomment-543204526)
|
||||
|
||||
## 无法输入中文
|
||||
安装搜狗输入法/QQ输入法就可以支持输入中文了
|
||||
手机端安装搜狗输入法/QQ输入法就可以支持输入中文了
|
||||
|
||||
## 可以看到画面,但无法控制
|
||||
有些手机(小米等手机)需要额外打开控制权限,检查是否USB调试里打开了允许模拟点击
|
||||
|
||||
.jpg)
|
||||
|
||||
## 错误信息Could not open video stream
|
||||
## 手机通过数据线连接电脑,刷新设备列表以后,没有任何设备出现
|
||||
随便下载一个手机助手,尝试连接成功以后,再用QtScrcpy刷新设备列表连接
|
||||
|
||||
## 错误信息:AdbProcess::error:adb server version (40) doesnt match this client (41)
|
||||
任务管理找到adb进程并杀死,重新操作即可
|
||||
|
||||
## 错误信息:Could not open video stream
|
||||
导致这个错误的原因有很多,最简单的解决方法是在分辨率设置中,选择一个较低的分辨率
|
||||
|
||||
## 声音
|
||||
[关于转发安卓声音到PC的讨论](https://github.com/Genymobile/scrcpy/issues/14#issuecomment-543204526)
|
||||
## 错误信息:QOpenGLShaderProgram::attributeLocation(vertexIn): shader program is not linked
|
||||
config.ini里修改下解码方式,改成1或者2试试
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
## 中优先级
|
||||
- 脚本
|
||||
- 群控
|
||||
- 软解
|
||||
- opengles 3.0 兼容性参考[这里](https://github.com/libretro/glsl-shaders/blob/master/nnedi3/shaders/yuv-to-rgb-2x.glsl)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue