mirror of https://code.videolan.org/videolan/vlc
210 lines
5.8 KiB
C++
210 lines
5.8 KiB
C++
/*****************************************************************************
|
|
* Copyright (C) 2023 VLC authors and VideoLAN
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
|
*****************************************************************************/
|
|
#include "compositor_wayland.hpp"
|
|
|
|
#include "maininterface/mainctx.hpp"
|
|
#include "maininterface/interface_window_handler.hpp"
|
|
|
|
#ifndef QT5_GUI_PRIVATE
|
|
#warning "qplatformnativeinterface is requried for wayland compositor"
|
|
#endif
|
|
|
|
#include <QtGui/qpa/qplatformnativeinterface.h>
|
|
#include <QtGui/qpa/qplatformwindow.h>
|
|
|
|
#include <vlc_window.h>
|
|
#include <vlc_modules.h>
|
|
|
|
#include "compositor_wayland_module.h"
|
|
|
|
namespace vlc {
|
|
|
|
static qreal dprForWindow(QQuickWindow* window)
|
|
{
|
|
QPlatformWindow* nativeWindow = window->handle();
|
|
if (!nativeWindow)
|
|
return 1.0;
|
|
|
|
return nativeWindow->devicePixelRatio();
|
|
}
|
|
|
|
CompositorWayland::CompositorWayland(qt_intf_t *p_intf, QObject* parent)
|
|
: CompositorVideo(p_intf, parent)
|
|
{
|
|
}
|
|
|
|
CompositorWayland::~CompositorWayland()
|
|
{
|
|
if (m_waylandImpl)
|
|
{
|
|
if (m_waylandImpl->p_module)
|
|
{
|
|
m_waylandImpl->close(m_waylandImpl);
|
|
module_unneed(m_waylandImpl, m_waylandImpl->p_module);
|
|
}
|
|
vlc_object_delete(m_waylandImpl);
|
|
}
|
|
}
|
|
|
|
bool CompositorWayland::preInit(qt_intf_t *)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool CompositorWayland::init()
|
|
{
|
|
QPlatformNativeInterface* native = QGuiApplication::platformNativeInterface();
|
|
|
|
//get "wl_display" and not "display", as "display" may refer to other concept in other QPA
|
|
//so this will fail if qt doesn't use wayland
|
|
void* qpni_display = native->nativeResourceForIntegration("wl_display");
|
|
if (!qpni_display)
|
|
return false;
|
|
|
|
/*
|
|
* a separate wayland module is used to perform direct wayland calls
|
|
* without requiring Qt module to be directly linked to wayland
|
|
*/
|
|
m_waylandImpl = static_cast<qtwayland_t*>(vlc_object_create(m_intf, sizeof(qtwayland_t)));
|
|
if (!m_waylandImpl)
|
|
return false;
|
|
|
|
m_waylandImpl->p_module = module_need(m_waylandImpl, "qtwayland", nullptr, false);
|
|
if (!m_waylandImpl->p_module)
|
|
{
|
|
msg_Err(m_intf, "the qtwayland module is not available, wayland"
|
|
"embedded video output will not be possible");
|
|
vlc_object_delete(m_waylandImpl);
|
|
m_waylandImpl = nullptr;
|
|
|
|
return false;
|
|
}
|
|
|
|
return m_waylandImpl->init(m_waylandImpl, qpni_display);
|
|
}
|
|
|
|
bool CompositorWayland::makeMainInterface(MainCtx* mainCtx)
|
|
{
|
|
assert(mainCtx);
|
|
m_mainCtx = mainCtx;
|
|
|
|
m_qmlView = std::make_unique<QQuickView>();
|
|
if (m_mainCtx->useClientSideDecoration())
|
|
m_qmlView->setFlag(Qt::FramelessWindowHint);
|
|
m_qmlView->setResizeMode(QQuickView::SizeRootObjectToView);
|
|
m_qmlView->setColor(QColor(Qt::transparent));
|
|
|
|
m_qmlView->show();
|
|
|
|
QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
|
|
void* interfaceSurface = nativeInterface->nativeResourceForWindow("surface", m_qmlView.get());
|
|
if (!interfaceSurface)
|
|
return false;
|
|
|
|
m_waylandImpl->setupInterface(m_waylandImpl, interfaceSurface, dprForWindow(m_qmlView.get()));
|
|
|
|
return commonGUICreate(m_qmlView.get(), m_qmlView.get(),
|
|
CompositorVideo::CAN_SHOW_PIP);
|
|
}
|
|
|
|
QWindow* CompositorWayland::interfaceMainWindow() const
|
|
{
|
|
return m_qmlView.get();
|
|
}
|
|
|
|
void CompositorWayland::destroyMainInterface()
|
|
{
|
|
unloadGUI();
|
|
}
|
|
|
|
void CompositorWayland::unloadGUI()
|
|
{
|
|
//needs to be released before the window
|
|
m_interfaceWindowHandler.reset();
|
|
|
|
m_qmlView.reset();
|
|
commonGUIDestroy();
|
|
}
|
|
|
|
Compositor::Type CompositorWayland::type() const
|
|
{
|
|
return Compositor::WaylandCompositor;
|
|
}
|
|
|
|
QQuickItem * CompositorWayland::activeFocusItem() const
|
|
{
|
|
return m_qmlView->activeFocusItem();
|
|
}
|
|
|
|
// vout functions
|
|
|
|
bool CompositorWayland::setupVoutWindow(vlc_window_t* p_wnd, VoutDestroyCb destroyCb)
|
|
{
|
|
int ret = m_waylandImpl->setupVoutWindow(m_waylandImpl, p_wnd);
|
|
if (ret != VLC_SUCCESS)
|
|
return false;
|
|
|
|
commonSetupVoutWindow(p_wnd, destroyCb);
|
|
|
|
return true;
|
|
}
|
|
|
|
void CompositorWayland::windowDestroy()
|
|
{
|
|
m_waylandImpl->teardownVoutWindow(m_waylandImpl);
|
|
CompositorVideo::windowDestroy();
|
|
}
|
|
|
|
int CompositorWayland::windowEnable(const vlc_window_cfg_t * cfg)
|
|
{
|
|
m_waylandImpl->enable(m_waylandImpl, cfg);
|
|
commonWindowEnable();
|
|
return VLC_SUCCESS;
|
|
}
|
|
|
|
void CompositorWayland::windowDisable()
|
|
{
|
|
m_waylandImpl->disable(m_waylandImpl);
|
|
commonWindowDisable();
|
|
}
|
|
|
|
void CompositorWayland::onSurfacePositionChanged(const QPointF& position)
|
|
{
|
|
QMargins margins = m_qmlView->frameMargins();
|
|
|
|
qreal qtDpr = m_qmlView.get()->effectiveDevicePixelRatio();
|
|
qreal nativeDpr = dprForWindow(m_qmlView.get());
|
|
|
|
m_waylandImpl->move(
|
|
m_waylandImpl,
|
|
(margins.left() * qtDpr + position.x() ) / nativeDpr,
|
|
(margins.top() * qtDpr + position.y() ) / nativeDpr
|
|
);
|
|
}
|
|
|
|
void CompositorWayland::onSurfaceSizeChanged(const QSizeF& size)
|
|
{
|
|
qreal nativeDpr = dprForWindow(m_qmlView.get());
|
|
|
|
m_waylandImpl->resize(m_waylandImpl,
|
|
size.width() / nativeDpr,
|
|
size.height() / nativeDpr);
|
|
}
|
|
|
|
}
|