6#include <QtCore/qcoreapplication.h>
7#include <QtCore/qdatetime.h>
8#include <QtCore/private/qfunctions_winrt_p.h>
9#include <QtCore/qloggingcategory.h>
10#include <QtCore/qmutex.h>
11#include <QtCore/qtimezone.h>
14#include <windows.system.h>
15#include <windows.devices.geolocation.h>
16#include <windows.foundation.h>
17#include <windows.foundation.collections.h>
20using namespace Microsoft::WRL::Wrappers;
23using namespace ABI::Windows::Foundation::Collections;
28typedef IAsyncOperationCompletedHandler<GeolocationAccessStatus>
AccessHandler;
37 GeolocationAccessStatus *
result)
39 ComPtr<IAsyncInfo> asyncInfo;
40 HRESULT hr = asyncOp.As(&asyncInfo);
45 while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == AsyncStatus::Started)
48 if (FAILED(hr) || status != AsyncStatus::Completed) {
50 hr = asyncInfo->get_ErrorCode(&ec);
53 hr = asyncInfo->Close();
62 return asyncOp->GetResults(
result);
74 mutable ComPtr<IGeolocatorStatics>
statics;
94 qRegisterMetaType<QGeoPositionInfoSource::Error>();
95 qCDebug(lcPositioningWinRT) << __FUNCTION__;
96 CoInitializeEx(
nullptr, COINIT_APARTMENTTHREADED);
99 d->updatesOngoing =
false;
100 d->positionToken.value = 0;
101 d->statusToken.value = 0;
106 qCDebug(lcPositioningWinRT) << __FUNCTION__;
117 qCDebug(lcPositioningWinRT) << __FUNCTION__;
122 qWarning (
"Location access failed.");
126 HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Devices_Geolocation_Geolocator).Get(),
128 RETURN_HR_IF_FAILED(
"Could not initialize native location services.");
130 if (
d->minimumUpdateInterval == -1) {
132 hr =
d->locator->get_ReportInterval(&interval);
133 RETURN_HR_IF_FAILED(
"Could not retrieve report interval.");
134 d->minimumUpdateInterval =
static_cast<int>(interval);
136 if (
d->updateInterval == -1)
137 d->updateInterval =
d->minimumUpdateInterval;
148 d->periodicTimer.setSingleShot(
true);
151 d->singleUpdateTimer.setSingleShot(
true);
166 qCDebug(lcPositioningWinRT) << __FUNCTION__;
168 Q_UNUSED(fromSatellitePositioningMethodsOnly);
169 return d->lastPosition;
190 const bool needsRestart =
d->positionToken.value != 0 ||
d->statusToken.value != 0;
196 PositionAccuracy::PositionAccuracy_High :
197 PositionAccuracy::PositionAccuracy_Default;
199 return d->locator->put_DesiredAccuracy(acc);
201 RETURN_VOID_IF_FAILED(
"Could not set positioning accuracy.");
209 qCDebug(lcPositioningWinRT) << __FUNCTION__ << msec;
212 d->updateInterval = msec;
222 const bool needsRestart =
d->positionToken.value != 0 ||
d->statusToken.value != 0;
227 HRESULT hr =
d->locator->put_ReportInterval(
static_cast<UINT32
>(msec));
234 d->updateInterval = msec;
235 d->periodicTimer.setInterval(
d->updateInterval);
246 return d->minimumUpdateInterval == -1 ? 1000 :
d->minimumUpdateInterval;
251 qCDebug(lcPositioningWinRT) << __FUNCTION__;
258 if (
d->updatesOngoing)
263 d->updatesOngoing =
true;
264 d->periodicTimer.start();
269 qCDebug(lcPositioningWinRT) << __FUNCTION__;
276 d->updatesOngoing =
false;
277 d->periodicTimer.stop();
280bool QGeoPositionInfoSourceWinRT::startHandler()
282 qCDebug(lcPositioningWinRT) << __FUNCTION__;
286 if (
d->positionToken.value != 0)
305 ComPtr<IAsyncOperation<Geoposition*>> op;
306 hr =
d->locator->GetGeopositionAsync(&op);
307 RETURN_HR_IF_FAILED(
"Could not start position operation");
309 hr =
d->locator->add_PositionChanged(Callback<GeoLocatorPositionHandler>(
this,
312 RETURN_HR_IF_FAILED(
"Could not add position handler");
314 hr =
d->locator->add_StatusChanged(Callback<GeoLocatorStatusHandler>(
this,
317 RETURN_HR_IF_FAILED(
"Could not add status handler");
328void QGeoPositionInfoSourceWinRT::stopHandler()
330 qCDebug(lcPositioningWinRT) << __FUNCTION__;
333 if (!
d->positionToken.value)
335 d->locator->remove_PositionChanged(
d->positionToken);
336 d->locator->remove_StatusChanged(
d->statusToken);
337 d->positionToken.value = 0;
338 d->statusToken.value = 0;
360 d->singleUpdateTimer.start(
timeout);
363void QGeoPositionInfoSourceWinRT::virtualPositionUpdate()
365 qCDebug(lcPositioningWinRT) << __FUNCTION__;
374 if (
d->lastPosition.isValid()) {
377 d->lastPosition = sent;
380 d->periodicTimer.start();
383void QGeoPositionInfoSourceWinRT::singleUpdateTimeOut()
388 if (
d->singleUpdateTimer.isActive()) {
391 if (!
d->updatesOngoing)
396void QGeoPositionInfoSourceWinRT::updateSynchronized(
QGeoPositionInfo currentInfo)
398 qCDebug(lcPositioningWinRT) << __FUNCTION__ << currentInfo;
402 d->periodicTimer.stop();
403 d->lastPosition = currentInfo;
405 if (
d->updatesOngoing)
406 d->periodicTimer.start();
408 if (
d->singleUpdateTimer.isActive()) {
409 d->singleUpdateTimer.stop();
410 if (!
d->updatesOngoing)
420 qCDebug(lcPositioningWinRT) << __FUNCTION__ <<
d->positionError;
428 return d->positionError;
435 if (positionError ==
d->positionError)
438 qCDebug(lcPositioningWinRT) << __FUNCTION__ << positionError;
439 d->positionError = positionError;
446 setError(positionError);
452 qCDebug(lcPositioningWinRT) << __FUNCTION__;
458 RETURN_HR_IF_FAILED(
"Could not access position object.");
462 ComPtr<IGeocoordinate>
coord;
467 ComPtr<IGeocoordinateWithPoint> pointCoordinate;
468 hr =
coord.As(&pointCoordinate);
472 ComPtr<IGeopoint> point;
473 hr = pointCoordinate->get_Point(&point);
477 BasicGeoposition
pos;
478 hr = point->get_Position(&
pos);
482 DOUBLE lat =
pos.Latitude;
483 DOUBLE lon =
pos.Longitude;
484 DOUBLE alt =
pos.Altitude;
486 bool altitudeAvailable =
false;
487 ComPtr<IGeoshape> shape;
488 hr = point.As(&shape);
489 if (SUCCEEDED(hr) && shape) {
490 AltitudeReferenceSystem altitudeSystem;
491 hr = shape->get_AltitudeReferenceSystem(&altitudeSystem);
492 if (SUCCEEDED(hr) && altitudeSystem == AltitudeReferenceSystem_Geoid)
493 altitudeAvailable =
true;
495 if (altitudeAvailable)
501 hr =
coord->get_Accuracy(&accuracy);
505 IReference<double> *altAccuracy;
506 hr =
coord->get_AltitudeAccuracy(&altAccuracy);
507 if (SUCCEEDED(hr) && altAccuracy) {
509 hr = altAccuracy->get_Value(&
value);
513 IReference<double> *speed;
514 hr =
coord->get_Speed(&speed);
515 if (SUCCEEDED(hr) && speed) {
517 hr = speed->get_Value(&
value);
521 IReference<double> *heading;
522 hr =
coord->get_Heading(&heading);
523 if (SUCCEEDED(hr) && heading) {
525 hr = heading->get_Value(&
value);
528 value +=
static_cast<int>(mod) % 360;
537 ULARGE_INTEGER uLarge;
538 uLarge.QuadPart =
dateTime.UniversalTime;
540 fileTime.dwHighDateTime = uLarge.HighPart;
541 fileTime.dwLowDateTime = uLarge.LowPart;
542 SYSTEMTIME systemTime;
543 if (FileTimeToSystemTime(&fileTime, &systemTime)) {
544 currentInfo.setTimestamp(
QDateTime(
QDate(systemTime.wYear, systemTime.wMonth,
546 QTime(systemTime.wHour, systemTime.wMinute,
547 systemTime.wSecond, systemTime.wMilliseconds),
559 return status == PositionStatus_NoData || status == PositionStatus_Disabled
560 || status == PositionStatus_NotAvailable;
567 const PositionStatus oldStatus =
d->positionStatus;
569 RETURN_HR_IF_FAILED(
"Could not obtain position status");
570 qCDebug(lcPositioningWinRT) << __FUNCTION__ <<
d->positionStatus;
572 switch (
d->positionStatus) {
573 case PositionStatus::PositionStatus_NotAvailable:
576 case PositionStatus::PositionStatus_Disabled:
579 case PositionStatus::PositionStatus_NoData:
598 qCDebug(lcPositioningWinRT) << __FUNCTION__;
599 GeolocationAccessStatus accessStatus;
601 ComPtr<IAsyncOperation<GeolocationAccessStatus>> op;
605 hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Geolocation_Geolocator).Get(),
606 IID_PPV_ARGS(&
d->statics));
607 RETURN_HR_IF_FAILED(
"Could not access Geolocation Statics.");
610 hr =
d->statics->RequestAccessAsync(&op);
614 qCDebug(lcPositioningWinRT) << __FUNCTION__ <<
"Requesting access from Xaml thread failed";
618 await(op, &accessStatus);
619 return accessStatus == GeolocationAccessStatus_Allowed;
static JNINativeMethod methods[]
\inmodule QtCore\reentrant
\inmodule QtCore \reentrant
QGeoPositionInfo lastPosition
InitializationState initState
QGeoPositionInfoSource::Error positionError
ComPtr< IGeolocator > locator
ComPtr< IGeolocatorStatics > statics
EventRegistrationToken positionToken
PositionStatus positionStatus
int minimumUpdateInterval
EventRegistrationToken statusToken
void setUpdateInterval(int msec) override
HRESULT onStatusChanged(ABI::Windows::Devices::Geolocation::IGeolocator *locator, ABI::Windows::Devices::Geolocation::IStatusChangedEventArgs *args)
QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly=false) const override
Returns an update containing the last known position, or a null update if none is available.
bool requestAccess() const
Error error() const override
Returns the type of error that last occurred.
~QGeoPositionInfoSourceWinRT() override
int minimumUpdateInterval() const override
void startUpdates() override
void nativePositionUpdate(const QGeoPositionInfo)
QGeoPositionInfoSourceWinRT(QObject *parent=nullptr)
HRESULT onPositionChanged(ABI::Windows::Devices::Geolocation::IGeolocator *locator, ABI::Windows::Devices::Geolocation::IPositionChangedEventArgs *args)
void requestUpdate(int timeout=0) override
void setPreferredPositioningMethods(PositioningMethods methods) override
void stopUpdates() override
PositioningMethods supportedPositioningMethods() const override
Returns the positioning methods available to this source.
int updateInterval
This property holds the requested interval in milliseconds between each update.
void positionUpdated(const QGeoPositionInfo &update)
If startUpdates() or requestUpdate() is called, this signal is emitted when an update becomes availab...
@ SatellitePositioningMethods
void errorOccurred(QGeoPositionInfoSource::Error)
This signal is emitted after an error occurred.
virtual void setPreferredPositioningMethods(PositioningMethods methods)
void supportedPositioningMethodsChanged()
This signal is emitted when the supported positioning methods changed.
Error
The Error enumeration represents the errors which can occur.
virtual void setUpdateInterval(int msec)
PositioningMethods preferredPositioningMethods
Sets the preferred positioning methods for this source.
void setTimestamp(const QDateTime ×tamp)
Sets the date and time at which this position was reported to timestamp.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
static void yieldCurrentThread()
\inmodule QtCore \reentrant
void timeout(QPrivateSignal)
This signal is emitted when the timer times out.
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
static QT_BEGIN_NAMESPACE bool await(IAsyncOperation< T > &&asyncInfo, T &result, uint timeout=0)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
IAsyncOperationCompletedHandler< Geoposition * > PositionHandler
ITypedEventHandler< Geolocator *, StatusChangedEventArgs * > GeoLocatorStatusHandler
static QT_BEGIN_NAMESPACE HRESULT await(const ComPtr< IAsyncOperation< GeolocationAccessStatus > > &asyncOp, GeolocationAccessStatus *result)
IAsyncOperationCompletedHandler< GeolocationAccessStatus > AccessHandler
ITypedEventHandler< Geolocator *, PositionChangedEventArgs * > GeoLocatorPositionHandler
static bool isDisabledStatus(PositionStatus status)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
#define Q_ARG(Type, data)
GLbitfield GLuint64 timeout
[4]
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)