Improve RTL Developer Scenarios for WinUI
Describe the bug
Currently in WinUI, there is no easy way to handle RTL scenarios. If a RTL language is set on the OS, it is up to the developer to handle that event listener. They would have to set the FlowDirection property and update the language on the app.
There is little to no documentation explaining this developer experience gap nor the workaround. As a result, most apps are just not RTL friendly, and that is a huge gap in accessibility and inclusitivity.
This task includes:
-
[ ] Improve documentation explaining the workaround in the interim.
-
[ ] Investigate how to better improve RTL scenarios
- Whether the code should live in XamlWindow or elsewhere.
- How to check if the app has the correct language localized to mirror the OS settings. Windows developer guidelines state that if the default is a LTR language, it should not become RTL just to mirror the OS.
-
[ ] Update AppWindow to automatically change captionButton orientation for RTL so developers don't have to use the Win32 workaround.
Internal Bug: 56332666, 56332722
Screenshots
NuGet package version
WinUI 3 - Windows App SDK 1.7 Preview 1: 1.7.250208002-preview1
Windows version
Windows Insider Build (xxxxx)
Additional context
No response
TitleBar listens to FlowDirection property changed to be configured into RTL. You would also need to set the caption buttons to the opposite side via Win32 APIs. The sample will be included in WinUI-Gallery, but I am happy to share it here in the mean time.
TitleBarPageWindowGrid.FlowDirection = FlowDirection.RightToLeft;
UpdateCaptionButtonDirection(TitleBarPageWindowGrid.FlowDirection);
private static nint GetWindowHandleForCurrentWindow(object target) =>
WinRT.Interop.WindowNative.GetWindowHandle(target);
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
internal static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, nint newProc);
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
internal static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
private void UpdateCaptionButtonDirection(FlowDirection direction)
{
var hwnd = GetWindowHandleForCurrentWindow(this);
if (hwnd != 0)
{
var exStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
if (direction == FlowDirection.RightToLeft)
{
exStyle |= WS_EX_LAYOUTRTL;
}
else
{
exStyle &= ~WS_EX_LAYOUTRTL;
}
SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle);
}
}
Note that there is an ongoing issue with padding when toggling LTR / RTL back and forth. This fix is blocked on AppWindowTitleBar.LeftInset / RightInset APIs.
@karkarl I think we should leave this open to track adding this to TitleBar rather than dismiss this as the final solution. The whole point of TitleBar was to simplify the developer experience for implementing the modern title bar.
I strongly recommend against including this as a sample in the WinUI gallery.
I agree. This shouldn’t be code you need to ask users to do. They’ll just not do it and fail in RTL mode
I agree with you all. A task is tracked internally to remove the needed overhead for future iterations. However, this code is needed as a workaround in the interim.
Do you mind if I update the title and description to track this?
I've posted an updated on the TitleBar API Spec Review PR as an FYI: https://github.com/microsoft/microsoft-ui-xaml/pull/10056#issuecomment-2660578450
FYI as its important to the discussion, the doc on RTL does call out how it's not something that is automatically updated (like theming is) and must be enabled by the developer (i.e. setting flow direction based on language): https://learn.microsoft.com/windows/apps/design/globalizing/adjust-layout-and-fonts--and-support-rtl#handling-right-to-left-rtl-languages
[!IMPORTANT] However, FlowDirection is not set automatically based on the user's selected display language in Windows settings; nor does it change dynamically in response to the user switching display language. If the user switches Windows settings from English to Arabic, for example, then the FlowDirection property will not automatically change from left-to-right to right-to-left. As the app developer, you have to set FlowDirection appropriately for the language that you are currently displaying.
Agree that it'd be nice if there was at least a better event to help developer detect this and just easily swap a property at their app root or what not.
I've re-opened issue and updated the description to better reflect the task being tracked.
@michael-hawker That's fair. In WPF, we also tap into CultureInfo.CurrentUICulture.TextInfo.IsRightToLeft and adjust flow direction manually.
Re-opening due to conversation with @Avid29 who was adding Hebrew to his app and running into these gaps. cc: @beth-panx