Skip to content

Commit

Permalink
Support right-to-left layout on Windows (#762)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>

---------

Signed-off-by: Abdo <[email protected]>
  • Loading branch information
abdnh authored Jul 17, 2023
1 parent 9a32088 commit 4d0e186
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changes/windows-rtl.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tao": "patch"
---

Add `WindowExtWindows::set_rtl` and `WindowBuilderExtWindows::with_rtl` to set right-to-left layout on Windows.
19 changes: 19 additions & 0 deletions src/platform/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions src/platform_impl/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -64,6 +65,7 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
preferred_theme: None,
skip_taskbar: false,
decoration_shadow: true,
rtl: false,
}
}
}
Expand Down
13 changes: 13 additions & 0 deletions src/platform_impl/windows/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions src/platform_impl/windows/window_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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)
}
Expand Down

0 comments on commit 4d0e186

Please sign in to comment.