Desktop: Mac menu workaround (#3398)

This commit is contained in:
Timon 2025-11-19 17:13:35 +00:00 committed by GitHub
parent 788e82a7d0
commit 548e0df1a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 139 additions and 122 deletions

147
Cargo.lock generated
View File

@ -1695,16 +1695,6 @@ dependencies = [
"bytemuck", "bytemuck",
] ]
[[package]]
name = "fontconfig-cache-parser"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7f8afb20c8069fd676d27b214559a337cc619a605d25a87baa90b49a06f3b18"
dependencies = [
"bytemuck",
"thiserror 1.0.69",
]
[[package]] [[package]]
name = "fontconfig-parser" name = "fontconfig-parser"
version = "0.5.8" version = "0.5.8"
@ -1744,25 +1734,25 @@ dependencies = [
[[package]] [[package]]
name = "fontique" name = "fontique"
version = "0.5.0" version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39f97079e1293b8c1e9fb03a2875d328bd2ee8f3b95ce62959c0acc04049c708" checksum = "ff3336bc0b87fe42305047263fa60d2eabd650d29cbe62fdeb2a66c7a0a595f9"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
"fontconfig-cache-parser",
"hashbrown 0.15.5", "hashbrown 0.15.5",
"icu_locid", "icu_locale_core",
"linebender_resource_handle",
"memmap2", "memmap2",
"objc2", "objc2",
"objc2-core-foundation", "objc2-core-foundation",
"objc2-core-text", "objc2-core-text",
"objc2-foundation", "objc2-foundation",
"peniko 0.4.0", "read-fonts 0.35.0",
"read-fonts 0.29.3",
"roxmltree", "roxmltree",
"smallvec", "smallvec",
"windows", "windows",
"windows-core 0.58.0", "windows-core 0.58.0",
"yeslogic-fontconfig-sys",
] ]
[[package]] [[package]]
@ -2265,6 +2255,9 @@ dependencies = [
"graphite-desktop-embedded-resources", "graphite-desktop-embedded-resources",
"graphite-desktop-wrapper", "graphite-desktop-wrapper",
"muda", "muda",
"objc2",
"objc2-app-kit",
"objc2-foundation",
"open", "open",
"rand 0.9.2", "rand 0.9.2",
"rfd", "rfd",
@ -2446,6 +2439,19 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "harfrust"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92c020db12c71d8a12a3fe7607873cade3a01a6287e29d540c8723276221b9d8"
dependencies = [
"bitflags 2.9.3",
"bytemuck",
"core_maths",
"read-fonts 0.35.0",
"smallvec",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.15.5" version = "0.15.5"
@ -2691,24 +2697,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"
dependencies = [ dependencies = [
"displaydoc", "displaydoc",
"litemap 0.8.0", "litemap",
"tinystr 0.8.1", "tinystr",
"writeable 0.6.1", "writeable",
"zerovec", "zerovec",
] ]
[[package]]
name = "icu_locid"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
dependencies = [
"displaydoc",
"litemap 0.7.5",
"tinystr 0.7.6",
"writeable 0.5.5",
]
[[package]] [[package]]
name = "icu_normalizer" name = "icu_normalizer"
version = "2.0.0" version = "2.0.0"
@ -2761,8 +2755,8 @@ dependencies = [
"displaydoc", "displaydoc",
"icu_locale_core", "icu_locale_core",
"stable_deref_trait", "stable_deref_trait",
"tinystr 0.8.1", "tinystr",
"writeable 0.6.1", "writeable",
"yoke", "yoke",
"zerofrom", "zerofrom",
"zerotrie", "zerotrie",
@ -3236,12 +3230,6 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
[[package]]
name = "litemap"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
[[package]] [[package]]
name = "litemap" name = "litemap"
version = "0.8.0" version = "0.8.0"
@ -3811,9 +3799,9 @@ dependencies = [
[[package]] [[package]]
name = "objc2-core-text" name = "objc2-core-text"
version = "0.3.1" version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ba833d4a1cb1aac330f8c973fd92b6ff1858e4aef5cdd00a255eefb28022fb5" checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
dependencies = [ dependencies = [
"bitflags 2.9.3", "bitflags 2.9.3",
"objc2-core-foundation", "objc2-core-foundation",
@ -4038,14 +4026,15 @@ dependencies = [
[[package]] [[package]]
name = "parley" name = "parley"
version = "0.5.0" version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13e57638545cf2ba4c3e72cc5715e53b1880b829cc3dbefda3d1700c58efe723" checksum = "26746861bb76dbc9bcd5ed1b0b55d2fedf291100961251702a031ab2abd2ce52"
dependencies = [ dependencies = [
"fontique", "fontique",
"harfrust",
"hashbrown 0.15.5", "hashbrown 0.15.5",
"peniko 0.4.0", "linebender_resource_handle",
"skrifa 0.31.3", "skrifa 0.37.0",
"swash", "swash",
] ]
@ -4095,17 +4084,6 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
[[package]]
name = "peniko"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f9529efd019889b2a205193c14ffb6e2839b54ed9d2720674f10f4b04d87ac9"
dependencies = [
"color",
"kurbo 0.11.3",
"smallvec",
]
[[package]] [[package]]
name = "peniko" name = "peniko"
version = "0.5.0" version = "0.5.0"
@ -4769,16 +4747,6 @@ dependencies = [
"crossbeam-utils", "crossbeam-utils",
] ]
[[package]]
name = "read-fonts"
version = "0.29.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04ca636dac446b5664bd16c069c00a9621806895b8bb02c2dc68542b23b8f25d"
dependencies = [
"bytemuck",
"font-types 0.9.0",
]
[[package]] [[package]]
name = "read-fonts" name = "read-fonts"
version = "0.34.0" version = "0.34.0"
@ -4796,6 +4764,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6717cf23b488adf64b9d711329542ba34de147df262370221940dfabc2c91358" checksum = "6717cf23b488adf64b9d711329542ba34de147df262370221940dfabc2c91358"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
"core_maths",
"font-types 0.10.0", "font-types 0.10.0",
] ]
@ -5434,16 +5403,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
[[package]]
name = "skrifa"
version = "0.31.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbeb4ca4399663735553a09dd17ce7e49a0a0203f03b706b39628c4d913a8607"
dependencies = [
"bytemuck",
"read-fonts 0.29.3",
]
[[package]] [[package]]
name = "skrifa" name = "skrifa"
version = "0.36.0" version = "0.36.0"
@ -5715,11 +5674,11 @@ dependencies = [
[[package]] [[package]]
name = "swash" name = "swash"
version = "0.2.5" version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f745de914febc7c9ab4388dfaf94bbc87e69f57bb41133a9b0c84d4be49856f3" checksum = "47846491253e976bdd07d0f9cc24b7daf24720d11309302ccbbc6e6b6e53550a"
dependencies = [ dependencies = [
"skrifa 0.31.3", "skrifa 0.37.0",
"yazi", "yazi",
"zeno", "zeno",
] ]
@ -5971,15 +5930,6 @@ dependencies = [
"strict-num", "strict-num",
] ]
[[package]]
name = "tinystr"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
dependencies = [
"displaydoc",
]
[[package]] [[package]]
name = "tinystr" name = "tinystr"
version = "0.8.1" version = "0.8.1"
@ -6580,7 +6530,7 @@ dependencies = [
"bytemuck", "bytemuck",
"futures-intrusive", "futures-intrusive",
"log", "log",
"peniko 0.5.0", "peniko",
"png", "png",
"skrifa 0.37.0", "skrifa 0.37.0",
"static_assertions", "static_assertions",
@ -6597,7 +6547,7 @@ source = "git+https://github.com/linebender/vello#8f2f2564127812362d2c57ded20cad
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
"guillotiere", "guillotiere",
"peniko 0.5.0", "peniko",
"skrifa 0.37.0", "skrifa 0.37.0",
"smallvec", "smallvec",
] ]
@ -7715,12 +7665,6 @@ version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814" checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814"
[[package]]
name = "writeable"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
[[package]] [[package]]
name = "writeable" name = "writeable"
version = "0.6.1" version = "0.6.1"
@ -7819,6 +7763,17 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5" checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5"
[[package]]
name = "yeslogic-fontconfig-sys"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "503a066b4c037c440169d995b869046827dbc71263f6e8f3be6d77d4f3229dbd"
dependencies = [
"dlib",
"once_cell",
"pkg-config",
]
[[package]] [[package]]
name = "yoke" name = "yoke"
version = "0.8.0" version = "0.8.0"

View File

@ -182,7 +182,7 @@ image = { version = "0.25", default-features = false, features = [
"jpeg", "jpeg",
"bmp", "bmp",
] } ] }
parley = "0.5" parley = "0.6"
skrifa = "0.36" skrifa = "0.36"
pretty_assertions = "1.4" pretty_assertions = "1.4"
fern = { version = "0.7", features = ["colored"] } fern = { version = "0.7", features = ["colored"] }

View File

@ -58,5 +58,8 @@ windows = { version = "0.58.0", features = [
# macOS-specific dependencies # macOS-specific dependencies
[target.'cfg(target_os = "macos")'.dependencies] [target.'cfg(target_os = "macos")'.dependencies]
objc2 = { version = "0.6.1", default-features = false }
objc2-foundation = { version = "0.3.2", default-features = false }
objc2-app-kit = { version = "0.3.2", default-features = false }
muda = { git = "https://github.com/tauri-apps/muda.git", rev = "3f460b8fbaed59cda6d95ceea6904f000f093f15", default-features = false } muda = { git = "https://github.com/tauri-apps/muda.git", rev = "3f460b8fbaed59cda6d95ceea6904f000f093f15", default-features = false }

View File

@ -44,6 +44,10 @@ pub(crate) struct App {
} }
impl App { impl App {
pub(crate) fn init() {
Window::init();
}
pub(crate) fn new( pub(crate) fn new(
cef_context: Box<dyn cef::CefContext>, cef_context: Box<dyn cef::CefContext>,
cef_view_info_sender: Sender<cef::ViewInfoUpdate>, cef_view_info_sender: Sender<cef::ViewInfoUpdate>,

View File

@ -88,11 +88,27 @@ pub(crate) fn handle_window_event(browser: &Browser, input_state: &mut InputStat
key_event.native_key_code = event.physical_key.to_native_keycode(); key_event.native_key_code = event.physical_key.to_native_keycode();
key_event.character = event.logical_key.to_char_representation() as u16; key_event.character = event.logical_key.to_char_representation() as u16;
key_event.unmodified_character = event.key_without_modifiers.to_char_representation() as u16;
// Mitigation for CEF on Mac bug to prevent NSMenu being triggered by this key event.
//
// CEF converts the key event into an `NSEvent` internally and passes that to Chromium.
// In some cases the `NSEvent` gets to the native Cocoa application, is considered "unhandled" and can trigger menus.
//
// Why mitigation works:
// Leaving `key_event.unmodified_character = 0` still leads to CEF forwarding a "unhandled" event to the native application
// but that event is discarded because `key_event.unmodified_character = 0` is considered non-printable and not used for shortcut matching.
//
// See https://github.com/chromiumembedded/cef/issues/3857
//
// TODO: Remove mitigation once bug is fixed or a better solution is found.
#[cfg(not(target_os = "macos"))]
{
key_event.unmodified_character = event.key_without_modifiers.to_char_representation() as u16;
}
#[cfg(target_os = "macos")] // See https://www.magpcss.org/ceforum/viewtopic.php?start=10&t=11650 #[cfg(target_os = "macos")] // See https://www.magpcss.org/ceforum/viewtopic.php?start=10&t=11650
if key_event.character == 0 && key_event.unmodified_character == 0 && event.text_with_all_modifiers.is_some() { if key_event.character == 0 && key_event.unmodified_character == 0 && event.text_with_all_modifiers.is_some() {
key_event.unmodified_character = 1; key_event.character = 1;
} }
if key_event.type_ == cef_key_event_type_t::KEYEVENT_CHAR.into() { if key_event.type_ == cef_key_event_type_t::KEYEVENT_CHAR.into() {

View File

@ -36,6 +36,8 @@ pub fn start() {
return; return;
} }
App::init();
let cli = Cli::parse(); let cli = Cli::parse();
let wgpu_context = futures::executor::block_on(gpu_context::create_wgpu_context()); let wgpu_context = futures::executor::block_on(gpu_context::create_wgpu_context());

View File

@ -4,9 +4,11 @@ use winit::window::{Window as WinitWindow, WindowAttributes};
use crate::consts::APP_NAME; use crate::consts::APP_NAME;
use crate::event::AppEventScheduler; use crate::event::AppEventScheduler;
use crate::window::mac::NativeWindowImpl;
use crate::wrapper::messages::MenuItem; use crate::wrapper::messages::MenuItem;
pub(crate) trait NativeWindow { pub(crate) trait NativeWindow {
fn init() {}
fn configure(attributes: WindowAttributes, event_loop: &dyn ActiveEventLoop) -> WindowAttributes; fn configure(attributes: WindowAttributes, event_loop: &dyn ActiveEventLoop) -> WindowAttributes;
fn new(window: &dyn WinitWindow, app_event_scheduler: AppEventScheduler) -> Self; fn new(window: &dyn WinitWindow, app_event_scheduler: AppEventScheduler) -> Self;
fn update_menu(&self, _entries: Vec<MenuItem>) {} fn update_menu(&self, _entries: Vec<MenuItem>) {}
@ -34,6 +36,10 @@ pub(crate) struct Window {
} }
impl Window { impl Window {
pub(crate) fn init() {
NativeWindowImpl::init();
}
pub(crate) fn new(event_loop: &dyn ActiveEventLoop, app_event_scheduler: AppEventScheduler) -> Self { pub(crate) fn new(event_loop: &dyn ActiveEventLoop, app_event_scheduler: AppEventScheduler) -> Self {
let mut attributes = WindowAttributes::default() let mut attributes = WindowAttributes::default()
.with_title(APP_NAME) .with_title(APP_NAME)

View File

@ -2,15 +2,21 @@ use winit::event_loop::ActiveEventLoop;
use winit::platform::macos::WindowAttributesMacOS; use winit::platform::macos::WindowAttributesMacOS;
use winit::window::{Window, WindowAttributes}; use winit::window::{Window, WindowAttributes};
use crate::consts::APP_NAME;
use crate::event::AppEventScheduler; use crate::event::AppEventScheduler;
use crate::wrapper::messages::MenuItem; use crate::wrapper::messages::MenuItem;
mod app;
mod menu;
pub(super) struct NativeWindowImpl { pub(super) struct NativeWindowImpl {
menu: menu::Menu, menu: menu::Menu,
} }
impl super::NativeWindow for NativeWindowImpl { impl super::NativeWindow for NativeWindowImpl {
fn init() {
app::init();
}
fn configure(attributes: WindowAttributes, _event_loop: &dyn ActiveEventLoop) -> WindowAttributes { fn configure(attributes: WindowAttributes, _event_loop: &dyn ActiveEventLoop) -> WindowAttributes {
let mac_window = WindowAttributesMacOS::default() let mac_window = WindowAttributesMacOS::default()
.with_titlebar_transparent(true) .with_titlebar_transparent(true)
@ -20,7 +26,7 @@ impl super::NativeWindow for NativeWindowImpl {
} }
fn new(_window: &dyn Window, app_event_scheduler: AppEventScheduler) -> Self { fn new(_window: &dyn Window, app_event_scheduler: AppEventScheduler) -> Self {
let menu = menu::Menu::new(app_event_scheduler, APP_NAME); let menu = menu::Menu::new(app_event_scheduler);
NativeWindowImpl { menu } NativeWindowImpl { menu }
} }
@ -29,5 +35,3 @@ impl super::NativeWindow for NativeWindowImpl {
self.menu.update(entries); self.menu.update(entries);
} }
} }
mod menu;

View File

@ -0,0 +1,27 @@
use objc2::{ClassType, define_class, msg_send};
use objc2_app_kit::{NSApplication, NSEvent, NSEventType, NSResponder};
use objc2_foundation::NSObject;
pub(super) fn init() {
unsafe {
let _: &NSApplication = msg_send![GraphiteApplication::class(), sharedApplication];
}
}
define_class!(
#[unsafe(super(NSApplication, NSResponder, NSObject))]
#[name = "GraphiteApplication"]
pub(super) struct GraphiteApplication;
impl GraphiteApplication {
#[unsafe(method(sendEvent:))]
fn send_event(&self, event: &NSEvent) {
// Route keyDown events straight to the key window to skip native menu shortcut handling.
if event.r#type() == NSEventType::KeyDown && let Some(key_window) = self.keyWindow() {
unsafe { msg_send![&key_window, sendEvent: event] }
} else {
unsafe { msg_send![super(self), sendEvent: event] }
}
}
}
);

View File

@ -1,6 +1,6 @@
use muda::Menu as MudaMenu; use muda::Menu as MudaMenu;
use muda::accelerator::Accelerator; use muda::accelerator::Accelerator;
use muda::{AboutMetadataBuilder, CheckMenuItem, IsMenuItem, MenuEvent, MenuId, MenuItem, MenuItemKind, PredefinedMenuItem, Result, Submenu}; use muda::{CheckMenuItem, IsMenuItem, MenuEvent, MenuId, MenuItem, MenuItemKind, PredefinedMenuItem, Result, Submenu};
use crate::event::{AppEvent, AppEventScheduler}; use crate::event::{AppEvent, AppEventScheduler};
use crate::wrapper::messages::MenuItem as WrapperMenuItem; use crate::wrapper::messages::MenuItem as WrapperMenuItem;
@ -10,18 +10,9 @@ pub(super) struct Menu {
} }
impl Menu { impl Menu {
pub(super) fn new(event_scheduler: AppEventScheduler, app_name: &str) -> Self { pub(super) fn new(event_scheduler: AppEventScheduler) -> Self {
let about = PredefinedMenuItem::about(None, Some(AboutMetadataBuilder::new().name(Some(app_name)).build())); // TODO: Remove as much app submenu special handling as possible
let hide = PredefinedMenuItem::hide(None); let app_submenu = Submenu::with_items("", true, &[]).unwrap();
let hide_others = PredefinedMenuItem::hide_others(None);
let show_all = PredefinedMenuItem::show_all(None);
let quit = PredefinedMenuItem::quit(None);
let app_submenu = Submenu::with_items(
"",
true,
&[&about, &PredefinedMenuItem::separator(), &hide, &hide_others, &show_all, &PredefinedMenuItem::separator(), &quit],
)
.unwrap();
let menu = MudaMenu::new(); let menu = MudaMenu::new();
menu.prepend(&app_submenu).unwrap(); menu.prepend(&app_submenu).unwrap();
@ -29,6 +20,16 @@ impl Menu {
menu.init_for_nsapp(); menu.init_for_nsapp();
MenuEvent::set_event_handler(Some(move |event: MenuEvent| { MenuEvent::set_event_handler(Some(move |event: MenuEvent| {
let mtm = objc2::MainThreadMarker::new().expect("only ever called from main thread");
let is_shortcut_triggered = objc2_app_kit::NSApplication::sharedApplication(mtm)
.mainMenu()
.map(|m| m.highlightedItem().is_some())
.unwrap_or_default();
if is_shortcut_triggered {
tracing::error!("A keyboard input triggered a menu event. This is most likely a bug. Please report!");
return;
}
if let Some(id) = menu_id_to_u64(event.id()) { if let Some(id) = menu_id_to_u64(event.id()) {
event_scheduler.schedule(AppEvent::MenuEvent { id }); event_scheduler.schedule(AppEvent::MenuEvent { id });
} }

View File

@ -164,8 +164,7 @@ fn convert_menu_bar_entry_to_menu_item(
} }
let shortcut = match shortcut { let shortcut = match shortcut {
//TODO: Reenable shortcuts once a workaround for missing keyboard events is found Some(ActionKeys::Keys(LayoutKeysGroup(keys))) => convert_layout_keys_to_shortcut(keys),
Some(ActionKeys::Keys(LayoutKeysGroup(keys))) if false => convert_layout_keys_to_shortcut(keys),
_ => None, _ => None,
}; };

View File

@ -26,9 +26,9 @@ impl From<TextAlign> for parley::Alignment {
fn from(val: TextAlign) -> Self { fn from(val: TextAlign) -> Self {
match val { match val {
TextAlign::Left => parley::Alignment::Left, TextAlign::Left => parley::Alignment::Left,
TextAlign::Center => parley::Alignment::Middle, TextAlign::Center => parley::Alignment::Center,
TextAlign::Right => parley::Alignment::Right, TextAlign::Right => parley::Alignment::Right,
TextAlign::JustifyLeft => parley::Alignment::Justified, TextAlign::JustifyLeft => parley::Alignment::Justify,
} }
} }
} }

View File

@ -33,9 +33,9 @@ impl From<TextAlign> for parley::Alignment {
fn from(val: TextAlign) -> Self { fn from(val: TextAlign) -> Self {
match val { match val {
TextAlign::Left => parley::Alignment::Left, TextAlign::Left => parley::Alignment::Left,
TextAlign::Center => parley::Alignment::Middle, TextAlign::Center => parley::Alignment::Center,
TextAlign::Right => parley::Alignment::Right, TextAlign::Right => parley::Alignment::Right,
TextAlign::JustifyLeft => parley::Alignment::Justified, TextAlign::JustifyLeft => parley::Alignment::Justify,
} }
} }
} }