1
0
forked from BRT/arc

Fix scrcpy

This commit is contained in:
slava 2025-04-26 13:50:05 +07:00
parent b125c509b3
commit cf543917b4
7 changed files with 182 additions and 108 deletions

View File

@ -64,95 +64,6 @@ void wait(const int milliseconds) {
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
// Шаг 1: запускаем приложение РСХБ
runADBCommand("monkey -p ru.rshb.dbo -c android.intent.category.LAUNCHER 1");
wait(4500); // Ждем пока загружается приложение, перед экраном ввода пин-кода
// Шаг 2: Ввод ПИН
runADBCommand("input tap 275 900"); // Клик по цифре 1
runADBCommand("input tap 560 900"); // Клик по цифре 2
runADBCommand("input tap 275 900"); // Клик по цифре 1
runADBCommand("input tap 275 900"); // Клик по цифре 1
wait(5500);
// Шаг 3: Закрытие рекламы
runADBCommand("input tap 300 2090"); // Закрыть баннер пуш-уведомлений (Баннер высвечивается при каждом 2-м запуске)
// runADBCommand("input tap 993 163"); // Закрыть сторис (только при первом входе после логина)
// runADBCommand("input tap 920 151"); // Закрыть окно перед главным экраном (только при первом входе после логина)
// runADBCommand("input tap 990 170"); // Закрыть другое окно (только при первом входе после логина)
wait(1500);
// Шаг 4: Пролистывание до кнопки "Все продукты"
runADBCommand("input swipe 1000 2000 1000 1300");
wait(3000);
// Шаг 5: Нажимаем на кнопку "Все продукты"
runADBCommand("input tap 570 1240");
wait(3000);
// Шаг 6: Выбор карты
// runADBCommand("input tap 530 535"); // Для карты дебетовая, цифровая, **6387
runADBCommand("input tap 530 675"); // Для карты дебетовая, **0823
// runADBCommand("input tap 530 800"); // Для карты дебетовая, **7498
wait(1500);
// Шаг 7: Нажимаем на кнопку "Оплатить"
runADBCommand("input tap 430 920");
wait(1200);
// Шаг 8: Нажимаем на блок "По номеру телефона"
runADBCommand("input tap 260 1500");
wait(2000);
// Шаг 8.1: Закрытие окна разрешения доступа к контактам
// runADBCommand("input tap 540 2140");
// wait(500);
// Вводим номер телефона для перевода
runADBCommand("input tap 250 250");
runADBCommand("input text '9272960333'");
wait(1200);
// Шаг 9: Нажимаем на область "Другой банк через СБП"
runADBCommand("input tap 500 600");
wait(2000);
// Шаг 10: Выбор банка
// runADBCommand("input tap 280 280"); // Нажимаем для фокуса у поля ввода текста
// runADBCommand("input text 'Т-Банк'"); // Передаем текст 'Т-банк' (Проблема - выдает NullPointerException из-за кириллицы)
runADBCommand("input tap 420 620"); // Т-Банк (Пока выбираю хардкодовым нажатием по списку)
wait(2000);
// Шаг 11: Ввод суммы
runADBCommand("input tap 300 1040");
runADBCommand("input text '10'");
wait(2000);
// Шаг 11.1: Подтверждаем перевод
runADBCommand("input tap 500 2170");
wait(2000);
// Завершаем перевод
runADBCommand("input tap 500 2170");
std::cout << "All commands executed successfully." << std::endl;
return 0;
QApplication app(argc, argv); QApplication app(argc, argv);
// QList<Card> cards = AccountInfoScreener::parseCardData(QByteArray()); // QList<Card> cards = AccountInfoScreener::parseCardData(QByteArray());
@ -169,7 +80,7 @@ int main(int argc, char *argv[]) {
// } // }
// setupWorkerAndThread(app); setupWorkerAndThread(app);
// //
// const QDateTime current = QDateTime::currentDateTimeUtc(); // const QDateTime current = QDateTime::currentDateTimeUtc();
// qDebug() << "Обновление lastScan:" << CommonDataDAO::updateLastScan(current); // qDebug() << "Обновление lastScan:" << CommonDataDAO::updateLastScan(current);

View File

@ -3,6 +3,7 @@
#include <QLabel> #include <QLabel>
#include <QPixmap> #include <QPixmap>
#include <QImage> #include <QImage>
#include <QMouseEvent>
DeviceWidget::DeviceWidget(const DeviceInfo &device, QWidget *parent): QWidget(parent) { DeviceWidget::DeviceWidget(const DeviceInfo &device, QWidget *parent): QWidget(parent) {
auto *layout = new QVBoxLayout(this); auto *layout = new QVBoxLayout(this);
@ -35,3 +36,17 @@ DeviceWidget::DeviceWidget(const DeviceInfo &device, QWidget *parent): QWidget(p
layout->setSpacing(0); layout->setSpacing(0);
layout->addWidget(statusLabel); layout->addWidget(statusLabel);
} }
void DeviceWidget::mouseDoubleClickEvent(QMouseEvent *event) {
if (event->button() == Qt::LeftButton) {
if (scrcpyWindow == nullptr) {
scrcpyWindow = new ScrcpyWindow();
scrcpyWindow->show();
// Подключаем сигнал закрытия окна
connect(scrcpyWindow, &ScrcpyWindow::destroyed, this, [this]() {
scrcpyWindow = nullptr; // Освобождаем память, когда окно закрыто
});
}
}
}

View File

@ -1,10 +1,17 @@
#pragma once #pragma once
#include <QWidget> #include <QWidget>
#include "db/DeviceInfo.h" #include "db/DeviceInfo.h"
#include "scrcpy/ScrcpyWindow.h"
class DeviceWidget final : public QWidget { class DeviceWidget final : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit DeviceWidget(const DeviceInfo& device, QWidget* parent = nullptr); explicit DeviceWidget(const DeviceInfo& device, QWidget* parent = nullptr);
private:
ScrcpyWindow *scrcpyWindow = nullptr;
protected:
void mouseDoubleClickEvent(QMouseEvent *event) override;
}; };

View File

@ -5,6 +5,8 @@
#include <QScrollArea> #include <QScrollArea>
#include <QMenuBar> #include <QMenuBar>
#include <QStackedWidget> #include <QStackedWidget>
#include <QApplication>
#include <QCloseEvent>
#include "db/DeviceInfo.h" #include "db/DeviceInfo.h"
#include "DeviceWidget.h" #include "DeviceWidget.h"
@ -12,6 +14,7 @@
#include "widget/FlowLayout.h" #include "widget/FlowLayout.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
// Инициализируем таймер обновления // Инициализируем таймер обновления
timer = new QTimer(this); timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &MainWindow::loadDevices); connect(timer, &QTimer::timeout, this, &MainWindow::loadDevices);
@ -21,12 +24,12 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
createDevicePage(); createDevicePage();
stackedWidget->addWidget(devicePage); stackedWidget->addWidget(devicePage);
// stackedWidget->setCurrentWidget(devicePage); FIXME stackedWidget->setCurrentWidget(devicePage);
// FIXME переделать на ленивое создание // FIXME переделать на ленивое создание
accountPage = new AccountWindow(this); accountPage = new AccountWindow(this);
stackedWidget->addWidget(accountPage); stackedWidget->addWidget(accountPage);
stackedWidget->setCurrentWidget(accountPage); // stackedWidget->setCurrentWidget(accountPage);
resize(800, 600); resize(800, 600);
@ -48,9 +51,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
stackedWidget->setCurrentWidget(accountPage); stackedWidget->setCurrentWidget(accountPage);
deleteDevicePage(); // освобождаем ресурсы deleteDevicePage(); // освобождаем ресурсы
}); });
scrcpyWindow = new ScrcpyWindow();
scrcpyWindow->show();
} }
@ -114,3 +114,18 @@ void MainWindow::loadDevices() {
flowLayout->addWidget(new DeviceWidget(device)); flowLayout->addWidget(new DeviceWidget(device));
} }
} }
void MainWindow::closeEvent(QCloseEvent *event) {
closeAllWindows(); // Закрываем все окна
// event->accept(); // Разрешаем закрытие окна
}
void MainWindow::closeAllWindows() {
// QList<QWidget*> topLevelWidgets = QApplication::topLevelWidgets(); // Получаем все верхние окна
// for (QWidget *widget : topLevelWidgets) {
// widget->close(); // Закрываем каждое окно
// }
QApplication::quit();
// QCoreApplication::exit(0);
}

