diff --git a/src/preferences/keymap/Jamfile b/src/preferences/keymap/Jamfile index 6f0c183160..9ffc182ace 100644 --- a/src/preferences/keymap/Jamfile +++ b/src/preferences/keymap/Jamfile @@ -20,6 +20,7 @@ Preference Keymap : DoCatalogs Keymap : x-vnd.Haiku-Keymap : + KeyboardLayoutView.cpp KeymapWindow.cpp ModifierKeysWindow.cpp ; diff --git a/src/preferences/keymap/KeyboardLayout.h b/src/preferences/keymap/KeyboardLayout.h index 985907c133..18627e464e 100644 --- a/src/preferences/keymap/KeyboardLayout.h +++ b/src/preferences/keymap/KeyboardLayout.h @@ -22,9 +22,9 @@ enum key_shape { }; struct Key { - int32 code; - int32 alternate_code[3]; - int32 alternate_modifier[3]; + uint32 code; + uint32 alternate_code[3]; + uint32 alternate_modifier[3]; key_shape shape; BRect frame; float second_row; diff --git a/src/preferences/keymap/KeyboardLayoutView.cpp b/src/preferences/keymap/KeyboardLayoutView.cpp index cce873ee55..154b6ca45d 100644 --- a/src/preferences/keymap/KeyboardLayoutView.cpp +++ b/src/preferences/keymap/KeyboardLayoutView.cpp @@ -13,10 +13,17 @@ #include #include #include +#include +#include #include #include #include "Keymap.h" +#include "KeymapApplication.h" + + +#undef B_TRANSLATION_CONTEXT +#define B_TRANSLATION_CONTEXT "Keyboard Layout View" static const rgb_color kBrightColor = {230, 230, 230, 255}; @@ -146,28 +153,105 @@ KeyboardLayoutView::MouseDown(BPoint point) fDragKey = NULL; fDropPoint.x = -1; - Key* key = _KeyAt(point); - if (key == NULL) - return; - int32 buttons = 0; if (Looper() != NULL && Looper()->CurrentMessage() != NULL) Looper()->CurrentMessage()->FindInt32("buttons", &buttons); - if ((buttons & B_TERTIARY_MOUSE_BUTTON) != 0 + Key* key = _KeyAt(point); + if (fKeymap == NULL || key == NULL) { + fButtons = buttons; + return; + } + + if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0) { + if (fKeymap->IsModifierKey(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; + + item = _SwapModifiersMenuItem(key->code, map.left_shift_key); + modifiersPopUp->AddItem(item); + if (key->code == map.left_shift_key) + item->SetMarked(true); + + item = _SwapModifiersMenuItem(key->code, map.left_control_key); + modifiersPopUp->AddItem(item); + if (key->code == map.left_control_key) + item->SetMarked(true); + + item = _SwapModifiersMenuItem(key->code, map.left_option_key); + modifiersPopUp->AddItem(item); + if (key->code == map.left_option_key) + item->SetMarked(true); + + item = _SwapModifiersMenuItem(key->code, map.left_command_key); + modifiersPopUp->AddItem(item); + if (key->code == map.left_command_key) + item->SetMarked(true); + + modifiersPopUp->AddSeparatorItem(); + + item = _SwapModifiersMenuItem(key->code, map.right_shift_key); + modifiersPopUp->AddItem(item); + if (key->code == map.right_shift_key) + item->SetMarked(true); + + item = _SwapModifiersMenuItem(key->code, map.right_control_key); + modifiersPopUp->AddItem(item); + if (key->code == map.right_control_key) + item->SetMarked(true); + + item = _SwapModifiersMenuItem(key->code, map.menu_key); + modifiersPopUp->AddItem(item); + if (key->code == map.menu_key) + item->SetMarked(true); + + item = _SwapModifiersMenuItem(key->code, map.right_option_key); + modifiersPopUp->AddItem(item); + if (key->code == map.right_option_key) + item->SetMarked(true); + + item = _SwapModifiersMenuItem(key->code, map.right_command_key); + modifiersPopUp->AddItem(item); + if (key->code == map.right_command_key) + item->SetMarked(true); + + modifiersPopUp->AddSeparatorItem(); + + item = _SwapModifiersMenuItem(key->code, map.caps_key); + modifiersPopUp->AddItem(item); + if (key->code == map.caps_key) + item->SetMarked(true); + + item = _SwapModifiersMenuItem(key->code, map.num_key); + modifiersPopUp->AddItem(item); + if (key->code == map.num_key) + item->SetMarked(true); + + item = _SwapModifiersMenuItem(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); + } + } else if ((buttons & B_TERTIARY_MOUSE_BUTTON) != 0 && (fButtons & B_TERTIARY_MOUSE_BUTTON) == 0) { // toggle the "deadness" of dead keys via middle mouse button - if (fKeymap != NULL) { - bool isEnabled = false; - uint8 deadKey - = fKeymap->DeadKey(key->code, fModifiers, &isEnabled); - if (deadKey > 0) { - fKeymap->SetDeadKeyEnabled(key->code, fModifiers, !isEnabled); - _InvalidateKey(key); - } + bool isEnabled = false; + uint8 deadKey + = fKeymap->DeadKey(key->code, fModifiers, &isEnabled); + if (deadKey > 0) { + fKeymap->SetDeadKeyEnabled(key->code, fModifiers, !isEnabled); + _InvalidateKey(key); } } else { - if (fKeymap != NULL && fKeymap->IsModifierKey(key->code)) { + // primary mouse button + if (fKeymap->IsModifierKey(key->code)) { if (_KeyState(key->code)) { uint32 modifier = fKeymap->Modifier(key->code); if ((modifier & modifiers()) == 0) { @@ -201,32 +285,37 @@ KeyboardLayoutView::MouseUp(BPoint point) if (Looper() != NULL && Looper()->CurrentMessage() != NULL) Looper()->CurrentMessage()->FindInt32("buttons", &buttons); - if (key != NULL) { - if ((fButtons & B_TERTIARY_MOUSE_BUTTON) != 0 - && (buttons & B_TERTIARY_MOUSE_BUTTON) == 0) { - _SetKeyState(key->code, false); - _InvalidateKey(key); - fButtons = buttons; - } else { - fButtons = buttons; - - // modifier keys are sticky when used with the mouse - if (fKeymap != NULL && fKeymap->IsModifierKey(key->code)) - return; - - _SetKeyState(key->code, false); - - if (_HandleDeadKey(key->code, fModifiers) && fDeadKey != 0) - return; - - _InvalidateKey(key); - - if (fDragKey == NULL && fKeymap != NULL) { - // Send fake key down message to target - _SendFakeKeyDown(key); - } - } + if (fKeymap == NULL || key == NULL) { + fDragKey = NULL; + return; } + + if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0) { + // do nothing + } else if ((fButtons & B_TERTIARY_MOUSE_BUTTON) != 0 + && (buttons & B_TERTIARY_MOUSE_BUTTON) == 0) { + _SetKeyState(key->code, false); + _InvalidateKey(key); + fButtons = buttons; + } else { + // primary mouse button + fButtons = buttons; + + // modifier keys are sticky when used with the mouse + if (fKeymap->IsModifierKey(key->code)) + return; + + _SetKeyState(key->code, false); + + if (_HandleDeadKey(key->code, fModifiers) && fDeadKey != 0) + return; + + _InvalidateKey(key); + + if (fDragKey == NULL && fKeymap != NULL) + _SendFakeKeyDown(key); + } + fDragKey = NULL; } @@ -915,7 +1004,7 @@ KeyboardLayoutView::_GetKeyLabel(const Key* key, char* text, size_t textSize, bool KeyboardLayoutView::_IsKeyPressed(uint32 code) { - if (fDropTarget != NULL && fDropTarget->code == (int32)code) + if (fDropTarget != NULL && fDropTarget->code == code) return true; return _KeyState(code); @@ -952,7 +1041,7 @@ KeyboardLayoutView::_KeyForCode(uint32 code) for (int32 i = 0; i < fLayout->CountKeys(); i++) { Key* key = fLayout->KeyAt(i); - if (key->code == (int32)code) + if (key->code == code) return key; } @@ -1168,3 +1257,50 @@ KeyboardLayoutView::_SendFakeKeyDown(const Key* key) fTarget.SendMessage(&message); } + + +BMenuItem* +KeyboardLayoutView::_SwapModifiersMenuItem(uint32 oldCode, uint32 newCode) +{ + int32 mask = B_SHIFT_KEY | B_COMMAND_KEY | B_CONTROL_KEY | B_OPTION_KEY; + uint32 oldModifier = fKeymap->Modifier(oldCode) & ~mask; + uint32 newModifier = fKeymap->Modifier(newCode) & ~mask; + + BMessage* message = new BMessage(kMsgUpdateModifierKeys); + message->AddUInt32(_NameForModifier(newModifier), oldCode); + message->AddUInt32(_NameForModifier(oldModifier), newCode); + + return new BMenuItem(_NameForModifier(newModifier, 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; +} diff --git a/src/preferences/keymap/KeyboardLayoutView.h b/src/preferences/keymap/KeyboardLayoutView.h index 1f3e5eee62..f3c4b96d64 100644 --- a/src/preferences/keymap/KeyboardLayoutView.h +++ b/src/preferences/keymap/KeyboardLayoutView.h @@ -12,6 +12,7 @@ #include "KeyboardLayout.h" +class BMenuItem; class Keymap; @@ -91,6 +92,10 @@ private: void _SetFontSize(BView* view, key_kind keyKind); void _EvaluateDropTarget(BPoint point); void _SendFakeKeyDown(const Key* key); + BMenuItem* _SwapModifiersMenuItem(uint32 old_code, + uint32 new_code); + const char* _NameForModifier(uint32 modifier, + bool pretty = false) const; BBitmap* fOffscreenBitmap; BView* fOffscreenView; diff --git a/src/preferences/keymap/KeymapWindow.cpp b/src/preferences/keymap/KeymapWindow.cpp index 1712175692..a1040ac7be 100644 --- a/src/preferences/keymap/KeymapWindow.cpp +++ b/src/preferences/keymap/KeymapWindow.cpp @@ -346,6 +346,18 @@ KeymapWindow::MessageReceived(BMessage* message) if (message->FindUInt32("right_command_key", &keycode) == B_OK) fCurrentMap.SetModifier(keycode, B_RIGHT_COMMAND_KEY); + if (message->FindUInt32("menu_key", &keycode) == B_OK) + fCurrentMap.SetModifier(keycode, B_MENU_KEY); + + if (message->FindUInt32("caps_key", &keycode) == B_OK) + fCurrentMap.SetModifier(keycode, B_CAPS_LOCK); + + if (message->FindUInt32("num_key", &keycode) == B_OK) + fCurrentMap.SetModifier(keycode, B_NUM_LOCK); + + if (message->FindUInt32("scroll_key", &keycode) == B_OK) + fCurrentMap.SetModifier(keycode, B_SCROLL_LOCK); + _UpdateButtons(); fKeyboardLayoutView->SetKeymap(&fCurrentMap); break;