keymap: limit set of left/right swap options

For Shift, Control, Option, and Command assume that you want to shift
on the same side, left-for-left, right-for-right. The Menu key is
available on either the left or right side, and lock keys can be
swapped with any other modifier left or right.

If we have multiple unmapped modifiers we need to do a little extra
work to figure out which of the unmapped modifiers to swap with.

Convert private class member methods to static functions.

Also update copyright info
This commit is contained in:
John Scipione
2014-02-20 15:18:37 -05:00
parent 8eb27eaa79
commit a073305c96
4 changed files with 221 additions and 148 deletions
+191 -122
View File
@@ -1,6 +1,11 @@
/*
* Copyright 2009-2010, Axel Dörfler, [email protected].
* Copyright 2013-2014 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, [email protected]
* John Scipione, [email protected]
*/
@@ -33,6 +38,116 @@ static const rgb_color kDeadKeyColor = {152, 203, 255, 255};
static const rgb_color kLitIndicatorColor = {116, 212, 83, 255};
static const char*
name_for_modifier(uint32 modifier, bool pretty)
{
if (modifier == B_CAPS_LOCK)
return pretty ? B_TRANSLATE("Caps lock") : "caps_key";
else if (modifier == B_NUM_LOCK)
return pretty ? B_TRANSLATE("Num lock") : "num_key";
else if (modifier == B_SCROLL_LOCK)
return pretty ? B_TRANSLATE("Scroll lock") : "scroll_key";
else if (modifier == B_SHIFT_KEY) {
return pretty ? B_TRANSLATE_COMMENT("Shift", "Shift key")
: "shift_key";
} else if (modifier == B_LEFT_SHIFT_KEY)
return pretty ? B_TRANSLATE("Left shift") : "left_shift_key";
else if (modifier == B_RIGHT_SHIFT_KEY)
return pretty ? B_TRANSLATE("Right shift") : "right_shift_key";
else if (modifier == B_COMMAND_KEY) {
return pretty ? B_TRANSLATE_COMMENT("Command", "Command key")
: "command_key";
} else if (modifier == B_LEFT_COMMAND_KEY)
return pretty ? B_TRANSLATE("Left command") : "left_command_key";
else if (modifier == B_RIGHT_COMMAND_KEY)
return pretty ? B_TRANSLATE("Right command") : "right_command_key";
else if (modifier == B_CONTROL_KEY) {
return pretty ? B_TRANSLATE_COMMENT("Control", "Control key")
: "control_key";
} else if (modifier == B_LEFT_CONTROL_KEY)
return pretty ? B_TRANSLATE("Left control") : "left_control_key";
else if (modifier == B_RIGHT_CONTROL_KEY)
return pretty ? B_TRANSLATE("Right control") : "right_control_key";
else if (modifier == B_OPTION_KEY) {
return pretty ? B_TRANSLATE_COMMENT("Option", "Option key")
: "option_key";
} else if (modifier == B_LEFT_OPTION_KEY)
return pretty ? B_TRANSLATE("Left option") : "left_option_key";
else if (modifier == B_RIGHT_OPTION_KEY)
return pretty ? B_TRANSLATE("Right option") : "right_option_key";
else if (modifier == B_MENU_KEY)
return pretty ? B_TRANSLATE_COMMENT("Menu", "Menu key") : "menu_key";
return NULL;
}
static BMenuItem*
swap_modifiers_menu_item(Keymap* map, uint32 modifier, uint32 displayModifier,
uint32 oldCode, uint32 newCode)
{
int32 mask = B_SHIFT_KEY | B_COMMAND_KEY | B_CONTROL_KEY | B_OPTION_KEY;
const char* oldName = name_for_modifier(oldCode == 0x00 ? modifier
: map->Modifier(oldCode) & ~mask, false);
const char* newName = name_for_modifier(newCode == 0x00 ? modifier
: map->Modifier(newCode) & ~mask, false);
BMessage* message = new BMessage(kMsgUpdateModifierKeys);
if (newName != NULL)
message->AddUInt32(newName, oldCode);
if (oldName != NULL)
message->AddUInt32(oldName, newCode);
if (oldCode == newCode)
message->AddBool("unset", true);
return new BMenuItem(name_for_modifier(displayModifier, true), message);
}
static bool
is_left_modifier_key(uint32 keyCode)
{
return keyCode == 0x4b // left shift
|| keyCode == 0x5d // left command
|| keyCode == 0x5c // left control
|| keyCode == 0x66; // left option
}
static bool
is_right_modifier_key(uint32 keyCode)
{
return keyCode == 0x56 // right shift
|| keyCode == 0x5f // right command
|| keyCode == 0x60 // right control
|| keyCode == 0x67 // right option
|| keyCode == 0x68; // menu
}
static bool
is_lock_key(uint32 keyCode)
{
return keyCode == 0x3b // caps lock
|| keyCode == 0x22 // num lock
|| keyCode == 0x0f; // scroll lock
}
static bool
is_mappable_to_modifier(uint32 keyCode)
{
return is_left_modifier_key(keyCode)
|| is_right_modifier_key(keyCode)
|| is_lock_key(keyCode);
}
// #pragma mark - KeyboardLayoutView
KeyboardLayoutView::KeyboardLayoutView(const char* name)
:
BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS),
@@ -164,96 +279,119 @@ KeyboardLayoutView::MouseDown(BPoint point)
}
if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0
|| ((buttons & B_PRIMARY_MOUSE_BUTTON) != 0
&& (modifiers() & B_CONTROL_KEY) != 0)) {
if (_IsMappableToModifierKey(key->code)) {
// pop up the modifier keys menu
BPopUpMenu* modifiersPopUp = new BPopUpMenu("Modifiers pop up",
true, true, B_ITEMS_IN_COLUMN);
const key_map& map = fKeymap->Map();
BMenuItem* item = NULL;
|| ((buttons & B_PRIMARY_MOUSE_BUTTON) != 0
&& (modifiers() & B_CONTROL_KEY) != 0)) {
// secondary mouse button, pop up a swap context menu
if (!is_mappable_to_modifier(key->code)) {
// ToDo: pop up a list of alternative characters
fButtons = buttons;
return;
}
item = _SwapModifiersMenuItem(B_LEFT_SHIFT_KEY, key->code,
map.left_shift_key);
// pop up the modifier keys menu
BPopUpMenu* modifiersPopUp = new BPopUpMenu("Modifiers pop up",
true, true, B_ITEMS_IN_COLUMN);
const key_map& map = fKeymap->Map();
bool isLockKey = is_lock_key(key->code);
BMenuItem* item = NULL;
if (is_left_modifier_key(key->code) || isLockKey) {
item = swap_modifiers_menu_item(fKeymap, B_LEFT_SHIFT_KEY,
isLockKey ? B_LEFT_SHIFT_KEY : B_SHIFT_KEY,
map.left_shift_key, key->code);
modifiersPopUp->AddItem(item);
if (key->code == map.left_shift_key)
item->SetMarked(true);
item = _SwapModifiersMenuItem(B_LEFT_CONTROL_KEY, key->code,
map.left_control_key);
item = swap_modifiers_menu_item(fKeymap, B_LEFT_CONTROL_KEY,
isLockKey ? B_LEFT_CONTROL_KEY : B_CONTROL_KEY,
map.left_control_key, key->code);
modifiersPopUp->AddItem(item);
if (key->code == map.left_control_key)
item->SetMarked(true);
item = _SwapModifiersMenuItem(B_LEFT_OPTION_KEY, key->code,
map.left_option_key);
item = swap_modifiers_menu_item(fKeymap, B_LEFT_OPTION_KEY,
isLockKey ? B_LEFT_OPTION_KEY : B_OPTION_KEY,
map.left_option_key, key->code);
modifiersPopUp->AddItem(item);
if (key->code == map.left_option_key)
item->SetMarked(true);
item = _SwapModifiersMenuItem(B_LEFT_COMMAND_KEY, key->code,
map.left_command_key);
item = swap_modifiers_menu_item(fKeymap, B_LEFT_COMMAND_KEY,
isLockKey ? B_LEFT_COMMAND_KEY : B_COMMAND_KEY,
map.left_command_key, key->code);
modifiersPopUp->AddItem(item);
if (key->code == map.left_command_key)
item->SetMarked(true);
}
modifiersPopUp->AddSeparatorItem();
if (is_right_modifier_key(key->code) || isLockKey) {
if (isLockKey)
modifiersPopUp->AddSeparatorItem();
item = _SwapModifiersMenuItem(B_RIGHT_SHIFT_KEY,
key->code, map.right_shift_key);
item = swap_modifiers_menu_item(fKeymap, B_RIGHT_SHIFT_KEY,
isLockKey ? B_RIGHT_SHIFT_KEY : B_SHIFT_KEY,
map.right_shift_key, key->code);
modifiersPopUp->AddItem(item);
if (key->code == map.right_shift_key)
item->SetMarked(true);
item = _SwapModifiersMenuItem(B_RIGHT_CONTROL_KEY,
key->code, map.right_control_key);
item = swap_modifiers_menu_item(fKeymap, B_RIGHT_CONTROL_KEY,
isLockKey ? B_RIGHT_CONTROL_KEY : B_CONTROL_KEY,
map.right_control_key, key->code);
modifiersPopUp->AddItem(item);
if (key->code == map.right_control_key)
item->SetMarked(true);
}
item = _SwapModifiersMenuItem(B_MENU_KEY, key->code, map.menu_key);
modifiersPopUp->AddItem(item);
if (key->code == map.menu_key)
item->SetMarked(true);
item = swap_modifiers_menu_item(fKeymap, B_MENU_KEY, B_MENU_KEY,
map.menu_key, key->code);
modifiersPopUp->AddItem(item);
if (key->code == map.menu_key)
item->SetMarked(true);
item = _SwapModifiersMenuItem(B_RIGHT_OPTION_KEY, key->code,
map.right_option_key);
if (is_right_modifier_key(key->code) || isLockKey) {
item = swap_modifiers_menu_item(fKeymap, B_RIGHT_OPTION_KEY,
isLockKey ? B_RIGHT_OPTION_KEY : B_OPTION_KEY,
map.right_option_key, key->code);
modifiersPopUp->AddItem(item);
if (key->code == map.right_option_key)
item->SetMarked(true);
item = _SwapModifiersMenuItem(B_RIGHT_COMMAND_KEY, key->code,
map.right_command_key);
item = swap_modifiers_menu_item(fKeymap, B_RIGHT_COMMAND_KEY,
isLockKey ? B_RIGHT_COMMAND_KEY : B_COMMAND_KEY,
map.right_command_key, key->code);
modifiersPopUp->AddItem(item);
if (key->code == map.right_command_key)
item->SetMarked(true);
modifiersPopUp->AddSeparatorItem();
item = _SwapModifiersMenuItem(B_CAPS_LOCK, key->code,
map.caps_key);
modifiersPopUp->AddItem(item);
if (key->code == map.caps_key)
item->SetMarked(true);
item = _SwapModifiersMenuItem(B_NUM_LOCK, key->code, map.num_key);
modifiersPopUp->AddItem(item);
if (key->code == map.num_key)
item->SetMarked(true);
item = _SwapModifiersMenuItem(B_SCROLL_LOCK, key->code,
map.scroll_key);
modifiersPopUp->AddItem(item);
if (key->code == map.scroll_key)
item->SetMarked(true);
modifiersPopUp->SetAsyncAutoDestruct(true);
if (modifiersPopUp->SetTargetForItems(Window()) == B_OK)
modifiersPopUp->Go(ConvertToScreen(point), true);
}
modifiersPopUp->AddSeparatorItem();
item = swap_modifiers_menu_item(fKeymap, B_CAPS_LOCK, B_CAPS_LOCK,
map.caps_key, key->code);
modifiersPopUp->AddItem(item);
if (key->code == map.caps_key)
item->SetMarked(true);
item = swap_modifiers_menu_item(fKeymap, B_NUM_LOCK, B_NUM_LOCK,
map.num_key, key->code);
modifiersPopUp->AddItem(item);
if (key->code == map.num_key)
item->SetMarked(true);
item = swap_modifiers_menu_item(fKeymap, B_SCROLL_LOCK, B_SCROLL_LOCK,
map.scroll_key, key->code);
modifiersPopUp->AddItem(item);
if (key->code == map.scroll_key)
item->SetMarked(true);
modifiersPopUp->SetAsyncAutoDestruct(true);
if (modifiersPopUp->SetTargetForItems(Window()) == B_OK)
modifiersPopUp->Go(ConvertToScreen(point), true);
} else if ((buttons & B_TERTIARY_MOUSE_BUTTON) != 0
&& (fButtons & B_TERTIARY_MOUSE_BUTTON) == 0) {
// toggle the "deadness" of dead keys via middle mouse button
// tertiary mouse button, toggle the "deadness" of dead keys
bool isEnabled = false;
uint8 deadKey = fKeymap->DeadKey(key->code, fModifiers, &isEnabled);
if (deadKey > 0) {
@@ -1276,72 +1414,3 @@ KeyboardLayoutView::_SendFakeKeyDown(const Key* key)
fTarget.SendMessage(&message);
}
BMenuItem*
KeyboardLayoutView::_SwapModifiersMenuItem(uint32 modifier, uint32 oldCode,
uint32 newCode)
{
int32 mask = B_SHIFT_KEY | B_COMMAND_KEY | B_CONTROL_KEY | B_OPTION_KEY;
const char* oldName = _NameForModifier(fKeymap->Modifier(oldCode) & ~mask);
const char* newName = _NameForModifier(fKeymap->Modifier(newCode) & ~mask);
BMessage* message = new BMessage(kMsgUpdateModifierKeys);
message->AddUInt32(newName, oldCode);
message->AddUInt32(oldName, newCode);
if (oldCode == newCode)
message->AddBool("unset", true);
return new BMenuItem(_NameForModifier(modifier, true), message);
}
const char*
KeyboardLayoutView::_NameForModifier(uint32 modifier, bool pretty) const
{
if (modifier == B_CAPS_LOCK)
return pretty ? B_TRANSLATE("Caps lock") : "caps_key";
else if (modifier == B_NUM_LOCK)
return pretty ? B_TRANSLATE("Num lock") : "num_key";
else if (modifier == B_SCROLL_LOCK)
return pretty ? B_TRANSLATE("Scroll lock") : "scroll_key";
else if (modifier == B_LEFT_SHIFT_KEY)
return pretty ? B_TRANSLATE("Left shift") : "left_shift_key";
else if (modifier == B_RIGHT_SHIFT_KEY)
return pretty ? B_TRANSLATE("Right shift") : "right_shift_key";
else if (modifier == B_LEFT_COMMAND_KEY)
return pretty ? B_TRANSLATE("Left command") : "left_command_key";
else if (modifier == B_RIGHT_COMMAND_KEY)
return pretty ? B_TRANSLATE("Right command") : "right_command_key";
else if (modifier == B_LEFT_CONTROL_KEY)
return pretty ? B_TRANSLATE("Left control") : "left_control_key";
else if (modifier == B_RIGHT_CONTROL_KEY)
return pretty ? B_TRANSLATE("Right control") : "right_control_key";
else if (modifier == B_LEFT_OPTION_KEY)
return pretty ? B_TRANSLATE("Left option") : "left_option_key";
else if (modifier == B_RIGHT_OPTION_KEY)
return pretty ? B_TRANSLATE("Right option") : "right_option_key";
else if (modifier == B_MENU_KEY)
return pretty ? B_TRANSLATE_COMMENT("Menu", "Menu key") : "menu_key";
return NULL;
}
bool
KeyboardLayoutView::_IsMappableToModifierKey(uint32 keyCode) const
{
return keyCode == 0x3b // caps lock
|| keyCode == 0x22 // num lock
|| keyCode == 0x0f // scroll lock
|| keyCode == 0x4b // left shift
|| keyCode == 0x56 // right shift
|| keyCode == 0x5d // left command
|| keyCode == 0x5f // right command
|| keyCode == 0x5c // left control
|| keyCode == 0x60 // right control
|| keyCode == 0x66 // left option
|| keyCode == 0x67 // right option
|| keyCode == 0x68; // menu
}
+5 -5
View File
@@ -1,6 +1,11 @@
/*
* Copyright 2009, Axel Dörfler, [email protected].
* Copyright 2013-2014 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, [email protected]
* John Scipione, [email protected]
*/
#ifndef KEYBOARD_LAYOUT_VIEW_H
#define KEYBOARD_LAYOUT_VIEW_H
@@ -92,11 +97,6 @@ private:
void _SetFontSize(BView* view, key_kind keyKind);
void _EvaluateDropTarget(BPoint point);
void _SendFakeKeyDown(const Key* key);
BMenuItem* _SwapModifiersMenuItem(uint32 modifier,
uint32 oldCode, uint32 newCode);
const char* _NameForModifier(uint32 modifier,
bool pretty = false) const;
bool _IsMappableToModifierKey(uint32 keyCode) const;
BBitmap* fOffscreenBitmap;
BView* fOffscreenView;
+20 -17
View File
@@ -1,12 +1,13 @@
/*
* Copyright 2004-2010 Haiku Inc. All rights reserved.
* Copyright 2004-2014 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Sandor Vroemisse
* Jérôme Duval
* Alexandre Deckner, [email protected]
* Axel Dörfler, [email protected].
* Axel Dörfler, [email protected]
* Jérôme Duval
* John Scipione, [email protected]
* Sandor Vroemisse
*/
@@ -325,55 +326,57 @@ KeymapWindow::MessageReceived(BMessage* message)
if (message->FindBool("unset", &unset) != B_OK)
unset = false;
if (message->FindUInt32("left_shift_key", &keyCode) == B_OK)
fCurrentMap.SetModifier(unset ? 0 : keyCode, B_LEFT_SHIFT_KEY);
if (message->FindUInt32("left_shift_key", &keyCode) == B_OK) {
fCurrentMap.SetModifier(unset ? 0x00 : keyCode,
B_LEFT_SHIFT_KEY);
}
if (message->FindUInt32("right_shift_key", &keyCode) == B_OK) {
fCurrentMap.SetModifier(unset ? 0 : keyCode,
fCurrentMap.SetModifier(unset ? 0x00 : keyCode,
B_RIGHT_SHIFT_KEY);
}
if (message->FindUInt32("left_control_key", &keyCode) == B_OK) {
fCurrentMap.SetModifier(unset ? 0 : keyCode,
fCurrentMap.SetModifier(unset ? 0x00 : keyCode,
B_LEFT_CONTROL_KEY);
}
if (message->FindUInt32("right_control_key", &keyCode) == B_OK) {
fCurrentMap.SetModifier(unset ? 0 : keyCode,
fCurrentMap.SetModifier(unset ? 0x00 : keyCode,
B_RIGHT_CONTROL_KEY);
}
if (message->FindUInt32("left_option_key", &keyCode) == B_OK) {
fCurrentMap.SetModifier(unset ? 0 : keyCode,
fCurrentMap.SetModifier(unset ? 0x00 : keyCode,
B_LEFT_OPTION_KEY);
}
if (message->FindUInt32("right_option_key", &keyCode) == B_OK) {
fCurrentMap.SetModifier(unset ? 0 : keyCode,
fCurrentMap.SetModifier(unset ? 0x00 : keyCode,
B_RIGHT_OPTION_KEY);
}
if (message->FindUInt32("left_command_key", &keyCode) == B_OK) {
fCurrentMap.SetModifier(unset ? 0 : keyCode,
fCurrentMap.SetModifier(unset ? 0x00 : keyCode,
B_LEFT_COMMAND_KEY);
}
if (message->FindUInt32("right_command_key", &keyCode) == B_OK) {
fCurrentMap.SetModifier(unset ? 0 : keyCode,
fCurrentMap.SetModifier(unset ? 0x00 : keyCode,
B_RIGHT_COMMAND_KEY);
}
if (message->FindUInt32("menu_key", &keyCode) == B_OK)
fCurrentMap.SetModifier(unset ? 0 : keyCode, B_MENU_KEY);
fCurrentMap.SetModifier(unset ? 0x00 : keyCode, B_MENU_KEY);
if (message->FindUInt32("caps_key", &keyCode) == B_OK)
fCurrentMap.SetModifier(unset ? 0 : keyCode, B_CAPS_LOCK);
fCurrentMap.SetModifier(unset ? 0x00 : keyCode, B_CAPS_LOCK);
if (message->FindUInt32("num_key", &keyCode) == B_OK)
fCurrentMap.SetModifier(unset ? 0 : keyCode, B_NUM_LOCK);
fCurrentMap.SetModifier(unset ? 0x00 : keyCode, B_NUM_LOCK);
if (message->FindUInt32("scroll_key", &keyCode) == B_OK)
fCurrentMap.SetModifier(unset ? 0 : keyCode, B_SCROLL_LOCK);
fCurrentMap.SetModifier(unset ? 0x00 : keyCode, B_SCROLL_LOCK);
_UpdateButtons();
fKeyboardLayoutView->SetKeymap(&fCurrentMap);
+5 -4
View File
@@ -1,12 +1,13 @@
/*
* Copyright 2004-2009 Haiku Inc. All rights reserved.
* Copyright 2004-2014 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Sandor Vroemisse
* Jérôme Duval
* Alexandre Deckner, [email protected]
* Axel Dörfler, [email protected].
* Axel Dörfler, [email protected]
* Jérôme Duval
* John Scipione, [email protected]
* Sandor Vroemisse
*/
#ifndef KEYMAP_WINDOW_H
#define KEYMAP_WINDOW_H