From 666614bd6186f497fdff56b888548dd4ec95f9e1 Mon Sep 17 00:00:00 2001 From: Regis Brid Date: Tue, 31 May 2022 18:51:17 -0700 Subject: [PATCH 1/2] Fixing TabViewItem sub-pixel bugs --- dev/TabView/TabViewItem.cpp | 52 ++++++++++++++++++++++++++++++++++--- dev/TabView/TabViewItem.h | 29 +++++++++++---------- 2 files changed, 64 insertions(+), 17 deletions(-) diff --git a/dev/TabView/TabViewItem.cpp b/dev/TabView/TabViewItem.cpp index fd473f0580..be321b7eb9 100644 --- a/dev/TabView/TabViewItem.cpp +++ b/dev/TabView/TabViewItem.cpp @@ -30,8 +30,28 @@ TabViewItem::TabViewItem() void TabViewItem::OnApplyTemplate() { + __super::OnApplyTemplate(); + winrt::IControlProtected controlProtected{ *this }; + m_selectedBackgroundPathSizeChangedRevoker.revoke(); + m_closeButtonClickRevoker.revoke(); + m_tabDragStartingRevoker.revoke(); + m_tabDragCompletedRevoker.revoke(); + + m_selectedBackgroundPath.set(GetTemplateChildT(L"SelectedBackgroundPath", controlProtected)); + + if (const auto selectedBackgroundPath = m_selectedBackgroundPath.get()) + { + m_selectedBackgroundPathSizeChangedRevoker = selectedBackgroundPath.SizeChanged(winrt::auto_revoke, + { + [this](auto const&, auto const&) + { + UpdateSelectedBackgroundPathTranslateTransform(); + } + }); + } + m_headerContentPresenter.set(GetTemplateChildT(L"ContentPresenter", controlProtected)); auto tabView = SharedHelpers::GetAncestorOfType(winrt::VisualTreeHelper::GetParent(*this)); @@ -115,14 +135,14 @@ void TabViewItem::UpdateTabGeometry() // Assumes 4px curving-out corners, which are hardcoded in the markup auto data = L"F1 M0,%f a 4,4 0 0 0 4,-4 L 4,%f a %f,%f 0 0 1 %f,-%f l %f,0 a %f,%f 0 0 1 %f,%f l 0,%f a 4,4 0 0 0 4,4 Z"; - + WCHAR strOut[1024]; StringCchPrintf(strOut, ARRAYSIZE(strOut), data, - height - 1.0f / scaleFactor, + height - 1.0, leftCorner, leftCorner, leftCorner, leftCorner, leftCorner, ActualWidth() - (leftCorner + rightCorner + 1.0f / scaleFactor), rightCorner, rightCorner, rightCorner, rightCorner, - height - (4 + rightCorner + 1.0f / scaleFactor)); + height - (5.0 + rightCorner)); const auto geometry = winrt::XamlReader::Load(strOut).try_as(); @@ -206,6 +226,31 @@ void TabViewItem::UpdateShadow() } } +void TabViewItem::UpdateSelectedBackgroundPathTranslateTransform() +{ + if (const auto selectedBackgroundPath = m_selectedBackgroundPath.get()) + { + const auto selectedBackgroundPathActualOffset = selectedBackgroundPath.ActualOffset(); + const auto roundedSelectedBackgroundPathActualOffsetY = std::round(selectedBackgroundPathActualOffset.y); + + if (roundedSelectedBackgroundPathActualOffsetY > selectedBackgroundPathActualOffset.y) + { + // Move the SelectedBackgroundPath element down by a fraction of a pixel to avoid a faint gap line + // between the selected TabViewItem and its content. + winrt::TranslateTransform translateTransform; + + translateTransform.Y(roundedSelectedBackgroundPathActualOffsetY - selectedBackgroundPathActualOffset.y); + + selectedBackgroundPath.RenderTransform(translateTransform); + } + else if (selectedBackgroundPath.RenderTransform()) + { + // Reset any TranslateTransform that may have been set above. + selectedBackgroundPath.RenderTransform(nullptr); + } + } +} + void TabViewItem::OnTabDragStarting(const winrt::IInspectable& sender, const winrt::TabViewTabDragStartingEventArgs& args) { @@ -427,7 +472,6 @@ void TabViewItem::HideLeftAdjacentTabSeparator() const auto index = internalTabView->IndexFromContainer(*this); internalTabView->SetTabSeparatorOpacity(index - 1, 0); } - } void TabViewItem::RestoreLeftAdjacentTabSeparatorVisibility() diff --git a/dev/TabView/TabViewItem.h b/dev/TabView/TabViewItem.h index 5b4abc1b67..43dedf0e6d 100755 --- a/dev/TabView/TabViewItem.h +++ b/dev/TabView/TabViewItem.h @@ -48,12 +48,6 @@ class TabViewItem : void StartBringTabIntoView(); private: - tracker_ref m_closeButton{ this }; - tracker_ref m_toolTip{ this }; - tracker_ref m_headerContentPresenter{ this }; - winrt::TabViewWidthMode m_tabViewWidthMode{ winrt::TabViewWidthMode::Equal }; - winrt::TabViewCloseButtonOverlayMode m_closeButtonOverlayMode{ winrt::TabViewCloseButtonOverlayMode::Auto }; - void UpdateCloseButton(); void UpdateForeground(); void RequestClose(); @@ -64,12 +58,6 @@ class TabViewItem : void OnSizeChanged(const winrt::IInspectable&, const winrt::SizeChangedEventArgs& args); void UpdateTabGeometry(); - bool m_firstTimeSettingToolTip{ true }; - - winrt::ButtonBase::Click_revoker m_closeButtonClickRevoker{}; - winrt::TabView::TabDragStarting_revoker m_tabDragStartingRevoker{}; - winrt::TabView::TabDragCompleted_revoker m_tabDragCompletedRevoker{}; - void OnCloseButtonClick(const winrt::IInspectable& sender, const winrt::RoutedEventArgs& args); void OnIsSelectedPropertyChanged(const winrt::DependencyObject& sender, const winrt::DependencyProperty& args); @@ -81,12 +69,27 @@ class TabViewItem : void HideLeftAdjacentTabSeparator(); void RestoreLeftAdjacentTabSeparatorVisibility(); + void UpdateShadow(); + void UpdateSelectedBackgroundPathTranslateTransform(); + bool m_hasPointerCapture = false; bool m_isMiddlePointerButtonPressed = false; bool m_isDragging = false; bool m_isPointerOver = false; + bool m_firstTimeSettingToolTip{ true }; + + tracker_ref m_selectedBackgroundPath{ this }; + tracker_ref m_closeButton{ this }; + tracker_ref m_toolTip{ this }; + tracker_ref m_headerContentPresenter{ this }; + winrt::TabViewWidthMode m_tabViewWidthMode{ winrt::TabViewWidthMode::Equal }; + winrt::TabViewCloseButtonOverlayMode m_closeButtonOverlayMode{ winrt::TabViewCloseButtonOverlayMode::Auto }; + + winrt::FrameworkElement::SizeChanged_revoker m_selectedBackgroundPathSizeChangedRevoker{}; + winrt::ButtonBase::Click_revoker m_closeButtonClickRevoker{}; + winrt::TabView::TabDragStarting_revoker m_tabDragStartingRevoker{}; + winrt::TabView::TabDragCompleted_revoker m_tabDragCompletedRevoker{}; - void UpdateShadow(); winrt::IInspectable m_shadow{ nullptr }; winrt::weak_ref m_parentTabView{ nullptr }; From f925bb0ac1825aa4150f13481a45b7f3b73ec6bc Mon Sep 17 00:00:00 2001 From: Regis Brid Date: Thu, 2 Jun 2022 10:17:34 -0700 Subject: [PATCH 2/2] Scope fix to post RS5 OS release --- dev/TabView/TabViewItem.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/dev/TabView/TabViewItem.cpp b/dev/TabView/TabViewItem.cpp index be321b7eb9..1670474465 100644 --- a/dev/TabView/TabViewItem.cpp +++ b/dev/TabView/TabViewItem.cpp @@ -39,17 +39,20 @@ void TabViewItem::OnApplyTemplate() m_tabDragStartingRevoker.revoke(); m_tabDragCompletedRevoker.revoke(); - m_selectedBackgroundPath.set(GetTemplateChildT(L"SelectedBackgroundPath", controlProtected)); - - if (const auto selectedBackgroundPath = m_selectedBackgroundPath.get()) + if (SharedHelpers::Is19H1OrHigher()) // UIElement.ActualOffset introduced in Win10 1903. { - m_selectedBackgroundPathSizeChangedRevoker = selectedBackgroundPath.SizeChanged(winrt::auto_revoke, + m_selectedBackgroundPath.set(GetTemplateChildT(L"SelectedBackgroundPath", controlProtected)); + + if (const auto selectedBackgroundPath = m_selectedBackgroundPath.get()) { - [this](auto const&, auto const&) + m_selectedBackgroundPathSizeChangedRevoker = selectedBackgroundPath.SizeChanged(winrt::auto_revoke, { - UpdateSelectedBackgroundPathTranslateTransform(); - } - }); + [this](auto const&, auto const&) + { + UpdateSelectedBackgroundPathTranslateTransform(); + } + }); + } } m_headerContentPresenter.set(GetTemplateChildT(L"ContentPresenter", controlProtected)); @@ -228,6 +231,8 @@ void TabViewItem::UpdateShadow() void TabViewItem::UpdateSelectedBackgroundPathTranslateTransform() { + MUX_ASSERT(SharedHelpers::Is19H1OrHigher()); + if (const auto selectedBackgroundPath = m_selectedBackgroundPath.get()) { const auto selectedBackgroundPathActualOffset = selectedBackgroundPath.ActualOffset();