tdf#125271 under wayland without gtksink, try waylandsink

and if there is no videosink then give up

Change-Id: I6b60e7be1e77dbf5c4c277ccf47a4d121f3cd6a5
Reviewed-on: https://gerrit.libreoffice.org/72871
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
Reviewed-on: https://gerrit.libreoffice.org/73087
Reviewed-by: Michael Stahl <Michael.Stahl@cib.de>
Tested-by: Jenkins
diff --git a/avmedia/source/gstreamer/gstplayer.cxx b/avmedia/source/gstreamer/gstplayer.cxx
index 46432c7..37c638a 100644
--- a/avmedia/source/gstreamer/gstplayer.cxx
+++ b/avmedia/source/gstreamer/gstplayer.cxx
@@ -302,6 +302,7 @@ Player::Player() :
    mbMuted( false ),
    mbLooping( false ),
    mbInitialized( false ),
    mpDisplay( nullptr ),
    mnWindowID( 0 ),
    mpXOverlay( nullptr ),
    mnDuration( 0 ),
@@ -453,6 +454,31 @@ static gboolean wrap_element_query_duration (GstElement *element, GstFormat form
#endif
}

#ifndef AVMEDIA_GST_0_10

#define LCL_WAYLAND_DISPLAY_HANDLE_CONTEXT_TYPE "GstWaylandDisplayHandleContextType"

static gboolean lcl_is_wayland_display_handle_need_context_message(GstMessage* msg)
{
    g_return_val_if_fail(GST_IS_MESSAGE(msg), false);

    if (GST_MESSAGE_TYPE(msg) != GST_MESSAGE_NEED_CONTEXT)
        return false;
    const gchar *type = nullptr;
    if (!gst_message_parse_context_type(msg, &type))
        return false;
    return !g_strcmp0(type, LCL_WAYLAND_DISPLAY_HANDLE_CONTEXT_TYPE);
}

static GstContext* lcl_wayland_display_handle_context_new(void* display)
{
    GstContext *context = gst_context_new(LCL_WAYLAND_DISPLAY_HANDLE_CONTEXT_TYPE, TRUE);
    gst_structure_set (gst_context_writable_structure (context),
                       "handle", G_TYPE_POINTER, display, nullptr);
    return context;
}

#endif

GstBusSyncReply Player::processSyncMessage( GstMessage *message )
{
@@ -490,6 +516,15 @@ GstBusSyncReply Player::processSyncMessage( GstMessage *message )
                gst_video_overlay_set_window_handle( mpXOverlay, mnWindowID );
            return GST_BUS_DROP;
        }
#ifndef AVMEDIA_GST_0_10
        else if (lcl_is_wayland_display_handle_need_context_message(message))
        {
            GstContext *context = lcl_wayland_display_handle_context_new(mpDisplay);
            gst_element_set_context(GST_ELEMENT(GST_MESSAGE_SRC(message)), context);

            return GST_BUS_DROP;
        }
#endif
    }

#ifdef AVMEDIA_GST_0_10
@@ -888,7 +923,6 @@ awt::Size SAL_CALL Player::getPreferredPlayerWindowSize()
    return aSize;
}


uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( const uno::Sequence< uno::Any >& rArguments )
{
    ::osl::MutexGuard aGuard(m_aMutex);
@@ -916,9 +950,13 @@ uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( co
            OSL_ASSERT(pEnvData);
            if (pEnvData)
            {
                OUString aToolkit = OUString::createFromAscii(pEnvData->pToolkit);
                OUString aPlatform = OUString::createFromAscii(pEnvData->pPlatformName);

                GstElement *pVideosink = nullptr;
#if defined(ENABLE_GTKSINK)
                GstElement *pVideosink = g_strcmp0(pEnvData->pToolkit, "gtk3") == 0 ?
                                           gst_element_factory_make("gtksink", "gtksink") : nullptr;
                pVideosink = (aToolkit == "gtk3") ?
                              gst_element_factory_make("gtksink", "gtksink") : nullptr;
                if (pVideosink)
                {
                    mbUseGtkSink = true;
@@ -936,14 +974,24 @@ uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( co
                else
#endif
                {
                    if (aPlatform == "wayland")
                        pVideosink = gst_element_factory_make("waylandsink", "video-output");
                    else
                        pVideosink = gst_element_factory_make("autovideosink", "video-output");
                    if (!pVideosink)
                    {
                        xRet.clear();
                        return nullptr;
                    }
                    g_object_set(G_OBJECT(mpPlaybin), "video-sink", pVideosink, nullptr);
                    mbUseGtkSink = false;
                    mnWindowID = pEnvData->aWindow;
                    mpDisplay = pEnvData->pDisplay;
                    SAL_INFO( "avmedia.gstreamer", AVVERSION "set window id to " << static_cast<int>(mnWindowID) << " XOverlay " << mpXOverlay);
                    gst_element_set_state( mpPlaybin, GST_STATE_PAUSED );
                    if ( mpXOverlay != nullptr )
                        gst_video_overlay_set_window_handle( mpXOverlay, mnWindowID );
                }

            }
        }
    }
@@ -951,7 +999,6 @@ uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( co
    return xRet;
}


uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber()
{
    ::osl::MutexGuard aGuard(m_aMutex);
diff --git a/avmedia/source/gstreamer/gstplayer.hxx b/avmedia/source/gstreamer/gstplayer.hxx
index 1af1ae8..6db9bc5 100644
--- a/avmedia/source/gstreamer/gstplayer.hxx
+++ b/avmedia/source/gstreamer/gstplayer.hxx
@@ -95,6 +95,7 @@ private:
    bool                    mbLooping;
    bool                    mbInitialized;

    void*                   mpDisplay;
    long                    mnWindowID;
    GstVideoOverlay*        mpXOverlay;
    gint64                  mnDuration;
diff --git a/include/vcl/sysdata.hxx b/include/vcl/sysdata.hxx
index 794f424..cc94ff4 100644
--- a/include/vcl/sysdata.hxx
+++ b/include/vcl/sysdata.hxx
@@ -73,6 +73,7 @@ struct SystemEnvData
    // however, the GTK3 vclplug wants to store pointers in here!
    sal_IntPtr          aShellWindow;   // the window of the frame's shell
    const char*         pToolkit;       // the toolkit in use (gtk2 vs gtk3)
    const char*         pPlatformName; // the windowing system in use (xcb vs wayland)
#endif

    SystemEnvData()
@@ -93,6 +94,7 @@ struct SystemEnvData
        , nScreen(0)
        , aShellWindow(0)
        , pToolkit(nullptr)
        , pPlatformName(nullptr)
#endif
    {
    }
diff --git a/vcl/qt5/Qt5Frame.cxx b/vcl/qt5/Qt5Frame.cxx
index 9f8be0a..069fa53 100644
--- a/vcl/qt5/Qt5Frame.cxx
+++ b/vcl/qt5/Qt5Frame.cxx
@@ -155,12 +155,34 @@ Qt5Frame::Qt5Frame(Qt5Frame* pParent, SalFrameStyleFlags nStyle, bool bUseCairo)
    }

    m_aSystemData.nSize = sizeof(SystemEnvData);
    m_aSystemData.aWindow = m_pQWidget->winId();

    // Calling 'QWidget::winId()' implicitly enables native windows to be used
    // rather than "alien widgets" that are unknown to the windowing system,
    // s. https://doc.qt.io/qt-5/qwidget.html#native-widgets-vs-alien-widgets
    // Avoid this on Wayland due to problems with missing 'mouseMoveEvent's,
    // s. tdf#122293/QTBUG-75766
    const bool bWayland = QGuiApplication::platformName() == "wayland";
    if (!bWayland)
        m_aSystemData.aWindow = m_pQWidget->winId();
    else
    {
        // TODO implement as needed for Wayland,
        // s.a. commit c0d4f3ad3307c which did this for gtk3
        // QPlatformNativeInterface* native = QGuiApplication::platformNativeInterface();
        // m_aSystemData.pDisplay = native->nativeResourceForWindow("display", nullptr);
        // m_aSystemData.aWindow = reinterpret_cast<unsigned long>(
        //     native->nativeResourceForWindow("surface", m_pQWidget->windowHandle()));
    }

    m_aSystemData.aShellWindow = reinterpret_cast<sal_IntPtr>(this);
    //m_aSystemData.pSalFrame = this;
    //m_aSystemData.pWidget = m_pQWidget;
    //m_aSystemData.nScreen = m_nXScreen.getXScreen();
    m_aSystemData.pToolkit = "qt5";
    if (!bWayland)
        m_aSystemData.pPlatformName = "xcb";
    else
        m_aSystemData.pPlatformName = "wayland";

    SetIcon(SV_ICON_ID_OFFICE);
}
diff --git a/vcl/qt5/Qt5Object.cxx b/vcl/qt5/Qt5Object.cxx
index 499cf190..d9ef910 100644
--- a/vcl/qt5/Qt5Object.cxx
+++ b/vcl/qt5/Qt5Object.cxx
@@ -23,6 +23,7 @@
#include <Qt5Frame.hxx>

#include <QtWidgets/QWidget>
#include <QtGui/QGuiApplication>
#include <QtGui/QWindow>

Qt5Object::Qt5Object(Qt5Frame* pParent, bool bShow)
@@ -40,12 +41,28 @@ Qt5Object::Qt5Object(Qt5Frame* pParent, bool bShow)
        m_pQWidget->show();

    m_aSystemData.nSize = sizeof(SystemEnvData);
    m_aSystemData.aWindow = m_pQWindow->winId(); // ID of the embedded window
    m_aSystemData.aShellWindow = reinterpret_cast<sal_IntPtr>(this);
    //m_aSystemData.pSalFrame = this;
    //m_aSystemData.pWidget = m_pQWidget;
    //m_aSystemData.nScreen = m_nXScreen.getXScreen();
    m_aSystemData.pToolkit = "qt5";
    m_aSystemData.pPlatformName = "xcb";
    const bool bWayland = QGuiApplication::platformName() == "wayland";
    if (!bWayland)
    {
        m_aSystemData.pPlatformName = "xcb";
        m_aSystemData.aWindow = m_pQWindow->winId(); // ID of the embedded window
    }
    else
    {
        m_aSystemData.pPlatformName = "wayland";
        // TODO implement as needed for Wayland,
        // s.a. commit c0d4f3ad3307c which did this for gtk3
        // QPlatformNativeInterface* native = QGuiApplication::platformNativeInterface();
        // m_aSystemData.pDisplay = native->nativeResourceForWindow("display", nullptr);
        // m_aSystemData.aWindow = reinterpret_cast<unsigned long>(
        //     native->nativeResourceForWindow("surface", m_pQWidget->windowHandle()));
    }
}

