Initial commit for the Keyboard Layout Manager

* Implements physical size:
    Full Size
    TKL
    60%
* Implements regional layouts
    ANSI QWERTY
    ISO QWERTY
    QWERTZ
    AZERTY
    JIS
* Customisible layouts produced by adding and swapping custom keys
allowing for keyboard SKU variants
* Exportable matrix maps filled by map count, matrix index or filled by an
array of values.
* Matrix map size adjustable to fixed width and height to support size
specific protocols. e.g. Razer
* Debug keyboards are customisable by adding the following values into
the JSON list.
    "Layout" (int),
    "Size" (int),
    "Linear" (bool),
    "Underglow" (bool),
    "Insert" array[ { "Zone" (int), "Row" (int), "Col" (int), "Val"
(int), "Name": (string) } ],
    "Swap" array[ { "Zone" (int), "Row" (int), "Col" (int), "Val" (int),
"Name": (string) } ]
This commit is contained in:
Chris M 2023-02-05 01:51:19 +11:00 committed by Adam Honse
parent 269ebeddb4
commit 35453db3e0
12 changed files with 1579 additions and 442 deletions

View file

@ -3,6 +3,7 @@
#include "RGBController_Debug.h"
#include "RGBController_Dummy.h"
#include "RGBControllerKeyNames.h"
#include "KeyboardLayoutManager.h"
#include "SettingsManager.h"
#include <vector>
#include <stdio.h>
@ -18,181 +19,11 @@
//0xFFFFFFFF indicates an unused entry in matrix
#define NA 0xFFFFFFFF
static unsigned int debug_keyboard_matrix_map[6][23] =
{ { 0, NA, 16, 30, 44, 54, NA, 65, 75, 84, 95, NA, 8, 23, 38, 6, 22, 36, 49, NA, NA, NA, NA },
{ 1, 17, 31, 45, 55, 66, 76, 85, 96, 9, 24, NA, 39, 7, 37, NA, 60, 70, 80, 52, 63, 73, 82 },
{ 2, NA, 18, 32, 46, 56, NA, 67, 77, 86, 97, 10, 25, 40, 90, 101, 50, 61, 71, 51, 62, 72, 93 },
{ 3, NA, 19, 33, 47, 57, NA, 68, 78, 87, 98, 11, 26, 41, 28, 14, NA, NA, NA, 92, 103, 53, NA },
{ 4, 20, 34, 48, 58, 69, NA, 79, NA, 88, 99, 12, 27, 42, 81, NA, NA, 102, NA, 64, 74, 83, 104 },
{ 5, 21, 35, NA, NA, NA, NA, 59, NA, NA, NA, NA, 89, 100, 13, 91, 15, 29, 43, 94, NA, 105, NA } };
static unsigned int dummy_keyboard_underglow_map[3][10] =
{ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 },
{ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 } };
static const char *led_names[] =
{
KEY_EN_ESCAPE,
KEY_EN_BACK_TICK,
KEY_EN_TAB,
KEY_EN_CAPS_LOCK,
KEY_EN_LEFT_SHIFT,
KEY_EN_LEFT_CONTROL,
KEY_EN_F12,
KEY_EN_EQUALS,
KEY_EN_F9,
KEY_EN_9,
KEY_EN_O,
KEY_EN_L,
KEY_EN_COMMA,
KEY_EN_MENU,
KEY_EN_ISO_ENTER,
KEY_EN_LEFT_ARROW,
KEY_EN_F1,
KEY_EN_1,
KEY_EN_Q,
KEY_EN_A,
KEY_EN_ISO_BACK_SLASH,
KEY_EN_LEFT_WINDOWS,
KEY_EN_PRINT_SCREEN,
KEY_EN_F10,
KEY_EN_0,
KEY_EN_P,
KEY_EN_SEMICOLON,
KEY_EN_PERIOD,
KEY_EN_ANSI_ENTER,
KEY_EN_DOWN_ARROW,
KEY_EN_F2,
KEY_EN_2,
KEY_EN_W,
KEY_EN_S,
KEY_EN_Z,
KEY_EN_LEFT_ALT,
KEY_EN_SCROLL_LOCK,
KEY_EN_BACKSPACE,
KEY_EN_F11,
KEY_EN_MINUS,
KEY_EN_LEFT_BRACKET,
KEY_EN_QUOTE,
KEY_EN_FORWARD_SLASH,
KEY_EN_RIGHT_ARROW,
KEY_EN_F3,
KEY_EN_3,
KEY_EN_E,
KEY_EN_D,
KEY_EN_X,
KEY_EN_PAUSE_BREAK,
KEY_EN_DELETE,
KEY_EN_NUMPAD_7,
KEY_EN_NUMPAD_LOCK,
KEY_EN_NUMPAD_6,
KEY_EN_F4,
KEY_EN_4,
KEY_EN_R,
KEY_EN_F,
KEY_EN_C,
KEY_EN_SPACE,
KEY_EN_INSERT,
KEY_EN_END,
KEY_EN_NUMPAD_8,
KEY_EN_NUMPAD_DIVIDE,
KEY_EN_NUMPAD_1,
KEY_EN_F5,
KEY_EN_5,
KEY_EN_T,
KEY_EN_G,
KEY_EN_V,
KEY_EN_HOME,
KEY_EN_PAGE_DOWN,
KEY_EN_NUMPAD_9,
KEY_EN_NUMPAD_TIMES,
KEY_EN_NUMPAD_2,
KEY_EN_F6,
KEY_EN_6,
KEY_EN_Y,
KEY_EN_H,
KEY_EN_B,
KEY_EN_PAGE_UP,
KEY_EN_RIGHT_SHIFT,
KEY_EN_NUMPAD_MINUS,
KEY_EN_NUMPAD_3,
KEY_EN_F7,
KEY_EN_7,
KEY_EN_U,
KEY_EN_J,
KEY_EN_N,
KEY_EN_RIGHT_ALT,
KEY_EN_RIGHT_BRACKET,
KEY_EN_RIGHT_CONTROL,
KEY_EN_NUMPAD_4,
KEY_EN_NUMPAD_PLUS,
KEY_EN_NUMPAD_0,
KEY_EN_F8,
KEY_EN_8,
KEY_EN_I,
KEY_EN_K,
KEY_EN_M,
KEY_EN_RIGHT_WINDOWS,
KEY_EN_ANSI_BACK_SLASH,
KEY_EN_UP_ARROW,
KEY_EN_NUMPAD_5,
KEY_EN_NUMPAD_ENTER,
KEY_EN_NUMPAD_PERIOD,
"RGB Strip 1",
"RGB Strip 2",
"RGB Strip 3",
"RGB Strip 4",
"RGB Strip 5",
"RGB Strip 6",
"RGB Strip 7",
"RGB Strip 8",
"RGB Strip 9",
"RGB Strip 10",
"RGB Strip 11",
"RGB Strip 12",
"RGB Strip 13",
"RGB Strip 14",
"RGB Strip 15",
"RGB Strip 16",
"RGB Strip 17",
"RGB Strip 18",
KEY_EN_MEDIA_PREVIOUS,
KEY_EN_MEDIA_PLAY_PAUSE,
KEY_EN_MEDIA_NEXT,
KEY_EN_MEDIA_MUTE,
"Underglow LED 1",
"Underglow LED 2",
"Underglow LED 3",
"Underglow LED 4",
"Underglow LED 5",
"Underglow LED 6",
"Underglow LED 7",
"Underglow LED 8",
"Underglow LED 9",
"Underglow LED 10",
"Underglow LED 11",
"Underglow LED 12",
"Underglow LED 13",
"Underglow LED 14",
"Underglow LED 15",
"Underglow LED 16",
"Underglow LED 17",
"Underglow LED 18",
"Underglow LED 19",
"Underglow LED 20",
"Underglow LED 21",
"Underglow LED 22",
"Underglow LED 23",
"Underglow LED 24",
"Underglow LED 25",
"Underglow LED 26",
"Underglow LED 27",
"Underglow LED 28",
"Underglow LED 29",
"Underglow LED 30"
};
/******************************************************************************************\
* *
* DetectDebugControllers *
@ -454,14 +285,74 @@ void DetectDebugControllers()
}
else if(type == "keyboard")
{
json json_kbd = debug_settings["devices"][device_idx];
KEYBOARD_LAYOUT layout = KEYBOARD_LAYOUT::KEYBOARD_LAYOUT_ANSI_QWERTY;
KEYBOARD_SIZE size = KEYBOARD_SIZE::KEYBOARD_SIZE_FULL;
if(json_kbd.contains("layout"))
{
layout = json_kbd["layout"];
}
if(json_kbd.contains("size"))
{
size = json_kbd["size"];
}
/*---------------------------------------------------------*\
| Create a dummy Keyboard |
\*---------------------------------------------------------*/
RGBController_Dummy* dummy_keyboard = new RGBController_Dummy();
KeyboardLayoutManager new_kb(layout, size);
dummy_keyboard->name = "Debug Keyboard";
/*---------------------------------------------------------*\
| Check for custom key inserts and swaps |
\*---------------------------------------------------------*/
if(json_kbd.contains("insert"))
{
std::vector<keyboard_led> insert;
for(size_t i = 0; i < json_kbd["insert"].size(); i++)
{
keyboard_led* key = new keyboard_led;
key->zone = json_kbd["insert"][i]["Zone"];
key->row = json_kbd["insert"][i]["Row"];
key->col = json_kbd["insert"][i]["Col"];
key->value = json_kbd["insert"][i]["Val"];
key->name = json_kbd["insert"][i]["Name"].get_ref<const std::string&>().c_str();
insert.push_back(*key);
}
new_kb.InsertKeys(insert);
new_kb.UpdateDimensions();
}
if(json_kbd.contains("swap"))
{
std::vector<keyboard_led> swap;
for(size_t i = 0; i < json_kbd["swap"].size(); i++)
{
keyboard_led* key = new keyboard_led;
key->zone = json_kbd["swap"][i]["Zone"];
key->row = json_kbd["swap"][i]["Row"];
key->col = json_kbd["swap"][i]["Col"];
key->value = json_kbd["swap"][i]["Val"];
key->name = json_kbd["swap"][i]["Name"].get_ref<const std::string&>().c_str();
swap.push_back(*key);
}
new_kb.SwapKeys(swap);
new_kb.UpdateDimensions();
}
dummy_keyboard->name = new_kb.GetName();
dummy_keyboard->type = DEVICE_TYPE_KEYBOARD;
dummy_keyboard->description = "Debug Keyboard Device";
dummy_keyboard->description = dummy_keyboard->name;
dummy_keyboard->description.append(" Debug Keyboard");
dummy_keyboard->location = "Debug Keyboard Location";
dummy_keyboard->version = "Debug Keyboard Version";
dummy_keyboard->serial = "Debug Keyboard Serial";
@ -485,52 +376,88 @@ void DetectDebugControllers()
dummy_keyboard_matrix_zone.name = "Keyboard Matrix Zone";
dummy_keyboard_matrix_zone.type = ZONE_TYPE_MATRIX;
dummy_keyboard_matrix_zone.leds_min = 106;
dummy_keyboard_matrix_zone.leds_max = 106;
dummy_keyboard_matrix_zone.leds_count = 106;
dummy_keyboard_matrix_zone.leds_min = new_kb.GetKeyCount();
dummy_keyboard_matrix_zone.leds_max = new_kb.GetKeyCount();
dummy_keyboard_matrix_zone.leds_count = new_kb.GetKeyCount();
dummy_keyboard_matrix_zone.matrix_map = new matrix_map_type;
dummy_keyboard_matrix_zone.matrix_map->height = 6;
dummy_keyboard_matrix_zone.matrix_map->width = 23;
dummy_keyboard_matrix_zone.matrix_map->map = (unsigned int*)&debug_keyboard_matrix_map;
dummy_keyboard_matrix_zone.matrix_map->height = new_kb.GetRowCount();
dummy_keyboard_matrix_zone.matrix_map->width = new_kb.GetColumnCount();
dummy_keyboard_matrix_zone.matrix_map->map = new unsigned int[dummy_keyboard_matrix_zone.matrix_map->height
* dummy_keyboard_matrix_zone.matrix_map->width];
new_kb.GetKeyMap(dummy_keyboard_matrix_zone.matrix_map->map, KEYBOARD_MAP_FILL_TYPE_COUNT);
dummy_keyboard->zones.push_back(dummy_keyboard_matrix_zone);
for(std::size_t led_idx = 0; led_idx < dummy_keyboard_matrix_zone.leds_count; led_idx++)
{
led dummy_keyboard_led;
dummy_keyboard_led.name = new_kb.GetKeyNameAt(led_idx);
dummy_keyboard->leds.push_back(dummy_keyboard_led);
}
/*-----------------------------------------------------------------*\
| Add another matrix zone so that is can resemble a huntsman elite |
\*-----------------------------------------------------------------*/
zone dummy_keyboard_underglow_matrix_zone;
bool underglow = true;
if(json_kbd.contains("underglow"))
{
underglow = json_kbd["underglow"];
}
dummy_keyboard_underglow_matrix_zone.name = "Underglow";
dummy_keyboard_underglow_matrix_zone.type = ZONE_TYPE_MATRIX;
dummy_keyboard_underglow_matrix_zone.leds_min = 30;
dummy_keyboard_underglow_matrix_zone.leds_max = 30;
dummy_keyboard_underglow_matrix_zone.leds_count = 30;
dummy_keyboard_underglow_matrix_zone.matrix_map = new matrix_map_type;
dummy_keyboard_underglow_matrix_zone.matrix_map->height = 3;
dummy_keyboard_underglow_matrix_zone.matrix_map->width = 10;
dummy_keyboard_underglow_matrix_zone.matrix_map->map = (unsigned int*)&dummy_keyboard_underglow_map;
if(underglow)
{
zone dummy_keyboard_underglow_matrix_zone;
dummy_keyboard->zones.push_back(dummy_keyboard_underglow_matrix_zone);
dummy_keyboard_underglow_matrix_zone.name = "Underglow";
dummy_keyboard_underglow_matrix_zone.type = ZONE_TYPE_MATRIX;
dummy_keyboard_underglow_matrix_zone.leds_min = 30;
dummy_keyboard_underglow_matrix_zone.leds_max = 30;
dummy_keyboard_underglow_matrix_zone.leds_count = 30;
dummy_keyboard_underglow_matrix_zone.matrix_map = new matrix_map_type;
dummy_keyboard_underglow_matrix_zone.matrix_map->height = 3;
dummy_keyboard_underglow_matrix_zone.matrix_map->width = 10;
dummy_keyboard_underglow_matrix_zone.matrix_map->map = (unsigned int*)&dummy_keyboard_underglow_map;
dummy_keyboard->zones.push_back(dummy_keyboard_underglow_matrix_zone);
for(std::size_t led_idx = 0; led_idx < dummy_keyboard_underglow_matrix_zone.leds_count; led_idx++)
{
led dummy_keyboard_led;
dummy_keyboard_led.name = dummy_keyboard_underglow_matrix_zone.name + " LED ";
dummy_keyboard_led.name.append(std::to_string(led_idx));
dummy_keyboard->leds.push_back(dummy_keyboard_led);
}
}
/*---------------------------------------------------------*\
| Create a linear zone for the dummy GPU |
| Create a linear zone for the dummy Keyboard |
\*---------------------------------------------------------*/
zone dummy_keyboard_linear_zone;
dummy_keyboard_linear_zone.name = "Linear Zone";
dummy_keyboard_linear_zone.type = ZONE_TYPE_LINEAR;
dummy_keyboard_linear_zone.leds_min = 18;
dummy_keyboard_linear_zone.leds_max = 18;
dummy_keyboard_linear_zone.leds_count = 18;
dummy_keyboard_linear_zone.matrix_map = NULL;
dummy_keyboard->zones.push_back(dummy_keyboard_linear_zone);
for(std::size_t led_idx = 0; led_idx < 154; led_idx++)
bool linear = true;
if(json_kbd.contains("linear"))
{
led dummy_keyboard_led;
dummy_keyboard_led.name = led_names[led_idx];
dummy_keyboard->leds.push_back(dummy_keyboard_led);
linear = json_kbd["linear"];
}
if(linear)
{
zone dummy_keyboard_linear_zone;
dummy_keyboard_linear_zone.name = "Linear Zone";
dummy_keyboard_linear_zone.type = ZONE_TYPE_LINEAR;
dummy_keyboard_linear_zone.leds_min = 18;
dummy_keyboard_linear_zone.leds_max = 18;
dummy_keyboard_linear_zone.leds_count = 18;
dummy_keyboard_linear_zone.matrix_map = NULL;
dummy_keyboard->zones.push_back(dummy_keyboard_linear_zone);
for(std::size_t led_idx = 0; led_idx < dummy_keyboard_linear_zone.leds_count; led_idx++)
{
led dummy_keyboard_led;
dummy_keyboard_led.name = "RGB Strip ";
dummy_keyboard_led.name.append(std::to_string(led_idx));
dummy_keyboard->leds.push_back(dummy_keyboard_led);
}
}
dummy_keyboard->SetupColors();

