diff --git a/src/preferences/keymap/KeyboardLayoutView.cpp b/src/preferences/keymap/KeyboardLayoutView.cpp index b070352e35..93d34ff896 100644 --- a/src/preferences/keymap/KeyboardLayoutView.cpp +++ b/src/preferences/keymap/KeyboardLayoutView.cpp @@ -33,6 +33,7 @@ KeyboardLayoutView::KeyboardLayoutView(const char* name) fEditable(true), fModifiers(0), fDeadKey(0), + fButtons(0), fDragKey(NULL), fDropTarget(NULL), fOldSize(0, 0) @@ -139,25 +140,45 @@ KeyboardLayoutView::MouseDown(BPoint point) if (key == NULL) return; - if (fKeymap != NULL && fKeymap->IsModifierKey(key->code)) { - if (_KeyState(key->code)) { - uint32 modifier = fKeymap->Modifier(key->code); - if ((modifier & modifiers()) == 0) { - _SetKeyState(key->code, false); - fModifiers &= ~modifier; + int32 buttons = 0; + if (Looper() != NULL && Looper()->CurrentMessage() != NULL) + Looper()->CurrentMessage()->FindInt32("buttons", &buttons); + + 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->IsDeadKey(key->code, fModifiers, &isEnabled); + if (deadKey > 0) { + fKeymap->SetDeadKeyEnabled(key->code, fModifiers, !isEnabled); + _InvalidateKey(key); + } + } + } else { + if (fKeymap != NULL && fKeymap->IsModifierKey(key->code)) { + if (_KeyState(key->code)) { + uint32 modifier = fKeymap->Modifier(key->code); + if ((modifier & modifiers()) == 0) { + _SetKeyState(key->code, false); + fModifiers &= ~modifier; + Invalidate(); + } + } else { + _SetKeyState(key->code, true); + fModifiers |= fKeymap->Modifier(key->code); Invalidate(); } + + // TODO: if possible, we could handle the lock keys for real } else { _SetKeyState(key->code, true); - fModifiers |= fKeymap->Modifier(key->code); - Invalidate(); + _InvalidateKey(key); } - - // TODO: if possible, we could handle the lock keys for real - } else { - _SetKeyState(key->code, true); - _InvalidateKey(key); } + + fButtons = buttons; } @@ -165,23 +186,38 @@ void KeyboardLayoutView::MouseUp(BPoint point) { Key* key = _KeyAt(fClickPoint); + + int32 buttons = 0; + if (Looper() != NULL && Looper()->CurrentMessage() != NULL) + Looper()->CurrentMessage()->FindInt32("buttons", &buttons); + if (key != NULL) { - // modifier keys are sticky when used with the mouse - if (fKeymap != NULL && fKeymap->IsModifierKey(key->code)) - return; + if ((fButtons & B_TERTIARY_MOUSE_BUTTON) != 0 + && (buttons & B_TERTIARY_MOUSE_BUTTON) == 0) { + _SetKeyState(key->code, false); + _InvalidateKey(key); + fButtons = buttons; + } else { + fButtons = buttons; - _SetKeyState(key->code, false); + // modifier keys are sticky when used with the mouse + if (fKeymap != NULL && fKeymap->IsModifierKey(key->code)) + return; - if (_HandleDeadKey(key->code, fModifiers) && fDeadKey != 0) - return; + _SetKeyState(key->code, false); - _InvalidateKey(key); + if (_HandleDeadKey(key->code, fModifiers) && fDeadKey != 0) + return; - if (fDragKey == NULL && fKeymap != NULL) { - // Send fake key down message to target - _SendFakeKeyDown(key); + _InvalidateKey(key); + + if (fDragKey == NULL && fKeymap != NULL) { + // Send fake key down message to target + _SendFakeKeyDown(key); + } } } + fDragKey = NULL; } @@ -192,6 +228,10 @@ KeyboardLayoutView::MouseMoved(BPoint point, uint32 transit, if (fKeymap == NULL) return; + // rule out dragging for tertiary mouse button + if ((fButtons & B_TERTIARY_MOUSE_BUTTON) != 0) + return; + if (dragMessage != NULL) { if (fEditable) { _InvalidateKey(fDropTarget); @@ -202,7 +242,7 @@ KeyboardLayoutView::MouseMoved(BPoint point, uint32 transit, return; } - + int32 buttons; if (Window()->CurrentMessage() == NULL || Window()->CurrentMessage()->FindInt32("buttons", &buttons) != B_OK @@ -515,7 +555,7 @@ KeyboardLayoutView::_DrawKeyButton(BView* view, BRect& rect, BRect updateRect, { be_control_look->DrawButtonFrame(view, rect, updateRect, base, background, pressed ? BControlLook::B_ACTIVATED : 0); - be_control_look->DrawButtonBackground(view, rect, updateRect, + be_control_look->DrawButtonBackground(view, rect, updateRect, base, pressed ? BControlLook::B_ACTIVATED : 0); } @@ -529,11 +569,12 @@ KeyboardLayoutView::_DrawKey(BView* view, BRect updateRect, const Key* key, key_kind keyKind = kNormalKey; int32 deadKey = 0; bool secondDeadKey = false; + bool isDeadKeyEnabled = true; char text[32]; if (fKeymap != NULL) { _GetKeyLabel(key, text, sizeof(text), keyKind); - deadKey = fKeymap->IsDeadKey(key->code, fModifiers); + deadKey = fKeymap->IsDeadKey(key->code, fModifiers, &isDeadKeyEnabled); secondDeadKey = fKeymap->IsDeadSecondKey(key->code, fModifiers, fDeadKey); } else { @@ -545,7 +586,7 @@ KeyboardLayoutView::_DrawKey(BView* view, BRect updateRect, const Key* key, if (secondDeadKey) base = kSecondDeadKeyColor; - else if (deadKey > 0) + else if (deadKey > 0 && isDeadKeyEnabled) base = kDeadKeyColor; if (key->shape == kRectangleKeyShape) { @@ -641,7 +682,7 @@ KeyboardLayoutView::_DrawIndicator(BView* view, BRect updateRect, be_control_look->DrawButtonFrame(view, rect, updateRect, base, background, BControlLook::B_DISABLED); - be_control_look->DrawButtonBackground(view, rect, updateRect, + be_control_look->DrawButtonBackground(view, rect, updateRect, base, BControlLook::B_DISABLED); } @@ -857,14 +898,17 @@ KeyboardLayoutView::_InvalidateKey(const Key* key) bool KeyboardLayoutView::_HandleDeadKey(uint32 key, int32 modifiers) { - if (fKeymap == NULL) + if (fKeymap == NULL || fKeymap->IsModifierKey(key)) return false; - int32 deadKey = fKeymap->IsDeadKey(key, modifiers); + bool isEnabled = false; + int32 deadKey = fKeymap->IsDeadKey(key, modifiers, &isEnabled); if (fDeadKey != deadKey) { - Invalidate(); - fDeadKey = deadKey; - return true; + if (isEnabled) { + Invalidate(); + fDeadKey = deadKey; + return true; + } } else if (fDeadKey != 0) { Invalidate(); fDeadKey = 0; diff --git a/src/preferences/keymap/KeyboardLayoutView.h b/src/preferences/keymap/KeyboardLayoutView.h index ec733f4495..2379ec182e 100644 --- a/src/preferences/keymap/KeyboardLayoutView.h +++ b/src/preferences/keymap/KeyboardLayoutView.h @@ -97,6 +97,7 @@ private: uint8 fKeyState[16]; int32 fModifiers; int32 fDeadKey; + int32 fButtons; BPoint fClickPoint; Key* fDragKey; diff --git a/src/preferences/keymap/Keymap.cpp b/src/preferences/keymap/Keymap.cpp index fcd77a84e1..7db533589a 100644 --- a/src/preferences/keymap/Keymap.cpp +++ b/src/preferences/keymap/Keymap.cpp @@ -351,57 +351,28 @@ Keymap::SetModifier(uint32 keyCode, uint32 modifier) } -//! Checks whether a key is a dead key. +/*! Checks whether a key is a dead key. + If it is, the enabled/disabled state of that dead key will be passed + out via isEnabled (isEnabled is not touched for non-dead keys). +*/ uint8 -Keymap::IsDeadKey(uint32 keyCode, uint32 modifiers) +Keymap::IsDeadKey(uint32 keyCode, uint32 modifiers, bool* isEnabled) { - if (fChars == NULL) - return 0; - uint32 tableMask = 0; int32 offset = _Offset(keyCode, modifiers, &tableMask); - if (offset <= 0) - return 0; - - uint32 numBytes = fChars[offset]; - if (!numBytes) - return 0; - - char chars[4]; - strncpy(chars, &fChars[offset + 1], numBytes); - chars[numBytes] = 0; - - int32 deadOffsets[] = { - fKeys.acute_dead_key[1], - fKeys.grave_dead_key[1], - fKeys.circumflex_dead_key[1], - fKeys.dieresis_dead_key[1], - fKeys.tilde_dead_key[1] - }; - - uint32 deadTables[] = { - fKeys.acute_tables, - fKeys.grave_tables, - fKeys.circumflex_tables, - fKeys.dieresis_tables, - fKeys.tilde_tables - }; - - for (int32 i = 0; i < 5; i++) { - if ((deadTables[i] & tableMask) == 0) - continue; - - if (offset == deadOffsets[i]) - return i + 1; - - uint32 deadNumBytes = fChars[deadOffsets[i]]; - if (!deadNumBytes) - continue; - - if (strncmp(chars, &fChars[deadOffsets[i] + 1], deadNumBytes) == 0) - return i + 1; + uint8 deadKeyIndex = _GetDeadKeyIndex(offset); + if (deadKeyIndex > 0 && isEnabled != NULL) { + uint32 deadTables[] = { + fKeys.acute_tables, + fKeys.grave_tables, + fKeys.circumflex_tables, + fKeys.dieresis_tables, + fKeys.tilde_tables + }; + *isEnabled = (deadTables[deadKeyIndex - 1] & tableMask) != 0; } - return 0; + + return deadKeyIndex; } @@ -448,6 +419,33 @@ Keymap::IsDeadSecondKey(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey) } +//! Enables/disables the "deadness" of the given keycode/modifier combo. +void +Keymap::SetDeadKeyEnabled(uint32 keyCode, uint32 modifiers, bool enabled) +{ + uint32 tableMask = 0; + int32 offset = _Offset(keyCode, modifiers, &tableMask); + uint8 deadKeyIndex = _GetDeadKeyIndex(offset); + if (deadKeyIndex > 0) { + uint32* deadTables[] = { + &fKeys.acute_tables, + &fKeys.grave_tables, + &fKeys.circumflex_tables, + &fKeys.dieresis_tables, + &fKeys.tilde_tables + }; + + if (enabled) + (*deadTables[deadKeyIndex - 1]) |= tableMask; + else + (*deadTables[deadKeyIndex - 1]) &= ~tableMask; + + if (fModificationMessage != NULL) + fTarget.SendMessage(fModificationMessage); + } +} + + //! Get the char for a key given modifiers and active dead key void Keymap::GetChars(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey, @@ -693,3 +691,46 @@ Keymap::_Offset(uint32 keyCode, uint32 modifiers, uint32* _table) return offset; } + + +uint8 +Keymap::_GetDeadKeyIndex(int32 offset) +{ + if (fChars == NULL || offset <= 0) + return 0; + + uint32 numBytes = fChars[offset]; + if (!numBytes) + return 0; + + char chars[4]; + strncpy(chars, &fChars[offset + 1], numBytes); + chars[numBytes] = 0; + + int32 deadOffsets[] = { + fKeys.acute_dead_key[1], + fKeys.grave_dead_key[1], + fKeys.circumflex_dead_key[1], + fKeys.dieresis_dead_key[1], + fKeys.tilde_dead_key[1] + }; + + uint8 result = 0; + for (int32 i = 0; i < 5; i++) { + if (offset == deadOffsets[i]) { + result = i + 1; + break; + } + + uint32 deadNumBytes = fChars[deadOffsets[i]]; + if (!deadNumBytes) + continue; + + if (strncmp(chars, &fChars[deadOffsets[i] + 1], deadNumBytes) == 0) { + result = i + 1; + break; + } + } + + return result; +} diff --git a/src/preferences/keymap/Keymap.h b/src/preferences/keymap/Keymap.h index 1b6325eafc..83184a7fe3 100644 --- a/src/preferences/keymap/Keymap.h +++ b/src/preferences/keymap/Keymap.h @@ -33,9 +33,12 @@ public: uint32 KeyForModifier(uint32 modifier); status_t SetModifier(uint32 keyCode, uint32 modifier); - uint8 IsDeadKey(uint32 keyCode, uint32 modifiers); + uint8 IsDeadKey(uint32 keyCode, uint32 modifiers, + bool* isEnabled = NULL); bool IsDeadSecondKey(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey); + void SetDeadKeyEnabled(uint32 keyCode, uint32 modifiers, + bool enabled); void GetChars(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey, char** chars, int32* numBytes); @@ -54,6 +57,7 @@ public: private: int32 _Offset(uint32 keyCode, uint32 modifiers, uint32* _table = NULL); + uint8 _GetDeadKeyIndex(int32 offset); char* fChars; key_map fKeys;