View File

@ -4,7 +4,6 @@
#include <QStackedWidget> #include <QStackedWidget>
#include <QTimer> #include <QTimer>
#include "db/DeviceInfo.h" #include "db/DeviceInfo.h"
#include "scrcpy/ScrcpyWindow.h"
#include "widget/FlowLayout.h" #include "widget/FlowLayout.h"
class MainWindow final : public QMainWindow { class MainWindow final : public QMainWindow {
@ -13,6 +12,9 @@ public:
explicit MainWindow(QWidget *parent = nullptr); explicit MainWindow(QWidget *parent = nullptr);
void loadDevices(); void loadDevices();
protected:
void closeEvent(QCloseEvent *event) override;
private: private:
QWidget* central; QWidget* central;
FlowLayout* flowLayout; FlowLayout* flowLayout;
@ -22,8 +24,8 @@ private:
QWidget* devicePage = nullptr; QWidget* devicePage = nullptr;
QWidget* accountPage = nullptr; QWidget* accountPage = nullptr;
ScrcpyWindow *scrcpyWindow;
void createDevicePage(); void createDevicePage();
void deleteDevicePage(); void deleteDevicePage();
void closeAllWindows();
}; };

View File

@ -1,13 +1,17 @@
#include "ScrcpyWindow.h" #include "ScrcpyWindow.h"
#include <QScreen>
#include <QDebug> #include <QDebug>
#include <QGuiApplication>
#include <QTimer> #include <QTimer>
#include <QCloseEvent>
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include <windows.h> #include <windows.h>
#include <windowsx.h>
#endif #endif
ScrcpyWindow::ScrcpyWindow(QWidget *parent) : QWidget(parent), m_process(nullptr) { ScrcpyWindow::ScrcpyWindow(QWidget *parent) : QWidget(parent), m_process(nullptr) {
setWindowFlag(Qt::WindowStaysOnTopHint); // setWindowFlag(Qt::WindowStaysOnTopHint);
startScrcpy(); startScrcpy();
} }
@ -15,45 +19,161 @@ ScrcpyWindow::~ScrcpyWindow() {
stopScrcpy(); stopScrcpy();
} }
void ScrcpyWindow::closeEvent(QCloseEvent *event) {
qDebug() << "closeEvent triggered";
stopScrcpy();
event->accept();
}
void ScrcpyWindow::startScrcpy() { void ScrcpyWindow::startScrcpy() {
m_process = new QProcess(this); int deviceWidth = 720;
m_process->start("scrcpy", {"--window-title", "scrcpy", "--always-on-top"}); int deviceHeight = 1600;
QScreen* screen = QGuiApplication::primaryScreen();
int screenHeight = screen->availableGeometry().height();
int screenWidth = screen->availableGeometry().width();
// Вычисляем масштаб так, чтобы устройство влезло в экран (и по ширине, и по высоте)
double scaleW = static_cast<double>(screenWidth) / deviceWidth;
double scaleH = static_cast<double>(screenHeight) / deviceHeight;
double scale = qMin(scaleW, scaleH) * 0.8; // 90% от доступного размера, с отступами
int windowWidth = static_cast<int>(deviceWidth * scale);
int windowHeight = static_cast<int>(deviceHeight * scale);
qDebug() << "windowWidth:" << windowWidth;
qDebug() << "windowHeight:" << windowHeight;
// Устанавливаем размер вашего окна
setFixedSize(windowWidth + 200, windowHeight);
// setWindowFlags(windowFlags() | Qt::MSWindowsFixedSizeDialogHint);
// QString("--window-width=%1").arg(windowWidth), QString("--window-height=%1").arg(windowHeight)
// m_process = new QProcess(this);
// m_process->start("scrcpy", { "--window-title", "scrcpy", "--always-on-top"});
// Подождём немного, чтобы окно scrcpy запустилось // Подождём немного, чтобы окно scrcpy запустилось
QTimer::singleShot(5000, this, &ScrcpyWindow::embedPlatformSpecific); // QTimer::singleShot(2000, this, &ScrcpyWindow::);
// embedPlatformSpecific();
} }
void ScrcpyWindow::stopScrcpy() { void ScrcpyWindow::stopScrcpy() {
if (m_process) { // m_process->terminate();
m_process->terminate(); // if (!m_process->waitForFinished(3000)) {
m_process->waitForFinished(); // qDebug() << "Process did not finish in time, killing it";
delete m_process; m_process->kill(); // Принудительное завершение процесса
m_process = nullptr; // }
delete m_process;
m_process = nullptr;
#ifdef Q_OS_WIN
HWND hwndScrcpy = FindWindowW(nullptr, L"scrcpy");
if (hwndScrcpy) {
PostMessage(hwndScrcpy, WM_CLOSE, 0, 0);
} }
#endif
} }
LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
OutputDebugString(L"WM_CLOSE received\n");
HWND hwndScrcpy = FindWindowW(nullptr, L"scrcpy");
if (!hwndScrcpy)
return DefWindowProc(hwnd, msg, wParam, lParam);
if (msg == WM_CLOSE) {
qDebug() << "WM_CLOSE received, closing scrcpy window.";
// Возможно, необходимо обработать конкретно это сообщение
// или сделать дополнительные проверки.
}
switch (msg) {
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MOUSEMOVE:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_MOUSEWHEEL:
{
// Перевод координат мыши в координаты окна scrcpy
POINT pt;
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);
qDebug() << "Before ClientToScreen: " << pt.x << ", " << pt.y;
ClientToScreen(hwnd, &pt);
qDebug() << "After ClientToScreen: " << pt.x << ", " << pt.y;
ScreenToClient(hwndScrcpy, &pt);
qDebug() << "After ScreenToClient: " << pt.x << ", " << pt.y;
LPARAM newLParam = MAKELPARAM(pt.x, pt.y);
SendMessage(hwndScrcpy, msg, wParam, newLParam);
return 0;
}
case WM_KEYDOWN:
case WM_KEYUP:
case WM_CHAR:
SendMessage(hwndScrcpy, msg, wParam, lParam);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
void ScrcpyWindow::embedPlatformSpecific() { void ScrcpyWindow::embedPlatformSpecific() {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
HWND hwndScrcpy = FindWindowW(nullptr, L"scrcpy"); HWND hwndScrcpy = FindWindowW(nullptr, L"scrcpy");
int attempts = 0;
while (!hwndScrcpy && attempts < 20) {
hwndScrcpy = FindWindowW(nullptr, L"scrcpy");
Sleep(100); // Задержка 100 мс
attempts++;
}
if (!hwndScrcpy) { if (!hwndScrcpy) {
qDebug() << "scrcpy window not found"; qDebug() << "scrcpy window not found";
return; return;
} }
Sleep(1000);
// Получаем hwnd текущего окна
HWND hwndTarget = (HWND)this->winId(); HWND hwndTarget = (HWND)this->winId();
// Устанавливаем окно scrcpy как дочернее
SetParent(hwndScrcpy, hwndTarget); SetParent(hwndScrcpy, hwndTarget);
// Убираем рамки и заголовок
LONG style = GetWindowLong(hwndScrcpy, GWL_STYLE); LONG style = GetWindowLong(hwndScrcpy, GWL_STYLE);
style &= ~(WS_CAPTION | WS_THICKFRAME | WS_BORDER); style &= ~(WS_CAPTION | WS_THICKFRAME | WS_BORDER);
SetWindowLong(hwndScrcpy, GWL_STYLE, style); SetWindowLong(hwndScrcpy, GWL_STYLE, style);
// Получаем размеры клиентской области
RECT rect; RECT rect;
GetClientRect(hwndTarget, &rect); GetClientRect(hwndTarget, &rect);
qDebug() << "Client area size: " << rect.right << ", " << rect.bottom;
// int deviceWidth = 720;
// int deviceHeight = 1600;
// Client area size: 676 , 1502
// Получаем размеры клиентской области
// RECT rect;
// GetClientRect(hwndTarget, &rect);
SetWindowPos(hwndScrcpy, HWND_TOP, 0, 0, SetWindowPos(hwndScrcpy, HWND_TOP, 0, 0,
rect.right - rect.left, rect.bottom - rect.top, rect.right - rect.left, rect.bottom - rect.top,
SWP_SHOWWINDOW); SWP_SHOWWINDOW | SWP_FRAMECHANGED);
// rect.right - rect.left, rect.bottom - rect.top,
// Сохраняем старую оконную процедуру
// LONG_PTR prevWndProc = GetWindowLongPtr(hwndTarget, GWLP_WNDPROC);
// SetWindowLongPtr(hwndTarget, GWLP_WNDPROC, (LONG_PTR)wndProc);
#elif defined(Q_OS_MAC) #elif defined(Q_OS_MAC)

View File

@ -2,6 +2,7 @@
#include <QWidget> #include <QWidget>
#include <QProcess> #include <QProcess>
#include <QCloseEvent>
class ScrcpyWindow final : public QWidget { class ScrcpyWindow final : public QWidget {
Q_OBJECT Q_OBJECT
@ -11,6 +12,9 @@ public:
~ScrcpyWindow() override; ~ScrcpyWindow() override;
protected:
void closeEvent(QCloseEvent *event) override;
private: private:
QProcess *m_process; QProcess *m_process;