diff --git a/LICENSE b/LICENSE index 261eeb9e9..c37d81f54 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,8 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright (C) 2019 Rankun + Copyright (C) 2019-2025 Rankun Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/QtScrcpy/QtScrcpy.pro b/QtScrcpy/QtScrcpy.pro index 0afdc4e7c..e61704ce9 100644 --- a/QtScrcpy/QtScrcpy.pro +++ b/QtScrcpy/QtScrcpy.pro @@ -179,7 +179,6 @@ macos { APP_CONFIG.files = $$files($$PWD/../config/config.ini) APP_CONFIG.path = Contents/MacOS/config QMAKE_BUNDLE_DATA += APP_CONFIG - # mac application icon ICON = $$PWD/res/QtScrcpy.icns QMAKE_INFO_PLIST = $$PWD/res/Info_Mac.plist diff --git a/QtScrcpy/device/device.cpp b/QtScrcpy/device/device.cpp index 78c516491..fc0b9597c 100644 --- a/QtScrcpy/device/device.cpp +++ b/QtScrcpy/device/device.cpp @@ -33,7 +33,7 @@ Device::Device(DeviceParams params, QObject *parent) : QObject(parent), m_params 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().getFramelessWindow(), Config::getInstance().getSkin()); + m_videoForm = new VideoForm(params.framelessWindow, Config::getInstance().getSkin()); m_videoForm->setDevice(this); } @@ -382,7 +382,7 @@ bool Device::saveFrame(const AVFrame *frame) // save QString absFilePath; - QString fileDir(Config::getInstance().getRecordPath()); + QString fileDir(m_params.recordPath); if (fileDir.isEmpty()) { qWarning() << "please select record save path!!!"; return false; diff --git a/QtScrcpy/device/device.h b/QtScrcpy/device/device.h index bbbf693c2..e07ee7664 100644 --- a/QtScrcpy/device/device.h +++ b/QtScrcpy/device/device.h @@ -26,6 +26,7 @@ class Device : public QObject struct DeviceParams { QString recordFileName = ""; // 视频录制文件名 + QString recordPath = ""; // 视频保存路径 QString serial = ""; // 设备序列号 quint16 localPort = 27183; // reverse时本地监听端口 quint16 maxSize = 720; // 视频分辨率 @@ -37,7 +38,8 @@ class Device : public QObject QString gameScript = ""; // 游戏映射脚本 bool renderExpiredFrames = false; // 是否渲染延迟视频帧 int lockVideoOrientation = -1; // 是否锁定视频方向 - int stayAwake = false; // 是否保持唤醒 + bool stayAwake = false; // 是否保持唤醒 + bool framelessWindow = false; // 是否无边框窗口 }; enum GroupControlState { diff --git a/QtScrcpy/dialog.cpp b/QtScrcpy/dialog.cpp index e5f68279a..71a4a07de 100644 --- a/QtScrcpy/dialog.cpp +++ b/QtScrcpy/dialog.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -43,8 +43,10 @@ Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) if (args.contains("devices")) { QStringList devices = m_adb.getDevicesSerialFromStdOut(); ui->serialBox->clear(); + ui->connectedPhoneList->clear(); for (auto &item : devices) { ui->serialBox->addItem(item); + ui->connectedPhoneList->addItem(item+"-"+Config::getInstance().getNickName(item)); } } else if (args.contains("show") && args.contains("wlan0")) { QString ip = m_adb.getDeviceIPFromStdOut(); @@ -74,10 +76,25 @@ Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) outLog(log, newLine); } }); + + m_hideIcon = new QSystemTrayIcon(); + m_hideIcon->setIcon(QIcon(":/image/tray/logo.png")); + m_menu = new QMenu(); + m_quit = new QAction(); + m_showWindow = new QAction();; + m_showWindow->setText(tr("show")); + m_quit->setText(tr("quit")); + m_menu->addAction(m_showWindow); + m_menu->addAction(m_quit); + m_hideIcon->setContextMenu(m_menu); + connect(m_showWindow, &QAction::triggered, this, &Dialog::slotShow); + connect(m_quit, SIGNAL(triggered()), this, SLOT(close())); + connect(m_hideIcon, &QSystemTrayIcon::activated,this,&Dialog::slotActivated); } Dialog::~Dialog() { + updateBootConfig(false); m_deviceManage.disconnectAllDevice(); delete ui; } @@ -95,7 +112,6 @@ void Dialog::initUI() ui->bitRateBox->addItem("50000000"); ui->bitRateBox->addItem("100000000"); ui->bitRateBox->addItem("200000000"); - ui->bitRateBox->setCurrentIndex(Config::getInstance().getBitRateIndex()); ui->maxSizeBox->addItem("640"); ui->maxSizeBox->addItem("720"); @@ -103,11 +119,9 @@ void Dialog::initUI() ui->maxSizeBox->addItem("1280"); ui->maxSizeBox->addItem("1920"); ui->maxSizeBox->addItem(tr("original")); - ui->maxSizeBox->setCurrentIndex(Config::getInstance().getMaxSizeIndex()); ui->formatBox->addItem("mp4"); ui->formatBox->addItem("mkv"); - ui->formatBox->setCurrentIndex(Config::getInstance().getRecordFormatIndex()); ui->lockOrientationBox->addItem(tr("no lock")); ui->lockOrientationBox->addItem("0"); @@ -116,20 +130,64 @@ void Dialog::initUI() ui->lockOrientationBox->addItem("270"); ui->lockOrientationBox->setCurrentIndex(0); - ui->recordPathEdt->setText(Config::getInstance().getRecordPath()); - ui->framelessCheck->setChecked(Config::getInstance().getFramelessWindow()); + updateBootConfig(true); + + on_useSingleModeCheck_clicked(); + + on_updateDevice_clicked(); #ifdef Q_OS_OSX // mac need more width - setFixedWidth(520); + setFixedWidth(550); #endif #ifdef Q_OS_LINUX // linux need more width - setFixedWidth(480); + setFixedWidth(520); #endif } +void Dialog::updateBootConfig(bool toView) +{ + if (toView) { + UserBootConfig config = Config::getInstance().getUserBootConfig(); + + ui->bitRateBox->setCurrentIndex(config.bitRateIndex); + ui->maxSizeBox->setCurrentIndex(config.maxSizeIndex); + ui->formatBox->setCurrentIndex(config.recordFormatIndex); + ui->recordPathEdt->setText(config.recordPath); + ui->lockOrientationBox->setCurrentIndex(config.lockOrientationIndex); + ui->framelessCheck->setChecked(config.framelessWindow); + ui->recordScreenCheck->setChecked(config.recordScreen); + ui->notDisplayCheck->setChecked(config.recordBackground); + ui->useReverseCheck->setChecked(config.reverseConnect); + ui->fpsCheck->setChecked(config.showFPS); + ui->alwaysTopCheck->setChecked(config.windowOnTop); + ui->closeScreenCheck->setChecked(config.autoOffScreen); + ui->stayAwakeCheck->setChecked(config.keepAlive); + ui->useSingleModeCheck->setChecked(config.simpleMode); + } else { + UserBootConfig config; + + config.bitRateIndex = ui->bitRateBox->currentIndex(); + config.maxSizeIndex = ui->maxSizeBox->currentIndex(); + config.recordFormatIndex = ui->formatBox->currentIndex(); + config.recordPath = ui->recordPathEdt->text(); + config.lockOrientationIndex = ui->lockOrientationBox->currentIndex(); + config.recordScreen = ui->recordScreenCheck->isChecked(); + config.recordBackground = ui->notDisplayCheck->isChecked(); + config.reverseConnect = ui->useReverseCheck->isChecked(); + config.showFPS = ui->fpsCheck->isChecked(); + config.windowOnTop = ui->alwaysTopCheck->isChecked(); + config.autoOffScreen = ui->closeScreenCheck->isChecked(); + config.framelessWindow = ui->framelessCheck->isChecked(); + config.keepAlive = ui->stayAwakeCheck->isChecked(); + config.simpleMode = ui->useSingleModeCheck->isChecked(); + + Config::getInstance().setUserBootConfig(config); + } +} + void Dialog::execAdbCmd() { if (checkAdbRun()) { @@ -140,6 +198,15 @@ void Dialog::execAdbCmd() m_adb.execute(ui->serialBox->currentText().trimmed(), cmd.split(" ", Qt::SkipEmptyParts)); } +void Dialog::delayMs(int ms) +{ + QTime dieTime = QTime::currentTime().addMSecs(ms); + + while (QTime::currentTime() < dieTime) { + QCoreApplication::processEvents(QEventLoop::AllEvents, 100); + } +} + QString Dialog::getGameScript(const QString &fileName) { QFile loadFile(KeyMap::getKeyMapPath() + "/" + fileName); @@ -153,6 +220,48 @@ QString Dialog::getGameScript(const QString &fileName) return ret; } +void Dialog::slotShow() +{ + this->show(); + m_hideIcon->hide(); +} + +void Dialog::slotActivated(QSystemTrayIcon::ActivationReason reason) +{ + switch (reason) { + case QSystemTrayIcon::Trigger: + this->show(); + m_hideIcon->hide(); + break; + default: + break; + } +} + +void Dialog::closeEvent(QCloseEvent *event) +{ + int res = QMessageBox::question(this,tr("warning"),tr("Quit or set tray?"),tr("Quit"),tr("Set tray"),tr("Cancel")); + + if(res == 0) + { + event->accept(); + } + else if(res == 1) + { + this->hide(); + m_hideIcon->show(); + m_hideIcon->showMessage(tr("Notice"), + tr("Hidden here!"), + QSystemTrayIcon::Information, + 3000); + event->ignore(); + } + else + { + event->ignore(); + } +} + void Dialog::on_updateDevice_clicked() { if (checkAdbRun()) { @@ -195,6 +304,8 @@ void Dialog::on_startServerBtn_clicked() params.renderExpiredFrames = Config::getInstance().getRenderExpiredFrames(); params.lockVideoOrientation = ui->lockOrientationBox->currentIndex() - 1; params.stayAwake = ui->stayAwakeCheck->isChecked(); + params.framelessWindow = ui->framelessCheck->isChecked(); + params.recordPath = ui->recordPathEdt->text().trimmed(); m_deviceManage.connectDevice(params); @@ -341,7 +452,6 @@ void Dialog::on_selectRecordPathBtn_clicked() void Dialog::on_recordPathEdt_textChanged(const QString &arg1) { - Config::getInstance().setRecordPath(arg1); ui->recordPathEdt->setToolTip(arg1.trimmed()); ui->notDisplayCheck->setCheckable(!arg1.trimmed().isEmpty()); } @@ -402,23 +512,118 @@ void Dialog::on_recordScreenCheck_clicked(bool checked) } } -void Dialog::on_bitRateBox_activated(int index) +void Dialog::on_usbConnectBtn_clicked() +{ + on_stopAllServerBtn_clicked(); + delayMs(200); + on_updateDevice_clicked(); + delayMs(200); + + int firstUsbDevice = findDeviceFromeSerialBox(false); + if (-1 == firstUsbDevice) { + qWarning() << "No use device is found!"; + return; + } + ui->serialBox->setCurrentIndex(firstUsbDevice); + + on_startServerBtn_clicked(); +} + +int Dialog::findDeviceFromeSerialBox(bool wifi) { + QRegExp regIP("\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\:([0-9]|[1-9]\\d|[1-9]\\d{2}|[1-9]\\d{3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])\\b"); + for (int i = 0; i < ui->serialBox->count(); ++i) + { + bool isWifi = regIP.exactMatch(ui->serialBox->itemText(i)); + bool found = wifi ? isWifi : !isWifi; + if(found) + { + return i; + } + } + + return -1; +} + +void Dialog::on_wifiConnectBtn_clicked() { - Config::getInstance().setBitRateIndex(index); + on_stopAllServerBtn_clicked(); + delayMs(200); + + on_updateDevice_clicked(); + delayMs(200); + + int firstUsbDevice = findDeviceFromeSerialBox(false); + if (-1 == firstUsbDevice) { + qWarning() << "No use device is found!"; + return; + } + ui->serialBox->setCurrentIndex(firstUsbDevice); + + on_getIPBtn_clicked(); + delayMs(200); + + on_startAdbdBtn_clicked(); + delayMs(1000); + + on_wirelessConnectBtn_clicked(); + delayMs(2000); + + on_updateDevice_clicked(); + delayMs(200); + + int firstWifiDevice = findDeviceFromeSerialBox(true); + if (-1 == firstWifiDevice) { + qWarning() << "No wifi device is found!"; + return; + } + ui->serialBox->setCurrentIndex(firstWifiDevice); + + on_startServerBtn_clicked(); } -void Dialog::on_maxSizeBox_activated(int index) +void Dialog::on_connectedPhoneList_itemDoubleClicked(QListWidgetItem *item) { - Config::getInstance().setMaxSizeIndex(index); + Q_UNUSED(item); + ui->serialBox->setCurrentIndex(ui->connectedPhoneList->currentRow()); + on_startServerBtn_clicked(); } -void Dialog::on_formatBox_activated(int index) +void Dialog::on_updateNameBtn_clicked() { - Config::getInstance().setRecordFormatIndex(index); + if(ui->serialBox->count()!=0) { + if(ui->userNameEdt->text().isEmpty()) { + Config::getInstance().setNickName(ui->serialBox->currentText(), "Phone"); + } else { + Config::getInstance().setNickName(ui->serialBox->currentText(), ui->userNameEdt->text()); + } + + on_updateDevice_clicked(); + + qDebug()<<"Update OK!"; + } else { + qWarning()<<"No device is connected!"; + } +} + +void Dialog::on_useSingleModeCheck_clicked() +{ + if(ui->useSingleModeCheck->isChecked()) + { + ui->configGroupBox->hide(); + ui->adbGroupBox->hide(); + ui->wirelessGroupBox->hide(); + ui->usbGroupBox->hide(); + } + else + { + ui->configGroupBox->show(); + ui->adbGroupBox->show(); + ui->wirelessGroupBox->show(); + ui->usbGroupBox->show(); + } } -void Dialog::on_framelessCheck_stateChanged(int arg1) +void Dialog::on_serialBox_currentIndexChanged(const QString &arg1) { - Q_UNUSED(arg1) - Config::getInstance().setFramelessWindow(ui->framelessCheck->isChecked()); + ui->userNameEdt->setText(Config::getInstance().getNickName(arg1)); } diff --git a/QtScrcpy/dialog.h b/QtScrcpy/dialog.h index 20eae6f7f..b29d123c3 100644 --- a/QtScrcpy/dialog.h +++ b/QtScrcpy/dialog.h @@ -1,8 +1,13 @@ -#ifndef DIALOG_H +#ifndef DIALOG_H #define DIALOG_H #include #include +#include +#include +#include +#include + #include "adbprocess.h" #include "devicemanage.h" @@ -58,24 +63,40 @@ private slots: void on_recordScreenCheck_clicked(bool checked); - void on_bitRateBox_activated(int index); + void on_usbConnectBtn_clicked(); + + void on_wifiConnectBtn_clicked(); - void on_maxSizeBox_activated(int index); + void on_connectedPhoneList_itemDoubleClicked(QListWidgetItem *item); - void on_formatBox_activated(int index); + void on_updateNameBtn_clicked(); - void on_framelessCheck_stateChanged(int arg1); + void on_useSingleModeCheck_clicked(); + + void on_serialBox_currentIndexChanged(const QString &arg1); private: bool checkAdbRun(); void initUI(); + void updateBootConfig(bool toView = true); void execAdbCmd(); + void delayMs(int ms); QString getGameScript(const QString &fileName); + void slotShow(); + void slotActivated(QSystemTrayIcon::ActivationReason reason); + int findDeviceFromeSerialBox(bool wifi); + +protected: + void closeEvent(QCloseEvent *event); private: Ui::Dialog *ui; AdbProcess m_adb; DeviceManage m_deviceManage; + QSystemTrayIcon *m_hideIcon; + QMenu *m_menu; + QAction *m_showWindow; + QAction *m_quit; }; #endif // DIALOG_H diff --git a/QtScrcpy/dialog.ui b/QtScrcpy/dialog.ui index ae80cab4b..b098da0c7 100644 --- a/QtScrcpy/dialog.ui +++ b/QtScrcpy/dialog.ui @@ -6,19 +6,19 @@ 0 0 - 420 - 517 + 500 + 745 - 420 + 500 0 - 420 + 500 16777215 @@ -26,6 +26,63 @@ QtScrcpy + + + + Use Simple Mode + + + false + + + + + + + Simple Mode + + + false + + + + + + + + WIFI Connect + + + + + + + USB Connect + + + + + + + + + Double click to connect: + + + + + + + + 16777215 + 16777215 + + + + + + + @@ -350,21 +407,43 @@ USB line - - 3 - - - 5 - - - 5 - - - 5 - - - 5 - + + + + + + + 110 + 0 + + + + device name: + + + + + + + + 16777215 + 16777215 + + + + + + + + update name + + + false + + + + + @@ -382,6 +461,12 @@ + + + 110 + 0 + + device serial: diff --git a/QtScrcpy/main.cpp b/QtScrcpy/main.cpp index 9f55a0f5e..50178f071 100644 --- a/QtScrcpy/main.cpp +++ b/QtScrcpy/main.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/QtScrcpy/res/i18n/QtScrcpy_en.qm b/QtScrcpy/res/i18n/QtScrcpy_en.qm index 9022ff731..32fa7302b 100644 Binary files a/QtScrcpy/res/i18n/QtScrcpy_en.qm and b/QtScrcpy/res/i18n/QtScrcpy_en.qm differ diff --git a/QtScrcpy/res/i18n/QtScrcpy_en.ts b/QtScrcpy/res/i18n/QtScrcpy_en.ts index 9c131b5ff..2161044b6 100644 --- a/QtScrcpy/res/i18n/QtScrcpy_en.ts +++ b/QtScrcpy/res/i18n/QtScrcpy_en.ts @@ -16,22 +16,22 @@ file transfer failed - + install apk install apk - + file transfer file transfer - + wait current %1 to complete wait current %1 to complete - + %1 complete, save in %2 %1 complete, save in %2 @@ -41,7 +41,7 @@ %1 complete\n save in %2 - + %1 failed %1 failed @@ -49,93 +49,134 @@ Dialog - + Wireless Wireless - + wireless connect wireless connect - + wireless disconnect wireless disconnect - + Start Config Start Config - + record save path: record save path: - - + + select path select path - + record format: record format: - + record screen record screen - + frameless frameless - + + Use Simple Mode + Use Simple Mode + Use Simple Mode + + + + Simple Mode + Simple Mode + Simple Mode + + + + WIFI Connect + WIFI Connect + WIFI Connect + + + + USB Connect + USB Connect + USB Connect + + + + Double click to connect: + Double click to connect: + + + lock orientation: lock orientation: - + show fps show fps - + stay awake stay awake - + + device name: + device name: + device name: + + + + update name + update name + update name + + + stop all server stop all server - + adb command: adb command: - + terminate terminate - + execute execute - + clear clear - + reverse connection reverse connection @@ -144,57 +185,57 @@ auto enable - + background record background record - + screen-off screen-off - + apply apply - + max size: max size: - + always on top always on top - + refresh script refresh script - + get device IP get device IP - + USB line USB line - + stop server stop server - + start server start server - + device serial: device serial: @@ -203,30 +244,110 @@ Config - + bit rate: bit rate: - + start adbd start adbd - + refresh devices refresh devices - + + show + show + show + + + + quit + quit + quit + + + original original - + no lock no lock + + + warning + Warning + Warning + + + + Quit or set tray? + Quit or set tray? + Quit or set tray? + + + + Quit + Quit + Quit + + + + Set tray + Set tray + Set tray + + + + Cancel + Cancel + Cancel + + + + Notice + Notice + Notice + + + + Hidden here! + Hidden here! + Hidden here! + + + + InputConvertGame + + + current keymap mode: %1 + + + + + custom + + + + + normal + + + + + KeyMap + + + Script updated, current keymap mode:normal, Press ~ key to switch keymap mode + + QObject @@ -241,7 +362,7 @@ You can download it at the following address: This software is completely open source and free.\nStrictly used for illegal purposes, or at your own risk.\nYou can download it at the following address: - + This software is completely open source and free. Strictly used for illegal purposes, or at your own risk. You can download it at the following address: This software is completely open source and free. Strictly used for illegal purposes, or at your own risk. You can download it at the following address: @@ -337,7 +458,7 @@ You can download it at the following address: file transfer failed - + file does not exist file does not exist diff --git a/QtScrcpy/res/i18n/QtScrcpy_zh.qm b/QtScrcpy/res/i18n/QtScrcpy_zh.qm index 3c6f972cf..e8b1e2163 100644 Binary files a/QtScrcpy/res/i18n/QtScrcpy_zh.qm and b/QtScrcpy/res/i18n/QtScrcpy_zh.qm differ diff --git a/QtScrcpy/res/i18n/QtScrcpy_zh.ts b/QtScrcpy/res/i18n/QtScrcpy_zh.ts index 27ea074f1..8b6fcb4e6 100644 --- a/QtScrcpy/res/i18n/QtScrcpy_zh.ts +++ b/QtScrcpy/res/i18n/QtScrcpy_zh.ts @@ -16,22 +16,22 @@ 文件传输失败 - + install apk 安装apk - + file transfer 文件传输 - + wait current %1 to complete 等待当前%1完成 - + %1 complete, save in %2 %1完成,保存在%2 @@ -41,7 +41,7 @@ %1完成\n 保存在 %2 - + %1 failed %1 失败 @@ -49,93 +49,134 @@ Dialog - + Wireless 无线 - + wireless connect 无线连接 - + wireless disconnect 无线断开 - + Start Config 启动配置 - + record save path: 录像保存路径: - - + + select path 选择路径 - + record format: 录制格式: - + record screen 录制屏幕 - + frameless 无边框 - + + Use Simple Mode + 启用精简模式 + 启用精简模式 + + + + Simple Mode + 精简模式 + 精简模式 + + + + WIFI Connect + 一键WIFI连接 + 一键WIFI连接 + + + + USB Connect + 一键USB连接 + 一键USB连接 + + + + Double click to connect: + 双击连接: + + + lock orientation: 锁定方向: - + show fps 显示fps - + stay awake 保持唤醒 - + + device name: + 设备名称: + 设备名称: + + + + update name + 更新设置名称 + 更新设置名称 + + + stop all server 停止所有服务 - + adb command: adb命令: - + terminate 终止 - + execute 执行 - + clear 清理 - + reverse connection 反向连接 @@ -144,57 +185,57 @@ 自动启用脚本 - + background record 后台录制 - + screen-off 自动息屏 - + apply 应用脚本 - + max size: 最大尺寸: - + always on top 窗口置顶 - + refresh script 刷新脚本 - + get device IP 获取设备IP - + USB line USB线 - + stop server 停止服务 - + start server 启动服务 - + device serial: 设备序列号: @@ -203,30 +244,110 @@ 配置 - + bit rate: 比特率: - + start adbd 启动adbd - + refresh devices 刷新设备列表 - + + show + 显示 + 显示 + + + + quit + 退出 + 退出 + + + original 原始 - + no lock 不锁定 + + + warning + 警告 + 警告 + + + + Quit or set tray? + 退出还是最小化到托盘? + 退出还是最小化到托盘? + + + + Quit + 退出 + 退出 + + + + Set tray + 最小化到系统托盘 + 最小化到系统托盘 + + + + Cancel + 取消 + 取消 + + + + Notice + 提示 + 提示 + + + + Hidden here! + 安卓录屏程序隐藏在这! + 安卓录屏程序隐藏在这! + + + + InputConvertGame + + + current keymap mode: %1 + + + + + custom + + + + + normal + + + + + KeyMap + + + Script updated, current keymap mode:normal, Press ~ key to switch keymap mode + + QObject @@ -241,7 +362,7 @@ You can download it at the following address: 本软件完全开源免费.\n严禁用于非法用途,否则后果自负.\n你可以在下面地址下载: - + This software is completely open source and free. Strictly used for illegal purposes, or at your own risk. You can download it at the following address: 本软件完全开源免费,严禁用于非法用途,否则后果自负,你可以在下面地址下载: @@ -337,7 +458,7 @@ You can download it at the following address: 文件传输失败 - + file does not exist 文件不存在 diff --git a/QtScrcpy/res/image/tray/logo.png b/QtScrcpy/res/image/tray/logo.png new file mode 100644 index 000000000..8fbaafe2e Binary files /dev/null and b/QtScrcpy/res/image/tray/logo.png differ diff --git a/QtScrcpy/res/res.qrc b/QtScrcpy/res/res.qrc index 840268d32..d2f53a4ce 100644 --- a/QtScrcpy/res/res.qrc +++ b/QtScrcpy/res/res.qrc @@ -2,7 +2,7 @@ font/fontawesome-webfont.ttf image/videoform/phone-h.png - image/videoform/phone-v.png + image/videoform/phone-v.png qss/psblack.css qss/psblack/add_bottom.png qss/psblack/add_left.png @@ -24,5 +24,6 @@ qss/psblack/radiobutton_unchecked_disable.png i18n/QtScrcpy_en.qm i18n/QtScrcpy_zh.qm + image/tray/logo.png diff --git a/QtScrcpy/uibase/magneticwidget.cpp b/QtScrcpy/uibase/magneticwidget.cpp index 3c7a9c27b..70e06201e 100644 --- a/QtScrcpy/uibase/magneticwidget.cpp +++ b/QtScrcpy/uibase/magneticwidget.cpp @@ -9,6 +9,7 @@ MagneticWidget::MagneticWidget(QWidget *adsorbWidget, AdsorbPositions adsorbPos) Q_ASSERT(m_adsorbWidget); setParent(m_adsorbWidget); setWindowFlags(windowFlags() | Qt::Tool); + m_adsorbWidgetSize = m_adsorbWidget->size(); m_adsorbWidget->installEventFilter(this); } @@ -30,6 +31,10 @@ bool MagneticWidget::eventFilter(QObject *watched, QEvent *event) if (watched != m_adsorbWidget || !event) { return false; } + // 始终记录adsorbWidget最新size + if (QEvent::Resize == event->type()) { + m_adsorbWidgetSize = m_adsorbWidget->size(); + } if (m_adsorbed && QEvent::Move == event->type()) { move(m_adsorbWidget->pos() - m_relativePos); } @@ -48,7 +53,7 @@ bool MagneticWidget::eventFilter(QObject *watched, QEvent *event) pos.setY(pos.y() - m_relativePos.y()); break; case AP_OUTSIDE_RIGHT: - pos.setX(pos.x() + m_adsorbWidget->width()); + pos.setX(pos.x() + m_adsorbWidgetSize.width()); pos.setY(pos.y() - m_relativePos.y()); break; case AP_OUTSIDE_TOP: @@ -165,8 +170,8 @@ void MagneticWidget::moveEvent(QMoveEvent *event) void MagneticWidget::getGeometry(QRect &relativeWidgetRect, QRect &targetWidgetRect) { relativeWidgetRect.setTopLeft(m_adsorbWidget->pos()); - relativeWidgetRect.setWidth(m_adsorbWidget->width()); - relativeWidgetRect.setHeight(m_adsorbWidget->height()); + relativeWidgetRect.setWidth(m_adsorbWidgetSize.width()); + relativeWidgetRect.setHeight(m_adsorbWidgetSize.height()); targetWidgetRect.setTopLeft(pos()); targetWidgetRect.setWidth(width()); diff --git a/QtScrcpy/uibase/magneticwidget.h b/QtScrcpy/uibase/magneticwidget.h index 23b6cffe0..843c835b1 100644 --- a/QtScrcpy/uibase/magneticwidget.h +++ b/QtScrcpy/uibase/magneticwidget.h @@ -46,6 +46,9 @@ class MagneticWidget : public QWidget QPoint m_relativePos; bool m_adsorbed = false; QPointer m_adsorbWidget; + // 单独记录adsorbWidgetSize,因为Widget setGeometry的时候,会先收到Move事件,后收到Resize事件, + // 但是收到Move事件时Widget的size()已经是setGeometry指定的size了 + QSize m_adsorbWidgetSize; AdsorbPosition m_curAdsorbPosition; }; diff --git a/QtScrcpy/util/config.cpp b/QtScrcpy/util/config.cpp index 8966a7db4..e5897ef7d 100644 --- a/QtScrcpy/util/config.cpp +++ b/QtScrcpy/util/config.cpp @@ -1,6 +1,7 @@ -#include +#include #include #include +#include #include "config.h" @@ -43,7 +44,7 @@ #define COMMON_CODEC_NAME_KEY "CodecName" #define COMMON_CODEC_NAME_DEF "-" -// user data +// user config #define COMMON_RECORD_KEY "RecordPath" #define COMMON_RECORD_DEF "" @@ -56,16 +57,44 @@ #define COMMON_RECORD_FORMAT_INDEX_KEY "RecordFormatIndex" #define COMMON_RECORD_FORMAT_INDEX_DEF 0 +#define COMMON_LOCK_ORIENTATION_INDEX_KEY "LockDirectionIndex" +#define COMMON_LOCK_ORIENTATION_INDEX_DEF 0 + +#define COMMON_RECORD_SCREEN_KEY "RecordScreen" +#define COMMON_RECORD_SCREEN_DEF false + +#define COMMON_RECORD_BACKGROUD_KEY "RecordBackGround" +#define COMMON_RECORD_BACKGROUD_DEF false + +#define COMMON_REVERSE_CONNECT_KEY "ReverseConnect" +#define COMMON_REVERSE_CONNECT_DEF true + +#define COMMON_SHOW_FPS_KEY "ShowFPS" +#define COMMON_SHOW_FPS_DEF false + +#define COMMON_WINDOW_ON_TOP_KEY "WindowOnTop" +#define COMMON_WINDOW_ON_TOP_DEF false + +#define COMMON_AUTO_OFF_SCREEN_KEY "AutoOffScreen" +#define COMMON_AUTO_OFF_SCREEN_DEF false + +#define COMMON_FRAMELESS_WINDOW_KEY "FramelessWindow" +#define COMMON_FRAMELESS_WINDOW_DEF false + +#define COMMON_KEEP_ALIVE_KEY "KeepAlive" +#define COMMON_KEEP_ALIVE_DEF false + +#define COMMON_SIMPLE_MODE_KEY "SimpleMode" +#define COMMON_SIMPLE_MODE_DEF false + +// device config #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 - -// 最大尺寸 录制格式 +#define SERIAL_NICK_NAME_KEY "NickName" +#define SERIAL_NICK_NAME_DEF "Phone" QString Config::s_configPath = ""; @@ -76,6 +105,8 @@ Config::Config(QObject *parent) : QObject(parent) m_userData = new QSettings(getConfigPath() + "/userdata.ini", QSettings::IniFormat); m_userData->setIniCodec("UTF-8"); + + qDebug()<childGroups(); } Config &Config::getInstance() @@ -97,68 +128,47 @@ const QString &Config::getConfigPath() return s_configPath; } -QString Config::getRecordPath() -{ - QString record; - m_userData->beginGroup(GROUP_COMMON); - record = m_userData->value(COMMON_RECORD_KEY, COMMON_RECORD_DEF).toString(); - m_userData->endGroup(); - return record; -} - -void Config::setRecordPath(const QString &path) -{ - m_userData->beginGroup(GROUP_COMMON); - m_userData->setValue(COMMON_RECORD_KEY, path); - m_userData->endGroup(); -} - -int Config::getBitRateIndex() -{ - int bitRateIndex; - m_userData->beginGroup(GROUP_COMMON); - bitRateIndex = m_userData->value(COMMON_BITRATE_INDEX_KEY, COMMON_BITRATE_INDEX_DEF).toInt(); - m_userData->endGroup(); - return bitRateIndex; -} - -void Config::setBitRateIndex(int bitRateIndex) -{ - m_userData->beginGroup(GROUP_COMMON); - m_userData->setValue(COMMON_BITRATE_INDEX_KEY, bitRateIndex); - m_userData->endGroup(); -} - -int Config::getMaxSizeIndex() -{ - int maxSizeIndex; - m_userData->beginGroup(GROUP_COMMON); - maxSizeIndex = m_userData->value(COMMON_MAX_SIZE_INDEX_KEY, COMMON_MAX_SIZE_INDEX_DEF).toInt(); - m_userData->endGroup(); - return maxSizeIndex; -} - -void Config::setMaxSizeIndex(int maxSizeIndex) -{ - m_userData->beginGroup(GROUP_COMMON); - m_userData->setValue(COMMON_MAX_SIZE_INDEX_KEY, maxSizeIndex); - m_userData->endGroup(); -} - -int Config::getRecordFormatIndex() +void Config::setUserBootConfig(const UserBootConfig &config) { - int recordFormatIndex; m_userData->beginGroup(GROUP_COMMON); - recordFormatIndex = m_userData->value(COMMON_RECORD_FORMAT_INDEX_KEY, COMMON_RECORD_FORMAT_INDEX_DEF).toInt(); + m_userData->setValue(COMMON_RECORD_KEY, config.recordPath); + m_userData->setValue(COMMON_BITRATE_INDEX_KEY, config.bitRateIndex); + m_userData->setValue(COMMON_MAX_SIZE_INDEX_KEY, config.maxSizeIndex); + m_userData->setValue(COMMON_RECORD_FORMAT_INDEX_KEY, config.recordFormatIndex); + m_userData->setValue(COMMON_FRAMELESS_WINDOW_KEY, config.framelessWindow); + m_userData->setValue(COMMON_LOCK_ORIENTATION_INDEX_KEY, config.lockOrientationIndex); + m_userData->setValue(COMMON_RECORD_SCREEN_KEY, config.recordScreen); + m_userData->setValue(COMMON_RECORD_BACKGROUD_KEY, config.recordBackground); + m_userData->setValue(COMMON_REVERSE_CONNECT_KEY, config.reverseConnect); + m_userData->setValue(COMMON_SHOW_FPS_KEY, config.showFPS); + m_userData->setValue(COMMON_WINDOW_ON_TOP_KEY, config.windowOnTop); + m_userData->setValue(COMMON_AUTO_OFF_SCREEN_KEY, config.autoOffScreen); + m_userData->setValue(COMMON_KEEP_ALIVE_KEY, config.keepAlive); + m_userData->setValue(COMMON_SIMPLE_MODE_KEY, config.simpleMode); m_userData->endGroup(); - return recordFormatIndex; + m_userData->sync(); } -void Config::setRecordFormatIndex(int recordFormatIndex) +UserBootConfig Config::getUserBootConfig() { + UserBootConfig config; m_userData->beginGroup(GROUP_COMMON); - m_userData->setValue(COMMON_RECORD_FORMAT_INDEX_KEY, recordFormatIndex); + config.recordPath = m_userData->value(COMMON_RECORD_KEY, COMMON_RECORD_DEF).toString(); + config.bitRateIndex = m_userData->value(COMMON_BITRATE_INDEX_KEY, COMMON_BITRATE_INDEX_DEF).toInt(); + config.maxSizeIndex = m_userData->value(COMMON_MAX_SIZE_INDEX_KEY, COMMON_MAX_SIZE_INDEX_DEF).toInt(); + config.recordFormatIndex = m_userData->value(COMMON_RECORD_FORMAT_INDEX_KEY, COMMON_RECORD_FORMAT_INDEX_DEF).toInt(); + config.lockOrientationIndex = m_userData->value(COMMON_LOCK_ORIENTATION_INDEX_KEY, COMMON_LOCK_ORIENTATION_INDEX_DEF).toInt(); + config.framelessWindow = m_userData->value(COMMON_FRAMELESS_WINDOW_KEY, COMMON_FRAMELESS_WINDOW_DEF).toBool(); + config.recordScreen = m_userData->value(COMMON_RECORD_SCREEN_KEY, COMMON_RECORD_SCREEN_DEF).toBool(); + config.recordBackground = m_userData->value(COMMON_RECORD_BACKGROUD_KEY, COMMON_RECORD_BACKGROUD_DEF).toBool(); + config.reverseConnect = m_userData->value(COMMON_REVERSE_CONNECT_KEY, COMMON_REVERSE_CONNECT_DEF).toBool(); + config.showFPS = m_userData->value(COMMON_SHOW_FPS_KEY, COMMON_SHOW_FPS_DEF).toBool(); + config.windowOnTop = m_userData->value(COMMON_WINDOW_ON_TOP_KEY, COMMON_WINDOW_ON_TOP_DEF).toBool(); + config.autoOffScreen = m_userData->value(COMMON_AUTO_OFF_SCREEN_KEY, COMMON_AUTO_OFF_SCREEN_DEF).toBool(); + config.keepAlive = m_userData->value(COMMON_KEEP_ALIVE_KEY, COMMON_KEEP_ALIVE_DEF).toBool(); + config.simpleMode = m_userData->value(COMMON_SIMPLE_MODE_KEY, COMMON_SIMPLE_MODE_DEF).toBool(); m_userData->endGroup(); + return config; } void Config::setRect(const QString &serial, const QRect &rc) @@ -184,20 +194,21 @@ QRect Config::getRect(const QString &serial) return rc; } -void Config::setFramelessWindow(bool frameless) +void Config::setNickName(const QString &serial, const QString &name) { - m_userData->beginGroup(GROUP_COMMON); - m_userData->setValue(COMMON_FRAMELESS_WINDOW_KEY, frameless); + m_userData->beginGroup(serial); + m_userData->setValue(SERIAL_NICK_NAME_KEY, name); m_userData->endGroup(); + m_userData->sync(); } -bool Config::getFramelessWindow() +QString Config::getNickName(const QString &serial) { - bool framelessWindow = false; - m_userData->beginGroup(GROUP_COMMON); - framelessWindow = m_userData->value(COMMON_FRAMELESS_WINDOW_KEY, COMMON_FRAMELESS_WINDOW_DEF).toBool(); + QString name; + m_userData->beginGroup(serial); + name = m_userData->value(SERIAL_NICK_NAME_KEY, SERIAL_NICK_NAME_DEF).toString(); m_userData->endGroup(); - return framelessWindow; + return name; } QString Config::getServerVersion() @@ -301,6 +312,16 @@ QString Config::getCodecName() return codecName; } +QStringList Config::getConnectedGroups() +{ + return m_userData->childGroups(); +} + +void Config::deleteGroup(const QString &serial) +{ + m_userData->remove(serial); +} + QString Config::getTitle() { QString title; diff --git a/QtScrcpy/util/config.h b/QtScrcpy/util/config.h index e0e7f5178..e978be435 100644 --- a/QtScrcpy/util/config.h +++ b/QtScrcpy/util/config.h @@ -1,16 +1,36 @@ -#ifndef CONFIG_H +#ifndef CONFIG_H #define CONFIG_H #include #include #include +struct UserBootConfig +{ + QString recordPath = ""; + int bitRateIndex = 0; + int maxSizeIndex = 0; + int recordFormatIndex = 0; + int lockOrientationIndex = 0; + bool recordScreen = false; + bool recordBackground = false; + bool reverseConnect = true; + bool showFPS = false; + bool windowOnTop = false; + bool autoOffScreen = false; + bool framelessWindow = false; + bool keepAlive = false; + bool simpleMode = false; +}; + class QSettings; class Config : public QObject { Q_OBJECT public: + static Config &getInstance(); + // config QString getTitle(); QString getServerVersion(); @@ -24,20 +44,19 @@ class Config : public QObject QString getLogLevel(); QString getCodecOptions(); QString getCodecName(); + QStringList getConnectedGroups(); + + // user data:common + void setUserBootConfig(const UserBootConfig &config); + UserBootConfig getUserBootConfig(); - // user data - QString getRecordPath(); - void setRecordPath(const QString &path); - int getBitRateIndex(); - void setBitRateIndex(int bitRateIndex); - int getMaxSizeIndex(); - void setMaxSizeIndex(int maxSizeIndex); - int getRecordFormatIndex(); - void setRecordFormatIndex(int recordFormatIndex); + // user data:device + void setNickName(const QString &serial, const QString &name); + QString getNickName(const QString &serial); void setRect(const QString &serial, const QRect &rc); QRect getRect(const QString &serial); - bool getFramelessWindow(); - void setFramelessWindow(bool frameless); + + void deleteGroup(const QString &serial); private: explicit Config(QObject *parent = nullptr); diff --git a/README.md b/README.md index 9a3327b1e..8d6ea4665 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,9 @@ you can [build it by yourself](##Build)(just ubuntu test) ## Run - +### Simple Mode +Connect to your Android device on your computer, then run the program and click `USB connect` or `WiFi connect` +### Not Simple Mode Connect to your Android device on your computer, then run the program and click the button below to connect to the Android device. ![run](screenshot/run.png) @@ -260,7 +262,7 @@ All the dependencies are provided and it is easy to compile. ## Licence Since it is based on scrcpy, respect its Licence - Copyright (C) 2020 Barry + Copyright (C) 2025 Rankun Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README_zh.md b/README_zh.md index b16147a74..4aba9f11c 100644 --- a/README_zh.md +++ b/README_zh.md @@ -128,7 +128,9 @@ Mac OS平台,你可以直接使用我编译好的可执行程序: 目前只在ubuntu上测试过 ## 运行 - +### 精简模式 +在你的电脑上接入Android设备,然后运行程序,点击`一键USB连接`或者`一键WIFI连接` +### 非精简模式 在你的电脑上接入Android设备,然后运行程序,按顺序点击如下按钮即可连接到Android设备 ![运行](screenshot/run.png) @@ -256,7 +258,7 @@ Mac OS平台,你可以直接使用我编译好的可执行程序: ## Licence 由于是复刻的scrcpy,尊重它的Licence - Copyright (C) 2020 Barry + Copyright (C) 2025 Rankun Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.