LCOV - code coverage report
Current view: top level - muse/framework/vst/widgets - vstviewdialog_qwidget.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 105 0
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : 
      23              : #include "vstviewdialog_qwidget.h"
      24              : 
      25              : #include <QWindow>
      26              : #include <QTimer>
      27              : #include <QKeyEvent>
      28              : #include <QScreen>
      29              : 
      30              : #include "ivstplugininstance.h"
      31              : #include "vsttypes.h"
      32              : 
      33              : #include "log.h"
      34              : 
      35              : using namespace muse::vst;
      36              : using namespace Steinberg;
      37              : 
      38            0 : ::Steinberg::uint32 PLUGIN_API VstViewDialog::addRef()
      39              : {
      40            0 :     return ::Steinberg::FUnknownPrivate::atomicAdd(__funknownRefCount, 1);
      41              : }
      42              : 
      43            0 : ::Steinberg::uint32 PLUGIN_API VstViewDialog::release()
      44              : {
      45            0 :     if (::Steinberg::FUnknownPrivate::atomicAdd(__funknownRefCount, -1) == 0) {
      46            0 :         return 0;
      47              :     }
      48            0 :     return __funknownRefCount;
      49              : }
      50              : 
      51            0 : IMPLEMENT_QUERYINTERFACE(VstViewDialog, IPlugFrame, IPlugFrame::iid)
      52              : 
      53            0 : VstViewDialog::VstViewDialog(QWidget* parent)
      54            0 :     : TopLevelDialog(parent)
      55              : {
      56            0 :     setAttribute(Qt::WA_NativeWindow);
      57            0 : }
      58              : 
      59            0 : VstViewDialog::~VstViewDialog()
      60              : {
      61            0 :     deinit();
      62            0 : }
      63              : 
      64            0 : void VstViewDialog::deinit()
      65              : {
      66            0 :     if (m_view) {
      67            0 :         m_view->setFrame(nullptr);
      68            0 :         m_view->removed();
      69            0 :         m_view = nullptr;
      70              :     }
      71              : 
      72            0 :     if (m_instance) {
      73            0 :         m_instance->loadingCompleted().disconnect(this);
      74            0 :         m_instance->refreshConfig();
      75            0 :         m_instance = nullptr;
      76              :     }
      77            0 : }
      78              : 
      79            0 : tresult VstViewDialog::resizeView(IPlugView* view, ViewRect* newSize)
      80              : {
      81            0 :     view->checkSizeConstraint(newSize);
      82              : 
      83            0 :     QScreen* screen = this->screen();
      84            0 :     QSize availableSize = screen->availableSize();
      85              : 
      86            0 :     int newWidth = newSize->getWidth();
      87            0 :     int newHeight = newSize->getHeight();
      88              : 
      89              : //! NOTE: newSize already includes the UI scaling on Windows, so we have to remove it before setting the fixed size.
      90              : //! Otherwise, the user will get an extremely large window and won't be able to resize it
      91              : #ifdef Q_OS_WIN
      92              :     qreal scaling = screen->devicePixelRatio();
      93              :     newWidth = newWidth / scaling;
      94              :     newHeight = newHeight / scaling;
      95              : #endif
      96              : 
      97            0 :     newWidth = std::min(newWidth, availableSize.width());
      98            0 :     newHeight = std::min(newHeight, availableSize.height());
      99              : 
     100            0 :     setFixedSize(newWidth, newHeight);
     101              : 
     102            0 :     view->onSize(newSize);
     103              : 
     104            0 :     update();
     105              : 
     106            0 :     return kResultTrue;
     107              : }
     108              : 
     109            0 : void VstViewDialog::wrapPluginView()
     110              : {
     111            0 :     m_instance = instancesRegister()->instanceById(m_instanceId);
     112            0 :     if (!m_instance) {
     113            0 :         return;
     114              :     }
     115              : 
     116            0 :     setWindowTitle(QString::fromStdString(m_instance->name()));
     117              : 
     118            0 :     if (m_instance->isLoaded()) {
     119            0 :         attachView(m_instance);
     120              :     } else {
     121            0 :         m_instance->loadingCompleted().onNotify(this, [this]() {
     122            0 :             attachView(m_instance);
     123            0 :         });
     124              :     }
     125              : }
     126              : 
     127            0 : void VstViewDialog::attachView(IVstPluginInstancePtr instance)
     128              : {
     129            0 :     if (!instance) {
     130            0 :         return;
     131              :     }
     132              : 
     133            0 :     m_view = instance->createView();
     134            0 :     if (!m_view) {
     135            0 :         return;
     136              :     }
     137              : 
     138            0 :     if (m_view->isPlatformTypeSupported(currentPlatformUiType()) != Steinberg::kResultTrue) {
     139            0 :         return;
     140              :     }
     141              : 
     142            0 :     m_view->setFrame(this);
     143              : 
     144              :     Steinberg::tresult attached;
     145            0 :     attached = m_view->attached(reinterpret_cast<void*>(windowHandle()->winId()), currentPlatformUiType());
     146            0 :     if (attached != kResultOk) {
     147            0 :         LOGE() << "Unable to attach vst plugin view to window"
     148            0 :                << ", m_instanceId: " << m_instanceId;
     149            0 :         return;
     150              :     }
     151              : 
     152            0 :     connect(windowHandle(), &QWindow::screenChanged, this, [this](QScreen*) {
     153            0 :         updateViewGeometry();
     154            0 :     });
     155              : 
     156            0 :     QTimer::singleShot(0, [this]() {
     157            0 :         updateViewGeometry();
     158            0 :         moveViewToMainWindowCenter();
     159            0 :     });
     160              : }
     161              : 
     162            0 : void VstViewDialog::updateViewGeometry()
     163              : {
     164            0 :     IF_ASSERT_FAILED(m_view) {
     165            0 :         return;
     166              :     }
     167              : 
     168              : #ifdef Q_OS_WIN
     169              :     FUnknownPtr<IPluginContentScaleHandler> scalingHandler(m_view);
     170              :     if (scalingHandler) {
     171              :         scalingHandler->setContentScaleFactor(screen()->devicePixelRatio());
     172              :     }
     173              : #endif
     174              : 
     175            0 :     ViewRect size;
     176            0 :     m_view->getSize(&size);
     177              : 
     178            0 :     resizeView(m_view, &size);
     179              : }
     180              : 
     181            0 : void VstViewDialog::moveViewToMainWindowCenter()
     182              : {
     183            0 :     QRectF mainWindowGeo = mainWindow()->qWindow()->geometry();
     184              : 
     185            0 :     int x = mainWindowGeo.x() + (mainWindowGeo.width() - width()) / 2;
     186            0 :     int y = mainWindowGeo.y() + (mainWindowGeo.height() - height()) / 2;
     187              : 
     188            0 :     move(x, y);
     189            0 : }
     190              : 
     191            0 : void VstViewDialog::showEvent(QShowEvent* ev)
     192              : {
     193            0 :     moveViewToMainWindowCenter();
     194              : 
     195            0 :     TopLevelDialog::showEvent(ev);
     196            0 : }
     197              : 
     198            0 : void VstViewDialog::closeEvent(QCloseEvent* ev)
     199              : {
     200            0 :     deinit();
     201              : 
     202            0 :     TopLevelDialog::closeEvent(ev);
     203            0 : }
     204              : 
     205            0 : bool VstViewDialog::event(QEvent* ev)
     206              : {
     207            0 :     if (ev && ev->spontaneous() && ev->type() == QEvent::ShortcutOverride) {
     208            0 :         if (QKeyEvent* keyEvent = dynamic_cast<QKeyEvent*>(ev)) {
     209            0 :             int key = keyEvent->key();
     210              : 
     211            0 :             if (key == 0 || key == static_cast<int>(Qt::Key_unknown)) {
     212            0 :                 keyEvent->accept();
     213            0 :                 return true;
     214              :             }
     215              :         }
     216              :     }
     217              : 
     218            0 :     return TopLevelDialog::event(ev);
     219              : }
     220              : 
     221            0 : FIDString VstViewDialog::currentPlatformUiType() const
     222              : {
     223              : #ifdef Q_OS_MAC
     224              :     return Steinberg::kPlatformTypeNSView;
     225              : #elif defined(Q_OS_IOS)
     226              :     return Steinberg::kPlatformTypeUIView;
     227              : #elif defined(Q_OS_WIN)
     228              :     return Steinberg::kPlatformTypeHWND;
     229              : #else
     230            0 :     return Steinberg::kPlatformTypeX11EmbedWindowID;
     231              : #endif
     232              : }
     233              : 
     234            0 : int VstViewDialog::instanceId() const
     235              : {
     236            0 :     return m_instanceId;
     237              : }
     238              : 
     239            0 : void VstViewDialog::setInstanceId(int newInstanceId)
     240              : {
     241            0 :     if (m_instanceId == newInstanceId) {
     242            0 :         return;
     243              :     }
     244            0 :     m_instanceId = newInstanceId;
     245            0 :     emit instanceIdChanged();
     246              : 
     247            0 :     wrapPluginView();
     248              : }
        

Generated by: LCOV version 2.0-1