#include #include #include #include #include #include #include #include #include #include #include "videoform.h" #include "mousetap/mousetap.h" #include "ui_videoform.h" #include "iconhelper.h" #include "toolform.h" #include "controller.h" #include "filehandler.h" #include "config.h" extern "C" { #include "libavutil/frame.h" } VideoForm::VideoForm(bool skin, QWidget *parent) : QWidget(parent) , ui(new Ui::videoForm) , m_skin(skin) { ui->setupUi(this); initUI(); updateShowSize(size()); bool vertical = size().height() > size().width(); if (m_skin) { updateStyleSheet(vertical); } } VideoForm::~VideoForm() { delete ui; } void VideoForm::initUI() { setAttribute(Qt::WA_DeleteOnClose); if (m_skin) { QPixmap phone; if (phone.load(":/res/phone.png")) { m_widthHeightRatio = 1.0f * phone.width() / phone.height(); } #ifndef Q_OS_OSX // mac下去掉标题栏影响showfullscreen // 去掉标题栏 setWindowFlags(windowFlags() | Qt::FramelessWindowHint); // 根据图片构造异形窗口 setAttribute(Qt::WA_TranslucentBackground); #endif } setMouseTracking(true); ui->videoWidget->setMouseTracking(true); ui->videoWidget->hide(); } void VideoForm::onGrabCursor(bool grab) { #if defined(Q_OS_WIN32) || defined(Q_OS_OSX) MouseTap::getInstance()->enableMouseEventTap(ui->videoWidget, grab); #else Q_UNUSED(grab) #endif } void VideoForm::updateRender(const AVFrame *frame) { if (ui->videoWidget->isHidden()) { if (m_loadingWidget) { m_loadingWidget->close(); } ui->videoWidget->show(); } updateShowSize(QSize(frame->width, frame->height)); ui->videoWidget->setFrameSize(QSize(frame->width, frame->height)); ui->videoWidget->updateTextures(frame->data[0], frame->data[1], frame->data[2], frame->linesize[0], frame->linesize[1], frame->linesize[2]); } void VideoForm::showToolForm(bool show) { if (!m_toolForm) { m_toolForm = new ToolForm(this, ToolForm::AP_OUTSIDE_RIGHT); m_toolForm->move(pos().x() + geometry().width(), pos().y() + 30); connect(m_toolForm, &ToolForm::screenshot, this, &VideoForm::screenshot); } m_toolForm->setVisible(show); } void VideoForm::updateStyleSheet(bool vertical) { if (vertical) { setStyleSheet(R"( #videoForm { border-image: url(:/image/videoform/phone-v.png) 150px 65px 85px 65px; border-width: 150px 65px 85px 65px; } )"); } else { setStyleSheet(R"( #videoForm { border-image: url(:/image/videoform/phone-h.png) 65px 85px 65px 150px; border-width: 65px 85px 65px 150px; } )"); } layout()->setContentsMargins(getMargins(vertical)); } QMargins VideoForm::getMargins(bool vertical) { QMargins margins; if (vertical) { margins = QMargins(10, 68, 12, 62); } else { margins = QMargins(68, 12, 62, 10); } return margins; } void VideoForm::updateScreenRatio(const QSize &newSize) { m_widthHeightRatio = 1.0f * qMin(newSize.width(),newSize.height()) / qMax(newSize.width(),newSize.height()); } void VideoForm::updateShowSize(const QSize &newSize) { if (m_frameSize != newSize) { m_frameSize = newSize; bool vertical = newSize.height() > newSize.width(); QSize showSize = newSize; QDesktopWidget* desktop = QApplication::desktop(); if (desktop) { QRect screenRect = desktop->availableGeometry(); if (vertical) { showSize.setHeight(qMin(newSize.height(), screenRect.height() - 200)); showSize.setWidth(showSize.height() * m_widthHeightRatio); } else { showSize.setWidth(qMin(newSize.width(), screenRect.width()/2)); showSize.setHeight(showSize.width() * m_widthHeightRatio); } if (isFullScreen()) { switchFullScreen(); } if (m_skin) { QMargins m = getMargins(vertical); showSize.setWidth(showSize.width() + m.left() + m.right()); showSize.setHeight(showSize.height() + m.top() + m.bottom()); } // 窗口居中 move(screenRect.center() - QRect(0, 0, showSize.width(), showSize.height()).center()); } if (!m_skin) { // 减去标题栏高度 (mark:已经没有标题栏了) int titleBarHeight = style()->pixelMetric(QStyle::PM_TitleBarHeight); showSize.setHeight(showSize.height() - titleBarHeight); } if (showSize != size()) { resize(showSize); if (m_skin) { updateStyleSheet(vertical); } } } } void VideoForm::switchFullScreen() { if (isFullScreen()) { showNormal(); #ifdef Q_OS_OSX //setWindowFlags(windowFlags() | Qt::FramelessWindowHint); //show(); #endif if (m_skin) { updateStyleSheet(height() > width()); } showToolForm(true); #ifdef Q_OS_WIN32 ::SetThreadExecutionState(ES_CONTINUOUS); #endif } else { // 这种临时增加标题栏再全屏的方案会导致收不到mousemove事件,导致setmousetrack失效 // mac fullscreen must show title bar #ifdef Q_OS_OSX //setWindowFlags(windowFlags() & ~Qt::FramelessWindowHint); #endif showToolForm(false); if (m_skin) { layout()->setContentsMargins(0, 0, 0, 0); } showFullScreen(); // 全屏状态禁止电脑休眠、息屏 #ifdef Q_OS_WIN32 ::SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED); #endif } } void VideoForm::staysOnTop(bool top) { bool needShow = false; if (isVisible()) { needShow = true; } setWindowFlag(Qt::WindowStaysOnTopHint, top); if (m_toolForm) { m_toolForm->setWindowFlag(Qt::WindowStaysOnTopHint, top); } if (needShow) { show(); } } Controller *VideoForm::getController() { 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; } void VideoForm::mousePressEvent(QMouseEvent *event) { if (ui->videoWidget->geometry().contains(event->pos())) { if (!m_controller) { return; } event->setLocalPos(ui->videoWidget->mapFrom(this, event->localPos().toPoint())); m_controller->mouseEvent(event, ui->videoWidget->frameSize(), ui->videoWidget->size()); } else { if (event->button() == Qt::LeftButton) { m_dragPosition = event->globalPos() - frameGeometry().topLeft(); event->accept(); } } } void VideoForm::mouseReleaseEvent(QMouseEvent *event) { if (m_dragPosition.isNull()) { if (!m_controller) { return; } event->setLocalPos(ui->videoWidget->mapFrom(this, event->localPos().toPoint())); // local check QPointF local = event->localPos(); if (local.x() < 0) { local.setX(0); } if (local.x() > ui->videoWidget->width()) { local.setX(ui->videoWidget->width()); } if (local.y() < 0) { local.setY(0); } if (local.y() > ui->videoWidget->height()) { local.setY(ui->videoWidget->height()); } event->setLocalPos(local); m_controller->mouseEvent(event, ui->videoWidget->frameSize(), ui->videoWidget->size()); } else { m_dragPosition = QPoint(0, 0); } } void VideoForm::mouseMoveEvent(QMouseEvent *event) { if (ui->videoWidget->geometry().contains(event->pos())) { if (!m_controller) { return; } event->setLocalPos(ui->videoWidget->mapFrom(this, event->localPos().toPoint())); m_controller->mouseEvent(event, ui->videoWidget->frameSize(), ui->videoWidget->size()); } else if (!m_dragPosition.isNull()){ if (event->buttons() & Qt::LeftButton) { move(event->globalPos() - m_dragPosition); event->accept(); } } } void VideoForm::wheelEvent(QWheelEvent *event) { if (ui->videoWidget->geometry().contains(event->pos())) { if (!m_controller) { return; } QPointF pos = ui->videoWidget->mapFrom(this, event->pos()); /* QWheelEvent(const QPointF &pos, const QPointF& globalPos, int delta, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::Orientation orient = Qt::Vertical); */ QWheelEvent wheelEvent(pos, event->globalPosF(), event->delta(), event->buttons(), event->modifiers(), event->orientation()); m_controller->wheelEvent(&wheelEvent, ui->videoWidget->frameSize(), ui->videoWidget->size()); } } void VideoForm::keyPressEvent(QKeyEvent *event) { 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; } m_controller->keyEvent(event, ui->videoWidget->frameSize(), ui->videoWidget->size()); } void VideoForm::keyReleaseEvent(QKeyEvent *event) { if (!m_controller) { return; } m_controller->keyEvent(event, ui->videoWidget->frameSize(), ui->videoWidget->size()); } void VideoForm::paintEvent(QPaintEvent *paint) { Q_UNUSED(paint) QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } void VideoForm::showEvent(QShowEvent *event) { Q_UNUSED(event) if (!isFullScreen()) { showToolForm(); } } void VideoForm::dragEnterEvent(QDragEnterEvent *event) { event->acceptProposedAction(); } void VideoForm::dragMoveEvent(QDragMoveEvent *event) { Q_UNUSED(event) } void VideoForm::dragLeaveEvent(QDragLeaveEvent *event) { Q_UNUSED(event) } void VideoForm::dropEvent(QDropEvent *event) { if (!m_fileHandler) { return; } const QMimeData* qm = event->mimeData(); QString file = qm->urls()[0].toLocalFile(); QFileInfo fileInfo(file); if (!fileInfo.exists()) { QMessageBox::warning(this, "QtScrcpy", tr("file does not exist"), QMessageBox::Ok); return; } if (fileInfo.isFile() && fileInfo.suffix() == "apk") { m_fileHandler->installApkRequest(m_serial, file); return; } m_fileHandler->pushFileRequest(m_serial, file, Config::getInstance().getPushFilePath() + fileInfo.fileName()); }