typedef ITypedEventHandler<CoreWindow*, WindowSizeChangedEventArgs*> SizeChangedHandler;
typedef ITypedEventHandler<CoreWindow*, VisibilityChangedEventArgs*> VisibilityChangedHandler;
typedef ITypedEventHandler<DisplayInformation*, IInspectable*> DisplayInformationHandler;
+#ifdef Q_OS_WINPHONE
+typedef ITypedEventHandler<StatusBar*, IInspectable*> StatusBarHandler;
+#endif
QT_BEGIN_NAMESPACE
uint qHash(CoreWindowCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
typedef HRESULT (__stdcall IDisplayInformation::*DisplayCallbackRemover)(EventRegistrationToken);
uint qHash(DisplayCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
+#ifdef Q_OS_WINPHONE
+typedef HRESULT (__stdcall IStatusBar::*StatusBarCallbackRemover)(EventRegistrationToken);
+uint qHash(StatusBarCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
+#endif
class QWinRTScreenPrivate
{
ComPtr<IDisplayInformation> displayInformation;
#ifdef Q_OS_WINPHONE
ComPtr<IStatusBar> statusBar;
-#endif // Q_OS_WINPHONE
+#endif
QScopedPointer<QWinRTCursor> cursor;
QHash<quint32, QWindowSystemInterface::TouchPoint> touchPoints;
QHash<CoreWindowCallbackRemover, EventRegistrationToken> windowTokens;
QHash<DisplayCallbackRemover, EventRegistrationToken> displayTokens;
+#ifdef Q_OS_WINPHONE
+ QHash<StatusBarCallbackRemover, EventRegistrationToken> statusBarTokens;
+#endif
};
// To be called from the XAML thread
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_PointerWheelChanged(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerWheelChanged]);
Q_ASSERT_SUCCEEDED(hr);
+#ifndef Q_OS_WINPHONE
hr = d->coreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &QWinRTScreen::onSizeChanged).Get(), &d->windowTokens[&ICoreWindow::remove_SizeChanged]);
Q_ASSERT_SUCCEEDED(hr);
+#endif
hr = d->coreWindow->add_Activated(Callback<ActivatedHandler>(this, &QWinRTScreen::onActivated).Get(), &d->windowTokens[&ICoreWindow::remove_Activated]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_Closed(Callback<ClosedHandler>(this, &QWinRTScreen::onClosed).Get(), &d->windowTokens[&ICoreWindow::remove_Closed]);
Q_ASSERT_SUCCEEDED(hr);
hr = statusBarStatics->GetForCurrentView(&d->statusBar);
Q_ASSERT_SUCCEEDED(hr);
+ hr = d->statusBar->add_Showing(Callback<StatusBarHandler>(this, &QWinRTScreen::onStatusBarShowing).Get(), &d->statusBarTokens[&IStatusBar::remove_Showing]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->statusBar->add_Hiding(Callback<StatusBarHandler>(this, &QWinRTScreen::onStatusBarHiding).Get(), &d->statusBarTokens[&IStatusBar::remove_Hiding]);
+ Q_ASSERT_SUCCEEDED(hr);
#endif // Q_OS_WINPHONE
}
hr = (d->displayInformation.Get()->*i.key())(i.value());
Q_ASSERT_SUCCEEDED(hr);
}
+#ifdef Q_OS_WINPHONE
+ for (QHash<StatusBarCallbackRemover, EventRegistrationToken>::const_iterator i = d->statusBarTokens.begin(); i != d->statusBarTokens.end(); ++i) {
+ hr = (d->statusBar.Get()->*i.key())(i.value());
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+#endif //Q_OS_WINPHONE
return hr;
});
RETURN_VOID_IF_FAILED("Failed to unregister screen event callbacks");
return QRect(QPoint(), (d->logicalSize * d->scaleFactor).toSize());
}
+#ifdef Q_OS_WINPHONE
+QRect QWinRTScreen::availableGeometry() const
+{
+ Q_D(const QWinRTScreen);
+ QRect statusBar;
+ QEventDispatcherWinRT::runOnXamlThread([d, &statusBar]() {
+ HRESULT hr;
+ Rect rect;
+ hr = d->statusBar->get_OccludedRect(&rect);
+ Q_ASSERT_SUCCEEDED(hr);
+ statusBar.setRect(qRound(rect.X * d->scaleFactor),
+ qRound(rect.Y * d->scaleFactor),
+ qRound(rect.Width * d->scaleFactor),
+ qRound(rect.Height * d->scaleFactor));
+ return S_OK;
+ });
+
+ return geometry().adjusted(
+ d->orientation == Qt::LandscapeOrientation ? statusBar.width() : 0,
+ d->orientation == Qt::PortraitOrientation ? statusBar.height() : 0,
+ d->orientation == Qt::InvertedLandscapeOrientation ? -statusBar.width() : 0,
+ 0);
+}
+#endif //Q_OS_WINPHONE
+
int QWinRTScreen::depth() const
{
return 32;
return d->canvas.Get();
}
+#ifdef Q_OS_WINPHONE
+void QWinRTScreen::setStatusBarVisibility(bool visible, QWindow *window)
+{
+ Q_D(QWinRTScreen);
+ if (!window || (window->flags() & Qt::WindowType_Mask) != Qt::Window)
+ return;
+
+ QEventDispatcherWinRT::runOnXamlThread([d, visible]() {
+ HRESULT hr;
+ ComPtr<IAsyncAction> op;
+ if (visible)
+ hr = d->statusBar->ShowAsync(&op);
+ else
+ hr = d->statusBar->HideAsync(&op);
+ Q_ASSERT_SUCCEEDED(hr);
+ return S_OK;
+ });
+}
+#endif //Q_OS_WINPHONE
+
QWindow *QWinRTScreen::topWindow() const
{
Q_D(const QWinRTScreen);
return;
#ifdef Q_OS_WINPHONE
- if (d->statusBar && (window->flags() & Qt::WindowType_Mask) == Qt::Window) {
- QEventDispatcherWinRT::runOnXamlThread([this, d]() {
- HRESULT hr;
- ComPtr<IAsyncAction> op;
- hr = d->statusBar->HideAsync(&op);
- Q_ASSERT_SUCCEEDED(hr);
- return S_OK;
- });
- }
-#endif // Q_OS_WINPHONE
+ if (window->visibility() != QWindow::Maximized && window->visibility() != QWindow::Windowed)
+ setStatusBarVisibility(false, window);
+#endif
d->visibleWindows.prepend(window);
QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason);
void QWinRTScreen::removeWindow(QWindow *window)
{
Q_D(QWinRTScreen);
+
+#ifdef Q_OS_WINPHONE
+ if (window->visibility() == QWindow::Minimized)
+ setStatusBarVisibility(false, window);
+#endif
+
const bool wasTopWindow = window == topWindow();
if (!d->visibleWindows.removeAll(window))
return;
HRESULT hr;
hr = d->coreWindow->get_Bounds(&size);
RETURN_OK_IF_FAILED("Failed to get window bounds");
- QSizeF logicalSize = QSizeF(size.Width, size.Height);
- if (d->logicalSize == logicalSize)
- return S_OK;
-
- d->logicalSize = logicalSize;
- const QRect newGeometry = geometry();
- QWindowSystemInterface::handleScreenGeometryChange(screen(), newGeometry, newGeometry);
+ d->logicalSize = QSizeF(size.Width, size.Height);
+ QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry());
QPlatformScreen::resizeMaximizedWindows();
handleExpose();
return S_OK;
Qt::ScreenOrientation newOrientation = static_cast<Qt::ScreenOrientation>(static_cast<int>(qtOrientationsFromNative(displayOrientation)));
if (d->orientation != newOrientation) {
d->orientation = newOrientation;
+#ifdef Q_OS_WINPHONE
+ onSizeChanged(nullptr, nullptr);
+#endif
QWindowSystemInterface::handleScreenOrientationChange(screen(), d->orientation);
handleExpose(); // Clean broken frames caused by race between Qt and ANGLE
}
return S_OK;
}
+#ifdef Q_OS_WINPHONE
+HRESULT QWinRTScreen::onStatusBarShowing(IStatusBar *, IInspectable *)
+{
+ onSizeChanged(nullptr, nullptr);
+ return S_OK;
+}
+
+HRESULT QWinRTScreen::onStatusBarHiding(IStatusBar *, IInspectable *)
+{
+ onSizeChanged(nullptr, nullptr);
+ return S_OK;
+}
+#endif //Q_OS_WINPHONE
+
QT_END_NAMESPACE
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Foundation::Collections;
using namespace ABI::Windows::UI;
+using namespace ABI::Windows::UI::Xaml;
+using namespace ABI::Windows::UI::Xaml::Controls;
QT_BEGIN_NAMESPACE
+static void setUIElementVisibility(IUIElement *uiElement, bool visibility)
+{
+ Q_ASSERT(uiElement);
+ QEventDispatcherWinRT::runOnXamlThread([uiElement, visibility]() {
+ HRESULT hr;
+ hr = uiElement->put_Visibility(visibility ? Visibility_Visible : Visibility_Collapsed);
+ Q_ASSERT_SUCCEEDED(hr);
+ return S_OK;
+ });
+}
+
class QWinRTWindowPrivate
{
public:
QSurfaceFormat surfaceFormat;
QString windowTitle;
+ Qt::WindowState state;
- ComPtr<Xaml::Controls::ISwapChainPanel> swapChainPanel;
+ ComPtr<ISwapChainPanel> swapChainPanel;
+ ComPtr<ICanvasStatics> canvas;
+ ComPtr<IUIElement> uiElement;
};
QWinRTWindow::QWinRTWindow(QWindow *window)
d->surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
HRESULT hr;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_Canvas).Get(),
+ IID_PPV_ARGS(&d->canvas));
+ Q_ASSERT_SUCCEEDED(hr);
hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
// Create a new swapchain and place it inside the canvas
HRESULT hr;
hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_SwapChainPanel).Get(),
&d->swapChainPanel);
Q_ASSERT_SUCCEEDED(hr);
- ComPtr<Xaml::IUIElement> uiElement;
- hr = d->swapChainPanel.As(&uiElement);
+ hr = d->swapChainPanel.As(&d->uiElement);
Q_ASSERT_SUCCEEDED(hr);
- ComPtr<Xaml::IDependencyObject> canvas = d->screen->canvas();
- ComPtr<Xaml::Controls::IPanel> panel;
+ ComPtr<IDependencyObject> canvas = d->screen->canvas();
+ ComPtr<IPanel> panel;
hr = canvas.As(&panel);
Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IVector<Xaml::UIElement *>> children;
+ ComPtr<IVector<UIElement *>> children;
hr = panel->get_Children(&children);
Q_ASSERT_SUCCEEDED(hr);
- hr = children->Append(uiElement.Get());
+ hr = children->Append(d->uiElement.Get());
Q_ASSERT_SUCCEEDED(hr);
return S_OK;
});
HRESULT hr;
hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
HRESULT hr;
- ComPtr<Xaml::IDependencyObject> canvas = d->screen->canvas();
- ComPtr<Xaml::Controls::IPanel> panel;
+ ComPtr<IDependencyObject> canvas = d->screen->canvas();
+ ComPtr<IPanel> panel;
hr = canvas.As(&panel);
Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IVector<Xaml::UIElement *>> children;
+ ComPtr<IVector<UIElement *>> children;
hr = panel->get_Children(&children);
Q_ASSERT_SUCCEEDED(hr);
- ComPtr<Xaml::IUIElement> uiElement;
- hr = d->swapChainPanel.As(&uiElement);
Q_ASSERT_SUCCEEDED(hr);
quint32 index;
boolean found;
- hr = children->IndexOf(uiElement.Get(), &index, &found);
+ hr = children->IndexOf(d->uiElement.Get(), &index, &found);
Q_ASSERT_SUCCEEDED(hr);
if (found) {
hr = children->RemoveAt(index);
Q_D(QWinRTWindow);
if (window()->isTopLevel()) {
- QPlatformWindow::setGeometry(d->screen->geometry());
+ QPlatformWindow::setGeometry(window()->flags() & Qt::MaximizeUsingFullscreenGeometryHint
+ ? d->screen->geometry() : d->screen->availableGeometry());
QWindowSystemInterface::handleGeometryChange(window(), geometry());
} else {
QPlatformWindow::setGeometry(rect);
HRESULT hr;
hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
HRESULT hr;
+ const QRect windowGeometry = geometry();
+ const QPointF topLeft= QPointF(windowGeometry.topLeft()) / d->screen->scaleFactor();
+ hr = d->canvas->SetTop(d->uiElement.Get(), topLeft.y());
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->canvas->SetLeft(d->uiElement.Get(), topLeft.x());
+ Q_ASSERT_SUCCEEDED(hr);
ComPtr<Xaml::IFrameworkElement> frameworkElement;
hr = d->swapChainPanel.As(&frameworkElement);
Q_ASSERT_SUCCEEDED(hr);
- const QSizeF size = QSizeF(geometry().size()) / d->screen->scaleFactor();
+ const QSizeF size = QSizeF(windowGeometry.size()) / d->screen->scaleFactor();
hr = frameworkElement->put_Width(size.width());
Q_ASSERT_SUCCEEDED(hr);
hr = frameworkElement->put_Height(size.height());
Q_D(QWinRTWindow);
if (!window()->isTopLevel())
return;
- if (visible)
+ if (visible) {
d->screen->addWindow(window());
- else
+ setUIElementVisibility(d->uiElement.Get(), d->state != Qt::WindowMinimized);
+ } else {
d->screen->removeWindow(window());
+ setUIElementVisibility(d->uiElement.Get(), false);
+ }
}
void QWinRTWindow::setWindowTitle(const QString &title)
return screen()->devicePixelRatio();
}
+void QWinRTWindow::setWindowState(Qt::WindowState state)
+{
+ Q_D(QWinRTWindow);
+ if (d->state == state)
+ return;
+
+#ifdef Q_OS_WINPHONE
+ d->screen->setStatusBarVisibility(state == Qt::WindowMaximized || state == Qt::WindowNoState, window());
+#endif
+
+ if (state == Qt::WindowMinimized)
+ setUIElementVisibility(d->uiElement.Get(), false);
+
+ if (d->state == Qt::WindowMinimized)
+ setUIElementVisibility(d->uiElement.Get(), true);
+
+ d->state = state;
+}
+
QT_END_NAMESPACE