Merge pull request 'MacOS: detect keyboard layout' (#26) from feature/mac-keyboard-layout into release/v9.1.0

Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/desktop-sdk/pulls/26
This commit is contained in:
Oleg Korshul
2025-09-16 12:03:58 +00:00
4 changed files with 100 additions and 10 deletions

View File

@ -14,6 +14,7 @@ CONFIG += plugin
CORE_ROOT_DIR = $$PWD/../../../core
include($$CORE_ROOT_DIR/Common/base.pri)
include($$CORE_ROOT_DIR/Common/3dParty/icu/icu.pri)
DEFINES += \
PDFFILE_USE_DYNAMIC_LIBRARY \
@ -161,7 +162,6 @@ SOURCES += \
}
!core_mac {
include($$CORE_ROOT_DIR/Common/3dParty/icu/icu.pri)
HEADERS += \
$$PWD/src/keyboardlayout.h
@ -174,14 +174,17 @@ core_mac {
LIBS += -framework Security
LIBS += -framework AVFoundation
LIBS += -framework CoreMedia
LIBS += -framework Carbon
HEADERS += \
$$PWD/src/mac_keyboardlayout.h \
./include/mac_cefview.h \
./include/mac_application.h \
./include/mac_cefviewmedia.h
OBJECTIVE_SOURCES += \
$$PWD/src/widget_impl.mm \
$$PWD/src/mac_keyboardlayout.mm \
$$PWD/src/mac_application.mm \
$$PWD/src/mac_cefview.mm \
$$PWD/src/mac_cefviewmedia.mm

View File

@ -35,7 +35,9 @@
#include "./cefwrapper/client_resource_handler_async.h"
#include "./cefwrapper/monitor_info.h"
#if !defined(_MAC)
#if defined(_MAC)
# include "mac_keyboardlayout.h"
#else
# include "keyboardlayout.h"
#endif
@ -925,11 +927,9 @@ void CAscApplicationManager::EndSaveDialog(const std::wstring& sPath, unsigned i
bool CAscApplicationManager::IsPlatformKeyboardSupport()
{
#ifdef WIN32
#if defined(WIN32) || defined(_MAC)
return true;
#endif
#if defined(_LINUX) && !defined(_MAC)
#elif defined(_LINUX)
KeyboardLayout kl;
return kl.IsKeyboardSupport();
#endif
@ -939,15 +939,17 @@ bool CAscApplicationManager::IsPlatformKeyboardSupport()
int CAscApplicationManager::GetPlatformKeyboardLayout()
{
#ifdef WIN32
#if defined(WIN32)
HWND wFocus = GetFocus();
DWORD dwThread = GetWindowThreadProcessId(wFocus, 0);
HKL hkl = GetKeyboardLayout(dwThread);
int nLang = LOWORD(hkl);
return nLang;
#endif
#if defined(_LINUX) && !defined(_MAC)
#elif defined(_MAC)
uint16_t nLang = GetKeyboardLayout();
if (nLang != 0)
return nLang;
#elif defined(_LINUX)
KeyboardLayout kl;
uint16_t layout = kl.GetKeyboardLayout();
if (layout != 0)

View File

@ -0,0 +1,16 @@
#ifndef MAC_KEYBOARDLAYOUT_H
#define MAC_KEYBOARDLAYOUT_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
uint16_t GetKeyboardLayout(void);
#ifdef __cplusplus
}
#endif
#endif // MAC_KEYBOARDLAYOUT_H

View File

@ -0,0 +1,69 @@
#import <Cocoa/Cocoa.h>
#import <Carbon/Carbon.h>
#include "mac_keyboardlayout.h"
#include <unicode/locid.h>
#include <string>
#define LANGIDFROMLCID(lcid) ((uint16_t)(lcid))
static std::string NSStringToStdString(NSString* nsString)
{
if (!nsString) return {};
const char* utf8Str = [nsString UTF8String];
if (!utf8Str) return {};
return std::string(utf8Str);
}
static uint16_t localeNameToLangId(const std::string &localeName)
{
if (!localeName.empty()) {
icu::Locale loc(localeName.c_str());
return LANGIDFROMLCID(loc.getLCID());
}
return 0;
}
uint16_t GetKeyboardLayout(void)
{
TISInputSourceRef src = TISCopyCurrentKeyboardInputSource();
if (!src) return 0;
CFArrayRef languages = (CFArrayRef)TISGetInputSourceProperty(src, kTISPropertyInputSourceLanguages);
CFStringRef lang = nullptr;
if (languages && CFArrayGetCount(languages) > 0) {
lang = (CFStringRef)CFArrayGetValueAtIndex(languages, 0);
}
if (!lang) {
CFRelease(src);
return 0;
}
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:(__bridge NSString*)lang];
CFRelease(src);
std::string language = NSStringToStdString([locale languageCode]);
std::string region = NSStringToStdString([locale countryCode]);
std::string script = NSStringToStdString([locale scriptCode]);
if (!language.empty()) {
if (!script.empty())
language.append("_" + script);
else
if (region.empty()) {
// try prevent neutral language
UErrorCode status = U_ZERO_ERROR;
char fullName[ULOC_FULLNAME_CAPACITY];
uloc_addLikelySubtags(language.c_str(), fullName, ULOC_FULLNAME_CAPACITY, &status);
if (U_SUCCESS(status)) {
icu::Locale loc(fullName);
region = loc.getCountry();
}
}
if (!region.empty())
language.append("_" + region);
// fprintf(stderr, "Canonical name: %s\n", language.c_str());
return localeNameToLangId(language);
}
return 0;
}