View file

@ -136,6 +136,35 @@ void RGBController_Razer::SetupZones()
unsigned int device_index = controller->GetDeviceIndex();
unsigned char layout_type = controller->GetKeyboardLayoutType();
/*---------------------------------------------------------*\
| Dynamically generate a keyboard layout |
\*---------------------------------------------------------*/
KEYBOARD_LAYOUT new_layout;
switch(layout_type)
{
case RAZER_LAYOUT_TYPE_AZERTY:
new_layout = KEYBOARD_LAYOUT::KEYBOARD_LAYOUT_ISO_AZERTY;
break;
case RAZER_LAYOUT_TYPE_ISO:
new_layout = KEYBOARD_LAYOUT::KEYBOARD_LAYOUT_ISO_QWERTY;
break;
case RAZER_LAYOUT_TYPE_JIS:
new_layout = KEYBOARD_LAYOUT::KEYBOARD_LAYOUT_ANSI_QWERTY;
break;
case RAZER_LAYOUT_TYPE_QWERTZ:
new_layout = KEYBOARD_LAYOUT::KEYBOARD_LAYOUT_ISO_QWERTZ;
break;
default:
new_layout = KEYBOARD_LAYOUT::KEYBOARD_LAYOUT_ANSI_QWERTY;
}
KeyboardLayoutManager new_kb(new_layout, device_list[device_index]->layout->base_size,
device_list[device_index]->layout->key_values);
/*---------------------------------------------------------*\
| Fill in zone information based on device table |
\*---------------------------------------------------------*/
@ -154,57 +183,72 @@ void RGBController_Razer::SetupZones()
if(new_zone.type == ZONE_TYPE_MATRIX)
{
matrix_map_type * new_map = new matrix_map_type;
new_zone.matrix_map = new_map;
matrix_map_type * new_map = new matrix_map_type;
new_zone.matrix_map = new_map;
new_map->height = device_list[device_index]->zones[zone_id]->rows;
new_map->width = device_list[device_index]->zones[zone_id]->cols;
new_map->map = new unsigned int[new_map->height * new_map->width];
new_map->height = device_list[device_index]->zones[zone_id]->rows;
new_map->width = device_list[device_index]->zones[zone_id]->cols;
new_map->map = new unsigned int[new_map->height * new_map->width];
for(unsigned int y = 0; y < new_map->height; y++)
if(device_list[device_index]->layout->base_size != KEYBOARD_SIZE::KEYBOARD_SIZE_EMPTY)
{
for(unsigned int x = 0; x < new_map->width; x++)
/*---------------------------------------------------------*\
| Minor adjustments to keyboard layout |
\*---------------------------------------------------------*/
keyboard_keymap_overlay_values* temp = device_list[device_index]->layout;
new_kb.ChangeKeys(*temp);
/*---------------------------------------------------------*\
| Matrix map still uses declared zone rows and columns |
| as the packet structure depends on the matrix map |
\*---------------------------------------------------------*/
new_kb.GetKeyMap(new_map->map, KEYBOARD_MAP_FILL_TYPE_INDEX, new_map->height, new_map->width);
}
else
{
for(unsigned int y = 0; y < new_map->height; y++)
{
bool exists_in_keymap = false;
for(unsigned int x = 0; x < new_map->width; x++)
{
bool exists_in_keymap = false;
if(new_zone.name != ZONE_EN_KEYBOARD)
{
/*---------------------------------------------------------*\
| For zones other than the actual keyboard, we want all |
| entries in the matrix visible in the LED view (such as |
| underglow) |
\*---------------------------------------------------------*/
exists_in_keymap = true;
}
else if(device_list[device_index]->keymap != NULL)
{
for(unsigned int i = 0; i < device_list[device_index]->keymap_size; i++)
if(new_zone.name != ZONE_EN_KEYBOARD)
{
razer_key key = device_list[device_index]->keymap[i];
if(zone_id == key.zone && y == key.row && x == key.col && (key.layout & layout_type))
/*---------------------------------------------------------*\
| For zones other than the actual keyboard, we want all |
| entries in the matrix visible in the LED view (such as |
| underglow) |
\*---------------------------------------------------------*/
exists_in_keymap = true;
}
else if(device_list[device_index]->keymap != NULL)
{
for(unsigned int i = 0; i < device_list[device_index]->keymap_size; i++)
{
exists_in_keymap = true;
break;
razer_key key = device_list[device_index]->keymap[i];
if(zone_id == key.zone && y == key.row && x == key.col && (key.layout & layout_type))
{
exists_in_keymap = true;
break;
}
}
}
}
else
{
/*---------------------------------------------------------*\
| If the device has no keymap defined we want all entries in|
| the matrix to be visible in the LED view |
\*---------------------------------------------------------*/
exists_in_keymap = true;
}
}
else
{
/*---------------------------------------------------------*\
| If the device has no keymap defined we want all entries in|
| the matrix to be visible in the LED view |
\*---------------------------------------------------------*/
exists_in_keymap = true;
}
if (exists_in_keymap)
{
new_map->map[(y * new_map->width) + x] = (y * new_map->width) + x;
}
else
{
new_map->map[(y * new_map->width) + x] = -1;
if (exists_in_keymap)
{
new_map->map[(y * new_map->width) + x] = (y * new_map->width) + x;
}
else
{
new_map->map[(y * new_map->width) + x] = -1;
}
}
}
}
@ -220,48 +264,68 @@ void RGBController_Razer::SetupZones()
for(unsigned int zone_id = 0; zone_id < zones.size(); zone_id++)
{
for (unsigned int row_id = 0; row_id < device_list[device_index]->zones[zone_id]->rows; row_id++)
/*---------------------------------------------------------*\
| Check the dynamic layout |
\*---------------------------------------------------------*/
if(device_list[device_index]->zones[zone_id]->name == ZONE_EN_KEYBOARD && new_kb.GetKeyCount() > 0)
{
for (unsigned int col_id = 0; col_id < device_list[device_index]->zones[zone_id]->cols; col_id++)
for(std::size_t row = 0; row < zones[zone_id].matrix_map->height; row++)
{
led* new_led = new led();
new_led->name = device_list[device_index]->zones[zone_id]->name;
if(zones[zone_id].leds_count > 1)
for(std::size_t col = 0; col < zones[zone_id].matrix_map->width; col++)
{
new_led->name.append(" LED ");
new_led->name.append(std::to_string(col_id + 1));
led* new_led = new led();
new_led->name = new_kb.GetKeyNameAt(row, col);
leds.push_back(*new_led);
}
if(device_list[device_index]->keymap != NULL)
}
}
else
{
for (unsigned int row_id = 0; row_id < device_list[device_index]->zones[zone_id]->rows; row_id++)
{
for (unsigned int col_id = 0; col_id < device_list[device_index]->zones[zone_id]->cols; col_id++)
{
bool not_found = true;
led* new_led = new led();
for(unsigned int i = 0; i < device_list[device_index]->keymap_size; i++)
new_led->name = device_list[device_index]->zones[zone_id]->name;
if(zones[zone_id].leds_count > 1)
{
if(zone_id == device_list[device_index]->keymap[i].zone &&
row_id == device_list[device_index]->keymap[i].row &&
col_id == device_list[device_index]->keymap[i].col &&
layout_type & device_list[device_index]->keymap[i].layout)
new_led->name.append(" LED ");
new_led->name.append(std::to_string(col_id + 1));
}
if(device_list[device_index]->keymap != NULL)
{
bool not_found = true;
for(unsigned int i = 0; i < device_list[device_index]->keymap_size; i++)
{
new_led->name = device_list[device_index]->keymap[i].name;
not_found = false;
break;
if(zone_id == device_list[device_index]->keymap[i].zone &&
row_id == device_list[device_index]->keymap[i].row &&
col_id == device_list[device_index]->keymap[i].col &&
layout_type & device_list[device_index]->keymap[i].layout)
{
new_led->name = device_list[device_index]->keymap[i].name;
not_found = false;
break;
}
}
/*-----------------------------------------------------------------*\
| If this is the "Keyboard" zone and key was not found in the map |
| then change the value of the key to hide it from view |
\*-----------------------------------------------------------------*/
if(not_found && zones[zone_id].name == ZONE_EN_KEYBOARD)
{
zones[zone_id].matrix_map->map[row_id * zones[zone_id].matrix_map->width + col_id] = NA;
}
}
/*-----------------------------------------------------------------*\
| If this is the "Keyboard" zone and key was not found in the map |
| then change the value of the key to hide it from view |
\*-----------------------------------------------------------------*/
if(not_found && zones[zone_id].name == ZONE_EN_KEYBOARD)
{
zones[zone_id].matrix_map->map[row_id * zones[zone_id].matrix_map->width + col_id] = NA;
}
leds.push_back(*new_led);
}
leds.push_back(*new_led);
}
}
}

View file

@ -1230,7 +1230,6 @@ unsigned char RazerController::GetKeyboardLayoutType()
return RAZER_LAYOUT_TYPE_ANSI;
case RAZER_KEYBOARD_LAYOUT_GREEK: // Unconfirmed
case RAZER_KEYBOARD_LAYOUT_FRENCH:
case RAZER_KEYBOARD_LAYOUT_UK:
case RAZER_KEYBOARD_LAYOUT_NORDIC:
case RAZER_KEYBOARD_LAYOUT_KOREAN: // Unconfirmed
@ -1243,6 +1242,9 @@ unsigned char RazerController::GetKeyboardLayoutType()
case RAZER_KEYBOARD_LAYOUT_HEBREW: // Unconfirmed
return RAZER_LAYOUT_TYPE_ISO;
case RAZER_KEYBOARD_LAYOUT_FRENCH:
return RAZER_LAYOUT_TYPE_AZERTY;
case RAZER_KEYBOARD_LAYOUT_JAPAN: // Unconfirmed
return RAZER_LAYOUT_TYPE_JIS;

View file

@ -138,6 +138,7 @@ enum
RAZER_LAYOUT_TYPE_ISO = 0x02,
RAZER_LAYOUT_TYPE_JIS = 0x04,
RAZER_LAYOUT_TYPE_QWERTZ = 0x08,
RAZER_LAYOUT_TYPE_AZERTY = 0x10,
RAZER_LAYOUT_TYPE_ALL = RAZER_LAYOUT_TYPE_ANSI | RAZER_LAYOUT_TYPE_ISO
| RAZER_LAYOUT_TYPE_JIS | RAZER_LAYOUT_TYPE_QWERTZ

File diff suppressed because it is too large Load diff

View file

@ -10,6 +10,7 @@
#include "RGBController.h"
#include "RGBControllerKeyNames.h"
#include "RazerController.h"
#include "KeyboardLayoutManager.h"
/*-----------------------------------------------------*\
| Razer vendor ID |
@ -222,32 +223,33 @@
typedef struct
{
std::string name;
unsigned int type;
unsigned int rows;
unsigned int cols;
std::string name;
unsigned int type;
unsigned int rows;
unsigned int cols;
} razer_zone;
typedef struct
{
unsigned int zone;
unsigned int row;
unsigned int col;
const char* name;
unsigned char layout = RAZER_LAYOUT_TYPE_ALL;
unsigned int zone;
unsigned int row;
unsigned int col;
const char* name;
unsigned char layout = RAZER_LAYOUT_TYPE_ALL;
} razer_key;
typedef struct
{
std::string name;
unsigned short pid;
device_type type;
bool matrix_type;
unsigned int rows;
unsigned int cols;
const razer_zone* zones[RAZER_MAX_ZONES];
const razer_key* keymap;
unsigned int keymap_size;
std::string name;
unsigned short pid;
device_type type;
bool matrix_type;
unsigned int rows;
unsigned int cols;
const razer_zone* zones[RAZER_MAX_ZONES];
const razer_key* keymap;
unsigned int keymap_size;
keyboard_keymap_overlay_values* layout;
} razer_device;
/*-----------------------------------------------------*\

View file

@ -682,6 +682,7 @@ HEADERS +=
Controllers/ZETKeyboardController/RGBController_ZETBladeOptical.h \
Controllers/ZotacTuringGPUController/ZotacTuringGPUController.h \
Controllers/ZotacTuringGPUController/RGBController_ZotacTuringGPU.h \
RGBController/KeyboardLayoutManager.h \
RGBController/RGBController.h \
RGBController/RGBController_Dummy.h \
RGBController/RGBControllerKeyNames.h \
@ -1324,6 +1325,7 @@ SOURCES +=
Controllers/ZotacTuringGPUController/ZotacTuringGPUController.cpp \
Controllers/ZotacTuringGPUController/ZotacTuringGPUControllerDetect.cpp \
Controllers/ZotacTuringGPUController/RGBController_ZotacTuringGPU.cpp \
RGBController/KeyboardLayoutManager.cpp \
RGBController/RGBController.cpp \
RGBController/RGBController_Dummy.cpp \
RGBController/RGBControllerKeyNames.cpp \

View file

@ -0,0 +1,703 @@
/*---------------------------------------------------------------------*\
| KeyboardLayoutManager.cpp |
| |
| Helper library to produce keyboard layouts |
| |
| Chris M (Dr_No) 04 Feb 2023 |
| |
\*---------------------------------------------------------------------*/
#include "LogManager.h"
#include "KeyboardLayoutManager.h"
const char* KEYBOARD_NAME_ISO = "ISO ";
const char* KEYBOARD_NAME_ANSI = "ANSI ";
const char* KEYBOARD_NAME_JIS = "JIS";
const char* KEYBOARD_NAME_AZERTY = "AZERTY";
const char* KEYBOARD_NAME_QWERTY = "QWERTY";
const char* KEYBOARD_NAME_QWERTZ = "QWERTZ";
const char* KEYBOARD_NAME_FULL = "Full 104 key ";
const char* KEYBOARD_NAME_TKL = "Tenkeyless ";
const char* KEYBOARD_NAME_SIXTY = "Sixty percent ";
const char* LOG_MSG_EMPTY = "empty ";
const char* LOG_MSG_UNUSED_KEY = "'unused' key ";
const char* LOG_MSG_SHIFTING_RIGHT = ", shifting keys right";
const char* LOG_MSG_CREATED_NEW = "[Keyboard Layout Manager] Created new %s%s with %d rows and %d columns containing %d keys";
const char* LOG_MSG_INSERT_BEFORE = "[%s] Inserting %s before %s @ %02d, %02d%s";
static const std::vector<keyboard_led> keyboard_basemap =
{
/*---------------------------------------------------------------------*\
| Zone, Row, Column, Value, Key |
\*---------------------------------------------------------------------*/
{ 0, 0, 0, 0, KEY_EN_ESCAPE, },
{ 0, 0, 2, 0, KEY_EN_F1, },
{ 0, 0, 3, 0, KEY_EN_F2, },
{ 0, 0, 4, 0, KEY_EN_F3, },
{ 0, 0, 5, 0, KEY_EN_F4, },
{ 0, 0, 6, 0, KEY_EN_F5, },
{ 0, 0, 7, 0, KEY_EN_F6, },
{ 0, 0, 8, 0, KEY_EN_F7, },
{ 0, 0, 9, 0, KEY_EN_F8, },
{ 0, 0, 10, 0, KEY_EN_F9, },
{ 0, 0, 11, 0, KEY_EN_F10, },
{ 0, 0, 12, 0, KEY_EN_F11, },
{ 0, 0, 13, 0, KEY_EN_F12, },
{ 0, 0, 14, 0, KEY_EN_PRINT_SCREEN, },
{ 0, 0, 15, 0, KEY_EN_SCROLL_LOCK, },
{ 0, 0, 16, 0, KEY_EN_PAUSE_BREAK, },
{ 0, 1, 0, 0, KEY_EN_BACK_TICK, },
{ 0, 1, 1, 0, KEY_EN_1, },
{ 0, 1, 2, 0, KEY_EN_2, },
{ 0, 1, 3, 0, KEY_EN_3, },
{ 0, 1, 4, 0, KEY_EN_4, },
{ 0, 1, 5, 0, KEY_EN_5, },
{ 0, 1, 6, 0, KEY_EN_6, },
{ 0, 1, 7, 0, KEY_EN_7, },
{ 0, 1, 8, 0, KEY_EN_8, },
{ 0, 1, 9, 0, KEY_EN_9, },
{ 0, 1, 10, 0, KEY_EN_0, },
{ 0, 1, 11, 0, KEY_EN_MINUS, },
{ 0, 1, 12, 0, KEY_EN_EQUALS, },
{ 0, 1, 13, 0, KEY_EN_BACKSPACE, },
{ 0, 1, 14, 0, KEY_EN_INSERT, },
{ 0, 1, 15, 0, KEY_EN_HOME, },
{ 0, 1, 16, 0, KEY_EN_PAGE_UP, },
{ 0, 1, 17, 0, KEY_EN_NUMPAD_LOCK, },
{ 0, 1, 18, 0, KEY_EN_NUMPAD_DIVIDE, },
{ 0, 1, 19, 0, KEY_EN_NUMPAD_TIMES, },
{ 0, 1, 20, 0, KEY_EN_NUMPAD_MINUS, },
{ 0, 2, 0, 0, KEY_EN_TAB, },
{ 0, 2, 1, 0, KEY_EN_Q, },
{ 0, 2, 2, 0, KEY_EN_W, },
{ 0, 2, 3, 0, KEY_EN_E, },
{ 0, 2, 4, 0, KEY_EN_R, },
{ 0, 2, 5, 0, KEY_EN_T, },
{ 0, 2, 6, 0, KEY_EN_Y, },
{ 0, 2, 7, 0, KEY_EN_U, },
{ 0, 2, 8, 0, KEY_EN_I, },
{ 0, 2, 9, 0, KEY_EN_O, },
{ 0, 2, 10, 0, KEY_EN_P, },
{ 0, 2, 11, 0, KEY_EN_LEFT_BRACKET, },
{ 0, 2, 12, 0, KEY_EN_RIGHT_BRACKET, },
{ 0, 2, 13, 0, KEY_EN_ANSI_BACK_SLASH, },
{ 0, 2, 14, 0, KEY_EN_DELETE, },
{ 0, 2, 15, 0, KEY_EN_END, },
{ 0, 2, 16, 0, KEY_EN_PAGE_DOWN, },
{ 0, 2, 17, 0, KEY_EN_NUMPAD_7, },
{ 0, 2, 18, 0, KEY_EN_NUMPAD_8, },
{ 0, 2, 19, 0, KEY_EN_NUMPAD_9, },
{ 0, 2, 20, 0, KEY_EN_NUMPAD_PLUS, },
{ 0, 3, 0, 0, KEY_EN_CAPS_LOCK, },
{ 0, 3, 1, 0, KEY_EN_A, },
{ 0, 3, 2, 0, KEY_EN_S, },
{ 0, 3, 3, 0, KEY_EN_D, },
{ 0, 3, 4, 0, KEY_EN_F, },
{ 0, 3, 5, 0, KEY_EN_G, },
{ 0, 3, 6, 0, KEY_EN_H, },
{ 0, 3, 7, 0, KEY_EN_J, },
{ 0, 3, 8, 0, KEY_EN_K, },
{ 0, 3, 9, 0, KEY_EN_L, },
{ 0, 3, 10, 0, KEY_EN_SEMICOLON, },
{ 0, 3, 11, 0, KEY_EN_QUOTE, },
{ 0, 3, 13, 0, KEY_EN_ANSI_ENTER, },
{ 0, 3, 17, 0, KEY_EN_NUMPAD_4, },
{ 0, 3, 18, 0, KEY_EN_NUMPAD_5, },
{ 0, 3, 19, 0, KEY_EN_NUMPAD_6, },
{ 0, 4, 0, 0, KEY_EN_LEFT_SHIFT, },
{ 0, 4, 2, 0, KEY_EN_Z, },
{ 0, 4, 3, 0, KEY_EN_X, },
{ 0, 4, 4, 0, KEY_EN_C, },
{ 0, 4, 5, 0, KEY_EN_V, },
{ 0, 4, 6, 0, KEY_EN_B, },
{ 0, 4, 7, 0, KEY_EN_N, },
{ 0, 4, 8, 0, KEY_EN_M, },
{ 0, 4, 9, 0, KEY_EN_COMMA, },
{ 0, 4, 10, 0, KEY_EN_PERIOD, },
{ 0, 4, 11, 0, KEY_EN_FORWARD_SLASH, },
{ 0, 4, 13, 0, KEY_EN_RIGHT_SHIFT, },
{ 0, 4, 15, 0, KEY_EN_UP_ARROW, },
{ 0, 4, 17, 0, KEY_EN_NUMPAD_1, },
{ 0, 4, 18, 0, KEY_EN_NUMPAD_2, },
{ 0, 4, 19, 0, KEY_EN_NUMPAD_3, },
{ 0, 4, 20, 0, KEY_EN_NUMPAD_ENTER, },
{ 0, 5, 0, 0, KEY_EN_LEFT_CONTROL, },
{ 0, 5, 1, 0, KEY_EN_LEFT_WINDOWS, },
{ 0, 5, 2, 0, KEY_EN_LEFT_ALT, },
{ 0, 5, 6, 0, KEY_EN_SPACE, },
{ 0, 5, 10, 0, KEY_EN_RIGHT_ALT, },
{ 0, 5, 11, 0, KEY_EN_RIGHT_FUNCTION, },
{ 0, 5, 12, 0, KEY_EN_MENU, },
{ 0, 5, 13, 0, KEY_EN_RIGHT_CONTROL, },
{ 0, 5, 14, 0, KEY_EN_LEFT_ARROW, },
{ 0, 5, 15, 0, KEY_EN_DOWN_ARROW, },
{ 0, 5, 16, 0, KEY_EN_RIGHT_ARROW, },
{ 0, 5, 18, 0, KEY_EN_NUMPAD_0, },
{ 0, 5, 19, 0, KEY_EN_NUMPAD_PERIOD, },
};
keyboard_keymap_overlay iso_azerty
{
KEYBOARD_SIZE_FULL,
{
/*---------------------------------------------------------------------*\
| Insert Keys |
\*---------------------------------------------------------------------*/
{ 0, 3, 12, 0, KEY_FR_ASTERIX, },
{ 0, 4, 1, 0, KEY_NORD_ANGLE_BRACKET, },
},
{
/*---------------------------------------------------------------------*\
| Swap Keys |
\*---------------------------------------------------------------------*/
{ 0, 1, 0, 0, KEY_FR_SUPER_2, },
{ 0, 1, 1, 0, KEY_FR_AMPERSAND, },
{ 0, 1, 2, 0, KEY_FR_ACUTE_E, },
{ 0, 1, 3, 0, KEY_FR_DOUBLEQUOTE, },
{ 0, 1, 4, 0, KEY_EN_QUOTE, },
{ 0, 1, 5, 0, KEY_FR_LEFT_PARENTHESIS, },
{ 0, 1, 6, 0, KEY_EN_MINUS, },
{ 0, 1, 7, 0, KEY_FR_GRAVE_E, },
{ 0, 1, 8, 0, KEY_FR_UNDERSCORE, },
{ 0, 1, 9, 0, KEY_FR_CEDILLA_C, },
{ 0, 1, 10, 0, KEY_FR_GRAVE_A, },
{ 0, 1, 11, 0, KEY_FR_RIGHT_PARENTHESIS, },
{ 0, 2, 1, 0, KEY_EN_A, },
{ 0, 2, 2, 0, KEY_EN_Z, },
{ 0, 2, 11, 0, KEY_JP_CHEVRON, },
{ 0, 2, 12, 0, KEY_FR_DOLLAR, },
{ 0, 2, 13, 0, KEY_EN_UNUSED, },
{ 0, 3, 1, 0, KEY_EN_Q, },
{ 0, 3, 10, 0, KEY_EN_M, },
{ 0, 3, 11, 0, KEY_FR_GRAVE_U, },
{ 0, 4, 2, 0, KEY_EN_W, },
{ 0, 4, 8, 0, KEY_EN_COMMA, },
{ 0, 4, 9, 0, KEY_EN_SEMICOLON, },
{ 0, 4, 10, 0, KEY_JP_COLON, },
{ 0, 4, 11, 0, KEY_FR_EXCLAIMATION, },
}
};
keyboard_keymap_overlay iso_qwerty
{
KEYBOARD_SIZE_FULL,
{
/*---------------------------------------------------------------------*\
| Insert Keys |
\*---------------------------------------------------------------------*/
{ 0, 3, 12, 0, KEY_EN_POUND, },
{ 0, 4, 1, 0, KEY_EN_ISO_BACK_SLASH, },
},
{
/*---------------------------------------------------------------------*\
| Swap Keys |
\*---------------------------------------------------------------------*/
{ 0, 2, 13, 0, KEY_EN_UNUSED, },
}
};
keyboard_keymap_overlay iso_qwertz
{
KEYBOARD_SIZE_FULL,
{
/*---------------------------------------------------------------------*\
| Insert Keys |
\*---------------------------------------------------------------------*/
{ 0, 3, 12, 0, KEY_EN_POUND, },
{ 0, 4, 1, 0, KEY_NORD_ANGLE_BRACKET, },
},
{
/*---------------------------------------------------------------------*\
| Swap Keys |
\*---------------------------------------------------------------------*/
{ 0, 1, 0, 0, KEY_JP_CHEVRON, },
{ 0, 1, 11, 0, KEY_DE_ESZETT, },
{ 0, 1, 12, 0, KEY_EN_BACK_TICK, },
{ 0, 2, 6, 0, KEY_EN_Z, },
{ 0, 2, 11, 0, KEY_DE_DIAERESIS_U, },
{ 0, 2, 12, 0, KEY_EN_PLUS, },
{ 0, 2, 13, 0, KEY_EN_UNUSED, },
{ 0, 3, 10, 0, KEY_DE_DIAERESIS_O, },
{ 0, 3, 11, 0, KEY_DE_DIAERESIS_A, },
{ 0, 4, 2, 0, KEY_EN_Y, },
{ 0, 5, 12, 0, KEY_EN_MINUS, },
}
};
keyboard_keymap_overlay jis
{
KEYBOARD_SIZE_FULL,
{
/*---------------------------------------------------------------------*\
| Insert Keys |
\*---------------------------------------------------------------------*/
{ 0, 3, 12, 0, KEY_EN_RIGHT_BRACKET, },
{ 0, 4, 12, 0, KEY_EN_BACK_SLASH, },
},
{
/*---------------------------------------------------------------------*\
| Swap Keys |
\*---------------------------------------------------------------------*/
{ 0, 1, 12, 0, KEY_JP_CHEVRON, },
{ 0, 2, 11, 0, KEY_JP_AT, },
{ 0, 2, 12, 0, KEY_EN_LEFT_BRACKET, },
{ 0, 3, 11, 0, KEY_JP_COLON, },
{ 0, 2, 13, 0, KEY_EN_UNUSED, },
}
};
keyboard_keymap_overlay full_to_tkl
{
KEYBOARD_SIZE_FULL,
{
/*---------------------------------------------------------------------*\
| Insert Keys |
\*---------------------------------------------------------------------*/
},
{
/*---------------------------------------------------------------------*\
| Swap Keys |
\*---------------------------------------------------------------------*/
{ 0, 1, 17, 0, KEY_EN_UNUSED, },
{ 0, 1, 18, 0, KEY_EN_UNUSED, },
{ 0, 1, 19, 0, KEY_EN_UNUSED, },
{ 0, 1, 20, 0, KEY_EN_UNUSED, },
{ 0, 2, 17, 0, KEY_EN_UNUSED, },
{ 0, 2, 18, 0, KEY_EN_UNUSED, },
{ 0, 2, 19, 0, KEY_EN_UNUSED, },
{ 0, 2, 20, 0, KEY_EN_UNUSED, },
{ 0, 3, 17, 0, KEY_EN_UNUSED, },
{ 0, 3, 18, 0, KEY_EN_UNUSED, },
{ 0, 3, 19, 0, KEY_EN_UNUSED, },
{ 0, 4, 17, 0, KEY_EN_UNUSED, },
{ 0, 4, 18, 0, KEY_EN_UNUSED, },
{ 0, 4, 19, 0, KEY_EN_UNUSED, },
{ 0, 4, 20, 0, KEY_EN_UNUSED, },
{ 0, 5, 18, 0, KEY_EN_UNUSED, },
{ 0, 5, 19, 0, KEY_EN_UNUSED, },
}
};
keyboard_keymap_overlay tkl_to_sixty
{
KEYBOARD_SIZE_TKL,
{
/*---------------------------------------------------------------------*\
| Insert Keys |
\*---------------------------------------------------------------------*/
},
{
/*---------------------------------------------------------------------*\
| Swap Keys |
\*---------------------------------------------------------------------*/
{ 0, 0, 0, 0, KEY_EN_UNUSED, },
{ 0, 0, 2, 0, KEY_EN_UNUSED, },
{ 0, 0, 3, 0, KEY_EN_UNUSED, },
{ 0, 0, 4, 0, KEY_EN_UNUSED, },
{ 0, 0, 5, 0, KEY_EN_UNUSED, },
{ 0, 0, 6, 0, KEY_EN_UNUSED, },
{ 0, 0, 7, 0, KEY_EN_UNUSED, },
{ 0, 0, 8, 0, KEY_EN_UNUSED, },
{ 0, 0, 9, 0, KEY_EN_UNUSED, },
{ 0, 0, 10, 0, KEY_EN_UNUSED, },
{ 0, 0, 11, 0, KEY_EN_UNUSED, },
{ 0, 0, 12, 0, KEY_EN_UNUSED, },
{ 0, 0, 13, 0, KEY_EN_UNUSED, },
{ 0, 0, 14, 0, KEY_EN_UNUSED, },
{ 0, 0, 15, 0, KEY_EN_UNUSED, },
{ 0, 0, 16, 0, KEY_EN_UNUSED, },
{ 0, 1, 0, 0, KEY_EN_ESCAPE, },
{ 0, 1, 14, 0, KEY_EN_UNUSED, },
{ 0, 1, 15, 0, KEY_EN_UNUSED, },
{ 0, 1, 16, 0, KEY_EN_UNUSED, },
{ 0, 2, 14, 0, KEY_EN_UNUSED, },
{ 0, 2, 15, 0, KEY_EN_UNUSED, },
{ 0, 2, 16, 0, KEY_EN_UNUSED, },
{ 0, 4, 15, 0, KEY_EN_UNUSED, },
{ 0, 5, 14, 0, KEY_EN_UNUSED, },
{ 0, 5, 15, 0, KEY_EN_UNUSED, },
{ 0, 5, 16, 0, KEY_EN_UNUSED, },
}
};
KeyboardLayoutManager::KeyboardLayoutManager(KEYBOARD_LAYOUT layout, KEYBOARD_SIZE size) : KeyboardLayoutManager(layout, size, {})
{
}
KeyboardLayoutManager::KeyboardLayoutManager(KEYBOARD_LAYOUT layout, KEYBOARD_SIZE size, layout_values values)
{
if(size == KEYBOARD_SIZE::KEYBOARD_SIZE_EMPTY)
{
LOG_INFO(LOG_MSG_CREATED_NEW, name.c_str(), LOG_MSG_EMPTY, rows, cols, keymap.size());
return;
}
std::string tmp_name;
keymap = keyboard_basemap;
rows = 6;
cols = 21;
/*---------------------------------------------------------------------*\
| Add any values passed into the constructor before switching layouts |
| and declare a value set for any changes afterwards |
\*---------------------------------------------------------------------*/
for(size_t key_idx = 0; key_idx < values.ansi.size() && key_idx < keymap.size(); key_idx++)
{
keymap[key_idx].value = values.ansi[key_idx];
}
switch(layout)
{
case KEYBOARD_LAYOUT::KEYBOARD_LAYOUT_ISO_AZERTY:
ChangeKeys(iso_azerty);
tmp_name = KEYBOARD_NAME_AZERTY;
break;
case KEYBOARD_LAYOUT::KEYBOARD_LAYOUT_ISO_QWERTY:
ChangeKeys(iso_qwerty);
tmp_name = KEYBOARD_NAME_ISO;
tmp_name.append(KEYBOARD_NAME_QWERTY);
break;
case KEYBOARD_LAYOUT::KEYBOARD_LAYOUT_ISO_QWERTZ:
ChangeKeys(iso_qwertz);
tmp_name = KEYBOARD_NAME_QWERTZ;
break;
case KEYBOARD_LAYOUT::KEYBOARD_LAYOUT_JIS:
ChangeKeys(jis);
tmp_name = KEYBOARD_NAME_JIS;
break;
default:
tmp_name = KEYBOARD_NAME_ANSI;
tmp_name.append(KEYBOARD_NAME_QWERTY);
break;
}
/*---------------------------------------------------------------------*\
| If the regional layouts were passed in count() returns true before |
| attempting to swap keys. |
\*---------------------------------------------------------------------*/
LOG_DEBUG("[%s] Looking for a regional overlay %d and found: %d", name.c_str(), layout, values.regional_overlay.count(layout));
if(values.regional_overlay.count(layout))
{
LOG_DEBUG("[%s] Found a regional overlay swapping keys", name.c_str());
SwapKeys(values.regional_overlay.find(layout)->second);
}
switch(size)
{
case KEYBOARD_SIZE::KEYBOARD_SIZE_SIXTY:
ChangeKeys(full_to_tkl);
ChangeKeys(tkl_to_sixty);
name = KEYBOARD_NAME_SIXTY + tmp_name;
break;
case KEYBOARD_SIZE::KEYBOARD_SIZE_TKL:
ChangeKeys(full_to_tkl);
name = KEYBOARD_NAME_TKL + tmp_name;
break;
default:
name = KEYBOARD_NAME_FULL + tmp_name;
break;
}
LOG_INFO(LOG_MSG_CREATED_NEW, name.c_str(), KEY_EN_UNUSED, rows, cols, keymap.size());
}
KeyboardLayoutManager::~KeyboardLayoutManager()
{
}
void KeyboardLayoutManager::ChangeKeys(keyboard_keymap_overlay new_layout)
{
InsertKeys(new_layout.insert);
SwapKeys(new_layout.swap);
UpdateDimensions();
}
void KeyboardLayoutManager::ChangeKeys(keyboard_keymap_overlay_values new_layout)
{
InsertKeys(new_layout.insert);
SwapKeys(new_layout.swap);
UpdateDimensions();
}
void KeyboardLayoutManager::InsertKeys(std::vector<keyboard_led> ins_keys)
{
LOG_DEBUG("[%s] Inserting %d keys", name.c_str(), ins_keys.size());
for(size_t i = 0; i < ins_keys.size(); i++)
{
/*---------------------------------------------------------------------*\
| Find the insertion point |
\*---------------------------------------------------------------------*/
std::vector<keyboard_led>::iterator key = keymap.begin();
while( key != keymap.end() &&
((ins_keys[i].col < cols && !(ins_keys[i].row == key->row && ins_keys[i].col <= key->col)) ||
( ins_keys[i].col >= cols && ins_keys[i].row >= key->row)))
{
key++;
}
if(key == keymap.end())
{
LOG_DEBUG(LOG_MSG_INSERT_BEFORE, name.c_str(), ins_keys[i].name, "the end", ins_keys[i].row, ins_keys[i].col, KEY_EN_UNUSED);
keymap.push_back(ins_keys[i]);
break;
}
else if(strlen(ins_keys[i].name) == 0)
{
LOG_DEBUG(LOG_MSG_INSERT_BEFORE, name.c_str(), LOG_MSG_UNUSED_KEY, key->name, key->row, key->col, LOG_MSG_SHIFTING_RIGHT);
key->col++;
}
else
{
LOG_DEBUG(LOG_MSG_INSERT_BEFORE, name.c_str(), ins_keys[i].name, key->name, key->row, key->col, KEY_EN_UNUSED);
key = keymap.insert(key, ins_keys[i]);
key++;
}
/*---------------------------------------------------------------------*\
| Provided key is not the end of the vector, until the end of the row |
| and assuming the column is equal to the key to the left |
| (i.e. sharing the same spot) shift 1 column right |
\*---------------------------------------------------------------------*/
for(std::vector<keyboard_led>::iterator shift = key + 1;
shift != keymap.end() && shift->row == key->row &&
shift->col == key->col; ++shift, ++key)
{
shift->col++;
}
}
}
void KeyboardLayoutManager::SwapKeys(std::vector<keyboard_led> swp_keys)
{
LOG_DEBUG("[%s] Swapping %d keys", name.c_str(), swp_keys.size());
for(size_t i = 0; i < swp_keys.size(); i++)
{
bool not_swapped = true;
for(std::vector<keyboard_led>::iterator key = keymap.begin(); key != keymap.end(); ++key)
{
if(key->row == swp_keys[i].row && key->col == swp_keys[i].col)
{
LOG_DEBUG("[%s] Swapping in %s and %s out @ %02d, %02d", name.c_str(), swp_keys[i].name, key->name, key->row, key->col);
key->name = swp_keys[i].name;
key->value = swp_keys[i].value;
not_swapped = false;
break;
}
}
/*---------------------------------------------------------------------*\
| If the key was not able to be swapped then insert the key instead |
\*---------------------------------------------------------------------*/
if(not_swapped)
{
std::vector<keyboard_led> insert;
insert.push_back(swp_keys[i]);
InsertKeys(insert);
}
}
}
void KeyboardLayoutManager::RemoveKeys(std::vector<keyboard_led> rmv_keys)
{
for(size_t i = 0; i < rmv_keys.size(); i++)
{
for(std::vector<keyboard_led>::iterator key = keymap.begin(); key != keymap.end(); ++key)
{
if(key->row == rmv_keys[i].row && key->col == rmv_keys[i].col)
{
LOG_DEBUG("[%s] Removing %s @ %02d, %02d and shifting keys left", name.c_str(), key->name, key->row, key->col);
for(std::vector<keyboard_led>::iterator shift = key + 1; shift != keymap.end() && shift->row == key->row; ++shift)
{
shift->col--;
}
keymap.erase(key);
break;
}
}
}
}
std::string KeyboardLayoutManager::GetName()
{
return name;
}
KEYBOARD_LAYOUT KeyboardLayoutManager::GetLayout()
{
return layout;
}
KEYBOARD_SIZE KeyboardLayoutManager::GetPhysicalSize()
{
return physical_size;
}
unsigned int KeyboardLayoutManager::GetKeyCount()
{
return keymap.size();
}
std::string KeyboardLayoutManager::GetKeyNameAt(unsigned int key_idx)
{
if(key_idx < keymap.size())
{
return keymap[key_idx].name;
}
return KEY_EN_UNUSED;
}
std::string KeyboardLayoutManager::GetKeyNameAt(unsigned int row, unsigned int col)
{
for(std::vector<keyboard_led>::iterator key = keymap.begin(); key != keymap.end(); ++key)
{
if(key->row == row && key->col == col)
{
return key->name;
}
}
return KEY_EN_UNUSED;
}
unsigned int KeyboardLayoutManager::GetKeyValueAt(unsigned int key_idx)
{
if(key_idx < keymap.size())
{
return keymap[key_idx].value;
}
return -1;
}
unsigned int KeyboardLayoutManager::GetKeyValueAt(unsigned int row, unsigned int col)
{
for(std::vector<keyboard_led>::iterator key = keymap.begin(); key != keymap.end(); ++key)
{
if(key->row == row && key->col == col)
{
return key->value;
}
}
return -1;
}
unsigned int KeyboardLayoutManager::GetRowCount()
{
return rows;
}
unsigned int KeyboardLayoutManager::GetColumnCount()
{
return cols;
}
void KeyboardLayoutManager::GetKeyMap(unsigned int* map_ptr)
{
GetKeyMap(map_ptr, KEYBOARD_MAP_FILL_TYPE_INDEX, rows, cols);
}
void KeyboardLayoutManager::GetKeyMap(unsigned int* map_ptr, KEYBOARD_MAP_FILL_TYPE fill_type)
{
GetKeyMap(map_ptr, fill_type, rows, cols);
}
void KeyboardLayoutManager::GetKeyMap(unsigned int* map_ptr, KEYBOARD_MAP_FILL_TYPE fill_type, uint8_t height = 0, uint8_t width = 0)
{
unsigned int no_key = -1;
width = std::max(width, cols);
height = std::max(height, rows);
for(size_t r = 0; r < height; r++)
{
size_t offset = r * width;
for(size_t c = 0; c < width; c++)
{
map_ptr[offset + c] = no_key;
}
}
for(size_t i = 0; i < keymap.size(); i++)
{
size_t offset = (keymap[i].row * width) + keymap[i].col;
switch(fill_type)
{
case KEYBOARD_MAP_FILL_TYPE_COUNT:
map_ptr[offset] = i;
break;
case KEYBOARD_MAP_FILL_TYPE_VALUE:
map_ptr[offset] = keymap[i].value;
break;
case KEYBOARD_MAP_FILL_TYPE_INDEX:
default:
map_ptr[offset] = offset;
break;
}
}
}
void KeyboardLayoutManager::UpdateDimensions()
{
/*---------------------------------------------------------------------*\
| Recalculate row and column values |
| First trim all "unused" entries by dropping zero length key names |
\*---------------------------------------------------------------------*/
std::vector<keyboard_led> km = keymap;
keymap.clear();
for(std::vector<keyboard_led>::iterator key = km.begin(); key != km.end(); ++key)
{
if(strlen(key->name) > 0)
{
keymap.push_back(*key);
}
}
/*-------------------------------------*\
| Sixty percent KBs fix |
| Check the first row is still row 0 |
\*-------------------------------------*/
if(keymap.begin()->row > 0)
{
for(std::vector<keyboard_led>::iterator key = keymap.begin(); key != keymap.end(); ++key)
{
key->row--;
}
}
/*---------------------------------------------------------------------*\
| Compute max_row and max_col. |
\*---------------------------------------------------------------------*/
uint8_t max_row = 0;
uint8_t max_col = 0;
for(std::vector<keyboard_led>::iterator key = keymap.begin(); key != keymap.end(); ++key)
{
if(key->row > max_row)
{
max_row = key->row;
}
if(key->col > max_col)
{
max_col = key->col;
}
}
rows = max_row + 1;
cols = max_col + 1;
}

View file

@ -0,0 +1,122 @@
/*---------------------------------------------------------------------*\
| KeyboardLayoutManager.h |
| |
| Helper library to produce keyboard layouts |
| |
| Chris M (Dr_No) 04 Feb 2023 |
| |
\*---------------------------------------------------------------------*/
#pragma once
#include <map>
#include <string>
#include <vector>
#include "RGBControllerKeyNames.h"
enum KEYBOARD_SIZE
{
KEYBOARD_SIZE_EMPTY = -1,
KEYBOARD_SIZE_FULL,
KEYBOARD_SIZE_TKL,
KEYBOARD_SIZE_SIXTY,
};
enum KEYBOARD_LAYOUT
{
KEYBOARD_LAYOUT_ANSI_QWERTY = 0,
KEYBOARD_LAYOUT_ISO_QWERTY,
KEYBOARD_LAYOUT_ISO_QWERTZ,
KEYBOARD_LAYOUT_ISO_AZERTY,
KEYBOARD_LAYOUT_JIS,
};
enum KEYBOARD_MAP_FILL_TYPE
{
KEYBOARD_MAP_FILL_TYPE_COUNT,
KEYBOARD_MAP_FILL_TYPE_INDEX,
KEYBOARD_MAP_FILL_TYPE_VALUE,
};
typedef struct
{
uint8_t zone;
uint8_t row;
uint8_t col;
unsigned int value;
const char* name;
} keyboard_led;
typedef
std::vector<keyboard_led> key_set;
typedef struct
{
std::vector<unsigned int> ansi;
std::map<KEYBOARD_LAYOUT, key_set> regional_overlay;
} layout_values;
typedef struct
{
KEYBOARD_SIZE base_size;
key_set insert;
key_set swap;
} keyboard_keymap_overlay;
typedef struct
{
KEYBOARD_SIZE base_size;
layout_values key_values;
key_set insert;
key_set swap;
} keyboard_keymap_overlay_values;
static const std::vector<keyboard_led> empty_basemap =
{
/*---------------------------------------------------------------------*\
| Zone, Row, Column, Index, Key |
\*---------------------------------------------------------------------*/
};
class KeyboardLayoutManager
{
public:
KeyboardLayoutManager(KEYBOARD_LAYOUT, KEYBOARD_SIZE);
KeyboardLayoutManager(KEYBOARD_LAYOUT, KEYBOARD_SIZE, layout_values values);
~KeyboardLayoutManager();
void ChangeKeys(keyboard_keymap_overlay new_layout);
void ChangeKeys(keyboard_keymap_overlay_values new_layout);
void InsertKeys(std::vector<keyboard_led> keys);
void SwapKeys(std::vector<keyboard_led> keys);
void UpdateDimensions();
std::string GetName();
KEYBOARD_LAYOUT GetLayout();
KEYBOARD_SIZE GetPhysicalSize();
unsigned int GetKeyCount();
std::string GetKeyNameAt(unsigned int key_idx);
std::string GetKeyNameAt(unsigned int row, unsigned int col);
unsigned int GetKeyValueAt(unsigned int key_idx);
unsigned int GetKeyValueAt(unsigned int row, unsigned int col);
unsigned int GetRowCount();
unsigned int GetColumnCount();
void GetKeyMap(unsigned int* map_ptr);
void GetKeyMap(unsigned int* map_ptr, KEYBOARD_MAP_FILL_TYPE fill_type);
void GetKeyMap(unsigned int* map_ptr, KEYBOARD_MAP_FILL_TYPE fill_type,
uint8_t height, uint8_t width);
private:
void RemoveKeys(std::vector<keyboard_led> keys);
KEYBOARD_LAYOUT layout;
KEYBOARD_SIZE physical_size;
std::string name = ZONE_EN_KEYBOARD;
uint8_t rows = 0;
uint8_t cols = 0;
std::vector<keyboard_led> keymap = empty_basemap;
};

View file

@ -64,6 +64,7 @@ const char* KEY_EN_O = "Key: O";
const char* KEY_EN_P = "Key: P";
const char* KEY_EN_LEFT_BRACKET = "Key: [";
const char* KEY_EN_RIGHT_BRACKET = "Key: ]";
const char* KEY_EN_BACK_SLASH = "Key: \\";
const char* KEY_EN_ANSI_BACK_SLASH = "Key: \\ (ANSI)";
const char* KEY_EN_DELETE = "Key: Delete";
const char* KEY_EN_END = "Key: End";
@ -169,3 +170,18 @@ const char* KEY_DE_ESZETT = "Key: ß";
const char* KEY_DE_DIAERESIS_A = "Key: Ä";
const char* KEY_DE_DIAERESIS_O = "Key: Ö";
const char* KEY_DE_DIAERESIS_U = "Key: Ü";
const char* KEY_FR_SUPER_2 = "Key: ²";
const char* KEY_FR_AMPERSAND = "Key: &";
const char* KEY_FR_ACUTE_E = "Key: é";
const char* KEY_FR_DOUBLEQUOTE = "Key: \"";
const char* KEY_FR_LEFT_PARENTHESIS = "Key: (";
const char* KEY_FR_GRAVE_E = "Key: è";
const char* KEY_FR_UNDERSCORE = "Key: _";
const char* KEY_FR_CEDILLA_C = "Key: ç";
const char* KEY_FR_GRAVE_A = "Key: à";
const char* KEY_FR_RIGHT_PARENTHESIS = "Key: )";
const char* KEY_FR_DOLLAR = "Key: $";
const char* KEY_FR_GRAVE_U = "Key: ù";
const char* KEY_FR_ASTERIX = "Key: *";
const char* KEY_FR_EXCLAIMATION = "Key: !";

View file

@ -64,6 +64,7 @@ extern const char* KEY_EN_O;
extern const char* KEY_EN_P;
extern const char* KEY_EN_LEFT_BRACKET;
extern const char* KEY_EN_RIGHT_BRACKET;
extern const char* KEY_EN_BACK_SLASH;
extern const char* KEY_EN_ANSI_BACK_SLASH;
extern const char* KEY_EN_DELETE;
extern const char* KEY_EN_END;
@ -169,3 +170,18 @@ extern const char* KEY_DE_ESZETT;
extern const char* KEY_DE_DIAERESIS_A;
extern const char* KEY_DE_DIAERESIS_O;
extern const char* KEY_DE_DIAERESIS_U;
extern const char* KEY_FR_SUPER_2;
extern const char* KEY_FR_AMPERSAND;
extern const char* KEY_FR_ACUTE_E;
extern const char* KEY_FR_DOUBLEQUOTE;
extern const char* KEY_FR_LEFT_PARENTHESIS;
extern const char* KEY_FR_GRAVE_E;
extern const char* KEY_FR_UNDERSCORE;
extern const char* KEY_FR_CEDILLA_C;
extern const char* KEY_FR_GRAVE_A;
extern const char* KEY_FR_RIGHT_PARENTHESIS;
extern const char* KEY_FR_DOLLAR;
extern const char* KEY_FR_GRAVE_U;
extern const char* KEY_FR_ASTERIX;
extern const char* KEY_FR_EXCLAIMATION;

View file

@ -103,6 +103,7 @@ static const std::map<std::string, led_label> led_label_lookup =
{ KEY_EN_EQUALS, { "=" , "=", }},
{ KEY_EN_LEFT_BRACKET, { "[" , "[", }},
{ KEY_EN_RIGHT_BRACKET, { "]" , "]", }},
{ KEY_EN_BACK_SLASH, { "\\" , "\\", }},
{ KEY_EN_ANSI_BACK_SLASH, { "\\" , "\\", }},
{ KEY_EN_ISO_BACK_SLASH, { "\\" , "\\", }},
{ KEY_EN_SEMICOLON, { ";" , ";", }},
@ -205,6 +206,20 @@ static const std::map<std::string, led_label> led_label_lookup =
{ KEY_DE_DIAERESIS_A, { "Ä" , "\xC3\x84", }},
{ KEY_DE_DIAERESIS_O, { "Ö" , "\xC3\x96", }},
{ KEY_DE_DIAERESIS_U, { "Ü" , "\xC3\x9C" }},
{ KEY_FR_SUPER_2, { "²" , "\xc2\xb2" }},
{ KEY_FR_AMPERSAND, { "&" , "&" }},
{ KEY_FR_ACUTE_E, { "é" , "\xc3\xa9" }},
{ KEY_FR_DOUBLEQUOTE, { "\"" , "\"" }},
{ KEY_FR_LEFT_PARENTHESIS, { "(" , "(" }},
{ KEY_FR_GRAVE_E, { "è" , "\xc3\xa8" }},
{ KEY_FR_UNDERSCORE, { "_" , "_" }},
{ KEY_FR_CEDILLA_C, { "ç" , "\xc3\xa7" }},
{ KEY_FR_GRAVE_A, { "à" , "\xc3\xa0" }},
{ KEY_FR_RIGHT_PARENTHESIS, { ")" , ")" }},
{ KEY_FR_DOLLAR, { "$" , "$" }},
{ KEY_FR_GRAVE_U, { "ù" , "\xc3\xb9" }},
{ KEY_FR_ASTERIX, { "*" , "*" }},
{ KEY_FR_EXCLAIMATION, { "!" , "!" }},
};
void DeviceView::setController(RGBController * controller_ptr)