summaryrefslogtreecommitdiffstats
path: root/src/plugins/position
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2016-01-26 14:25:06 +0100
committerLiang Qi <liang.qi@theqtcompany.com>2016-01-26 14:25:06 +0100
commitc6a28570a7300788127117378eb7cd36dcd0953f (patch)
treeb8e56b1bd18fb4438de171004d588d12dbf7abec /src/plugins/position
parente9ead74ec4169d483de0b711986b5b560bbb730a (diff)
parent24e50e40caaa2f2e057180b8ed8179795e605e2a (diff)
Merge remote-tracking branch 'origin/5.6' into dev
Diffstat (limited to 'src/plugins/position')
-rw-r--r--src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java102
-rw-r--r--src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp16
-rw-r--r--src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp327
-rw-r--r--src/plugins/position/winrt/qgeopositioninfosource_winrt_p.h29
-rw-r--r--src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.cpp8
-rw-r--r--src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.h2
-rw-r--r--src/plugins/position/winrt/winrt.pro4
7 files changed, 322 insertions, 166 deletions
diff --git a/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java b/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java
index 4723a805..43767f0e 100644
--- a/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java
+++ b/src/plugins/position/android/jar/src/org/qtproject/qt5/android/positioning/QtPositioning.java
@@ -179,6 +179,58 @@ public class QtPositioning implements LocationListener
return false;
}
+
+ static private void addActiveListener(QtPositioning listener, String provider)
+ {
+ int androidClassKey = listener.nativeClassReference;
+ //start update thread
+ listener.setActiveLooper(true);
+
+ if (runningListeners.containsKey(androidClassKey) && runningListeners.get(androidClassKey) != listener) {
+ removeActiveListener(androidClassKey);
+ }
+
+ locationManager.requestSingleUpdate(provider,
+ listener,
+ listener.looper());
+
+ runningListeners.put(androidClassKey, listener);
+ }
+
+
+ static private void addActiveListener(QtPositioning listener, String provider, long minTime, float minDistance)
+ {
+ int androidClassKey = listener.nativeClassReference;
+ //start update thread
+ listener.setActiveLooper(true);
+
+ if (runningListeners.containsKey(androidClassKey) && runningListeners.get(androidClassKey) != listener) {
+ removeActiveListener(androidClassKey);
+ }
+
+ locationManager.requestLocationUpdates(provider,
+ minTime, minDistance,
+ listener,
+ listener.looper());
+
+ runningListeners.put(androidClassKey, listener);
+ }
+
+
+ static private void removeActiveListener(QtPositioning listener)
+ {
+ removeActiveListener(listener.nativeClassReference);
+ }
+
+
+ static private void removeActiveListener(int androidClassKey)
+ {
+ QtPositioning listener = runningListeners.remove(androidClassKey);
+ locationManager.removeUpdates(listener);
+ listener.setActiveLooper(false);
+ }
+
+
static public int startUpdates(int androidClassKey, int locationProvider, int updateInterval)
{
synchronized (m_syncObject) {
@@ -188,8 +240,6 @@ public class QtPositioning implements LocationListener
positioningListener.nativeClassReference = androidClassKey;
positioningListener.expectedProviders = locationProvider;
positioningListener.isSatelliteUpdate = false;
- //start update thread
- positioningListener.setActiveLooper(true);
if (updateInterval == 0)
updateInterval = 1000; //don't update more often than once per second
@@ -198,10 +248,9 @@ public class QtPositioning implements LocationListener
if ((locationProvider & QT_GPS_PROVIDER) > 0) {
Log.d(TAG, "Regular updates using GPS " + updateInterval);
try {
- locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
- updateInterval, 0,
- positioningListener,
- positioningListener.looper());
+ addActiveListener(positioningListener,
+ LocationManager.GPS_PROVIDER,
+ updateInterval, 0);
} catch (SecurityException se) {
se.printStackTrace();
exceptionOccurred = true;
@@ -211,18 +260,16 @@ public class QtPositioning implements LocationListener
if ((locationProvider & QT_NETWORK_PROVIDER) > 0) {
Log.d(TAG, "Regular updates using network " + updateInterval);
try {
- locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
- updateInterval, 0,
- positioningListener,
- positioningListener.looper());
+ addActiveListener(positioningListener,
+ LocationManager.NETWORK_PROVIDER,
+ updateInterval, 0);
} catch (SecurityException se) {
se.printStackTrace();
exceptionOccurred = true;
}
}
if (exceptionOccurred) {
- positioningListener.setActiveLooper(false);
- locationManager.removeUpdates(positioningListener);
+ removeActiveListener(positioningListener);
return QT_ACCESS_ERROR;
}
@@ -231,7 +278,6 @@ public class QtPositioning implements LocationListener
return QT_CLOSED_ERROR;
}
- runningListeners.put(androidClassKey, positioningListener);
} catch(Exception e) {
e.printStackTrace();
return QT_POSITION_UNKNOWN_SOURCE_ERROR;
@@ -246,9 +292,7 @@ public class QtPositioning implements LocationListener
synchronized (m_syncObject) {
try {
Log.d(TAG, "Stopping updates");
- QtPositioning listener = runningListeners.remove(androidClassKey);
- locationManager.removeUpdates(listener);
- listener.setActiveLooper(false);
+ removeActiveListener(androidClassKey);
} catch(Exception e) {
e.printStackTrace();
return;
@@ -266,15 +310,11 @@ public class QtPositioning implements LocationListener
positioningListener.isSingleUpdate = true;
positioningListener.expectedProviders = locationProvider;
positioningListener.isSatelliteUpdate = false;
- //start update thread
- positioningListener.setActiveLooper(true);
if ((locationProvider & QT_GPS_PROVIDER) > 0) {
Log.d(TAG, "Single update using GPS");
try {
- locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER,
- positioningListener,
- positioningListener.looper());
+ addActiveListener(positioningListener, LocationManager.GPS_PROVIDER);
} catch (SecurityException se) {
se.printStackTrace();
exceptionOccurred = true;
@@ -284,17 +324,14 @@ public class QtPositioning implements LocationListener
if ((locationProvider & QT_NETWORK_PROVIDER) > 0) {
Log.d(TAG, "Single update using network");
try {
- locationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER,
- positioningListener,
- positioningListener.looper());
+ addActiveListener(positioningListener, LocationManager.NETWORK_PROVIDER);
} catch (SecurityException se) {
se.printStackTrace();
exceptionOccurred = true;
}
}
if (exceptionOccurred) {
- positioningListener.setActiveLooper(false);
- locationManager.removeUpdates(positioningListener);
+ removeActiveListener(positioningListener);
return QT_ACCESS_ERROR;
}
@@ -304,7 +341,6 @@ public class QtPositioning implements LocationListener
return QT_CLOSED_ERROR;
}
- runningListeners.put(androidClassKey, positioningListener);
} catch(Exception e) {
e.printStackTrace();
return QT_POSITION_UNKNOWN_SOURCE_ERROR;
@@ -324,8 +360,6 @@ public class QtPositioning implements LocationListener
positioningListener.nativeClassReference = androidClassKey;
positioningListener.expectedProviders = 1; //always satellite provider
positioningListener.isSingleUpdate = isSingleRequest;
- //start update thread
- positioningListener.setActiveLooper(true);
if (updateInterval == 0)
updateInterval = 1000; //don't update more often than once per second
@@ -335,18 +369,15 @@ public class QtPositioning implements LocationListener
else
Log.d(TAG, "Regular updates for Satellites " + updateInterval);
try {
- locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
- updateInterval, 0,
- positioningListener,
- positioningListener.looper());
+ addActiveListener(positioningListener, LocationManager.GPS_PROVIDER,
+ updateInterval, 0);
} catch (SecurityException se) {
se.printStackTrace();
exceptionOccurred = true;
}
if (exceptionOccurred) {
- positioningListener.setActiveLooper(false);
- locationManager.removeUpdates(positioningListener);
+ removeActiveListener(positioningListener);
return QT_ACCESS_ERROR;
}
@@ -356,7 +387,6 @@ public class QtPositioning implements LocationListener
return QT_CLOSED_ERROR;
}
- runningListeners.put(androidClassKey, positioningListener);
} catch(Exception e) {
e.printStackTrace();
return QT_SATELLITE_UNKNOWN_SOURCE_ERROR;
diff --git a/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp b/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp
index c9b209e8..1d1a6f4f 100644
--- a/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp
+++ b/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp
@@ -42,6 +42,7 @@
#include <QtSerialPort/qserialport.h>
#include <QtSerialPort/qserialportinfo.h>
#include <QtCore/qloggingcategory.h>
+#include <QSet>
Q_LOGGING_CATEGORY(lcSerial, "qt.positioning.serialnmea")
@@ -70,16 +71,13 @@ NmeaSource::NmeaSource(QObject *parent)
}
// Try to find a well-known device.
+ QSet<int> supportedDevices;
+ supportedDevices << 0x67b; // GlobalSat (BU-353S4 and probably others)
+ supportedDevices << 0xe8d; // Qstarz MTK II
QString portName;
- for (int i = 0; i < ports.count(); ++i) {
- const QString candidatePortName = ports[i].portName();
- bool acceptThis = false;
-
- // GlobalSat (BU-353S4 and probably others)
- acceptThis |= ports[i].hasVendorIdentifier() && ports[i].vendorIdentifier() == 0x67b;
-
- if (acceptThis) {
- portName = candidatePortName;
+ foreach (const QSerialPortInfo& port, ports) {
+ if (port.hasVendorIdentifier() && supportedDevices.contains(port.vendorIdentifier())) {
+ portName = port.portName();
break;
}
}
diff --git a/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp b/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp
index 4e70cc07..5dbbacb5 100644
--- a/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp
+++ b/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp
@@ -37,75 +37,119 @@
#include "qgeopositioninfosource_winrt_p.h"
#include <QCoreApplication>
+#include <QMutex>
+#include <qfunctions_winrt.h>
+#include <private/qeventdispatcher_winrt_p.h>
+#include <functional>
#include <windows.system.h>
#include <windows.devices.geolocation.h>
+#include <windows.foundation.h>
#include <windows.foundation.collections.h>
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Devices::Geolocation;
using namespace ABI::Windows::Foundation;
-using namespace ABI::Windows::System;
+using namespace ABI::Windows::Foundation::Collections;
typedef ITypedEventHandler<Geolocator *, PositionChangedEventArgs *> GeoLocatorPositionHandler;
typedef ITypedEventHandler<Geolocator *, StatusChangedEventArgs *> GeoLocatorStatusHandler;
+typedef IAsyncOperationCompletedHandler<Geoposition*> PositionHandler;
+#if _MSC_VER >= 1900
+typedef IAsyncOperationCompletedHandler<GeolocationAccessStatus> AccessHandler;
+#endif
QT_BEGIN_NAMESPACE
-QGeoPositionInfoSourceWinrt::QGeoPositionInfoSourceWinrt(QObject *parent)
+Q_DECLARE_METATYPE(QGeoPositionInfo)
+
+class QGeoPositionInfoSourceWinRTPrivate {
+public:
+ ComPtr<IGeolocator> locator;
+ QTimer periodicTimer;
+ QTimer singleUpdateTimer;
+ QGeoPositionInfo lastPosition;
+ QGeoPositionInfoSource::Error positionError;
+ EventRegistrationToken statusToken;
+ EventRegistrationToken positionToken;
+ QMutex mutex;
+ bool updatesOngoing;
+};
+
+
+QGeoPositionInfoSourceWinRT::QGeoPositionInfoSourceWinRT(QObject *parent)
: QGeoPositionInfoSource(parent)
- , m_positionError(QGeoPositionInfoSource::NoError)
- , m_updatesOngoing(false)
+ , d_ptr(new QGeoPositionInfoSourceWinRTPrivate)
{
- HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Devices_Geolocation_Geolocator).Get(),
- &m_locator);
+ Q_D(QGeoPositionInfoSourceWinRT);
+ d->positionError = QGeoPositionInfoSource::NoError;
+ d->updatesOngoing = false;
+
+ qRegisterMetaType<QGeoPositionInfo>();
+
+ requestAccess();
+ HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
+ HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Devices_Geolocation_Geolocator).Get(),
+ &d->locator);
+ RETURN_HR_IF_FAILED("Could not initialize native location services.");
+
+ // StatusChanged throws an exception on Windows 8.1
+#if _MSC_VER >= 1900
+ hr = d->locator->add_StatusChanged(Callback<GeoLocatorStatusHandler>(this,
+ &QGeoPositionInfoSourceWinRT::onStatusChanged).Get(),
+ &d->statusToken);
+ RETURN_HR_IF_FAILED("Could not add status callback.");
+#endif
- if (FAILED(hr)) {
- setError(QGeoPositionInfoSource::UnknownSourceError);
- qErrnoWarning(hr, "Could not initialize native location services");
- return;
- }
+ hr = d->locator->put_ReportInterval(1000);
+ RETURN_HR_IF_FAILED("Could not initialize report interval.");
- hr = m_locator->put_ReportInterval(minimumUpdateInterval());
- if (FAILED(hr)) {
- setError(QGeoPositionInfoSource::UnknownSourceError);
- qErrnoWarning(hr, "Could not initialize report interval");
- return;
- }
- hr = m_locator->put_DesiredAccuracy(PositionAccuracy::PositionAccuracy_High);
+ return hr;
+ });
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = d->locator->put_DesiredAccuracy(PositionAccuracy::PositionAccuracy_Default);
if (FAILED(hr)) {
setError(QGeoPositionInfoSource::UnknownSourceError);
- qErrnoWarning(hr, "Could not initialize desired accuracy");
+ qErrnoWarning(hr, "Could not initialize desired accuracy.");
return;
}
- m_positionToken.value = 0;
+ d->positionToken.value = 0;
- m_periodicTimer.setSingleShot(true);
- m_periodicTimer.setInterval(minimumUpdateInterval());
- connect(&m_periodicTimer, SIGNAL(timeout()), this, SLOT(virtualPositionUpdate()));
+ d->periodicTimer.setSingleShot(true);
+ d->periodicTimer.setInterval(minimumUpdateInterval());
+ connect(&d->periodicTimer, &QTimer::timeout, this, &QGeoPositionInfoSourceWinRT::virtualPositionUpdate);
- m_singleUpdateTimer.setSingleShot(true);
- connect(&m_singleUpdateTimer, SIGNAL(timeout()), this, SLOT(singleUpdateTimeOut()));
+ d->singleUpdateTimer.setSingleShot(true);
+ connect(&d->singleUpdateTimer, &QTimer::timeout, this, &QGeoPositionInfoSourceWinRT::singleUpdateTimeOut);
setPreferredPositioningMethods(QGeoPositionInfoSource::AllPositioningMethods);
+
+ connect(this, &QGeoPositionInfoSourceWinRT::nativePositionUpdate, this, &QGeoPositionInfoSourceWinRT::updateSynchronized);
}
-QGeoPositionInfoSourceWinrt::~QGeoPositionInfoSourceWinrt()
+QGeoPositionInfoSourceWinRT::~QGeoPositionInfoSourceWinRT()
{
}
-QGeoPositionInfo QGeoPositionInfoSourceWinrt::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const
+QGeoPositionInfo QGeoPositionInfoSourceWinRT::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const
{
+ Q_D(const QGeoPositionInfoSourceWinRT);
Q_UNUSED(fromSatellitePositioningMethodsOnly)
- return m_lastPosition;
+ return d->lastPosition;
}
-QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSourceWinrt::supportedPositioningMethods() const
+QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSourceWinRT::supportedPositioningMethods() const
{
+ Q_D(const QGeoPositionInfoSourceWinRT);
+
PositionStatus status;
- HRESULT hr = m_locator->get_LocationStatus(&status);
+ HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([d, &status]() {
+ HRESULT hr = d->locator->get_LocationStatus(&status);
+ return hr;
+ });
if (FAILED(hr))
return QGeoPositionInfoSource::NoPositioningMethods;
@@ -119,88 +163,94 @@ QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSourceWinrt::supporte
return QGeoPositionInfoSource::AllPositioningMethods;
}
-void QGeoPositionInfoSourceWinrt::setPreferredPositioningMethods(QGeoPositionInfoSource::PositioningMethods methods)
+void QGeoPositionInfoSourceWinRT::setPreferredPositioningMethods(QGeoPositionInfoSource::PositioningMethods methods)
{
+ Q_D(QGeoPositionInfoSourceWinRT);
+
PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods();
QGeoPositionInfoSource::setPreferredPositioningMethods(methods);
if (previousPreferredPositioningMethods == preferredPositioningMethods())
return;
- bool needsRestart = m_positionToken.value != 0;
+ bool needsRestart = d->positionToken.value != 0;
if (needsRestart)
stopHandler();
- HRESULT hr;
- if (methods & PositioningMethod::SatellitePositioningMethods)
- hr = m_locator->put_DesiredAccuracy(PositionAccuracy::PositionAccuracy_High);
- else
- hr = m_locator->put_DesiredAccuracy(PositionAccuracy::PositionAccuracy_Default);
-
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Could not set positioning accuracy");
- return;
- }
+ PositionAccuracy acc = methods & PositioningMethod::SatellitePositioningMethods ?
+ PositionAccuracy::PositionAccuracy_High :
+ PositionAccuracy::PositionAccuracy_Default;
+ HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([d, acc]() {
+ HRESULT hr = d->locator->put_DesiredAccuracy(acc);
+ return hr;
+ });
+ RETURN_VOID_IF_FAILED("Could not set positioning accuracy.");
if (needsRestart)
startHandler();
}
-void QGeoPositionInfoSourceWinrt::setUpdateInterval(int msec)
+void QGeoPositionInfoSourceWinRT::setUpdateInterval(int msec)
{
- // Windows Phone does not support 0 interval
-#ifdef Q_OS_WINPHONE
+ Q_D(QGeoPositionInfoSourceWinRT);
+ // Windows Phone 8.1 and Windows 10 do not support 0 interval
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
if (msec == 0)
msec = minimumUpdateInterval();
#endif
+
// If msec is 0 we send updates as data becomes available, otherwise we force msec to be equal
// to or larger than the minimum update interval.
if (msec != 0 && msec < minimumUpdateInterval())
msec = minimumUpdateInterval();
- HRESULT hr = m_locator->put_ReportInterval(msec);
+ HRESULT hr = d->locator->put_ReportInterval(msec);
if (FAILED(hr)) {
setError(QGeoPositionInfoSource::UnknownSourceError);
qErrnoWarning(hr, "Failed to set update interval");
return;
}
- if (msec != 0)
- m_periodicTimer.setInterval(msec);
- else
- m_periodicTimer.setInterval(minimumUpdateInterval());
+
+ d->periodicTimer.setInterval(qMax(msec, minimumUpdateInterval()));
QGeoPositionInfoSource::setUpdateInterval(msec);
}
-int QGeoPositionInfoSourceWinrt::minimumUpdateInterval() const
+int QGeoPositionInfoSourceWinRT::minimumUpdateInterval() const
{
// We use one second to reduce potential timer events
// in case the platform itself stops reporting
return 1000;
}
-void QGeoPositionInfoSourceWinrt::startUpdates()
+void QGeoPositionInfoSourceWinRT::startUpdates()
{
- if (m_updatesOngoing)
+ Q_D(QGeoPositionInfoSourceWinRT);
+
+ if (d->updatesOngoing)
return;
if (!startHandler())
return;
- m_updatesOngoing = true;
- m_periodicTimer.start();
+ d->updatesOngoing = true;
+ d->periodicTimer.start();
}
-void QGeoPositionInfoSourceWinrt::stopUpdates()
+void QGeoPositionInfoSourceWinRT::stopUpdates()
{
+ Q_D(QGeoPositionInfoSourceWinRT);
+
stopHandler();
- m_updatesOngoing = false;
- m_periodicTimer.stop();
+ d->updatesOngoing = false;
+ d->periodicTimer.stop();
}
-bool QGeoPositionInfoSourceWinrt::startHandler()
+bool QGeoPositionInfoSourceWinRT::startHandler()
{
+ Q_D(QGeoPositionInfoSourceWinRT);
+
// Check if already attached
- if (m_positionToken.value != 0)
+ if (d->positionToken.value != 0)
return true;
if (preferredPositioningMethods() == QGeoPositionInfoSource::NoPositioningMethods) {
@@ -208,31 +258,49 @@ bool QGeoPositionInfoSourceWinrt::startHandler()
return false;
}
- if (!checkNativeState())
+ if (!requestAccess() || !checkNativeState())
return false;
- HRESULT hr = m_locator->add_PositionChanged(Callback<GeoLocatorPositionHandler>(this,
- &QGeoPositionInfoSourceWinrt::onPositionChanged).Get(),
- &m_positionToken);
+ HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
+ HRESULT hr;
+ // We need to call this at least once on Windows 10 Mobile.
+ // Unfortunately this operation does not have a completion handler
+ // registered. That could have helped in the single update case
+ ComPtr<IAsyncOperation<Geoposition*>> op;
+ hr = d->locator->GetGeopositionAsync(&op);
+
+ hr = d->locator->add_PositionChanged(Callback<GeoLocatorPositionHandler>(this,
+ &QGeoPositionInfoSourceWinRT::onPositionChanged).Get(),
+ &d->positionToken);
+ return hr;
+ });
if (FAILED(hr)) {
setError(QGeoPositionInfoSource::UnknownSourceError);
qErrnoWarning(hr, "Could not add position handler");
return false;
}
+
return true;
}
-void QGeoPositionInfoSourceWinrt::stopHandler()
+void QGeoPositionInfoSourceWinRT::stopHandler()
{
- if (!m_positionToken.value)
+ Q_D(QGeoPositionInfoSourceWinRT);
+
+ if (!d->positionToken.value)
return;
- m_locator->remove_PositionChanged(m_positionToken);
- m_positionToken.value = 0;
+ QEventDispatcherWinRT::runOnXamlThread([d]() {
+ d->locator->remove_PositionChanged(d->positionToken);
+ return S_OK;
+ });
+ d->positionToken.value = 0;
}
-void QGeoPositionInfoSourceWinrt::requestUpdate(int timeout)
+void QGeoPositionInfoSourceWinRT::requestUpdate(int timeout)
{
+ Q_D(QGeoPositionInfoSourceWinRT);
+
if (timeout != 0 && timeout < minimumUpdateInterval()) {
emit updateTimeout();
return;
@@ -242,11 +310,14 @@ void QGeoPositionInfoSourceWinrt::requestUpdate(int timeout)
timeout = 2*60*1000; // Maximum time for cold start (see Android)
startHandler();
- m_singleUpdateTimer.start(timeout);
+ d->singleUpdateTimer.start(timeout);
}
-void QGeoPositionInfoSourceWinrt::virtualPositionUpdate()
+void QGeoPositionInfoSourceWinRT::virtualPositionUpdate()
{
+ Q_D(QGeoPositionInfoSourceWinRT);
+ QMutexLocker locker(&d->mutex);
+
// Need to check if services are still running and ok
if (!checkNativeState()) {
stopUpdates();
@@ -258,39 +329,69 @@ void QGeoPositionInfoSourceWinrt::virtualPositionUpdate()
// between backends.
// This only applies to the periodic timer, not for single requests
// We can only do this if we received a valid position before
- if (m_lastPosition.isValid()) {
- QGeoPositionInfo sent = m_lastPosition;
+ if (d->lastPosition.isValid()) {
+ QGeoPositionInfo sent = d->lastPosition;
sent.setTimestamp(QDateTime::currentDateTime());
- m_lastPosition = sent;
+ d->lastPosition = sent;
emit positionUpdated(sent);
}
- m_periodicTimer.start();
+ d->periodicTimer.start();
}
-void QGeoPositionInfoSourceWinrt::singleUpdateTimeOut()
+void QGeoPositionInfoSourceWinRT::singleUpdateTimeOut()
{
- emit updateTimeout();
- if (!m_updatesOngoing)
+ Q_D(QGeoPositionInfoSourceWinRT);
+ QMutexLocker locker(&d->mutex);
+
+ if (d->singleUpdateTimer.isActive()) {
+ emit updateTimeout();
+ if (!d->updatesOngoing)
+ stopHandler();
+ }
+}
+
+void QGeoPositionInfoSourceWinRT::updateSynchronized(QGeoPositionInfo currentInfo)
+{
+ Q_D(QGeoPositionInfoSourceWinRT);
+ QMutexLocker locker(&d->mutex);
+
+ d->periodicTimer.stop();
+ d->lastPosition = currentInfo;
+
+ if (d->updatesOngoing)
+ d->periodicTimer.start();
+
+ if (d->singleUpdateTimer.isActive()) {
+ d->singleUpdateTimer.stop();
+ if (!d->updatesOngoing)
stopHandler();
+ }
+
+ emit positionUpdated(currentInfo);
}
-QGeoPositionInfoSource::Error QGeoPositionInfoSourceWinrt::error() const
+QGeoPositionInfoSource::Error QGeoPositionInfoSourceWinRT::error() const
{
- return m_positionError;
+ Q_D(const QGeoPositionInfoSourceWinRT);
+ return d->positionError;
}
-void QGeoPositionInfoSourceWinrt::setError(QGeoPositionInfoSource::Error positionError)
+void QGeoPositionInfoSourceWinRT::setError(QGeoPositionInfoSource::Error positionError)
{
- if (positionError == m_positionError)
+ Q_D(QGeoPositionInfoSourceWinRT);
+
+ if (positionError == d->positionError)
return;
- m_positionError = positionError;
+ d->positionError = positionError;
emit QGeoPositionInfoSource::error(positionError);
}
-bool QGeoPositionInfoSourceWinrt::checkNativeState()
+bool QGeoPositionInfoSourceWinRT::checkNativeState()
{
+ Q_D(QGeoPositionInfoSourceWinRT);
+
PositionStatus status;
- HRESULT hr = m_locator->get_LocationStatus(&status);
+ HRESULT hr = d->locator->get_LocationStatus(&status);
if (FAILED(hr)) {
setError(QGeoPositionInfoSource::UnknownSourceError);
qErrnoWarning(hr, "Could not query status");
@@ -314,17 +415,14 @@ bool QGeoPositionInfoSourceWinrt::checkNativeState()
return result;
}
-HRESULT QGeoPositionInfoSourceWinrt::onPositionChanged(IGeolocator *locator, IPositionChangedEventArgs *args)
+HRESULT QGeoPositionInfoSourceWinRT::onPositionChanged(IGeolocator *locator, IPositionChangedEventArgs *args)
{
Q_UNUSED(locator);
- m_periodicTimer.stop();
-
HRESULT hr;
ComPtr<IGeoposition> pos;
hr = args->get_Position(&pos);
- if (FAILED(hr))
- qErrnoWarning(hr, "Could not access position object");
+ RETURN_HR_IF_FAILED("Could not access position object.");
QGeoPositionInfo currentInfo;
@@ -378,19 +476,48 @@ HRESULT QGeoPositionInfoSourceWinrt::onPositionChanged(IGeolocator *locator, IPo
currentInfo.setTimestamp(QDateTime::currentDateTime());
- m_lastPosition = currentInfo;
+ emit nativePositionUpdate(currentInfo);
- if (m_updatesOngoing)
- m_periodicTimer.start();
-
- if (m_singleUpdateTimer.isActive()) {
- m_singleUpdateTimer.stop();
- if (!m_updatesOngoing)
- stopHandler();
- }
+ return S_OK;
+}
- emit positionUpdated(currentInfo);
+HRESULT QGeoPositionInfoSourceWinRT::onStatusChanged(IGeolocator*, IStatusChangedEventArgs *args)
+{
+ PositionStatus st;
+ args->get_Status(&st);
return S_OK;
}
+bool QGeoPositionInfoSourceWinRT::requestAccess() const
+{
+#if _MSC_VER >= 1900
+ static GeolocationAccessStatus accessStatus = GeolocationAccessStatus_Unspecified;
+ static ComPtr<IGeolocatorStatics> statics;
+
+ if (accessStatus == GeolocationAccessStatus_Allowed)
+ return true;
+ else if (accessStatus == GeolocationAccessStatus_Denied)
+ return false;
+
+ ComPtr<IAsyncOperation<GeolocationAccessStatus>> op;
+ HRESULT hr;
+ hr = QEventDispatcherWinRT::runOnXamlThread([&op]() {
+ HRESULT hr;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Geolocation_Geolocator).Get(),
+ IID_PPV_ARGS(&statics));
+ RETURN_HR_IF_FAILED("Could not access Geolocation Statics.");
+
+ hr = statics->RequestAccessAsync(&op);
+ return hr;
+ });
+ Q_ASSERT_SUCCEEDED(hr);
+
+ // We cannot wait inside the XamlThread as that would deadlock
+ QWinRTFunctions::await(op, &accessStatus);
+ return accessStatus == GeolocationAccessStatus_Allowed;
+#else // _MSC_VER < 1900
+ return true;
+#endif // _MSC_VER < 1900
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/position/winrt/qgeopositioninfosource_winrt_p.h b/src/plugins/position/winrt/qgeopositioninfosource_winrt_p.h
index 45c22847..b8820dd2 100644
--- a/src/plugins/position/winrt/qgeopositioninfosource_winrt_p.h
+++ b/src/plugins/position/winrt/qgeopositioninfosource_winrt_p.h
@@ -70,12 +70,14 @@ namespace ABI {
QT_BEGIN_NAMESPACE
-class QGeoPositionInfoSourceWinrt : public QGeoPositionInfoSource
+class QGeoPositionInfoSourceWinRTPrivate;
+
+class QGeoPositionInfoSourceWinRT : public QGeoPositionInfoSource
{
Q_OBJECT
public:
- QGeoPositionInfoSourceWinrt(QObject *parent = 0);
- ~QGeoPositionInfoSourceWinrt();
+ QGeoPositionInfoSourceWinRT(QObject *parent = 0);
+ ~QGeoPositionInfoSourceWinRT();
QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const;
PositioningMethods supportedPositioningMethods() const;
@@ -89,6 +91,12 @@ public:
HRESULT onPositionChanged(ABI::Windows::Devices::Geolocation::IGeolocator *locator,
ABI::Windows::Devices::Geolocation::IPositionChangedEventArgs *args);
+ HRESULT onStatusChanged(ABI::Windows::Devices::Geolocation::IGeolocator*,
+ ABI::Windows::Devices::Geolocation::IStatusChangedEventArgs *args);
+
+ bool requestAccess() const;
+Q_SIGNALS:
+ void nativePositionUpdate(const QGeoPositionInfo);
public slots:
void startUpdates();
void stopUpdates();
@@ -99,23 +107,16 @@ private slots:
void stopHandler();
void virtualPositionUpdate();
void singleUpdateTimeOut();
+ void updateSynchronized(const QGeoPositionInfo info);
private:
bool startHandler();
- Q_DISABLE_COPY(QGeoPositionInfoSourceWinrt)
+ Q_DISABLE_COPY(QGeoPositionInfoSourceWinRT)
void setError(QGeoPositionInfoSource::Error positionError);
bool checkNativeState();
- Microsoft::WRL::ComPtr<ABI::Windows::Devices::Geolocation::IGeolocator> m_locator;
- EventRegistrationToken m_positionToken;
-
- QGeoPositionInfo m_lastPosition;
- QGeoPositionInfoSource::Error m_positionError;
-
- //EventRegistrationToken m_StatusToken;
- QTimer m_periodicTimer;
- QTimer m_singleUpdateTimer;
- bool m_updatesOngoing;
+ QScopedPointer<QGeoPositionInfoSourceWinRTPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QGeoPositionInfoSourceWinRT)
};
QT_END_NAMESPACE
diff --git a/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.cpp b/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.cpp
index 0f9a21f2..81656c21 100644
--- a/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.cpp
+++ b/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.cpp
@@ -37,18 +37,18 @@
#include "qgeopositioninfosourcefactory_winrt.h"
#include "qgeopositioninfosource_winrt_p.h"
-QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryWinrt::positionInfoSource(QObject *parent)
+QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryWinRT::positionInfoSource(QObject *parent)
{
- return new QGeoPositionInfoSourceWinrt(parent);
+ return new QGeoPositionInfoSourceWinRT(parent);
}
-QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryWinrt::satelliteInfoSource(QObject *parent)
+QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryWinRT::satelliteInfoSource(QObject *parent)
{
Q_UNUSED(parent);
return 0;
}
-QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryWinrt::areaMonitor(QObject *parent)
+QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryWinRT::areaMonitor(QObject *parent)
{
Q_UNUSED(parent);
return 0;
diff --git a/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.h b/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.h
index 0627abc4..46cd3853 100644
--- a/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.h
+++ b/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.h
@@ -42,7 +42,7 @@
QT_BEGIN_NAMESPACE
-class QGeoPositionInfoSourceFactoryWinrt : public QObject, public QGeoPositionInfoSourceFactory
+class QGeoPositionInfoSourceFactoryWinRT : public QObject, public QGeoPositionInfoSourceFactory
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0"
diff --git a/src/plugins/position/winrt/winrt.pro b/src/plugins/position/winrt/winrt.pro
index 228a9e78..c58c6c18 100644
--- a/src/plugins/position/winrt/winrt.pro
+++ b/src/plugins/position/winrt/winrt.pro
@@ -1,8 +1,8 @@
TARGET = qtposition_winrt
-QT = core positioning
+QT = core core-private positioning
PLUGIN_TYPE = position
-PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactoryWinrt
+PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactoryWinRT
load(qt_plugin)
SOURCES += qgeopositioninfosource_winrt.cpp \