XOverlay on a QDeclarativeItem
-
Hello,
I need to set up an XOverlay in my QML app. My current solution is to show a QWidget in the background and my QDeclarativeView with a transparent background in the foreground. That way I can use QML for the UI and control the position and geometry of the QWidget in the background. The Window ID of the QWidget is passed to the video app to set up the XOverlay.
Is it possible to create a QML component that inherits QWidget so I can get a Window ID?
I have tried making the QWidget a child of the QDeclarativeView and vice versa. When I do that, I can't get the DeclarativeView in the foreground with transparent background. The QWidget always winds up in front.
Any advice appreciated!
Thanks,
Matt -
Here's some code to create a test pattern in an overlay. Usage: ./overlay 1287463 # <-- window ID
overlay.pro
@#-------------------------------------------------Project created by QtCreator 2010-11-09T17:20:52
#-------------------------------------------------
QT += core gui
TARGET = overlay
TEMPLATE = appSOURCES += main.cpp
HEADERS +=
FORMS +=
INCLUDEPATH += /usr/include
CONFIG += link_pkgconfig
PKGCONFIG += glib-2.0 gstreamer-0.10 gstreamer-interfaces-0.10
@main.cpp
@#include <glib.h>
#include <gst/gst.h>
#include <gst/interfaces/xoverlay.h>
#include <unistd.h>int main(int argc, char *argv[])
{
if (!g_thread_supported ())
g_thread_init (NULL);gst_init (&argc, &argv); // prepare the pipeline GstElement *pipeline = gst_pipeline_new ("xvoverlay"); GstElement *src = gst_element_factory_make ("videotestsrc", NULL); GstElement *sink = gst_element_factory_make ("xvimagesink", NULL); gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL); gst_element_link (src, sink); int xwinid = atoi(argv[1]); //109051906; //0x05c00002; // window.winId(); //gst_x_overlay_set_window_handle (GST_X_OVERLAY (sink), xwinid); gst_x_overlay_set_xwindow_id(GST_X_OVERLAY (sink), xwinid); // run the pipeline GstStateChangeReturn sret = gst_element_set_state (pipeline, GST_STATE_PLAYING); if (sret == GST_STATE_CHANGE_FAILURE) { gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); exit(1); } while(1) { sleep(30); } gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); return 0;
}
@ -
In a Qt app:
test.pro
@
QT += core gui declarative
TARGET = test
TEMPLATE = app
SOURCES += main.cpp
OTHER_FILES +=
main.qml
@main.cpp
@
#include <QtGui/QApplication>
#include <QDeclarativeView>
#include <QDebug>int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QDeclarativeView view;
view.setSource(QUrl("main.qml"));
QWidget *overlay = new QWidget(&view);
overlay->move(0,0);
overlay->resize(640, 480);
overlay->lower();view.move(0,0); view.show(); qDebug() << "Run ./overlay " << overlay->winId(); return a.exec();
}
@main.qml
@import Qt 4.7Item {
width: 640
height: 480Rectangle { width: 50 height: 50 color: "red" MouseArea { anchors.fill: parent onClicked: { console.log("clicked") } } }
}
@ -
If you build the QML app and run it, you will see a debug output like "Run ./overlay 12345" Go over to your overlay build, and run that command. The Qt app will be replaced with the test pattern, but you can still click the little Rectangle in the GUI.
In the Qt app, I even try to lower the overlay QWidget at line 13, but still the XOverlay covers the entire window. I want the little red rectangle from main.qml to be on top of the overlay QWidget.
For now, I am calling overlay->show() as an independent window, so I wind up with two windows for my app. That works, but it would be great to have the overlay inside Qt Quick so I could use state transitions and animations on its size and shape.
Let me know if you figure something out!
Regards,
Matt