Create the UI

Add the foreign window

In main.qml, we start by removing all existing code and creating a NavigationPane. The Page has a Container that fills the screen horizontally and vertically and contains our ForeignWindowControl.

On our ForeignWindowControl, we set an id and objectName so that we can access it from C++ and QML.

import bb.cascades 1.0

NavigationPane {
    Page {
        content: Container {
            id: back
            
            objectName: "back"           
            background: Color.create("#262626")
            horizontalAlignment: HorizontalAlignment.Fill
            verticalAlignment: VerticalAlignment.Fill
            
            layout: StackLayout {
                orientation: LayoutOrientation.TopToBottom
            }
            
            ForeignWindowControl {
                id: foreignWindow
                objectName: "myForeignWindow"
                visible: true
                
                horizontalAlignment: HorizontalAlignment.Fill
                verticalAlignment: VerticalAlignment.Fill
            }       
        }
    }    
}

Declare functions and variables

In applicationui.hpp, we need to declare the functions and variables that we use in our app. First, remove any existing include statements and include the following header files. MyView.hpp is a class that will defines our OpenGL ES view, which we create in the next section.

#include <QtCore/QObject>
#include <QtCore/QMetaType>

#include "MyView.h"
#include "OpenGLThread.hpp"

#include <bb/cascades/Application>
#include <bb/cascades/Event>
#include <bb/cascades/UiObject>
#include <bb/cascades/Control>
#include <bb/cascades/ForeignWindowControl>
#include <bb/cascades/LayoutUpdateHandler>
#include <bb/cascades/NavigationPane>
#include <bb/cascades/OrientationSupport>
#include <bb/cascades/UIOrientation>

Next, we replace the existing class declaration with a new declaration and declare a constructor and two slot functions. The shutdown() slot function overrides the existing QObject::shutdown() function that is used to shut down the thread. The onLayoutFrameChanged() slot function is used to respond to layout frame changes including the initial setup. This function is used to modify our view class in response to orientation changes.

using namespace bb::cascades;

class ApplicationUI : public QObject
{
    Q_OBJECT
public:
    ApplicationUI(bb::cascades::Application *app);
    virtual ~ApplicationUI() { }
private Q_SLOTS:
    void shutdown();
    void onLayoutFrameChanged(const QRectF &layoutFrame);

We define some member variables:

  • A Boolean called fwc_bound that indicates whether our ForeignWindowControl is bound or not
  • A pointer to a NavigationPane called navPane
  • A pointer to our ForeignWindowControl called foreignWindow
  • A pointer to our custom MyView class called myView
private:
    bool fwc_bound;
    NavigationPane *navPane;
    ForeignWindowControl *foreignWindow;
    MyView *myView;
};

Implement the main application class

In applicationui.cpp, remove the contents and add the following libraries.

#include <bb/cascades/AbsoluteLayout>
#include <bb/cascades/StackLayoutProperties>
#include <bb/cascades/Application>
#include <bb/cascades/Window>
#include <bb/cascades/Button>
#include <bb/cascades/Container>
#include <bb/cascades/Color>
#include <bb/cascades/ForeignWindowControl>
#include <bb/cascades/ImplicitAnimationController>
#include <bb/cascades/Page>
#include <bb/cascades/LayoutUpdateHandler>
#include <bb/cascades/NavigationPane>
#include <bb/cascades/QmlDocument>
#include <bb/cascades/SceneCover>

#include <QtCore/QTimer>
#include <QDebug>

#include "applicationui.hpp"

#include <screen/screen.h>

#include <GLES/gl.h>
#include <GLES/glext.h>
#include <EGL/egl.h>
#include <sys/strm.h>

using namespace bb::cascades;

In the constructor, connect the manualExit() signal to the shutdown() slot function that we declared in applicationui.hpp and turn off the auto exit property of the app.

