From 89df6e7242858ec513424835f8cb1788e0c4166c Mon Sep 17 00:00:00 2001 From: Viktor Liu <17948409+lixmal@users.noreply.github.com> Date: Fri, 12 Jul 2024 08:25:33 +0200 Subject: [PATCH] Get client ui locale on windows natively (#2251) --- client/ui/client_ui.go | 85 ------------------------------------ client/ui/font_bsd.go | 26 +++++++++++ client/ui/font_linux.go | 7 +++ client/ui/font_windows.go | 91 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+), 85 deletions(-) create mode 100644 client/ui/font_bsd.go create mode 100644 client/ui/font_linux.go create mode 100644 client/ui/font_windows.go diff --git a/client/ui/client_ui.go b/client/ui/client_ui.go index cadd14f18..67f3ef07b 100644 --- a/client/ui/client_ui.go +++ b/client/ui/client_ui.go @@ -877,88 +877,3 @@ func checkPIDFile() error { return os.WriteFile(pidFile, []byte(fmt.Sprintf("%d", os.Getpid())), 0o664) //nolint:gosec } - -func (s *serviceClient) setDefaultFonts() { - var ( - defaultFontPath string - ) - - //TODO: Linux Multiple Language Support - switch runtime.GOOS { - case "darwin": - defaultFontPath = "/Library/Fonts/Arial Unicode.ttf" - case "windows": - fontPath := s.getWindowsFontFilePath() - defaultFontPath = fontPath - } - - _, err := os.Stat(defaultFontPath) - - if err == nil { - os.Setenv("FYNE_FONT", defaultFontPath) - } -} - -func (s *serviceClient) getWindowsFontFilePath() (fontPath string) { - /* - https://learn.microsoft.com/en-us/windows/apps/design/globalizing/loc-international-fonts - https://learn.microsoft.com/en-us/typography/fonts/windows_11_font_list - */ - - var ( - fontFolder string = "C:/Windows/Fonts" - fontMapping = map[string]string{ - "default": "Segoeui.ttf", - "zh-CN": "Msyh.ttc", - "am-ET": "Ebrima.ttf", - "nirmala": "Nirmala.ttf", - "chr-CHER-US": "Gadugi.ttf", - "zh-HK": "Msjh.ttc", - "zh-TW": "Msjh.ttc", - "ja-JP": "Yugothm.ttc", - "km-KH": "Leelawui.ttf", - "ko-KR": "Malgun.ttf", - "th-TH": "Leelawui.ttf", - "ti-ET": "Ebrima.ttf", - } - nirMalaLang = []string{ - "as-IN", - "bn-BD", - "bn-IN", - "gu-IN", - "hi-IN", - "kn-IN", - "kok-IN", - "ml-IN", - "mr-IN", - "ne-NP", - "or-IN", - "pa-IN", - "si-LK", - "ta-IN", - "te-IN", - } - ) - cmd := exec.Command("powershell", "-Command", "(Get-Culture).Name") - output, err := cmd.Output() - if err != nil { - log.Errorf("Failed to get Windows default language setting: %v", err) - fontPath = path.Join(fontFolder, fontMapping["default"]) - return - } - defaultLanguage := strings.TrimSpace(string(output)) - - for _, lang := range nirMalaLang { - if defaultLanguage == lang { - fontPath = path.Join(fontFolder, fontMapping["nirmala"]) - return - } - } - - if font, ok := fontMapping[defaultLanguage]; ok { - fontPath = path.Join(fontFolder, font) - } else { - fontPath = path.Join(fontFolder, fontMapping["default"]) - } - return -} diff --git a/client/ui/font_bsd.go b/client/ui/font_bsd.go new file mode 100644 index 000000000..41bccceca --- /dev/null +++ b/client/ui/font_bsd.go @@ -0,0 +1,26 @@ +//go:build darwin || dragonfly || freebsd || netbsd || openbsd + +package main + +import ( + "os" + "runtime" + + log "github.com/sirupsen/logrus" +) + +const defaultFontPath = "/Library/Fonts/Arial Unicode.ttf" + +func (s *serviceClient) setDefaultFonts() { + // TODO: add other bsd paths + if runtime.GOOS != "darwin" { + return + } + + if _, err := os.Stat(defaultFontPath); err != nil { + log.Errorf("Failed to find default font file: %v", err) + return + } + + os.Setenv("FYNE_FONT", defaultFontPath) +} diff --git a/client/ui/font_linux.go b/client/ui/font_linux.go new file mode 100644 index 000000000..4aa92494a --- /dev/null +++ b/client/ui/font_linux.go @@ -0,0 +1,7 @@ +//go:build !386 + +package main + +func (s *serviceClient) setDefaultFonts() { + //TODO: Linux Multiple Language Support +} diff --git a/client/ui/font_windows.go b/client/ui/font_windows.go new file mode 100644 index 000000000..c37a5455f --- /dev/null +++ b/client/ui/font_windows.go @@ -0,0 +1,91 @@ +package main + +import ( + "os" + "path" + "unsafe" + + log "github.com/sirupsen/logrus" + "golang.org/x/sys/windows" +) + +func (s *serviceClient) setDefaultFonts() { + defaultFontPath := s.getWindowsFontFilePath() + + if _, err := os.Stat(defaultFontPath); err != nil { + log.Errorf("Failed to find default font file: %v", err) + return + } + + os.Setenv("FYNE_FONT", defaultFontPath) +} + +func (s *serviceClient) getWindowsFontFilePath() string { + var ( + fontFolder = "C:/Windows/Fonts" + fontMapping = map[string]string{ + "default": "Segoeui.ttf", + "zh-CN": "Msyh.ttc", + "am-ET": "Ebrima.ttf", + "nirmala": "Nirmala.ttf", + "chr-CHER-US": "Gadugi.ttf", + "zh-HK": "Msjh.ttc", + "zh-TW": "Msjh.ttc", + "ja-JP": "Yugothm.ttc", + "km-KH": "Leelawui.ttf", + "ko-KR": "Malgun.ttf", + "th-TH": "Leelawui.ttf", + "ti-ET": "Ebrima.ttf", + } + nirMalaLang = []string{ + "as-IN", + "bn-BD", + "bn-IN", + "gu-IN", + "hi-IN", + "kn-IN", + "kok-IN", + "ml-IN", + "mr-IN", + "ne-NP", + "or-IN", + "pa-IN", + "si-LK", + "ta-IN", + "te-IN", + } + ) + + // getUserDefaultLocaleName.Call() panics if the func is not found + defer func() { + if r := recover(); r != nil { + log.Errorf("Recovered from panic: %v", r) + } + }() + + kernel32 := windows.NewLazySystemDLL("kernel32.dll") + getUserDefaultLocaleName := kernel32.NewProc("GetUserDefaultLocaleName") + + buf := make([]uint16, 85) // LOCALE_NAME_MAX_LENGTH is usually 85 + r, _, err := getUserDefaultLocaleName.Call(uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf))) + // returns 0 on failure, err is always non-nil + // https://learn.microsoft.com/en-us/windows/win32/api/winnls/nf-winnls-getuserdefaultlocalename + if r == 0 { + log.Errorf("GetUserDefaultLocaleName call failed: %v", err) + return path.Join(fontFolder, fontMapping["default"]) + } + + defaultLanguage := windows.UTF16ToString(buf) + + for _, lang := range nirMalaLang { + if defaultLanguage == lang { + return path.Join(fontFolder, fontMapping["nirmala"]) + } + } + + if font, ok := fontMapping[defaultLanguage]; ok { + return path.Join(fontFolder, font) + } + + return path.Join(fontFolder, fontMapping["default"]) +}