1313* limitations under the License.
1414*/
1515#include < bb/cascades/Application>
16- #include < bb/cascades/ForeignWindow >
16+ #include < bb/cascades/ForeignWindowControl >
1717#include < bb/cascades/Container>
1818#include < bb/cascades/StackLayout>
1919#include < bb/cascades/DockLayout>
20- #include < bb/cascades/DockLayoutProperties>
20+ #include < bb/cascades/LayoutProperties>
21+ #include < bb/cascades/WindowProperty>
2122#include < bb/cascades/Button>
2223#include < bb/cascades/Page>
2324
2930
3031using namespace bb ::cascades;
3132
33+ // define this to debug the ForeignWindowControl race condition
34+ #define BREAK_FWC
35+ // define this to enable a workaround for the above race condition
36+ #define WORKAROUND_FWC
37+
3238HelloCameraApp::HelloCameraApp () :
3339 mCameraHandle(CAMERA_HANDLE_INVALID)
3440{
3541 qDebug () << " HelloCameraApp" ;
3642
3743 // create our foreign window
38- // Using .id() in the builder is equivalent to mViewfinderWindow->setWindowId()
39- mViewfinderWindow = ForeignWindow::create ()
40- .id (QString (" cameraViewfinder" ));
41- // NOTE that there is a bug in ForeignWindow in 10.0.6 whereby the
42- // SCREEN_PROPERTY_SOURCE_SIZE is updated when windows are attached.
43- // We don't want this to happen, so we are disabling WindowFrameUpdates.
44- // What this means is that if the ForeignWindow geometry is changed, then
45- // the underlying screen window properties are not automatically updated to
46- // match. You will have to manually do so by listening for controlFrameChanged
47- // signals. This is outside of the scope of this sample.
48- mViewfinderWindow ->setWindowFrameUpdateEnabled (false );
49-
50- QObject::connect (mViewfinderWindow ,
51- SIGNAL (windowAttached (unsigned long ,
52- const QString &, const QString &)),
53- this ,
54- SLOT (onWindowAttached (unsigned long ,
55- const QString &,const QString &)));
44+ mViewfinderWindow = ForeignWindowControl::create ()
45+ .windowId (QString (" cameraViewfinder" ));
46+ // Allow Cascades to update the native window's size, position, and visibility, but not the source-size.
47+ // Cascades may otherwise attempt to redefine the buffer source-size to match the window size, which would yield
48+ // undesirable results. You can experiment with this if you want to see what I mean.
49+ mViewfinderWindow ->setUpdatedProperties (WindowProperty::Position | WindowProperty::Size | WindowProperty::Visible);
5650
57- // NOTE that there is a bug in ForeignWindow in 10.0.6 whereby
58- // when a window is detached, it's windowHandle is not reset to 0.
59- // We need to connect a detach handler to implement a workaround.
6051 QObject::connect (mViewfinderWindow ,
61- SIGNAL (windowDetached (unsigned long ,
62- const QString &, const QString &)),
63- this ,
64- SLOT (onWindowDetached (unsigned long ,
65- const QString &,const QString &)));
52+ SIGNAL (windowAttached (screen_window_t , const QString &, const QString &)),
53+ this , SLOT (onWindowAttached (screen_window_t , const QString &,const QString &)));
6654
6755 // create a bunch of camera control buttons
6856 // NOTE: some of these buttons are not initially visible
69- mStartFrontButton = Button::create (" Front Camera" );
70- mStartRearButton = Button::create (" Rear Camera" );
71- mStopButton = Button::create (" Stop Camera" );
57+ mStartFrontButton = Button::create (" Front Camera" )
58+ .onClicked (this , SLOT (onStartFront ()));
59+ mStartRearButton = Button::create (" Rear Camera" )
60+ .onClicked (this , SLOT (onStartRear ()));
61+ mStopButton = Button::create (" Stop Camera" )
62+ .onClicked (this , SLOT (onStopCamera ()));
7263 mStopButton ->setVisible (false );
73- mTakePictureButton = Button::create (" Take Picture" );
64+ mTakePictureButton = Button::create (" Take Picture" )
65+ .onClicked (this , SLOT (onTakePicture ()));
7466 mTakePictureButton ->setVisible (false );
75- // connect actions to the buttons
76- QObject::connect (mStartFrontButton ,
77- SIGNAL (clicked ()), this , SLOT (onStartFront ()));
78- QObject::connect (mStartRearButton ,
79- SIGNAL (clicked ()), this , SLOT (onStartRear ()));
80- QObject::connect (mStopButton ,
81- SIGNAL (clicked ()), this , SLOT (onStopCamera ()));
82- QObject::connect (mTakePictureButton ,
83- SIGNAL (clicked ()), this , SLOT (onTakePicture ()));
8467
8568 // note that since saving pictures happens in a different thread,
8669 // we need to use a signal/slot in order to re-enable the 'take picture' button.
@@ -92,22 +75,20 @@ HelloCameraApp::HelloCameraApp() :
9275 Container* container = Container::create ()
9376 .layout (DockLayout::create ())
9477 .add (Container::create ()
95- .layoutProperties (DockLayoutProperties::create ()
96- .horizontal (HorizontalAlignment::Center)
97- .vertical (VerticalAlignment::Center))
78+ .horizontal (HorizontalAlignment::Center)
79+ .vertical (VerticalAlignment::Center)
9880 .add (mViewfinderWindow ))
9981 .add (Container::create ()
100- .layoutProperties (DockLayoutProperties::create ()
101- .horizontal (HorizontalAlignment::Center)
102- .vertical (VerticalAlignment::Bottom))
82+ .horizontal (HorizontalAlignment::Center)
83+ .vertical (VerticalAlignment::Bottom)
10384 .layout (StackLayout::create ()
104- .direction (LayoutDirection ::LeftToRight))
85+ .orientation (LayoutOrientation ::LeftToRight))
10586 .add (mStartFrontButton )
10687 .add (mStartRearButton )
10788 .add (mTakePictureButton )
10889 .add (mStopButton ));
10990
110- Application::setScene (Page::create ().content (container));
91+ Application::instance ()-> setScene (Page::create ().content (container));
11192}
11293
11394
@@ -117,42 +98,28 @@ HelloCameraApp::~HelloCameraApp()
11798}
11899
119100
120- void HelloCameraApp::onWindowAttached (unsigned long handle ,
101+ void HelloCameraApp::onWindowAttached (screen_window_t win ,
121102 const QString &group,
122103 const QString &id)
123104{
124- qDebug () << " onWindowAttached: " << handle << " , " << group << " , " << id;
125- screen_window_t win = (screen_window_t )handle;
105+ #ifdef BREAK_FWC
106+ // typically a value of 1ms will cause the window to only be visible the
107+ // first time you start it. on subsequent invocations, it does not become visible
108+ // unless you force a refresh of the cascades window.
109+ // a value of 10 ms seems to expose the problem every time.
110+ usleep (10000 );
111+ #endif
112+ qDebug () << " onWindowAttached: " << win << " , " << group << " , " << id;
126113 // set screen properties to mirror if this is the front-facing camera
127114 int i = (mCameraUnit == CAMERA_UNIT_FRONT);
128115 screen_set_window_property_iv (win, SCREEN_PROPERTY_MIRROR, &i);
129116 // put the viewfinder window behind the cascades window
130117 i = -1 ;
131118 screen_set_window_property_iv (win, SCREEN_PROPERTY_ZORDER, &i);
132- // make the window visible. by default, the camera creates an invisible
133- // viewfinder, so that the user can decide when and where to place it
134- i = 1 ;
135- screen_set_window_property_iv (win, SCREEN_PROPERTY_VISIBLE, &i);
136- // There is a bug in ForeignWindow in 10.0.6 which defers window context
137- // flushing until some future UI update. As a result, the window will
138- // not actually be visible until someone flushes the context. This is
139- // fixed in the next release. For now, we will just manually flush the
140- // window context.
141- screen_context_t ctx;
142- screen_get_window_property_pv (win, SCREEN_PROPERTY_CONTEXT, (void **)&ctx);
143- screen_flush_context (ctx, 0 );
144- }
145-
146-
147- void HelloCameraApp::onWindowDetached (unsigned long handle,
148- const QString &group,
149- const QString &id)
150- {
151- qDebug () << " onWindowDetached: " << handle << " , " << group << " , " << id;
152- // There is a bug in ForeignWindow in 10.0.6 whereby the windowHandle is not
153- // reset to 0 when a detach event happens. We must forcefully zero it here
154- // in order for a re-attach to work again in the future.
155- mViewfinderWindow ->setWindowHandle (0 );
119+ #ifdef WORKAROUND_FWC
120+ mViewfinderWindow ->setVisible (false );
121+ mViewfinderWindow ->setVisible (true );
122+ #endif
156123}
157124
158125
@@ -173,7 +140,6 @@ int HelloCameraApp::createViewfinder(camera_unit_t cameraUnit,
173140 return EIO;
174141 }
175142 qDebug () << " camera opened" ;
176- // configure viewfinder properties so our ForeignWindow can find the resulting screen window
177143 if (camera_set_photovf_property (mCameraHandle ,
178144 CAMERA_IMGPROP_WIN_GROUPID, group.toStdString ().c_str (),
179145 CAMERA_IMGPROP_WIN_ID, id.toStdString ().c_str ()) == CAMERA_EOK) {
@@ -259,6 +225,7 @@ void HelloCameraApp::onStartFront()
259225{
260226 qDebug () << " onStartFront" ;
261227 if (mViewfinderWindow ) {
228+ // create a window and see if we can catch the join
262229 if (createViewfinder (CAMERA_UNIT_FRONT,
263230 mViewfinderWindow ->windowGroup ().toStdString ().c_str (),
264231 mViewfinderWindow ->windowId ().toStdString ().c_str ()) == EOK) {
@@ -271,6 +238,7 @@ void HelloCameraApp::onStartRear()
271238{
272239 qDebug () << " onStartRear" ;
273240 if (mViewfinderWindow ) {
241+ // create a window and see if we can catch the join
274242 if (createViewfinder (CAMERA_UNIT_REAR,
275243 mViewfinderWindow ->windowGroup ().toStdString ().c_str (),
276244 mViewfinderWindow ->windowId ().toStdString ().c_str ()) == EOK) {
@@ -283,9 +251,8 @@ void HelloCameraApp::onStopCamera()
283251{
284252 qDebug () << " onStopCamera" ;
285253 if (mCameraHandle != CAMERA_HANDLE_INVALID) {
286- // NOTE that closing the camera causes the viewfinder to stop.
287- // When the viewfinder stops, it's window is destroyed and the
288- // ForeignWindow object will emit a windowDetached signal.
254+ // closing the camera handle causes the viewfinder to stop which will in turn
255+ // cause it to detach from the foreign window
289256 camera_close (mCameraHandle );
290257 mCameraHandle = CAMERA_HANDLE_INVALID;
291258 // reset button visibility
0 commit comments