ApplicationUI::ApplicationUI
    (bb::cascades::Application *app) :QObject(app)
{
    // Connect the manualExit() signal to the
    // shutdown() slot, which closes the app manually.

    bool result;
    Q_UNUSED(result);

	result = QObject::connect(
		Application::instance(),
		SIGNAL(manualExit()),
		this,
		SLOT(shutdown()));

    Q_ASSERT(result);

    // Set the autoExit() signal to false to control
    // the app's exit.

	Application::instance()->setAutoExit(false);

To avoid potential race conditions when your app exits, make sure that you connect a slot to the manualExit() signal before the auto exit flag is set to false.

We use the standard Cascades build pattern. If the QML file is error-free, set the rendering API to OpenGL ES 1.1 by using the static function setRenderingAPI(). Then we'll create our MyView instance by passing a DISPLAY_DEVICE enum specifying that we're using the device display (instead of an external display).

    QmlDocument *qml = QmlDocument::create("asset:///main.qml");

	if (!qml->hasErrors()) {
        OpenGLView::setRenderingAPI(GL_ES_1);

		myView = new MyView(DISPLAY_DEVICE);

	    qml->setContextProperty("myView", myView);

	    // The application NavigationPane is created from QML.
	    navPane = qml->createRootObject<NavigationPane>();
	    if (navPane) {

If the root NavigationPane is valid, set the our fwc_bound variable to false, and locate the ForeignWindowControl in the scene graph.

            fwc_bound = false;

            foreignWindow = navPane->
                findChild<ForeignWindowControl*>
                    ("myForeignWindow");

Next, add a LayoutUpdateHandler to your ForeignWindowControl, connect the layoutFrameChanged() signal to the onLayoutFrameChanged() slot, and connect the foreign window's touch event to the slots that handle touch events for the view class.

        LayoutUpdateHandler *handler = 
                    LayoutUpdateHandler::create(foreignWindow)
                        .onLayoutFrameChanged(this, 
                        SLOT(onLayoutFrameChanged(const QRectF &)));


	    	// connect ForeignWindowControl signals to slots
	    	QObject::connect(foreignWindow, 
                       SIGNAL(touch(bb::cascades::TouchEvent *)),
	    	           myView,   
                       SLOT(onTouch(bb::cascades::TouchEvent *)) );

	        // The main scene for the application is set the Page.
	        Application::instance()->setScene(navPane);
	     }//if navPane is valid
	 }//if QML has no errors   
}//constructor

The shutdown() function calls shutdown() on the OpenGLView object, and calls quit() on the application instance. This is necessary for the OpenGLView class to properly shut down rendering in the OpenGLThread class and the app itself.

void ApplicationUI::shutdown() {

	OpenGLView::shutdown();

	Application::instance()->quit();
}

Next, we need to define the onLayoutFrameChanged() slot. We need to check if this is the first time this function is called by checking the value of fwc_bound to see if it's false. If fwc_bound is false, it's our first time running this slot function, so we set the window group and window ID so that the ForeignWindowControl is bound to the Screen window.

Then we'll set the size and position using the setSize() and setPosition() functions from our view class. We can add this view class to the collection of views in the OpenGLThread, and set the view to enabled. We also set the ForeignWindowControl visibility to true.

void ApplicationUI::onLayoutFrameChanged(const QRectF &layoutFrame) {
	if (fwc_bound == false) {
		fwc_bound = true;

        //obtain the window group
		QString mainWindowGroupId = 
            Application::instance()->
            mainWindow()->groupId();

		myView->setWindowGroup(mainWindowGroupId);
		myView->setWindowID("MyView");
		myView->setPosition(layoutFrame.x(), 
                                  layoutFrame.y());
		myView->setSize(layoutFrame.width(), 
                              layoutFrame.height());
		myView->add();
		myView->setEnabled(true);
		foreignWindow->setVisible(true);
	

If the ForeignWindowControl is already bound, we've run this function before. In that case, we update the angle, size, and position of the Screen window and ForeignWindowControl. This completes our onLayoutFrameChanged() slot function.

    } else {
		myView->setAngle
            (OrientationSupport::instance()->
                displayDirection());
		myView->setPosition(layoutFrame.x(),
                                  layoutFrame.y());
		myView->setSize(layoutFrame.width(),
                              layoutFrame.height());
		myView->setAltered(true);
	}
}

Last modified: 2015-03-31



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus