Ticket #7078: menuItemsShortcutsPatch.diff
File menuItemsShortcutsPatch.diff, 11.4 KB (added by , 13 years ago) |
---|
-
headers/os/interface/Window.h
334 334 bool notifyIputServer = false); 335 335 void _SetName(const char* title); 336 336 337 void _AddShortcut(uint32 key, uint32 modifiers, Shortcut* shortcut); 337 338 Shortcut* _FindShortcut(uint32 key, uint32 modifiers); 338 339 BView* _FindView(BView* view, BPoint point) const; 339 340 BView* _FindView(int32 token); -
headers/os/interface/MenuItem.h
85 85 void _DrawSubmenuSymbol(rgb_color backgroundColor); 86 86 void _DrawControlChar(char shortcut, BPoint where); 87 87 88 bool _IsValidShortcut(char shortcut, uint32 modifiers); 89 88 90 private: 89 91 char* fLabel; 90 92 BMenu* fSubmenu; -
headers/os/interface/InterfaceDefs.h
151 151 B_LEFT_CONTROL_KEY = 0x00001000, 152 152 B_RIGHT_CONTROL_KEY = 0x00002000, 153 153 B_LEFT_OPTION_KEY = 0x00004000, 154 B_RIGHT_OPTION_KEY = 0x00008000 154 B_RIGHT_OPTION_KEY = 0x00008000, 155 B_NO_MODIFIERS = 0x00010000 155 156 }; 156 157 157 158 -
src/kits/interface/Window.cpp
103 103 static uint32 PrepareModifiers(uint32 modifiers); 104 104 105 105 private: 106 uint32 _InitializeModifiers(uint32 modifiers); 107 106 108 uint32 fKey; 107 109 uint32 fModifiers; 108 110 BMenuItem* fMenuItem; … … 237 239 BWindow::Shortcut::Shortcut(uint32 key, uint32 modifiers, BMenuItem* item) 238 240 : 239 241 fKey(PrepareKey(key)), 240 fModifiers( PrepareModifiers(modifiers)),242 fModifiers(_InitializeModifiers(modifiers)), 241 243 fMenuItem(item), 242 244 fMessage(NULL), 243 245 fTarget(NULL) … … 249 251 BHandler* target) 250 252 : 251 253 fKey(PrepareKey(key)), 252 fModifiers( PrepareModifiers(modifiers)),254 fModifiers(_InitializeModifiers(modifiers)), 253 255 fMenuItem(NULL), 254 256 fMessage(message), 255 257 fTarget(target) … … 267 269 bool 268 270 BWindow::Shortcut::Matches(uint32 key, uint32 modifiers) const 269 271 { 270 return fKey == key && fModifiers == modifiers; 272 if (fModifiers == B_NO_MODIFIERS && modifiers == 0) 273 return fKey == key; 274 else 275 return fKey == key && fModifiers == modifiers; 271 276 } 272 277 273 278 279 uint32 280 BWindow::Shortcut::_InitializeModifiers(uint32 modifiers) 281 { 282 if (modifiers == B_NO_MODIFIERS) 283 return modifiers; 284 else 285 return PrepareModifiers(modifiers) | B_COMMAND_KEY; 286 } 287 288 274 289 /*static*/ 275 290 uint32 276 291 BWindow::Shortcut::AllowedModifiers() … … 284 299 uint32 285 300 BWindow::Shortcut::PrepareModifiers(uint32 modifiers) 286 301 { 287 return (modifiers & AllowedModifiers()) | B_COMMAND_KEY;302 return modifiers & AllowedModifiers(); 288 303 } 289 304 290 305 … … 1785 1800 BWindow::AddShortcut(uint32 key, uint32 modifiers, BMenuItem* item) 1786 1801 { 1787 1802 Shortcut* shortcut = new(std::nothrow) Shortcut(key, modifiers, item); 1788 if (shortcut == NULL) 1789 return; 1790 1791 // removes the shortcut if it already exists! 1792 RemoveShortcut(key, modifiers); 1793 1794 fShortcuts.AddItem(shortcut); 1803 _AddShortcut(key, modifiers, shortcut); 1795 1804 } 1796 1805 1797 1806 … … 1811 1820 1812 1821 Shortcut* shortcut = new(std::nothrow) Shortcut(key, modifiers, message, 1813 1822 target); 1814 if (shortcut == NULL) 1815 return; 1816 1817 // removes the shortcut if it already exists! 1818 RemoveShortcut(key, modifiers); 1819 1820 fShortcuts.AddItem(shortcut); 1823 _AddShortcut(key, modifiers, shortcut); 1821 1824 } 1822 1825 1823 1826 … … 3669 3672 } 3670 3673 3671 3674 // Handle shortcuts 3672 if ((modifiers & B_COMMAND_KEY) != 0) {3673 3674 3675 if (!fNoQuitShortcut && (key == 'Q' || key == 'q')) {3676 3677 3675 bool shortcutCalled = false; 3676 // Command+q has been pressed, so, we will quit 3677 // the shortcut mechanism doesn't allow handlers outside the window 3678 if (!fNoQuitShortcut && (key == 'Q' || key == 'q') && (modifiers & B_COMMAND_KEY) != 0) { 3679 BMessage message(B_QUIT_REQUESTED); 3680 message.AddBool("shortcut", true); 3678 3681 3679 3680 3681 3682 be_app->PostMessage(&message); 3683 return true; 3684 } 3682 3685 3683 3684 3685 3686 3687 3686 // Pretend that the user opened a menu, to give the subclass a 3687 // chance to update it's menus. This may install new shortcuts, 3688 // which is why we have to call it here, before trying to find 3689 // a shortcut for the given key. 3690 MenusBeginning(); 3688 3691 3689 Shortcut* shortcut = _FindShortcut(key, modifiers); 3690 if (shortcut != NULL) { 3691 // TODO: would be nice to move this functionality to 3692 // a Shortcut::Invoke() method - but since BMenu::InvokeItem() 3693 // (and BMenuItem::Invoke()) are private, I didn't want 3694 // to mess with them (BMenuItem::Invoke() is public in 3695 // Dano/Zeta, though, maybe we should just follow their 3696 // example) 3697 if (shortcut->MenuItem() != NULL) { 3698 BMenu* menu = shortcut->MenuItem()->Menu(); 3699 if (menu != NULL) 3700 MenuPrivate(menu).InvokeItem(shortcut->MenuItem(), true); 3701 } else { 3702 BHandler* target = shortcut->Target(); 3703 if (target == NULL) 3704 target = CurrentFocus(); 3692 Shortcut* shortcut = NULL; 3693 // Handle function keys 3694 if (key == B_FUNCTION_KEY && rawKey >= B_F1_KEY && rawKey <= B_F12_KEY) 3695 shortcut = _FindShortcut(rawKey, modifiers); 3696 else 3697 shortcut = _FindShortcut(key, modifiers); 3705 3698 3706 if (shortcut->Message() != NULL) { 3707 BMessage message(*shortcut->Message()); 3699 if (shortcut != NULL) { 3700 shortcutCalled = true; 3701 // TODO: would be nice to move this functionality to 3702 // a Shortcut::Invoke() method - but since BMenu::InvokeItem() 3703 // (and BMenuItem::Invoke()) are private, I didn't want 3704 // to mess with them (BMenuItem::Invoke() is public in 3705 // Dano/Zeta, though, maybe we should just follow their 3706 // example) 3707 if (shortcut->MenuItem() != NULL) { 3708 BMenu* menu = shortcut->MenuItem()->Menu(); 3709 if (menu != NULL) 3710 MenuPrivate(menu).InvokeItem(shortcut->MenuItem(), true); 3711 } else { 3712 BHandler* target = shortcut->Target(); 3713 if (target == NULL) 3714 target = CurrentFocus(); 3708 3715 3709 if (message.ReplaceInt64("when", system_time()) != B_OK) 3710 message.AddInt64("when", system_time()); 3711 if (message.ReplaceBool("shortcut", true) != B_OK) 3712 message.AddBool("shortcut", true); 3716 if (shortcut->Message() != NULL) { 3717 BMessage message(*shortcut->Message()); 3713 3718 3714 PostMessage(&message, target); 3715 } 3719 if (message.ReplaceInt64("when", system_time()) != B_OK) 3720 message.AddInt64("when", system_time()); 3721 if (message.ReplaceBool("shortcut", true) != B_OK) 3722 message.AddBool("shortcut", true); 3723 3724 PostMessage(&message, target); 3716 3725 } 3717 3726 } 3727 } 3718 3728 3719 3729 MenusEnded(); 3720 3730 3721 // we always eat the event if the command key was pressed3722 return true;3723 }3724 3725 3731 // TODO: convert keys to the encoding of the target view 3726 3732 3727 return false; 3733 // we always eat the event if a shortcut handled it 3734 return shortcutCalled; 3728 3735 } 3729 3736 3730 3737 … … 3788 3795 } 3789 3796 3790 3797 3798 void 3799 BWindow::_AddShortcut(uint32 key, uint32 modifiers, Shortcut* shortcut) 3800 { 3801 if (shortcut == NULL) 3802 return; 3803 3804 // removes the shortcut if it already exists! 3805 RemoveShortcut(key, modifiers); 3806 3807 fShortcuts.AddItem(shortcut); 3808 } 3809 3810 3791 3811 BWindow::Shortcut* 3792 3812 BWindow::_FindShortcut(uint32 key, uint32 modifiers) 3793 3813 { -
src/kits/interface/MenuItem.cpp
12 12 //! Display item for BMenu class 13 13 14 14 #include <ctype.h> 15 #include <stdio.h> 15 16 #include <stdlib.h> 16 17 #include <string.h> 17 18 … … 63 64 fLabel = strdup(label); 64 65 65 66 SetMessage(message); 66 67 fShortcutChar = shortcut; 68 69 if (shortcut != 0) 70 fModifiers = modifiers | B_COMMAND_KEY; 71 else 72 fModifiers = 0; 67 SetShortcut(shortcut, modifiers); 73 68 } 74 69 75 70 … … 266 261 267 262 268 263 void 269 BMenuItem::SetShortcut(char ch, uint32 modifiers)264 BMenuItem::SetShortcut(char shortcut, uint32 modifiers) 270 265 { 271 if ( fShortcutChar != 0 && (fModifiers & B_COMMAND_KEY) && fWindow)266 if (_IsValidShortcut(fShortcutChar, fModifiers) && fWindow) 272 267 fWindow->RemoveShortcut(fShortcutChar, fModifiers); 273 268 274 fShortcutChar = ch;269 fShortcutChar = shortcut; 275 270 276 if (ch != 0) 277 fModifiers = modifiers | B_COMMAND_KEY; 278 else 271 if (shortcut != 0) { 272 if (modifiers != B_NO_MODIFIERS) 273 fModifiers = modifiers | B_COMMAND_KEY; 274 else 275 fModifiers = B_NO_MODIFIERS; 276 } else 279 277 fModifiers = 0; 280 278 281 if ( fShortcutChar != 0 && (fModifiers & B_COMMAND_KEY) && fWindow)279 if (_IsValidShortcut(fShortcutChar, fModifiers) && fWindow) 282 280 fWindow->AddShortcut(fShortcutChar, fModifiers, this); 283 281 284 282 if (fSuper) { … … 583 581 void 584 582 BMenuItem::Install(BWindow *window) 585 583 { 586 if (fSubmenu) {584 if (fSubmenu) 587 585 MenuPrivate(fSubmenu).Install(window); 588 }589 586 590 587 fWindow = window; 591 588 592 if ( fShortcutChar != 0 && (fModifiers & B_COMMAND_KEY) && fWindow)589 if (_IsValidShortcut(fShortcutChar, fModifiers) && fWindow) 593 590 window->AddShortcut(fShortcutChar, fModifiers, this); 594 591 595 592 if (!Messenger().IsValid()) … … 646 643 if (Target() == fWindow) 647 644 SetTarget(BMessenger()); 648 645 649 if (fShortcutChar != 0 && (fModifiers & B_COMMAND_KEY) != 0 650 && fWindow != NULL) 646 if (_IsValidShortcut(fShortcutChar, fModifiers) && fWindow != NULL) 651 647 fWindow->RemoveShortcut(fShortcutChar, fModifiers); 652 648 653 649 fWindow = NULL; … … 734 730 where.x -= fBounds.Height() - 3; 735 731 736 732 const float ascent = MenuPrivate(fSuper).Ascent(); 737 if (fShortcutChar < B_SPACE && kUTF8ControlMap[(int)fShortcutChar])733 if (fShortcutChar < B_SPACE) 738 734 _DrawControlChar(fShortcutChar, where + BPoint(0, ascent)); 739 735 else 740 736 fSuper->DrawChar(fShortcutChar, where + BPoint(0, ascent)); … … 818 814 { 819 815 // TODO: If needed, take another font for the control characters 820 816 // (or have font overlays in the app_server!) 821 const char* symbol = " "; 822 if (kUTF8ControlMap[(int)fShortcutChar]) 823 symbol = kUTF8ControlMap[(int)fShortcutChar]; 817 if (kUTF8ControlMap[(int)fShortcutChar]) { 818 const char* symbol = kUTF8ControlMap[(int)fShortcutChar]; 819 fSuper->DrawString(symbol, where); 820 } else if (shortcut >= B_F1_KEY && shortcut <= B_F12_KEY) { 821 int number = 1 + (shortcut - B_F1_KEY); 822 char shortcutString[10]; 823 snprintf(shortcutString, sizeof(shortcutString), "F%d", number); 824 // Account for this being longer that one character. Subtracting two 825 // times the size of space seems to align this nicely. 826 where.x -= (fSuper->StringWidth(shortcutString) - (2 * fSuper->StringWidth(" "))); 827 fSuper->DrawString(shortcutString, where); 828 } 829 } 824 830 825 fSuper->DrawString(symbol, where); 831 832 bool 833 BMenuItem::_IsValidShortcut(char shortcut, uint32 modifiers) 834 { 835 if (shortcut != 0) { 836 // Either explicitly ask for no modifiers or must have at least 837 // B_COMMAND_KEY 838 if (modifiers == B_NO_MODIFIERS) 839 return true; 840 else 841 return (modifiers & B_COMMAND_KEY) != 0; 842 } 843 return false; 826 844 } 827 845 828 846