* dead keys can now be enabled/disabled via middle mouse button
* fDragKey must be reset in MouseUp() as otherwise it is not possible to drag a key from one keymap to the textview and then from the textview to the same key of another keymap * _HandleDeadKey() now ignores modifier keys as otherwise dead keys that required pressing a modifier (like the tilde on the German keyboard) failed to highlight the resulting characters What's still missing is a way to edit the resulting characters for each dead key, but I am not yet sure how to do that in an elegant way git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30699 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
6f260d075b
commit
8365643720
@ -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;
|
||||
|
@ -97,6 +97,7 @@ private:
|
||||
uint8 fKeyState[16];
|
||||
int32 fModifiers;
|
||||
int32 fDeadKey;
|
||||
int32 fButtons;
|
||||
|
||||
BPoint fClickPoint;
|
||||
Key* fDragKey;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user