Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing TabViewItem sub-pixel bugs #7174

Merged
merged 2 commits into from
Jun 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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