Skip to content

Commit

Permalink
Fixing TabViewItem sub-pixel bugs (#7174)
Browse files Browse the repository at this point in the history
* Fixing TabViewItem sub-pixel bugs

* Scope fix to post RS5 OS release
  • Loading branch information
RBrid authored Jun 6, 2022
1 parent ab27840 commit 76d8ebe
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 17 deletions.
57 changes: 53 additions & 4 deletions dev/TabView/TabViewItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,31 @@ TabViewItem::TabViewItem()

void TabViewItem::OnApplyTemplate()
{
__super::OnApplyTemplate();

winrt::IControlProtected controlProtected{ *this };

m_selectedBackgroundPathSizeChangedRevoker.revoke();
m_closeButtonClickRevoker.revoke();
m_tabDragStartingRevoker.revoke();
m_tabDragCompletedRevoker.revoke();

if (SharedHelpers::Is19H1OrHigher()) // UIElement.ActualOffset introduced in Win10 1903.
{
m_selectedBackgroundPath.set(GetTemplateChildT<winrt::Path>(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<winrt::ContentPresenter>(L"ContentPresenter", controlProtected));

auto tabView = SharedHelpers::GetAncestorOfType<winrt::TabView>(winrt::VisualTreeHelper::GetParent(*this));
Expand Down Expand Up @@ -115,14 +138,14 @@ void TabViewItem::UpdateTabGeometry()

// Assumes 4px curving-out corners, which are hardcoded in the markup
auto data = L"<Geometry xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>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</Geometry>";

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<winrt::Geometry>();

Expand Down Expand Up @@ -206,6 +229,33 @@ void TabViewItem::UpdateShadow()
}
}

void TabViewItem::UpdateSelectedBackgroundPathTranslateTransform()
{
MUX_ASSERT(SharedHelpers::Is19H1OrHigher());

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)
{
Expand Down Expand Up @@ -427,7 +477,6 @@ void TabViewItem::HideLeftAdjacentTabSeparator()
const auto index = internalTabView->IndexFromContainer(*this);
internalTabView->SetTabSeparatorOpacity(index - 1, 0);
}

}

void TabViewItem::RestoreLeftAdjacentTabSeparatorVisibility()
Expand Down
29 changes: 16 additions & 13 deletions dev/TabView/TabViewItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,6 @@ class TabViewItem :
void StartBringTabIntoView();

private:
tracker_ref<winrt::Button> m_closeButton{ this };
tracker_ref<winrt::ToolTip> m_toolTip{ this };
tracker_ref<winrt::ContentPresenter> m_headerContentPresenter{ this };
winrt::TabViewWidthMode m_tabViewWidthMode{ winrt::TabViewWidthMode::Equal };
winrt::TabViewCloseButtonOverlayMode m_closeButtonOverlayMode{ winrt::TabViewCloseButtonOverlayMode::Auto };

void UpdateCloseButton();
void UpdateForeground();
void RequestClose();
Expand All @@ -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);
Expand All @@ -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<winrt::Path> m_selectedBackgroundPath{ this };
tracker_ref<winrt::Button> m_closeButton{ this };
tracker_ref<winrt::ToolTip> m_toolTip{ this };
tracker_ref<winrt::ContentPresenter> 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<winrt::TabView> m_parentTabView{ nullptr };
Expand Down

0 comments on commit 76d8ebe

Please sign in to comment.