Keymap: swap modifiers keys via context menu
When the user right clicks on a modifier key pop up a menu listing the available modifiers. When the user selects a modifier from the menu swap the key with the selected modifier. This provides an alternative way to swap modifier keys other than drag&drop that works for just modifier keys.
This commit is contained in:
@@ -20,6 +20,7 @@ Preference Keymap :
|
|||||||
DoCatalogs Keymap :
|
DoCatalogs Keymap :
|
||||||
x-vnd.Haiku-Keymap
|
x-vnd.Haiku-Keymap
|
||||||
:
|
:
|
||||||
|
KeyboardLayoutView.cpp
|
||||||
KeymapWindow.cpp
|
KeymapWindow.cpp
|
||||||
ModifierKeysWindow.cpp
|
ModifierKeysWindow.cpp
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ enum key_shape {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Key {
|
struct Key {
|
||||||
int32 code;
|
uint32 code;
|
||||||
int32 alternate_code[3];
|
uint32 alternate_code[3];
|
||||||
int32 alternate_modifier[3];
|
uint32 alternate_modifier[3];
|
||||||
key_shape shape;
|
key_shape shape;
|
||||||
BRect frame;
|
BRect frame;
|
||||||
float second_row;
|
float second_row;
|
||||||
|
|||||||
@@ -13,10 +13,17 @@
|
|||||||
#include <Bitmap.h>
|
#include <Bitmap.h>
|
||||||
#include <ControlLook.h>
|
#include <ControlLook.h>
|
||||||
#include <LayoutUtils.h>
|
#include <LayoutUtils.h>
|
||||||
|
#include <MenuItem.h>
|
||||||
|
#include <PopUpMenu.h>
|
||||||
#include <Region.h>
|
#include <Region.h>
|
||||||
#include <Window.h>
|
#include <Window.h>
|
||||||
|
|
||||||
#include "Keymap.h"
|
#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};
|
static const rgb_color kBrightColor = {230, 230, 230, 255};
|
||||||
@@ -146,28 +153,105 @@ KeyboardLayoutView::MouseDown(BPoint point)
|
|||||||
fDragKey = NULL;
|
fDragKey = NULL;
|
||||||
fDropPoint.x = -1;
|
fDropPoint.x = -1;
|
||||||
|
|
||||||
Key* key = _KeyAt(point);
|
|
||||||
if (key == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int32 buttons = 0;
|
int32 buttons = 0;
|
||||||
if (Looper() != NULL && Looper()->CurrentMessage() != NULL)
|
if (Looper() != NULL && Looper()->CurrentMessage() != NULL)
|
||||||
Looper()->CurrentMessage()->FindInt32("buttons", &buttons);
|
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) {
|
&& (fButtons & B_TERTIARY_MOUSE_BUTTON) == 0) {
|
||||||
// toggle the "deadness" of dead keys via middle mouse button
|
// toggle the "deadness" of dead keys via middle mouse button
|
||||||
if (fKeymap != NULL) {
|
bool isEnabled = false;
|
||||||
bool isEnabled = false;
|
uint8 deadKey
|
||||||
uint8 deadKey
|
= fKeymap->DeadKey(key->code, fModifiers, &isEnabled);
|
||||||
= fKeymap->DeadKey(key->code, fModifiers, &isEnabled);
|
if (deadKey > 0) {
|
||||||
if (deadKey > 0) {
|
fKeymap->SetDeadKeyEnabled(key->code, fModifiers, !isEnabled);
|
||||||
fKeymap->SetDeadKeyEnabled(key->code, fModifiers, !isEnabled);
|
_InvalidateKey(key);
|
||||||
_InvalidateKey(key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (fKeymap != NULL && fKeymap->IsModifierKey(key->code)) {
|
// primary mouse button
|
||||||
|
if (fKeymap->IsModifierKey(key->code)) {
|
||||||
if (_KeyState(key->code)) {
|
if (_KeyState(key->code)) {
|
||||||
uint32 modifier = fKeymap->Modifier(key->code);
|
uint32 modifier = fKeymap->Modifier(key->code);
|
||||||
if ((modifier & modifiers()) == 0) {
|
if ((modifier & modifiers()) == 0) {
|
||||||
@@ -201,32 +285,37 @@ KeyboardLayoutView::MouseUp(BPoint point)
|
|||||||
if (Looper() != NULL && Looper()->CurrentMessage() != NULL)
|
if (Looper() != NULL && Looper()->CurrentMessage() != NULL)
|
||||||
Looper()->CurrentMessage()->FindInt32("buttons", &buttons);
|
Looper()->CurrentMessage()->FindInt32("buttons", &buttons);
|
||||||
|
|
||||||
if (key != NULL) {
|
if (fKeymap == NULL || key == NULL) {
|
||||||
if ((fButtons & B_TERTIARY_MOUSE_BUTTON) != 0
|
fDragKey = NULL;
|
||||||
&& (buttons & B_TERTIARY_MOUSE_BUTTON) == 0) {
|
return;
|
||||||
_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 ((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;
|
fDragKey = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -915,7 +1004,7 @@ KeyboardLayoutView::_GetKeyLabel(const Key* key, char* text, size_t textSize,
|
|||||||
bool
|
bool
|
||||||
KeyboardLayoutView::_IsKeyPressed(uint32 code)
|
KeyboardLayoutView::_IsKeyPressed(uint32 code)
|
||||||
{
|
{
|
||||||
if (fDropTarget != NULL && fDropTarget->code == (int32)code)
|
if (fDropTarget != NULL && fDropTarget->code == code)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return _KeyState(code);
|
return _KeyState(code);
|
||||||
@@ -952,7 +1041,7 @@ KeyboardLayoutView::_KeyForCode(uint32 code)
|
|||||||
|
|
||||||
for (int32 i = 0; i < fLayout->CountKeys(); i++) {
|
for (int32 i = 0; i < fLayout->CountKeys(); i++) {
|
||||||
Key* key = fLayout->KeyAt(i);
|
Key* key = fLayout->KeyAt(i);
|
||||||
if (key->code == (int32)code)
|
if (key->code == code)
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1168,3 +1257,50 @@ KeyboardLayoutView::_SendFakeKeyDown(const Key* key)
|
|||||||
|
|
||||||
fTarget.SendMessage(&message);
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "KeyboardLayout.h"
|
#include "KeyboardLayout.h"
|
||||||
|
|
||||||
|
|
||||||
|
class BMenuItem;
|
||||||
class Keymap;
|
class Keymap;
|
||||||
|
|
||||||
|
|
||||||
@@ -91,6 +92,10 @@ private:
|
|||||||
void _SetFontSize(BView* view, key_kind keyKind);
|
void _SetFontSize(BView* view, key_kind keyKind);
|
||||||
void _EvaluateDropTarget(BPoint point);
|
void _EvaluateDropTarget(BPoint point);
|
||||||
void _SendFakeKeyDown(const Key* key);
|
void _SendFakeKeyDown(const Key* key);
|
||||||
|
BMenuItem* _SwapModifiersMenuItem(uint32 old_code,
|
||||||
|
uint32 new_code);
|
||||||
|
const char* _NameForModifier(uint32 modifier,
|
||||||
|
bool pretty = false) const;
|
||||||
|
|
||||||
BBitmap* fOffscreenBitmap;
|
BBitmap* fOffscreenBitmap;
|
||||||
BView* fOffscreenView;
|
BView* fOffscreenView;
|
||||||
|
|||||||
@@ -346,6 +346,18 @@ KeymapWindow::MessageReceived(BMessage* message)
|
|||||||
if (message->FindUInt32("right_command_key", &keycode) == B_OK)
|
if (message->FindUInt32("right_command_key", &keycode) == B_OK)
|
||||||
fCurrentMap.SetModifier(keycode, B_RIGHT_COMMAND_KEY);
|
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();
|
_UpdateButtons();
|
||||||
fKeyboardLayoutView->SetKeymap(&fCurrentMap);
|
fKeyboardLayoutView->SetKeymap(&fCurrentMap);
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user