Fix alt+mnemonic on macOS

This commit is contained in:
David Capello 2016-11-24 19:26:21 -03:00
parent 783acfc61a
commit 701170d85e
5 changed files with 24 additions and 22 deletions

View File

@ -161,10 +161,8 @@ bool ButtonSet::Item::onProcessMessage(ui::Message* msg)
case ui::kKeyDownMessage: case ui::kKeyDownMessage:
if (isEnabled() && hasText()) { if (isEnabled() && hasText()) {
KeyMessage* keymsg = static_cast<KeyMessage*>(msg); KeyMessage* keymsg = static_cast<KeyMessage*>(msg);
bool mnemonicPressed = bool mnemonicPressed = (msg->altPressed() &&
(msg->altPressed() && mnemonicCharPressed(keymsg));
mnemonicChar() &&
mnemonicChar() == tolower(keymsg->unicodeChar()));
if (mnemonicPressed || if (mnemonicPressed ||
(hasFocus() && keymsg->scancode() == kKeySpace)) { (hasFocus() && keymsg->scancode() == kKeySpace)) {

View File

@ -101,8 +101,7 @@ bool ButtonBase::onProcessMessage(Message* msg)
if (isEnabled()) { if (isEnabled()) {
bool mnemonicPressed = bool mnemonicPressed =
(msg->altPressed() && (msg->altPressed() &&
mnemonicChar() && mnemonicCharPressed(keymsg));
mnemonicChar() == tolower(keymsg->unicodeChar()));
// For kButtonWidget // For kButtonWidget
if (m_behaviorType == kButtonWidget) { if (m_behaviorType == kButtonWidget) {

View File

@ -118,7 +118,7 @@ protected:
static MenuBox* get_base_menubox(Widget* widget); static MenuBox* get_base_menubox(Widget* widget);
static MenuBaseData* get_base(Widget* widget); static MenuBaseData* get_base(Widget* widget);
static MenuItem* check_for_letter(Menu* menu, int ascii); static MenuItem* check_for_letter(Menu* menu, const KeyMessage* keymsg);
static MenuItem* find_nextitem(Menu* menu, MenuItem* menuitem); static MenuItem* find_nextitem(Menu* menu, MenuItem* menuitem);
static MenuItem* find_previtem(Menu* menu, MenuItem* menuitem); static MenuItem* find_previtem(Menu* menu, MenuItem* menuitem);
@ -485,17 +485,9 @@ bool MenuBox::onProcessMessage(Message* msg)
if (((this->type() == kMenuBoxWidget) && (msg->modifiers() == kKeyNoneModifier || // <-- Inside menu-boxes we can use letters without Alt modifier pressed if (((this->type() == kMenuBoxWidget) && (msg->modifiers() == kKeyNoneModifier || // <-- Inside menu-boxes we can use letters without Alt modifier pressed
msg->modifiers() == kKeyAltModifier)) || msg->modifiers() == kKeyAltModifier)) ||
((this->type() == kMenuBarWidget) && (msg->modifiers() == kKeyAltModifier))) { ((this->type() == kMenuBarWidget) && (msg->modifiers() == kKeyAltModifier))) {
int unicode = static_cast<KeyMessage*>(msg)->unicodeChar(); auto keymsg = static_cast<KeyMessage*>(msg);
selected = check_for_letter(menu, unicode);
if (!selected) {
KeyScancode scancode = static_cast<KeyMessage*>(msg)->scancode();
if (scancode >= kKeyA && scancode <= kKeyZ)
selected = check_for_letter(menu, 'a' + scancode - kKeyA);
else if (scancode >= kKey0 && scancode <= kKey9)
selected = check_for_letter(menu, '0' + scancode - kKey0);
}
if (selected) { if (check_for_letter(menu, keymsg)) {
menu->highlightItem(selected, true, true, true); menu->highlightItem(selected, true, true, true);
return true; return true;
} }
@ -1194,15 +1186,14 @@ void MenuItem::executeClick()
Manager::getDefault()->enqueueMessage(msg); Manager::getDefault()->enqueueMessage(msg);
} }
static MenuItem* check_for_letter(Menu* menu, int ascii) static MenuItem* check_for_letter(Menu* menu, const KeyMessage* keymsg)
{ {
for (auto child : menu->children()) { for (auto child : menu->children()) {
if (child->type() != kMenuItemWidget) if (child->type() != kMenuItemWidget)
continue; continue;
MenuItem* menuitem = static_cast<MenuItem*>(child); MenuItem* menuitem = static_cast<MenuItem*>(child);
int mnemonic = menuitem->mnemonicChar(); if (menuitem->mnemonicCharPressed(keymsg))
if (mnemonic > 0 && mnemonic == std::tolower(ascii))
return menuitem; return menuitem;
} }
return NULL; return NULL;

View File

@ -1275,11 +1275,21 @@ int Widget::mnemonicChar() const
if (hasText()) { if (hasText()) {
for (int c=0; m_text[c]; ++c) for (int c=0; m_text[c]; ++c)
if ((m_text[c] == '&') && (m_text[c+1] != '&')) if ((m_text[c] == '&') && (m_text[c+1] != '&'))
return tolower(m_text[c+1]); return std::tolower(m_text[c+1]);
} }
return 0; return 0;
} }
bool Widget::mnemonicCharPressed(const KeyMessage* keyMsg) const
{
int chr = mnemonicChar();
return
((chr) &&
((chr == std::tolower(keyMsg->unicodeChar())) ||
(chr >= 'a' && chr <= 'z' && keyMsg->scancode() == (kKeyA + chr - 'a')) ||
(chr >= '0' && chr <= '9' && keyMsg->scancode() == (kKey0 + chr - '0'))));
}
bool Widget::onProcessMessage(Message* msg) bool Widget::onProcessMessage(Message* msg)
{ {
ASSERT(msg != NULL); ASSERT(msg != NULL);

View File

@ -31,14 +31,15 @@ namespace she {
namespace ui { namespace ui {
class InitThemeEvent; class InitThemeEvent;
class KeyMessage;
class LoadLayoutEvent; class LoadLayoutEvent;
class Manager; class Manager;
class Message; class Message;
class MouseMessage; class MouseMessage;
class PaintEvent; class PaintEvent;
class SizeHintEvent;
class ResizeEvent; class ResizeEvent;
class SaveLayoutEvent; class SaveLayoutEvent;
class SizeHintEvent;
class Theme; class Theme;
class Window; class Window;
@ -348,6 +349,9 @@ namespace ui {
// (the underscored character, i.e. the letter after & symbol). // (the underscored character, i.e. the letter after & symbol).
int mnemonicChar() const; int mnemonicChar() const;
// Returns true if the mnemonic character is pressed.
bool mnemonicCharPressed(const ui::KeyMessage* keyMsg) const;
protected: protected:
// =============================================================== // ===============================================================
// MESSAGE PROCESSING // MESSAGE PROCESSING