Support right-to-left layout on Windows (#762)

* Support right-to-left layout on Windows

* Make RTL platform-specific

* Document RTL support on Windows

* RTL -> RIGHT_TO_LEFT_LAYOUT

* Add line about what set_rtl exactly does

* Fix formatting

Signed-off-by: Abdo <abdo@abdnh.net>

---------

Signed-off-by: Abdo <abdo@abdnh.net>
This commit is contained in:
Abdo
2023-07-17 17:41:25 +03:00
committed by GitHub
parent 9a320882ed
commit 4d0e1862b6
5 changed files with 44 additions and 0 deletions

5
.changes/windows-rtl.md Normal file
View File

@@ -0,0 +1,5 @@
---
"tao": "patch"
---
Add `WindowExtWindows::set_rtl` and `WindowBuilderExtWindows::with_rtl` to set right-to-left layout on Windows.

View File

@@ -121,6 +121,11 @@ pub trait WindowExtWindows {
///
/// Enabling the shadow causes a thin 1px line to appear on the top of the window.
fn set_undecorated_shadow(&self, shadow: bool);
/// Sets right-to-left layout.
///
/// Enabling this mainly flips the orientation of menus and title bar buttons
fn set_rtl(&self, rtl: bool);
}
impl WindowExtWindows for Window {
@@ -170,6 +175,11 @@ impl WindowExtWindows for Window {
fn set_undecorated_shadow(&self, shadow: bool) {
self.window.set_undecorated_shadow(shadow)
}
#[inline]
fn set_rtl(&self, rtl: bool) {
self.window.set_rtl(rtl)
}
}
/// Additional methods on `WindowBuilder` that are specific to Windows.
@@ -226,6 +236,9 @@ pub trait WindowBuilderExtWindows {
/// The shadow is hidden by default.
/// Enabling the shadow causes a thin 1px line to appear on the top of the window.
fn with_undecorated_shadow(self, shadow: bool) -> WindowBuilder;
/// Sets right-to-left layout.
fn with_rtl(self, rtl: bool) -> WindowBuilder;
}
impl WindowBuilderExtWindows for WindowBuilder {
@@ -276,6 +289,12 @@ impl WindowBuilderExtWindows for WindowBuilder {
self.platform_specific.decoration_shadow = shadow;
self
}
#[inline]
fn with_rtl(mut self, rtl: bool) -> WindowBuilder {
self.platform_specific.rtl = rtl;
self
}
}
/// Additional methods on `MonitorHandle` that are specific to Windows.

View File

@@ -51,6 +51,7 @@ pub struct PlatformSpecificWindowBuilderAttributes {
pub drag_and_drop: bool,
pub preferred_theme: Option<Theme>,
pub decoration_shadow: bool,
pub rtl: bool,
}
impl Default for PlatformSpecificWindowBuilderAttributes {
@@ -64,6 +65,7 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
preferred_theme: None,
skip_taskbar: false,
decoration_shadow: true,
rtl: false,
}
}
}

View File

@@ -756,6 +756,17 @@ impl Window {
});
}
pub fn set_rtl(&self, rtl: bool) {
let window = self.window.clone();
let window_state = Arc::clone(&self.window_state);
self.thread_executor.execute_in_thread(move || {
WindowState::set_window_flags(window_state.lock(), window.0, |f| {
f.set(WindowFlags::RIGHT_TO_LEFT_LAYOUT, rtl)
});
});
}
#[inline]
pub fn current_monitor(&self) -> Option<RootMonitorHandle> {
Some(RootMonitorHandle {
@@ -1010,6 +1021,8 @@ unsafe fn init<T: 'static>(
window_flags.set(WindowFlags::MARKER_DONT_FOCUS, !attributes.focused);
window_flags.set(WindowFlags::RIGHT_TO_LEFT_LAYOUT, pl_attribs.rtl);
let parent = match pl_attribs.parent {
Parent::ChildOf(parent) => {
window_flags.set(WindowFlags::CHILD, true);

View File

@@ -107,6 +107,8 @@ bitflags! {
/// Drop shadow for undecorated windows.
const MARKER_UNDECORATED_SHADOW = 1 << 21;
const RIGHT_TO_LEFT_LAYOUT = 1 << 22;
const EXCLUSIVE_FULLSCREEN_OR_MASK = WindowFlags::ALWAYS_ON_TOP.bits;
}
}
@@ -269,6 +271,9 @@ impl WindowFlags {
) {
style &= !WS_OVERLAPPEDWINDOW;
}
if self.contains(WindowFlags::RIGHT_TO_LEFT_LAYOUT) {
style_ex |= WS_EX_LAYOUTRTL | WS_EX_RTLREADING | WS_EX_RIGHT;
}
(style, style_ex)
}