void Qt5Object::ResetClipRegion()
diff --git a/vcl/unx/gtk/gtkobject.cxx b/vcl/unx/gtk/gtkobject.cxx
index 38d4c1a..3e00174 100644
--- a/vcl/unx/gtk/gtkobject.cxx
+++ b/vcl/unx/gtk/gtkobject.cxx
@@ -61,6 +61,7 @@ GtkSalObject::GtkSalObject( GtkSalFrame* pParent, bool bShow )
    m_aSystemData.pWidget       = m_pSocket;
    m_aSystemData.nScreen       = pParent->getXScreenNumber().getXScreen();
    m_aSystemData.pToolkit      = "gtk2";
    m_aSystemData.pPlatformName = "xcb";

    g_signal_connect( G_OBJECT(m_pSocket), "button-press-event", G_CALLBACK(signalButton), this );
    g_signal_connect( G_OBJECT(m_pSocket), "button-release-event", G_CALLBACK(signalButton), this );
diff --git a/vcl/unx/gtk/gtksalframe.cxx b/vcl/unx/gtk/gtksalframe.cxx
index 1499af9..b162b5c 100644
--- a/vcl/unx/gtk/gtksalframe.cxx
+++ b/vcl/unx/gtk/gtksalframe.cxx
@@ -999,6 +999,7 @@ void GtkSalFrame::InitCommon()
    m_aSystemData.pWidget       = m_pWindow;
    m_aSystemData.nScreen       = m_nXScreen.getXScreen();
    m_aSystemData.pToolkit      = "gtk2";
    m_aSystemData.pPlatformName = "xcb";

    m_bGraphics = false;
    m_pGraphics = nullptr;
diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx
index 184102e..2127a52 100644
--- a/vcl/unx/gtk3/gtk3gtkframe.cxx
+++ b/vcl/unx/gtk3/gtk3gtkframe.cxx
@@ -1115,6 +1115,14 @@ void GtkSalFrame::InitCommon()
    {
        m_aSystemData.pDisplay = gdk_x11_display_get_xdisplay(pDisplay);
        m_aSystemData.pVisual = gdk_x11_visual_get_xvisual(pVisual);
        m_aSystemData.pPlatformName = "xcb";
    }
#endif
#if defined(GDK_WINDOWING_WAYLAND)
    if (DLSYM_GDK_IS_WAYLAND_DISPLAY(pDisplay))
    {
        m_aSystemData.pDisplay = gdk_wayland_display_get_wl_display(pDisplay);
        m_aSystemData.pPlatformName = "wayland";
    }
#endif

diff --git a/vcl/unx/gtk3/gtk3gtkobject.cxx b/vcl/unx/gtk3/gtk3gtkobject.cxx
index 33fd6d0..70b5c86 100644
--- a/vcl/unx/gtk3/gtk3gtkobject.cxx
+++ b/vcl/unx/gtk3/gtk3gtkobject.cxx
@@ -64,6 +64,14 @@ GtkSalObject::GtkSalObject( GtkSalFrame* pParent, bool bShow )
    {
        m_aSystemData.pDisplay = gdk_x11_display_get_xdisplay(pDisplay);
        m_aSystemData.pVisual = gdk_x11_visual_get_xvisual(pVisual);
        m_aSystemData.pPlatformName = "xcb";
    }
#endif
#if defined(GDK_WINDOWING_WAYLAND)
    if (DLSYM_GDK_IS_WAYLAND_DISPLAY(pDisplay))
    {
        m_aSystemData.pDisplay = gdk_wayland_display_get_wl_display(pDisplay);
        m_aSystemData.pPlatformName = "wayland";
    }
#endif