keyboard layout support

This commit is contained in:
nakst 2021-10-12 15:35:32 +01:00
parent f53bb37c84
commit 257ceaa170
107 changed files with 861 additions and 117 deletions

View File

@ -28,6 +28,7 @@ They licenses may be found in the following files:
- shared/stb_image.h, shared/stb_sprintf.h, shared/stb_ds.h and util/stb_truetype.h
- res/Fonts/Hack License.txt, res/Fonts/Inter License.txt
- res/Icons/elementary Icons License.txt
- res/Media/Licenses.txt
- res/Sample Images/Licenses.txt
- res/Keyboard Layouts/License.txt
- Ported applications have their licenses in their respective folders.
Please tell me if I've forgotten something!

View File

@ -156,6 +156,9 @@ struct {
Array<Work> workQueue;
Array<EsHandle> workThreads;
volatile bool workFinish;
const uint16_t *keyboardLayout;
uint16_t keyboardLayoutIdentifier;
} api;
ptrdiff_t tlsStorageOffset;

View File

@ -606,7 +606,7 @@ int ProcessGlobalKeyboardShortcuts(EsElement *, EsMessage *message) {
// Do not process global keyboard shortcuts if the installer is running.
} else if (message->type == ES_MSG_KEY_DOWN) {
bool ctrlOnly = message->keyboard.modifiers == ES_MODIFIER_CTRL;
int scancode = message->keyboard.scancode;
int scancode = ScancodeMapToLabel(message->keyboard.scancode);
if (ctrlOnly && scancode == ES_SCANCODE_N && !message->keyboard.repeat) {
ApplicationInstanceCreate(APPLICATION_ID_DESKTOP_BLANK_TAB, nullptr, nullptr);
@ -651,7 +651,7 @@ int ContainerWindowMessage(EsElement *element, EsMessage *message) {
container->taskBarButton->MaybeRefreshStyle();
} else if (message->type == ES_MSG_KEY_DOWN) {
bool ctrlOnly = message->keyboard.modifiers == ES_MODIFIER_CTRL;
int scancode = message->keyboard.scancode;
int scancode = ScancodeMapToLabel(message->keyboard.scancode);
if (((message->keyboard.modifiers & ~ES_MODIFIER_SHIFT) == ES_MODIFIER_CTRL) && message->keyboard.scancode == ES_SCANCODE_TAB) {
int tab = -1;

View File

@ -343,7 +343,7 @@ struct ScrollPane {
void Setup(EsElement *parent, uint8_t xMode, uint8_t yMode, uint16_t flags);
void SetPosition(int axis, double newPosition, bool sendMovedMessage = true);
void Refresh();
void ReceivedMessage(EsMessage *message);
int ReceivedMessage(EsMessage *message);
inline void SetX(double scrollX, bool sendMovedMessage = true) { SetPosition(0, scrollX, sendMovedMessage); }
inline void SetY(double scrollY, bool sendMovedMessage = true) { SetPosition(1, scrollY, sendMovedMessage); }
@ -2840,7 +2840,7 @@ void ScrollPane::Setup(EsElement *_parent, uint8_t _xMode, uint8_t _yMode, uint1
}
}
void ScrollPane::ReceivedMessage(EsMessage *message) {
int ScrollPane::ReceivedMessage(EsMessage *message) {
if (message->type == ES_MSG_LAYOUT) {
Refresh();
} else if (message->type == ES_MSG_MOUSE_LEFT_DRAG || message->type == ES_MSG_MOUSE_RIGHT_DRAG || message->type == ES_MSG_MOUSE_MIDDLE_DRAG) {
@ -2884,7 +2884,11 @@ void ScrollPane::ReceivedMessage(EsMessage *message) {
} else if (message->type == ES_MSG_SCROLL_WHEEL) {
SetPosition(0, position[0] + 60 * message->scrollWheel.dx / ES_SCROLL_WHEEL_NOTCH, true);
SetPosition(1, position[1] - 60 * message->scrollWheel.dy / ES_SCROLL_WHEEL_NOTCH, true);
if (message->scrollWheel.dx && mode[0]) return ES_HANDLED;
if (message->scrollWheel.dy && mode[1]) return ES_HANDLED;
}
return 0;
}
void ScrollPane::SetPosition(int axis, double newScroll, bool sendMovedMessage) {
@ -2990,7 +2994,7 @@ struct EsScrollView : EsElement { ScrollPane scroll; };
void EsScrollViewSetup(EsScrollView *view, uint8_t xMode, uint8_t yMode, uint16_t flags) { view->scroll.Setup(view, xMode, yMode, flags); }
void EsScrollViewSetPosition(EsScrollView *view, int axis, double newPosition, bool notify) { view->scroll.SetPosition(axis, newPosition, notify); }
void EsScrollViewRefresh(EsScrollView *view) { view->scroll.Refresh(); }
void EsScrollViewReceivedMessage(EsScrollView *view, EsMessage *message) { view->scroll.ReceivedMessage(message); }
int EsScrollViewReceivedMessage(EsScrollView *view, EsMessage *message) { return view->scroll.ReceivedMessage(message); }
int64_t EsScrollViewGetPosition(EsScrollView *view, int axis) { return view->scroll.position[axis]; }
int64_t EsScrollViewGetLimit(EsScrollView *view, int axis) { return view->scroll.limit[axis]; }
void EsScrollViewSetFixedViewport(EsScrollView *view, int axis, int32_t value) { view->scroll.fixedViewport[axis] = value; }
@ -3048,7 +3052,8 @@ int ProcessPanelMessage(EsElement *element, EsMessage *message) {
EsPanel *panel = (EsPanel *) element;
EsRectangle bounds = panel->GetBounds();
panel->scroll.ReceivedMessage(message);
int response = panel->scroll.ReceivedMessage(message);
if (response) return response;
if (message->type == ES_MSG_LAYOUT) {
if (panel->flags & ES_PANEL_TABLE) {
@ -3748,7 +3753,8 @@ EsElement *CanvasPaneGetCanvas(EsElement *element) {
int ProcessCanvasPaneMessage(EsElement *element, EsMessage *message) {
EsCanvasPane *pane = (EsCanvasPane *) element;
pane->scroll.ReceivedMessage(message);
int response = pane->scroll.ReceivedMessage(message);
if (response) return response;
if (message->type == ES_MSG_LAYOUT) {
EsElement *canvas = CanvasPaneGetCanvas(element);
@ -6879,9 +6885,10 @@ void AccessKeyModeHandleKeyPress(EsMessage *message) {
EsWindow *window = gui.accessKeys.window;
int ic, isc;
ConvertScancodeToCharacter(message->keyboard.scancode, &ic, &isc, false, false);
ic = EsCRTtoupper(ic);
const char *inputString = KeyboardLayoutLookup(message->keyboard.scancode,
message->keyboard.modifiers & ES_MODIFIER_SHIFT, message->keyboard.modifiers & ES_MODIFIER_ALT_GR,
false, false);
int ic = EsCRTtoupper(inputString ? *inputString : 0);
bool keepAccessKeyModeActive = false;
bool regatherKeys = false;
@ -6945,7 +6952,7 @@ bool UIHandleKeyMessage(EsWindow *window, EsMessage *message) {
if (message->keyboard.scancode == ES_SCANCODE_LEFT_SHIFT ) gui.leftModifiers &= ~ES_MODIFIER_SHIFT;
if (message->keyboard.scancode == ES_SCANCODE_LEFT_FLAG ) gui.leftModifiers &= ~ES_MODIFIER_FLAG;
if (message->keyboard.scancode == ES_SCANCODE_RIGHT_CTRL ) gui.rightModifiers &= ~ES_MODIFIER_CTRL;
if (message->keyboard.scancode == ES_SCANCODE_RIGHT_ALT ) gui.rightModifiers &= ~ES_MODIFIER_ALT;
if (message->keyboard.scancode == ES_SCANCODE_RIGHT_ALT ) gui.rightModifiers &= ~ES_MODIFIER_ALT_GR;
if (message->keyboard.scancode == ES_SCANCODE_RIGHT_SHIFT) gui.rightModifiers &= ~ES_MODIFIER_SHIFT;
if (message->keyboard.scancode == ES_SCANCODE_RIGHT_FLAG ) gui.rightModifiers &= ~ES_MODIFIER_FLAG;
@ -6973,7 +6980,7 @@ bool UIHandleKeyMessage(EsWindow *window, EsMessage *message) {
if (message->keyboard.scancode == ES_SCANCODE_LEFT_SHIFT ) gui.leftModifiers |= ES_MODIFIER_SHIFT;
if (message->keyboard.scancode == ES_SCANCODE_LEFT_FLAG ) gui.leftModifiers |= ES_MODIFIER_FLAG;
if (message->keyboard.scancode == ES_SCANCODE_RIGHT_CTRL ) gui.rightModifiers |= ES_MODIFIER_CTRL;
if (message->keyboard.scancode == ES_SCANCODE_RIGHT_ALT ) gui.rightModifiers |= ES_MODIFIER_ALT;
if (message->keyboard.scancode == ES_SCANCODE_RIGHT_ALT ) gui.rightModifiers |= ES_MODIFIER_ALT_GR;
if (message->keyboard.scancode == ES_SCANCODE_RIGHT_SHIFT) gui.rightModifiers |= ES_MODIFIER_SHIFT;
if (message->keyboard.scancode == ES_SCANCODE_RIGHT_FLAG ) gui.rightModifiers |= ES_MODIFIER_FLAG;
@ -7065,7 +7072,7 @@ bool UIHandleKeyMessage(EsWindow *window, EsMessage *message) {
// TODO Sort out what commands can be used from within dialogs and menus.
if (!gui.keyboardShortcutNames.itemCount) UIInitialiseKeyboardShortcutNamesTable();
const char *shortcutName = (const char *) HashTableGetShort(&gui.keyboardShortcutNames, message->keyboard.scancode);
const char *shortcutName = (const char *) HashTableGetShort(&gui.keyboardShortcutNames, ScancodeMapToLabel(message->keyboard.scancode));
if (shortcutName && window->instance && window->instance->_private) {
APIInstance *instance = (APIInstance *) window->instance->_private;

View File

@ -95,6 +95,11 @@ struct EsListView : EsElement {
int maximumItemsPerBand;
EsListViewIndex ensureVisibleGroupIndex;
EsListViewIndex ensureVisibleIndex;
uint8_t ensureVisibleAlign;
bool ensureVisibleQueued;
// Fixed item storage:
Array<ListViewFixedItem> fixedItems;
ptrdiff_t fixedItemSelection;
@ -300,7 +305,15 @@ struct EsListView : EsElement {
*_itemSize = itemSize;
}
void EnsureItemVisible(EsListViewIndex groupIndex, EsListViewIndex index, bool alignTop) {
void EnsureItemVisible(EsListViewIndex groupIndex, EsListViewIndex index, uint8_t align) {
ensureVisibleQueued = true;
ensureVisibleGroupIndex = groupIndex;
ensureVisibleIndex = index;
ensureVisibleAlign = align;
EsElementRelayout(this);
}
void _EnsureItemVisible(EsListViewIndex groupIndex, EsListViewIndex index, uint8_t align) {
EsRectangle contentBounds = GetListBounds();
int64_t startInset = flags & ES_LIST_VIEW_HORIZONTAL ? style->insets.l : style->insets.t,
@ -314,12 +327,18 @@ struct EsListView : EsElement {
return;
}
if (alignTop) {
if (align == 1) {
if (flags & ES_LIST_VIEW_HORIZONTAL) {
scroll.SetX(scroll.position[0] + position - startInset);
} else {
scroll.SetY(scroll.position[1] + position - startInset);
}
} else if (align == 2) {
if (flags & ES_LIST_VIEW_HORIZONTAL) {
scroll.SetX(scroll.position[0] + position + itemSize / 2 - contentSize / 2);
} else {
scroll.SetY(scroll.position[1] + position + itemSize / 2 - contentSize / 2);
}
} else {
if (flags & ES_LIST_VIEW_HORIZONTAL) {
scroll.SetX(scroll.position[0] + position + itemSize - contentSize + endInset);
@ -1491,15 +1510,15 @@ struct EsListView : EsElement {
}
StartAnimating();
searchBufferLastKeyTime = currentTime;
int ic, isc;
ConvertScancodeToCharacter(scancode, &ic, &isc, false, false);
int character = shift ? isc : ic;
if (character != -1 && searchBufferBytes + 4 < sizeof(searchBuffer)) {
utf8_encode(character, searchBuffer + searchBufferBytes);
const char *inputString = KeyboardLayoutLookup(scancode, shift, false, false, false);
size_t inputStringBytes = EsCStringLength(inputString);
if (inputString && searchBufferBytes + inputStringBytes < sizeof(searchBuffer)) {
searchBufferLastKeyTime = currentTime;
EsMemoryCopy(searchBuffer + searchBufferBytes, inputString, inputStringBytes);
size_t previousSearchBufferBytes = searchBufferBytes;
searchBufferBytes += utf8_length_char(searchBuffer + searchBufferBytes);
searchBufferBytes += inputStringBytes;
if (!Search()) searchBufferBytes = previousSearchBufferBytes;
return true;
}
@ -1574,7 +1593,8 @@ struct EsListView : EsElement {
}
int ProcessMessage(EsMessage *message) {
scroll.ReceivedMessage(message);
int response = scroll.ReceivedMessage(message);
if (response) return response;
if (message->type == ES_MSG_GET_WIDTH || message->type == ES_MSG_GET_HEIGHT) {
if (flags & ES_LIST_VIEW_HORIZONTAL) {
@ -1590,6 +1610,13 @@ struct EsListView : EsElement {
} else if (message->type == ES_MSG_LAYOUT) {
firstLayout = true;
Wrap(message->layout.sizeChanged);
if (ensureVisibleQueued) {
ensureVisibleQueued = false;
_EnsureItemVisible(ensureVisibleGroupIndex, ensureVisibleIndex, ensureVisibleAlign);
// TODO _EnsureItemVisible may call Populate; if this happens, we don't need to call it below.
}
Populate();
if (columnHeader) {
@ -2432,7 +2459,15 @@ bool EsListViewFixedItemSelect(EsListView *view, EsGeneric data) {
EsMessageMutexCheck();
EsListViewIndex index;
bool found = EsListViewFixedItemFindIndex(view, data, &index);
if (found) EsListViewSelect(view, 0, index);
if (found) {
EsListViewSelect(view, 0, index);
// TODO Maybe you should have to separately call EsListViewFocusItem to get this behaviour.
EsListViewFocusItem(view, 0, index);
view->EnsureItemVisible(0, index, 2 /* center */);
}
return found;
}

View File

@ -707,6 +707,7 @@ define ES_MODIFIER_CTRL (1 << 0)
define ES_MODIFIER_SHIFT (1 << 1)
define ES_MODIFIER_ALT (1 << 2)
define ES_MODIFIER_FLAG (1 << 3)
define ES_MODIFIER_ALT_GR (1 << 4)
define ES_PROCESS_CREATE_PAUSED (1 << 0)
@ -1556,7 +1557,7 @@ struct EsMessageMouseButton {
};
struct EsMessageKeyboard {
uint32_t scancode;
uint16_t scancode;
uint8_t modifiers;
bool repeat, numpad, numlock, single;
};
@ -2419,7 +2420,7 @@ function EsRectangle EsElementGetScreenBounds(EsElement *element, bool client =
function EsElement *EsCustomElementCreate(EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT, const EsStyle *style = ES_NULL);
function EsScrollView *EsCustomScrollViewCreate(EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT, const EsStyle *style = ES_NULL);
function void EsScrollViewReceivedMessage(EsScrollView *view, EsMessage *message); // You *must* call this *before* handling any messages.
function int EsScrollViewReceivedMessage(EsScrollView *view, EsMessage *message); // You *must* call this *before* handling any messages. If this returns non-zero, immediately return that value from your message handler.
function void EsScrollViewSetup(EsScrollView *view, uint8_t xMode, uint8_t yMode, uint16_t flags);
function void EsScrollViewSetPosition(EsScrollView *view, int axis, double newPosition, bool sendMovedMessage = true);
function void EsScrollViewRefresh(EsScrollView *view);

View File

@ -289,6 +289,7 @@ struct GlobalData {
volatile float animationTimeMultiplier;
volatile uint64_t schedulerTimeMs;
volatile uint64_t schedulerTimeOffset;
volatile uint16_t keyboardLayout;
};
#ifdef KERNEL

View File

@ -17,9 +17,11 @@ struct SettingsControl {
#define SETTINGS_CONTROL_CHECKBOX (1)
#define SETTINGS_CONTROL_NUMBER (2)
#define SETTINGS_CONTROL_SLIDER (3)
#define SETTINGS_CONTROL_CHOICE_LIST (4)
uint8_t type;
bool originalValueBool;
int32_t originalValueInt;
EsGeneric originalValueData;
int32_t minimumValue, maximumValue;
uint32_t steps;
double dragSpeed, dragValue, discreteStep;
@ -193,6 +195,7 @@ void SettingsLoadDefaults() {
SettingsPutValue("general", "use_smart_quotes", EsLiteral("1"), nullptr, nullptr, true, false);
SettingsPutValue("general", "enable_hover_state", EsLiteral("1"), nullptr, nullptr, true, false);
SettingsPutValue("general", "enable_animations", EsLiteral("1"), nullptr, nullptr, true, false);
SettingsPutValue("general", "keyboard_layout", EsLiteral("us"), nullptr, nullptr, true, false);
SettingsPutValue("paths", "default_user_documents", EsLiteral("0:/"), nullptr, nullptr, true, false);
}
@ -204,6 +207,11 @@ void SettingsUpdateGlobalAndWindowManager() {
api.global->enableHoverState = EsSystemConfigurationReadInteger(EsLiteral("general"), EsLiteral("enable_hover_state"));
api.global->animationTimeMultiplier = EsSystemConfigurationReadInteger(EsLiteral("general"), EsLiteral("enable_animations")) ? 1.0f : 0.0f;
size_t keyboardLayoutBytes;
char *keyboardLayout = EsSystemConfigurationReadString(EsLiteral("general"), EsLiteral("keyboard_layout"), &keyboardLayoutBytes);
api.global->keyboardLayout = keyboardLayout && keyboardLayoutBytes == 2 ? (keyboardLayout[0] | ((uint16_t) keyboardLayout[1] << 8)) : 1;
EsHeapFree(keyboardLayout);
{
float newUIScale = EsSystemConfigurationReadInteger(EsLiteral("general"), EsLiteral("ui_scale")) * 0.01f;
bool changed = api.global->uiScale != newUIScale && api.global->uiScale;
@ -289,6 +297,8 @@ void SettingsUndoButton(EsInstance *_instance, EsElement *, EsCommand *) {
SettingsNumberBoxSetValue(control->element, control->originalValueInt);
} else if (control->type == SETTINGS_CONTROL_SLIDER) {
EsSliderSetValue((EsSlider *) control->element, LinearMap(control->minimumValue, control->maximumValue, 0, 1, control->originalValueInt), true);
} else if (control->type == SETTINGS_CONTROL_CHOICE_LIST) {
EsListViewFixedItemSelect((EsListView *) control->element, control->originalValueData);
}
}
@ -496,6 +506,65 @@ void SettingsAddSlider(EsElement *table, const char *string, ptrdiff_t stringByt
instance->controls.Add(control);
}
int SettingsChoiceListMessage(EsElement *element, EsMessage *message) {
EsListView *list = (EsListView *) element;
SettingsInstance *instance = (SettingsInstance *) list->instance;
SettingsControl *control = (SettingsControl *) list->userData.p;
if (message->type == ES_MSG_LIST_VIEW_SELECT) {
EsGeneric _newValue;
if (EsListViewFixedItemGetSelected(((EsListView *) element), &_newValue)) {
EsMutexAcquire(&api.systemConfigurationMutex);
const char *newValue = (const char *) _newValue.p;
size_t newValueBytes = 0;
while (newValue[newValueBytes] && newValue[newValueBytes] != '=') newValueBytes++;
char *value = (char *) EsHeapAllocate(newValueBytes, false), *_oldValue;
EsMemoryCopy(value, newValue, newValueBytes);
size_t _oldValueBytes;
bool changed = true;
if (SettingsPutValue(control->cConfigurationSection, control->cConfigurationKey, value, newValueBytes,
&_oldValue, &_oldValueBytes, false, true)) {
changed = _oldValueBytes != newValueBytes || EsMemoryCompare(_oldValue, newValue, newValueBytes);
EsHeapFree(_oldValue);
}
EsMutexRelease(&api.systemConfigurationMutex);
if (changed) {
SettingsUpdateGlobalAndWindowManager();
EsElementSetDisabled(instance->undoButton, false);
desktop.configurationModified = true;
}
}
}
return 0;
}
EsListView *SettingsAddChoiceList(EsElement *table, const char *string, ptrdiff_t stringBytes, char accessKey,
const char *cConfigurationSection, const char *cConfigurationKey) {
SettingsInstance *instance = (SettingsInstance *) table->instance;
SettingsControl *control = (SettingsControl *) EsHeapAllocate(sizeof(SettingsControl), true);
control->type = SETTINGS_CONTROL_CHOICE_LIST;
control->cConfigurationSection = cConfigurationSection;
control->cConfigurationKey = cConfigurationKey;
EsTextDisplayCreate(table, ES_CELL_H_RIGHT | ES_CELL_V_TOP, 0, string, stringBytes);
EsListView *list = EsListViewCreate(table, ES_CELL_H_EXPAND | ES_CELL_H_PUSH | ES_LIST_VIEW_CHOICE_SELECT | ES_LIST_VIEW_FIXED_ITEMS, ES_STYLE_LIST_CHOICE_BORDERED);
list->accessKey = accessKey;
list->userData = control;
list->messageUser = SettingsChoiceListMessage;
control->element = list;
instance->controls.Add(control);
return list;
}
int SettingsDoubleClickTestMessage(EsElement *element, EsMessage *message) {
if (message->type == ES_MSG_MOUSE_LEFT_DOWN) {
if (message->mouseDown.clickChainCount >= 2) {
@ -562,15 +631,44 @@ void SettingsPageKeyboard(EsElement *element, SettingsPage *page) {
EsPanel *container = EsPanelCreate(content, ES_PANEL_VERTICAL | ES_CELL_H_SHRINK, &styleSettingsGroupContainer2);
SettingsAddTitle(container, page);
EsPanel *table;
EsTextbox *textbox;
table = EsPanelCreate(container, ES_CELL_H_FILL | ES_PANEL_TABLE | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_FORM_TABLE);
EsPanelSetBands(table, 2);
EsListView *list = SettingsAddChoiceList(table, INTERFACE_STRING(DesktopSettingsKeyboardLayout), 'L', "general", "keyboard_layout");
EsINIState s = {};
s.buffer = (char *) EsBundleFind(&bundleDesktop, EsLiteral("Keyboard Layouts.ini"), &s.bytes);
void *activeKeyboardLayout = nullptr;
while (EsINIParse(&s)) {
if (s.key[0] != ';') {
EsListViewFixedItemInsert(list, s.value, s.valueBytes, s.key);
EsAssert(s.keyBytes == 2);
if (s.key[0] + ((uint16_t) s.key[1] << 8) == api.global->keyboardLayout) {
activeKeyboardLayout = s.key;
((SettingsControl *) list->userData.p)->originalValueData = activeKeyboardLayout;
}
}
}
EsListViewFixedItemSelect(list, activeKeyboardLayout);
table = EsPanelCreate(container, ES_CELL_H_FILL, &styleSettingsCheckboxGroup);
SettingsAddCheckbox(table, INTERFACE_STRING(DesktopSettingsKeyboardUseSmartQuotes), 'Q', "general", "use_smart_quotes");
EsSpacerCreate(container, ES_CELL_H_FILL, ES_STYLE_BUTTON_GROUP_SEPARATOR);
EsPanel *warningRow = EsPanelCreate(container, ES_CELL_H_CENTER | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_FORM_TABLE);
EsIconDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, ES_ICON_DIALOG_WARNING);
EsTextDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, "Work in progress" ELLIPSIS);
EsPanel *table = EsPanelCreate(container, ES_CELL_H_FILL | ES_PANEL_TABLE | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_FORM_TABLE);
table = EsPanelCreate(container, ES_CELL_H_FILL | ES_PANEL_TABLE | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_FORM_TABLE);
EsPanelSetBands(table, 2);
EsTextbox *textbox;
EsTextDisplayCreate(table, ES_CELL_H_RIGHT | ES_CELL_H_PUSH, 0, INTERFACE_STRING(DesktopSettingsKeyboardKeyRepeatDelay)); // TODO.
textbox = EsTextboxCreate(table, ES_CELL_H_LEFT | ES_CELL_H_PUSH | ES_TEXTBOX_EDIT_BASED, &styleSettingsNumberTextbox);
textbox->accessKey = 'D';
@ -593,9 +691,6 @@ void SettingsPageKeyboard(EsElement *element, SettingsPage *page) {
EsTextDisplayCreate(testBox, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(DesktopSettingsKeyboardTestTextboxIntroduction));
EsSpacerCreate(testBox, ES_FLAGS_DEFAULT, 0, 0, 5);
EsTextboxCreate(testBox, ES_CELL_H_LEFT)->accessKey = 'T';
table = EsPanelCreate(container, ES_CELL_H_FILL, &styleSettingsCheckboxGroup);
SettingsAddCheckbox(table, INTERFACE_STRING(DesktopSettingsKeyboardUseSmartQuotes), 'Q', "general", "use_smart_quotes");
}
void SettingsPageDisplay(EsElement *element, SettingsPage *page) {

View File

@ -2970,7 +2970,37 @@ void TextboxBufferResize(void **array, uintptr_t *allocated, uintptr_t needed, u
*array = newArray;
}
bool IsScancodeNonTypeable(unsigned scancode) {
void KeyboardLayoutLoad() {
if (api.keyboardLayoutIdentifier != api.global->keyboardLayout) {
char buffer[64];
api.keyboardLayoutIdentifier = api.global->keyboardLayout;
api.keyboardLayout = (const uint16_t *) EsBundleFind(&bundleDesktop, buffer, EsStringFormat(buffer, sizeof(buffer), "Keyboard Layouts/%c%c.dat",
(uint8_t) api.keyboardLayoutIdentifier, (uint8_t) (api.keyboardLayoutIdentifier >> 8)));
if (!api.keyboardLayout) {
// Fallback to the US layout if the specifier layout was not found.
api.keyboardLayout = (const uint16_t *) EsBundleFind(&bundleDesktop, buffer, EsStringFormat(buffer, sizeof(buffer), "Keyboard Layouts/us.dat"));
}
}
}
const char *KeyboardLayoutLookup(uint32_t scancode, bool isShiftHeld, bool isAltGrHeld, bool enableTabs, bool enableNewline) {
KeyboardLayoutLoad();
if (scancode >= 0x200) return nullptr;
if (scancode == ES_SCANCODE_ENTER || scancode == ES_SCANCODE_NUM_ENTER) return enableNewline ? "\n" : nullptr;
if (scancode == ES_SCANCODE_TAB) return enableTabs ? "\t" : nullptr;
if (scancode == ES_SCANCODE_BACKSPACE || scancode == ES_SCANCODE_DELETE) return nullptr;
uint16_t offset = api.keyboardLayout[scancode + (isShiftHeld ? 0x200 : 0) + (isAltGrHeld ? 0x400 : 0)];
return offset ? ((char *) api.keyboardLayout + 0x1000 + offset) : nullptr;
}
uint32_t ScancodeMapToLabel(uint32_t scancode) {
KeyboardLayoutLoad();
// TODO.
return scancode;
}
bool ScancodeIsNonTypeable(uint32_t scancode) {
switch (scancode) {
case ES_SCANCODE_CAPS_LOCK:
case ES_SCANCODE_SCROLL_LOCK:
@ -3025,73 +3055,14 @@ bool IsScancodeNonTypeable(unsigned scancode) {
}
}
void ConvertScancodeToCharacter(unsigned scancode, int *_ic, int *_isc, bool enableTabs, bool enableNewline) {
int ic = -1, isc = -1;
switch (scancode) {
case ES_SCANCODE_A: ic = 'a'; isc = 'A'; break;
case ES_SCANCODE_B: ic = 'b'; isc = 'B'; break;
case ES_SCANCODE_C: ic = 'c'; isc = 'C'; break;
case ES_SCANCODE_D: ic = 'd'; isc = 'D'; break;
case ES_SCANCODE_E: ic = 'e'; isc = 'E'; break;
case ES_SCANCODE_F: ic = 'f'; isc = 'F'; break;
case ES_SCANCODE_G: ic = 'g'; isc = 'G'; break;
case ES_SCANCODE_H: ic = 'h'; isc = 'H'; break;
case ES_SCANCODE_I: ic = 'i'; isc = 'I'; break;
case ES_SCANCODE_J: ic = 'j'; isc = 'J'; break;
case ES_SCANCODE_K: ic = 'k'; isc = 'K'; break;
case ES_SCANCODE_L: ic = 'l'; isc = 'L'; break;
case ES_SCANCODE_M: ic = 'm'; isc = 'M'; break;
case ES_SCANCODE_N: ic = 'n'; isc = 'N'; break;
case ES_SCANCODE_O: ic = 'o'; isc = 'O'; break;
case ES_SCANCODE_P: ic = 'p'; isc = 'P'; break;
case ES_SCANCODE_Q: ic = 'q'; isc = 'Q'; break;
case ES_SCANCODE_R: ic = 'r'; isc = 'R'; break;
case ES_SCANCODE_S: ic = 's'; isc = 'S'; break;
case ES_SCANCODE_T: ic = 't'; isc = 'T'; break;
case ES_SCANCODE_U: ic = 'u'; isc = 'U'; break;
case ES_SCANCODE_V: ic = 'v'; isc = 'V'; break;
case ES_SCANCODE_W: ic = 'w'; isc = 'W'; break;
case ES_SCANCODE_X: ic = 'x'; isc = 'X'; break;
case ES_SCANCODE_Y: ic = 'y'; isc = 'Y'; break;
case ES_SCANCODE_Z: ic = 'z'; isc = 'Z'; break;
case ES_SCANCODE_0: ic = '0'; isc = ')'; break;
case ES_SCANCODE_1: ic = '1'; isc = '!'; break;
case ES_SCANCODE_2: ic = '2'; isc = '@'; break;
case ES_SCANCODE_3: ic = '3'; isc = '#'; break;
case ES_SCANCODE_4: ic = '4'; isc = '$'; break;
case ES_SCANCODE_5: ic = '5'; isc = '%'; break;
case ES_SCANCODE_6: ic = '6'; isc = '^'; break;
case ES_SCANCODE_7: ic = '7'; isc = '&'; break;
case ES_SCANCODE_8: ic = '8'; isc = '*'; break;
case ES_SCANCODE_9: ic = '9'; isc = '('; break;
case ES_SCANCODE_SLASH: ic = '/'; isc = '?'; break;
case ES_SCANCODE_PUNCTUATION_1: ic = '\\'; isc = '|'; break;
case ES_SCANCODE_LEFT_BRACE: ic = '['; isc = '{'; break;
case ES_SCANCODE_RIGHT_BRACE: ic = ']'; isc = '}'; break;
case ES_SCANCODE_EQUALS: ic = '='; isc = '+'; break;
case ES_SCANCODE_PUNCTUATION_5: ic = '`'; isc = '~'; break;
case ES_SCANCODE_HYPHEN: ic = '-'; isc = '_'; break;
case ES_SCANCODE_PUNCTUATION_3: ic = ';'; isc = ':'; break;
case ES_SCANCODE_PUNCTUATION_4: ic = '\''; isc = '"'; break;
case ES_SCANCODE_COMMA: ic = ','; isc = '<'; break;
case ES_SCANCODE_PERIOD: ic = '.'; isc = '>'; break;
case ES_SCANCODE_SPACE: ic = ' '; isc = ' '; break;
case ES_SCANCODE_ENTER: if (enableNewline) { ic = '\n'; isc = '\n'; } break;
case ES_SCANCODE_TAB: if (enableTabs) { ic = '\t'; isc = '\t'; } break;
}
*_ic = ic, *_isc = isc;
}
size_t EsMessageGetInputText(EsMessage *message, char *buffer) {
int ic, isc;
ConvertScancodeToCharacter(message->keyboard.scancode, &ic, &isc, true, true);
if (message->keyboard.modifiers & ES_MODIFIER_SHIFT) ic = isc;
if (ic == -1) return 0;
return utf8_encode(ic, buffer);
const char *string = KeyboardLayoutLookup(message->keyboard.scancode,
message->keyboard.modifiers & ES_MODIFIER_SHIFT, message->keyboard.modifiers & ES_MODIFIER_ALT_GR,
true, true);
size_t bytes = string ? EsCStringLength(string) : 0;
EsAssert(bytes < 64);
EsMemoryCopy(buffer, string, bytes);
return bytes;
}
enum CharacterType {
@ -4318,9 +4289,9 @@ int ProcessTextboxMessage(EsElement *element, EsMessage *message) {
if (response != 0 && message->type != ES_MSG_DESTROY) return response;
}
textbox->scroll.ReceivedMessage(message);
int response = ES_HANDLED;
int response = textbox->scroll.ReceivedMessage(message);
if (response) return response;
response = ES_HANDLED;
if (message->type == ES_MSG_PAINT) {
EsPainter *painter = message->painter;
@ -4418,11 +4389,11 @@ int ProcessTextboxMessage(EsElement *element, EsMessage *message) {
EsHeapFree(textbox->activeLine);
EsHeapFree(textbox->data);
EsHeapFree(textbox->editStartContent);
} else if (message->type == ES_MSG_KEY_TYPED && !IsScancodeNonTypeable(message->keyboard.scancode)) {
} else if (message->type == ES_MSG_KEY_TYPED && !ScancodeIsNonTypeable(message->keyboard.scancode)) {
bool verticalMotion = false;
bool ctrl = message->keyboard.modifiers & ES_MODIFIER_CTRL;
if (message->keyboard.modifiers & ~(ES_MODIFIER_CTRL | ES_MODIFIER_ALT | ES_MODIFIER_SHIFT)) {
if (message->keyboard.modifiers & ~(ES_MODIFIER_CTRL | ES_MODIFIER_ALT | ES_MODIFIER_SHIFT | ES_MODIFIER_ALT_GR)) {
// Unused modifier.
return 0;
}
@ -4498,27 +4469,26 @@ int ProcessTextboxMessage(EsElement *element, EsMessage *message) {
EsTextboxStartEdit(textbox);
}
int ic, isc;
ConvertScancodeToCharacter(message->keyboard.scancode, &ic, &isc, true, textbox->flags & ES_TEXTBOX_MULTILINE);
int character = (message->keyboard.modifiers & ES_MODIFIER_SHIFT) ? isc : ic;
const char *inputString = KeyboardLayoutLookup(message->keyboard.scancode,
message->keyboard.modifiers & ES_MODIFIER_SHIFT, message->keyboard.modifiers & ES_MODIFIER_ALT_GR,
true, textbox->flags & ES_TEXTBOX_MULTILINE);
if (ic != -1 && (message->keyboard.modifiers & ~ES_MODIFIER_SHIFT) == 0) {
if (inputString && (message->keyboard.modifiers & ~(ES_MODIFIER_SHIFT | ES_MODIFIER_ALT_GR)) == 0) {
if (textbox->smartQuotes && api.global->useSmartQuotes) {
DocumentLine *currentLine = &textbox->lines[textbox->carets[0].line];
const char *buffer = currentLine->GetBuffer(textbox);
bool left = !textbox->carets[0].byte || buffer[textbox->carets[0].byte - 1] == ' ';
if (character == '"') {
character = left ? 0x201C : 0x201D;
} else if (character == '\'') {
character = left ? 0x2018 : 0x2019;
if (inputString[0] == '"' && inputString[1] == 0) {
inputString = left ? "\u201C" : "\u201D";
} else if (inputString[0] == '\'' && inputString[1] == 0) {
inputString = left ? "\u2018" : "\u2019";
}
}
char buffer[4];
EsTextboxInsert(textbox, buffer, utf8_encode(character, buffer));
EsTextboxInsert(textbox, inputString, -1);
if (buffer[0] == '\n' && textbox->carets[0].line) {
if (inputString[0] == '\n' && inputString[1] == 0 && textbox->carets[0].line) {
// Copy the indentation from the previous line.
DocumentLine *previousLine = &textbox->lines[textbox->carets[0].line - 1];

View File

@ -321,7 +321,8 @@ void WindowManager::PressKey(unsigned scancode) {
if (scancode == ES_SCANCODE_RIGHT_FLAG) flag2 = true;
if (scancode == (ES_SCANCODE_RIGHT_FLAG | K_SCANCODE_KEY_RELEASED)) flag2 = false;
modifiers = ((alt | alt2) ? ES_MODIFIER_ALT : 0)
modifiers = (alt ? ES_MODIFIER_ALT : 0)
| (alt2 ? ES_MODIFIER_ALT_GR : 0)
| ((ctrl | ctrl2) ? ES_MODIFIER_CTRL : 0)
| ((shift | shift2) ? ES_MODIFIER_SHIFT : 0)
| ((flag | flag2) ? ES_MODIFIER_FLAG : 0);

View File

@ -0,0 +1,193 @@
Extracted from the XKB data by nakst.
License of the XKB data (MIT) follows:
Copyright 1996 by Joseph Moss
Copyright (C) 2002-2007 Free Software Foundation, Inc.
Copyright (C) Dmitry Golubev <lastguru@mail.ru>, 2003-2004
Copyright (C) 2004, Gregory Mokhin <mokhin@bog.msu.ru>
Copyright (C) 2006 Erdal Ronahî
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of the copyright holder(s) not be used in
advertising or publicity pertaining to distribution of the software without
specific, written prior permission. The copyright holder(s) makes no
representations about the suitability of this software for any purpose. It
is provided "as is" without express or implied warranty.
THE COPYRIGHT HOLDER(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
Copyright (c) 1996 Digital Equipment Corporation
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of the Digital Equipment
Corporation shall not be used in advertising or otherwise to promote
the sale, use or other dealings in this Software without prior written
authorization from Digital Equipment Corporation.
Copyright 1996, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.
Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
Copyright (c) 1996 by Silicon Graphics Computer Systems, Inc.
Permission to use, copy, modify, and distribute this
software and its documentation for any purpose and without
fee is hereby granted, provided that the above copyright
notice appear in all copies and that both that copyright
notice and this permission notice appear in supporting
documentation, and that the name of Silicon Graphics not be
used in advertising or publicity pertaining to distribution
of the software without specific prior written permission.
Silicon Graphics makes no representation about the suitability
of this software for any purpose. It is provided "as is"
without any express or implied warranty.
SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
THE USE OR PERFORMANCE OF THIS SOFTWARE.
Copyright (c) 1996 X Consortium
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of the X Consortium shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the X Consortium.
Copyright (C) 2004, 2006 Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of a copyright holder shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization of
the copyright holder.
Copyright (C) 1999, 2000 by Anton Zinoviev <anton@lml.bas.bg>
This software may be used, modified, copied, distributed, and sold,
in both source and binary form provided that the above copyright
and these terms are retained. Under no circumstances is the author
responsible for the proper functioning of this software, nor does
the author assume any responsibility for damages incurred with its
use.
Permission is granted to anyone to use, distribute and modify
this file in any way, provided that the above copyright notice
is left intact and the author of the modification summarizes
the changes in this header.
This file is distributed without any expressed or implied warranty.

BIN
res/Keyboard Layouts/af.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/al.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/am.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/at.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/au.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/az.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/bd.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/be.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/bg.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/br.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/bt.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/bw.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/by.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/ca.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/cd.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/ch.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/cm.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/cn.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/cz.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/de.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/dk.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/dz.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/ee.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/es.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/et.dat Normal file

Binary file not shown.

View File

@ -0,0 +1,329 @@
#include <X11/Xlib.h>
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// It looks like ES_SCANCODE_PUNCTUATION_1 and ES_SCANCODE_PUNCTUATION_2 are mutually exclusive
// (_1 only on US keyboards, and _2 on everything else),
// and X11 merges them into key code 0x33.
#define ES_SCANCODE_A (0x04)
#define ES_SCANCODE_B (0x05)
#define ES_SCANCODE_C (0x06)
#define ES_SCANCODE_D (0x07)
#define ES_SCANCODE_E (0x08)
#define ES_SCANCODE_F (0x09)
#define ES_SCANCODE_G (0x0A)
#define ES_SCANCODE_H (0x0B)
#define ES_SCANCODE_I (0x0C)
#define ES_SCANCODE_J (0x0D)
#define ES_SCANCODE_K (0x0E)
#define ES_SCANCODE_L (0x0F)
#define ES_SCANCODE_M (0x10)
#define ES_SCANCODE_N (0x11)
#define ES_SCANCODE_O (0x12)
#define ES_SCANCODE_P (0x13)
#define ES_SCANCODE_Q (0x14)
#define ES_SCANCODE_R (0x15)
#define ES_SCANCODE_S (0x16)
#define ES_SCANCODE_T (0x17)
#define ES_SCANCODE_U (0x18)
#define ES_SCANCODE_V (0x19)
#define ES_SCANCODE_W (0x1A)
#define ES_SCANCODE_X (0x1B)
#define ES_SCANCODE_Y (0x1C)
#define ES_SCANCODE_Z (0x1D)
#define ES_SCANCODE_1 (0x1E)
#define ES_SCANCODE_2 (0x1F)
#define ES_SCANCODE_3 (0x20)
#define ES_SCANCODE_4 (0x21)
#define ES_SCANCODE_5 (0x22)
#define ES_SCANCODE_6 (0x23)
#define ES_SCANCODE_7 (0x24)
#define ES_SCANCODE_8 (0x25)
#define ES_SCANCODE_9 (0x26)
#define ES_SCANCODE_0 (0x27)
#define ES_SCANCODE_ENTER (0x28)
#define ES_SCANCODE_ESCAPE (0x29)
#define ES_SCANCODE_BACKSPACE (0x2A)
#define ES_SCANCODE_TAB (0x2B)
#define ES_SCANCODE_SPACE (0x2C)
#define ES_SCANCODE_HYPHEN (0x2D)
#define ES_SCANCODE_EQUALS (0x2E)
#define ES_SCANCODE_LEFT_BRACE (0x2F)
#define ES_SCANCODE_RIGHT_BRACE (0x30)
#define ES_SCANCODE_COMMA (0x36)
#define ES_SCANCODE_PERIOD (0x37)
#define ES_SCANCODE_SLASH (0x38)
#define ES_SCANCODE_PUNCTUATION_1 (0x31) // On US keyboard, \|
#define ES_SCANCODE_PUNCTUATION_2 (0x32) // Not on US keyboard
#define ES_SCANCODE_PUNCTUATION_3 (0x33) // On US keyboard, ;:
#define ES_SCANCODE_PUNCTUATION_4 (0x34) // On US keyboard, '"
#define ES_SCANCODE_PUNCTUATION_5 (0x35) // On US keyboard, `~
#define ES_SCANCODE_PUNCTUATION_6 (0x64) // Not on US keyboard
#define ES_SCANCODE_F1 (0x3A)
#define ES_SCANCODE_F2 (0x3B)
#define ES_SCANCODE_F3 (0x3C)
#define ES_SCANCODE_F4 (0x3D)
#define ES_SCANCODE_F5 (0x3E)
#define ES_SCANCODE_F6 (0x3F)
#define ES_SCANCODE_F7 (0x40)
#define ES_SCANCODE_F8 (0x41)
#define ES_SCANCODE_F9 (0x42)
#define ES_SCANCODE_F10 (0x43)
#define ES_SCANCODE_F11 (0x44)
#define ES_SCANCODE_F12 (0x45)
#define ES_SCANCODE_F13 (0x68)
#define ES_SCANCODE_F14 (0x69)
#define ES_SCANCODE_F15 (0x6A)
#define ES_SCANCODE_F16 (0x6B)
#define ES_SCANCODE_F17 (0x6C)
#define ES_SCANCODE_F18 (0x6D)
#define ES_SCANCODE_F19 (0x6E)
#define ES_SCANCODE_F20 (0x6F)
#define ES_SCANCODE_F21 (0x70)
#define ES_SCANCODE_F22 (0x71)
#define ES_SCANCODE_F23 (0x72)
#define ES_SCANCODE_F24 (0x73)
#define ES_SCANCODE_CAPS_LOCK (0x39)
#define ES_SCANCODE_PRINT_SCREEN (0x46)
#define ES_SCANCODE_SCROLL_LOCK (0x47)
#define ES_SCANCODE_PAUSE (0x48)
#define ES_SCANCODE_INSERT (0x49)
#define ES_SCANCODE_HOME (0x4A)
#define ES_SCANCODE_PAGE_UP (0x4B)
#define ES_SCANCODE_DELETE (0x4C)
#define ES_SCANCODE_END (0x4D)
#define ES_SCANCODE_PAGE_DOWN (0x4E)
#define ES_SCANCODE_RIGHT_ARROW (0x4F)
#define ES_SCANCODE_LEFT_ARROW (0x50)
#define ES_SCANCODE_DOWN_ARROW (0x51)
#define ES_SCANCODE_UP_ARROW (0x52)
#define ES_SCANCODE_NUM_LOCK (0x53)
#define ES_SCANCODE_CONTEXT_MENU (0x65)
#define ES_SCANCODE_SYSTEM_REQUEST (0x9A)
#define ES_SCANCODE_ACTION_EXECUTE (0x74)
#define ES_SCANCODE_ACTION_HELP (0x75)
#define ES_SCANCODE_ACTION_MENU (0x76)
#define ES_SCANCODE_ACTION_SELECT (0x77)
#define ES_SCANCODE_ACTION_STOP (0x78)
#define ES_SCANCODE_ACTION_AGAIN (0x79)
#define ES_SCANCODE_ACTION_UNDO (0x7A)
#define ES_SCANCODE_ACTION_CUT (0x7B)
#define ES_SCANCODE_ACTION_COPY (0x7C)
#define ES_SCANCODE_ACTION_PASTE (0x7D)
#define ES_SCANCODE_ACTION_FIND (0x7E)
#define ES_SCANCODE_ACTION_CANCEL (0x9B)
#define ES_SCANCODE_ACTION_CLEAR (0x9C)
#define ES_SCANCODE_ACTION_PRIOR (0x9D)
#define ES_SCANCODE_ACTION_RETURN (0x9E)
#define ES_SCANCODE_ACTION_SEPARATOR (0x9F)
#define ES_SCANCODE_MM_MUTE (0x7F)
#define ES_SCANCODE_MM_LOUDER (0x80)
#define ES_SCANCODE_MM_QUIETER (0x81)
#define ES_SCANCODE_MM_NEXT (0x103)
#define ES_SCANCODE_MM_PREVIOUS (0x104)
#define ES_SCANCODE_MM_STOP (0x105)
#define ES_SCANCODE_MM_PAUSE (0x106)
#define ES_SCANCODE_MM_SELECT (0x107)
#define ES_SCANCODE_MM_EMAIL (0x108)
#define ES_SCANCODE_MM_CALC (0x109)
#define ES_SCANCODE_MM_FILES (0x10A)
#define ES_SCANCODE_INTERNATIONAL_1 (0x87)
#define ES_SCANCODE_INTERNATIONAL_2 (0x88)
#define ES_SCANCODE_INTERNATIONAL_3 (0x89)
#define ES_SCANCODE_INTERNATIONAL_4 (0x8A)
#define ES_SCANCODE_INTERNATIONAL_5 (0x8B)
#define ES_SCANCODE_INTERNATIONAL_6 (0x8C)
#define ES_SCANCODE_INTERNATIONAL_7 (0x8D)
#define ES_SCANCODE_INTERNATIONAL_8 (0x8E)
#define ES_SCANCODE_INTERNATIONAL_9 (0x8F)
#define ES_SCANCODE_HANGUL_ENGLISH_TOGGLE (0x90)
#define ES_SCANCODE_HANJA_CONVERSION (0x91)
#define ES_SCANCODE_KATAKANA (0x92)
#define ES_SCANCODE_HIRAGANA (0x93)
#define ES_SCANCODE_HANKAKU_ZENKAKU_TOGGLE (0x94)
#define ES_SCANCODE_ALTERNATE_ERASE (0x99)
#define ES_SCANCODE_THOUSANDS_SEPARATOR (0xB2)
#define ES_SCANCODE_DECIMAL_SEPARATOR (0xB3)
#define ES_SCANCODE_CURRENCY_UNIT (0xB4)
#define ES_SCANCODE_CURRENCY_SUBUNIT (0xB5)
#define ES_SCANCODE_NUM_DIVIDE (0x54)
#define ES_SCANCODE_NUM_MULTIPLY (0x55)
#define ES_SCANCODE_NUM_SUBTRACT (0x56)
#define ES_SCANCODE_NUM_ADD (0x57)
#define ES_SCANCODE_NUM_ENTER (0x58)
#define ES_SCANCODE_NUM_1 (0x59)
#define ES_SCANCODE_NUM_2 (0x5A)
#define ES_SCANCODE_NUM_3 (0x5B)
#define ES_SCANCODE_NUM_4 (0x5C)
#define ES_SCANCODE_NUM_5 (0x5D)
#define ES_SCANCODE_NUM_6 (0x5E)
#define ES_SCANCODE_NUM_7 (0x5F)
#define ES_SCANCODE_NUM_8 (0x60)
#define ES_SCANCODE_NUM_9 (0x61)
#define ES_SCANCODE_NUM_0 (0x62)
#define ES_SCANCODE_NUM_POINT (0x63)
#define ES_SCANCODE_NUM_EQUALS (0x67)
#define ES_SCANCODE_NUM_COMMA (0x82)
#define ES_SCANCODE_NUM_00 (0xB0)
#define ES_SCANCODE_NUM_000 (0xB1)
#define ES_SCANCODE_NUM_LEFT_PAREN (0xB6)
#define ES_SCANCODE_NUM_RIGHT_PAREN (0xB7)
#define ES_SCANCODE_NUM_LEFT_BRACE (0xB8)
#define ES_SCANCODE_NUM_RIGHT_BRACE (0xB9)
#define ES_SCANCODE_NUM_TAB (0xBA)
#define ES_SCANCODE_NUM_BACKSPACE (0xBB)
#define ES_SCANCODE_NUM_A (0xBC)
#define ES_SCANCODE_NUM_B (0xBD)
#define ES_SCANCODE_NUM_C (0xBE)
#define ES_SCANCODE_NUM_D (0xBF)
#define ES_SCANCODE_NUM_E (0xC0)
#define ES_SCANCODE_NUM_F (0xC1)
#define ES_SCANCODE_NUM_XOR (0xC2)
#define ES_SCANCODE_NUM_CARET (0xC3)
#define ES_SCANCODE_NUM_PERCENT (0xC4)
#define ES_SCANCODE_NUM_LESS_THAN (0xC5)
#define ES_SCANCODE_NUM_GREATER_THAN (0xC6)
#define ES_SCANCODE_NUM_AMPERSAND (0xC7)
#define ES_SCANCODE_NUM_DOUBLE_AMPERSAND (0xC8)
#define ES_SCANCODE_NUM_BAR (0xC9)
#define ES_SCANCODE_NUM_DOUBLE_BAR (0xCA)
#define ES_SCANCODE_NUM_COLON (0xCB)
#define ES_SCANCODE_NUM_HASH (0xCC)
#define ES_SCANCODE_NUM_SPACE (0xCD)
#define ES_SCANCODE_NUM_AT (0xCE)
#define ES_SCANCODE_NUM_EXCLAMATION_MARK (0xCF)
#define ES_SCANCODE_NUM_MEMORY_STORE (0xD0)
#define ES_SCANCODE_NUM_MEMORY_RECALL (0xD1)
#define ES_SCANCODE_NUM_MEMORY_CLEAR (0xD2)
#define ES_SCANCODE_NUM_MEMORY_ADD (0xD3)
#define ES_SCANCODE_NUM_MEMORY_SUBTRACT (0xD4)
#define ES_SCANCODE_NUM_MEMORY_MULTIPLY (0xD5)
#define ES_SCANCODE_NUM_MEMORY_DIVIDE (0xD6)
#define ES_SCANCODE_NUM_NEGATE (0xD7)
#define ES_SCANCODE_NUM_CLEAR_ALL (0xD8)
#define ES_SCANCODE_NUM_CLEAR (0xD9)
#define ES_SCANCODE_NUM_BINARY (0xDA)
#define ES_SCANCODE_NUM_OCTAL (0xDB)
#define ES_SCANCODE_NUM_DECIMAL (0xDC)
#define ES_SCANCODE_NUM_HEXADECIMAL (0xDD)
#define ES_SCANCODE_LEFT_CTRL (0xE0)
#define ES_SCANCODE_LEFT_SHIFT (0xE1)
#define ES_SCANCODE_LEFT_ALT (0xE2)
#define ES_SCANCODE_LEFT_FLAG (0xE3)
#define ES_SCANCODE_RIGHT_CTRL (0xE4)
#define ES_SCANCODE_RIGHT_SHIFT (0xE5)
#define ES_SCANCODE_RIGHT_ALT (0xE6)
#define ES_SCANCODE_RIGHT_FLAG (0xE7)
#define ES_SCANCODE_ACPI_POWER (0x100)
#define ES_SCANCODE_ACPI_SLEEP (0x101)
#define ES_SCANCODE_ACPI_WAKE (0x102)
#define ES_SCANCODE_WWW_SEARCH (0x10B)
#define ES_SCANCODE_WWW_HOME (0x10C)
#define ES_SCANCODE_WWW_BACK (0x10D)
#define ES_SCANCODE_WWW_FORWARD (0x10E)
#define ES_SCANCODE_WWW_STOP (0x10F)
#define ES_SCANCODE_WWW_REFRESH (0x110)
#define ES_SCANCODE_WWW_STARRED (0x111)
uint32_t remap[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, ES_SCANCODE_ESCAPE, ES_SCANCODE_1, ES_SCANCODE_2, ES_SCANCODE_3, ES_SCANCODE_4, ES_SCANCODE_5, ES_SCANCODE_6,
ES_SCANCODE_7, ES_SCANCODE_8, ES_SCANCODE_9, ES_SCANCODE_0, ES_SCANCODE_HYPHEN, ES_SCANCODE_EQUALS, ES_SCANCODE_BACKSPACE, ES_SCANCODE_TAB,
ES_SCANCODE_Q, ES_SCANCODE_W, ES_SCANCODE_E, ES_SCANCODE_R, ES_SCANCODE_T, ES_SCANCODE_Y, ES_SCANCODE_U, ES_SCANCODE_I,
ES_SCANCODE_O, ES_SCANCODE_P, ES_SCANCODE_LEFT_BRACE, ES_SCANCODE_RIGHT_BRACE, ES_SCANCODE_ENTER, ES_SCANCODE_LEFT_CTRL, ES_SCANCODE_A, ES_SCANCODE_S,
ES_SCANCODE_D, ES_SCANCODE_F, ES_SCANCODE_G, ES_SCANCODE_H, ES_SCANCODE_J, ES_SCANCODE_K, ES_SCANCODE_L, ES_SCANCODE_PUNCTUATION_3,
ES_SCANCODE_PUNCTUATION_4, ES_SCANCODE_PUNCTUATION_5, ES_SCANCODE_LEFT_SHIFT, ES_SCANCODE_PUNCTUATION_1, ES_SCANCODE_Z, ES_SCANCODE_X, ES_SCANCODE_C, ES_SCANCODE_V,
ES_SCANCODE_B, ES_SCANCODE_N, ES_SCANCODE_M, ES_SCANCODE_COMMA, ES_SCANCODE_PERIOD, ES_SCANCODE_SLASH, ES_SCANCODE_RIGHT_SHIFT, ES_SCANCODE_NUM_MULTIPLY,
ES_SCANCODE_LEFT_ALT, ES_SCANCODE_SPACE, ES_SCANCODE_CAPS_LOCK, ES_SCANCODE_F1, ES_SCANCODE_F2, ES_SCANCODE_F3, ES_SCANCODE_F4, ES_SCANCODE_F5,
ES_SCANCODE_F6, ES_SCANCODE_F7, ES_SCANCODE_F8, ES_SCANCODE_F9, ES_SCANCODE_F10, ES_SCANCODE_NUM_LOCK, ES_SCANCODE_SCROLL_LOCK, ES_SCANCODE_NUM_7,
ES_SCANCODE_NUM_8, ES_SCANCODE_NUM_9, ES_SCANCODE_NUM_SUBTRACT, ES_SCANCODE_NUM_4, ES_SCANCODE_NUM_5, ES_SCANCODE_NUM_6, ES_SCANCODE_NUM_ADD, ES_SCANCODE_NUM_1,
ES_SCANCODE_NUM_2, ES_SCANCODE_NUM_3, ES_SCANCODE_NUM_0, ES_SCANCODE_NUM_POINT, 0, 0, ES_SCANCODE_PUNCTUATION_6, ES_SCANCODE_F11,
ES_SCANCODE_F12, 0, ES_SCANCODE_KATAKANA, ES_SCANCODE_HIRAGANA, 0, 0, 0, 0,
ES_SCANCODE_NUM_ENTER, ES_SCANCODE_RIGHT_CTRL, ES_SCANCODE_NUM_DIVIDE, ES_SCANCODE_PRINT_SCREEN, ES_SCANCODE_RIGHT_ALT, 0, ES_SCANCODE_HOME, ES_SCANCODE_UP_ARROW,
ES_SCANCODE_PAGE_UP, ES_SCANCODE_LEFT_ARROW, ES_SCANCODE_RIGHT_ARROW, ES_SCANCODE_END, ES_SCANCODE_DOWN_ARROW, ES_SCANCODE_PAGE_DOWN, ES_SCANCODE_INSERT, ES_SCANCODE_DELETE,
0, ES_SCANCODE_MM_MUTE, ES_SCANCODE_MM_QUIETER, ES_SCANCODE_MM_LOUDER, ES_SCANCODE_ACPI_POWER, ES_SCANCODE_NUM_EQUALS, 0, ES_SCANCODE_PAUSE,
};
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <layout>\n", argv[0]);
return 1;
}
FILE *f = popen("setxkbmap -query | grep layout", "r");
char oldLayout[64] = {};
fread(oldLayout, 1, sizeof(oldLayout) - 1, f);
pclose(f);
char setLayout[128];
snprintf(setLayout, sizeof(setLayout), "setxkbmap %s", argv[1]);
system(setLayout);
Display *display = XOpenDisplay(NULL);
XIM xim = XOpenIM(display, 0, 0, 0);
XSetLocaleModifiers("");
XSetWindowAttributes attributes = {};
Window window = XCreateWindow(display, DefaultRootWindow(display), 0, 0, 800, 600, 0, 0,
InputOutput, CopyFromParent, CWOverrideRedirect, &attributes);
XIC xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, window, XNFocusWindow, window, NULL);
uint16_t table[512 * 4] = {};
char stringBuffer[65536] = {};
size_t stringBufferPosition = 0;
for (uintptr_t state = 0; state < 4; state++) {
for (uintptr_t i = 0; i < 0x80; i++) {
XEvent event = {};
event.xkey.type = KeyPress;
event.xkey.display = display;
event.xkey.window = window;
event.xkey.state = state == 0 ? 0x00 : state == 1 ? 0x01 /* shift */ : state == 2 ? 0x80 /* alt gr */ : state == 3 ? 0x81 : 0;
event.xkey.keycode = i;
char text[32];
KeySym symbol = NoSymbol;
Status status;
size_t textBytes = Xutf8LookupString(xic, &event.xkey, text, sizeof(text) - 1, &symbol, &status);
uint16_t offset = 0;
if (textBytes) {
offset = stringBufferPosition;
assert(stringBufferPosition + textBytes + 1 < sizeof(stringBuffer));
memcpy(stringBuffer + stringBufferPosition, text, textBytes);
stringBuffer[stringBufferPosition + textBytes] = 0;
stringBufferPosition += textBytes + 1;
}
table[remap[i] + state * 512] = offset;
if (remap[i] == ES_SCANCODE_PUNCTUATION_1) {
table[ES_SCANCODE_PUNCTUATION_2 + state * 512] = offset;
}
}
}
snprintf(setLayout, sizeof(setLayout), "setxkbmap %s", oldLayout + 7);
system(setLayout);
fwrite(table, 1, sizeof(table), stdout);
fwrite(stringBuffer, 1, stringBufferPosition, stdout);
return 0;
}

BIN
res/Keyboard Layouts/fi.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/fo.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/fr.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/gb.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/ge.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/gh.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/gr.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/hr.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/hu.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/id.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/ie.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/il.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/in.dat Normal file

Binary file not shown.

View File

@ -0,0 +1,89 @@
af=Afghani
al=Albanian
et=Amharic
sy=Arabic (Syria)
am=Armenian
az=Azerbaijani
ml=Bambara
bd=Bangla
by=Belarusian
be=Belgian
dz=Berber (Algeria, Latin)
bg=Bulgarian
mm=Burmese
cn=Chinese
hr=Croatian
cz=Czech
dk=Danish
mv=Dhivehi
nl=Dutch
bt=Dzongkha
au=English (Australian)
cm=English (Cameroon)
gh=English (Ghana)
ng=English (Nigeria)
za=English (South Africa)
gb=English (UK)
us=English (US)
ee=Estonian
fo=Faroese
ph=Filipino
fi=Finnish
ca=French (Canada)
cd=French (Democratic Republic of the Congo)
tg=French (Togo)
fr=French
ge=Georgian
at=German (Austria)
ch=German (Switzerland)
de=German
gr=Greek
il=Hebrew
hu=Hungarian
is=Icelandic
in=Indian
jv=Indonesian (Javanese)
id=Indonesian (Latin)
iq=Iraqi
ie=Irish
it=Italian
jp=Japanese
kz=Kazakh
kh=Khmer (Cambodia)
kr=Korean
kg=Kyrgyz
la=Lao
lv=Latvian
lt=Lithuanian
mk=Macedonian
my=Malay (Jawi, Arabic Keyboard)
mt=Maltese
md=Moldavian
mn=Mongolian
me=Montenegrin
np=Nepali
no=Norwegian
ir=Persian
pl=Polish
br=Portuguese (Brazil)
pt=Portuguese
ro=Romanian
ru=Russian
rs=Serbian
lk=Sinhala (phonetic)
sk=Slovak
si=Slovenian
es=Spanish
ke=Swahili (Kenya)
tz=Swahili (Tanzania)
se=Swedish
tw=Taiwanese
tj=Tajik
th=Thai
bw=Tswana
tr=Turkish
ua=Ukrainian
pk=Urdu (Pakistan)
uz=Uzbek
vn=Vietnamese
sn=Wolof

BIN
res/Keyboard Layouts/iq.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/ir.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/is.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/it.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/jp.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/jv.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/ke.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/kg.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/kh.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/kr.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/kz.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/la.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/lk.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/lt.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/lv.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/md.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/me.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/mk.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/ml.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/mm.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/mn.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/mt.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/mv.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/my.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/ng.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/nl.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/no.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/np.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/ph.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/pk.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/pl.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/pt.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/ro.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/rs.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/ru.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/se.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/si.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/sk.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/sn.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/sy.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/tg.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/th.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/tj.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/tr.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/tw.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/tz.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/ua.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/us.dat Normal file

Binary file not shown.

BIN
res/Keyboard Layouts/uz.dat Normal file

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More