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>
13#include <QtCore/private/qeventdispatcher_winrt_p.h>
17#include <windows.system.h>
18#include <windows.devices.geolocation.h>
19#include <windows.foundation.h>
20#include <windows.foundation.collections.h>
23using namespace Microsoft::WRL::Wrappers;
26using namespace ABI::Windows::Foundation::Collections;
31typedef IAsyncOperationCompletedHandler<GeolocationAccessStatus>
AccessHandler;
49 GeolocationAccessStatus *
result)
52 HRESULT hr = asyncOp.As(&asyncInfo);
57 while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == AsyncStatus::Started)
60 if (FAILED(hr) || status != AsyncStatus::Completed) {
62 hr = asyncInfo->get_ErrorCode(&ec);
65 hr = asyncInfo->Close();
74 return asyncOp->GetResults(
result);
107 qRegisterMetaType<QGeoPositionInfoSource::Error>();
108 qCDebug(lcPositioningWinRT) << __FUNCTION__;
109 CoInitializeEx(
nullptr, COINIT_APARTMENTTHREADED);
112 d->updatesOngoing =
false;
113 d->positionToken.value = 0;
114 d->statusToken.value = 0;
119 qCDebug(lcPositioningWinRT) << __FUNCTION__;
130 qCDebug(lcPositioningWinRT) << __FUNCTION__;
135 qWarning (
"Location access failed.");
139 HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Devices_Geolocation_Geolocator).Get(),
141 RETURN_HR_IF_FAILED(
"Could not initialize native location services.");
143 if (
d->minimumUpdateInterval == -1) {
145 hr =
d->locator->get_ReportInterval(&interval);
146 RETURN_HR_IF_FAILED(
"Could not retrieve report interval.");
147 d->minimumUpdateInterval =
static_cast<int>(interval);
149 if (
d->updateInterval == -1)
150 d->updateInterval =
d->minimumUpdateInterval;
161 d->periodicTimer.setSingleShot(
true);
164 d->singleUpdateTimer.setSingleShot(
true);
179 qCDebug(lcPositioningWinRT) << __FUNCTION__;
181 Q_UNUSED(fromSatellitePositioningMethodsOnly);
182 return d->lastPosition;
203 const bool needsRestart =
d->positionToken.value != 0 ||
d->statusToken.value != 0;
209 PositionAccuracy::PositionAccuracy_High :
210 PositionAccuracy::PositionAccuracy_Default;
212 return d->locator->put_DesiredAccuracy(acc);
214 RETURN_VOID_IF_FAILED(
"Could not set positioning accuracy.");
222 qCDebug(lcPositioningWinRT) << __FUNCTION__ << msec;
225 d->updateInterval = msec;
235 const bool needsRestart =
d->positionToken.value != 0 ||
d->statusToken.value != 0;
240 HRESULT hr =
d->locator->put_ReportInterval(
static_cast<UINT32
>(msec));
247 d->updateInterval = msec;
248 d->periodicTimer.setInterval(
d->updateInterval);
259 return d->minimumUpdateInterval == -1 ? 1000 :
d->minimumUpdateInterval;
264 qCDebug(lcPositioningWinRT) << __FUNCTION__;
271 if (
d->updatesOngoing)
276 d->updatesOngoing =
true;
277 d->periodicTimer.start();
282 qCDebug(lcPositioningWinRT) << __FUNCTION__;
289 d->updatesOngoing =
false;
290 d->periodicTimer.stop();
293bool QGeoPositionInfoSourceWinRT::startHandler()
295 qCDebug(lcPositioningWinRT) << __FUNCTION__;
299 if (
d->positionToken.value != 0)
319 hr =
d->locator->GetGeopositionAsync(&op);
320 RETURN_HR_IF_FAILED(
"Could not start position operation");
322 hr =
d->locator->add_PositionChanged(Callback<GeoLocatorPositionHandler>(
this,
325 RETURN_HR_IF_FAILED(
"Could not add position handler");
327 hr =
d->locator->add_StatusChanged(Callback<GeoLocatorStatusHandler>(
this,
330 RETURN_HR_IF_FAILED(
"Could not add status handler");
341void QGeoPositionInfoSourceWinRT::stopHandler()
343 qCDebug(lcPositioningWinRT) << __FUNCTION__;
346 if (!
d->positionToken.value)
349 d->locator->remove_PositionChanged(
d->positionToken);
350 d->locator->remove_StatusChanged(
d->statusToken);
353 d->positionToken.value = 0;
354 d->statusToken.value = 0;
376 d->singleUpdateTimer.start(
timeout);
379void QGeoPositionInfoSourceWinRT::virtualPositionUpdate()
381 qCDebug(lcPositioningWinRT) << __FUNCTION__;
390 if (
d->lastPosition.isValid()) {
393 d->lastPosition = sent;
396 d->periodicTimer.start();
399void QGeoPositionInfoSourceWinRT::singleUpdateTimeOut()
404 if (
d->singleUpdateTimer.isActive()) {
407 if (!
d->updatesOngoing)
412void QGeoPositionInfoSourceWinRT::updateSynchronized(
QGeoPositionInfo currentInfo)
414 qCDebug(lcPositioningWinRT) << __FUNCTION__ << currentInfo;
418 d->periodicTimer.stop();
419 d->lastPosition = currentInfo;
421 if (
d->updatesOngoing)
422 d->periodicTimer.start();
424 if (
d->singleUpdateTimer.isActive()) {
425 d->singleUpdateTimer.stop();
426 if (!
d->updatesOngoing)
436 qCDebug(lcPositioningWinRT) << __FUNCTION__ <<
d->positionError;
444 return d->positionError;
451 if (positionError ==
d->positionError)
454 qCDebug(lcPositioningWinRT) << __FUNCTION__ << positionError;
455 d->positionError = positionError;
462 setError(positionError);
468 qCDebug(lcPositioningWinRT) << __FUNCTION__;
474 RETURN_HR_IF_FAILED(
"Could not access position object.");
484 hr =
coord.As(&pointCoordinate);
489 hr = pointCoordinate->get_Point(&point);
493 BasicGeoposition
pos;
494 hr = point->get_Position(&
pos);
498 DOUBLE lat =
pos.Latitude;
499 DOUBLE lon =
pos.Longitude;
500 DOUBLE alt =
pos.Altitude;
502 bool altitudeAvailable =
false;
504 hr = point.As(&shape);
505 if (SUCCEEDED(hr) && shape) {
506 AltitudeReferenceSystem altitudeSystem;
507 hr = shape->get_AltitudeReferenceSystem(&altitudeSystem);
508 if (SUCCEEDED(hr) && altitudeSystem == AltitudeReferenceSystem_Geoid)
509 altitudeAvailable =
true;
511 if (altitudeAvailable)
517 hr =
coord->get_Accuracy(&accuracy);
521 IReference<double> *altAccuracy;
522 hr =
coord->get_AltitudeAccuracy(&altAccuracy);
523 if (SUCCEEDED(hr) && altAccuracy) {
525 hr = altAccuracy->get_Value(&
value);
529 IReference<double> *speed;
530 hr =
coord->get_Speed(&speed);
531 if (SUCCEEDED(hr) && speed) {
533 hr = speed->get_Value(&
value);
537 IReference<double> *heading;
538 hr =
coord->get_Heading(&heading);
539 if (SUCCEEDED(hr) && heading) {
541 hr = heading->get_Value(&
value);
544 value +=
static_cast<int>(mod) % 360;
553 ULARGE_INTEGER uLarge;
554 uLarge.QuadPart =
dateTime.UniversalTime;
556 fileTime.dwHighDateTime = uLarge.HighPart;
557 fileTime.dwLowDateTime = uLarge.LowPart;
558 SYSTEMTIME systemTime;
559 if (FileTimeToSystemTime(&fileTime, &systemTime)) {
562 QTime(systemTime.wHour, systemTime.wMinute,
563 systemTime.wSecond, systemTime.wMilliseconds),
575 return status == PositionStatus_NoData || status == PositionStatus_Disabled
576 || status == PositionStatus_NotAvailable;
583 const PositionStatus oldStatus =
d->positionStatus;
585 RETURN_HR_IF_FAILED(
"Could not obtain position status");
586 qCDebug(lcPositioningWinRT) << __FUNCTION__ <<
d->positionStatus;
588 switch (
d->positionStatus) {
589 case PositionStatus::PositionStatus_NotAvailable:
592 case PositionStatus::PositionStatus_Disabled:
595 case PositionStatus::PositionStatus_NoData:
614 qCDebug(lcPositioningWinRT) << __FUNCTION__;
615 GeolocationAccessStatus accessStatus;
622 hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Geolocation_Geolocator).Get(),
623 IID_PPV_ARGS(&d->statics));
624 RETURN_HR_IF_FAILED(
"Could not access Geolocation Statics.");
627 hr =
d->statics->RequestAccessAsync(&op);
631 qCDebug(lcPositioningWinRT) << __FUNCTION__ <<
"Requesting access from Xaml thread failed";
637 QWinRTFunctions::await(op, &accessStatus);
639 await(op, &accessStatus);
641 return accessStatus == GeolocationAccessStatus_Allowed;
static JNINativeMethod methods[]
\inmodule QtCore\reentrant
QDateTime addMSecs(qint64 msecs) const
Returns a QDateTime object containing a datetime msecs milliseconds later than the datetime of this o...
\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 setCoordinate(const QGeoCoordinate &coordinate)
Sets the coordinate for this position to coordinate.
void setAttribute(Attribute attribute, qreal value)
Sets the value for attribute to value.
void setTimestamp(const QDateTime ×tamp)
Sets the date and time at which this position was reported to timestamp.
QDateTime timestamp() const
Returns the date and time at which this position was reported, in UTC time.
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,...)
HRESULT runOnXamlThread(const std::function< HRESULT()> &delegate, bool waitForRun=true)
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
IAsyncOperationCompletedHandler< GeolocationAccessStatus > AccessHandler
static HRESULT await(const ComPtr< IAsyncOperation< GeolocationAccessStatus > > &asyncOp, GeolocationAccessStatus *result)
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)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent