diff options
Diffstat (limited to 'chrome/browser/cocoa/nsmenuitem_additions_unittest.mm')
-rw-r--r-- | chrome/browser/cocoa/nsmenuitem_additions_unittest.mm | 351 |
1 files changed, 0 insertions, 351 deletions
diff --git a/chrome/browser/cocoa/nsmenuitem_additions_unittest.mm b/chrome/browser/cocoa/nsmenuitem_additions_unittest.mm deleted file mode 100644 index 869cade..0000000 --- a/chrome/browser/cocoa/nsmenuitem_additions_unittest.mm +++ /dev/null @@ -1,351 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "chrome/browser/cocoa/nsmenuitem_additions.h" - -#include <Carbon/Carbon.h> - -#include <ostream> - -#include "base/scoped_nsobject.h" -#include "base/sys_string_conversions.h" -#include "testing/gtest/include/gtest/gtest.h" - -NSEvent* KeyEvent(const NSUInteger modifierFlags, - NSString* chars, - NSString* charsNoMods, - const NSUInteger keyCode) { - return [NSEvent keyEventWithType:NSKeyDown - location:NSZeroPoint - modifierFlags:modifierFlags - timestamp:0.0 - windowNumber:0 - context:nil - characters:chars - charactersIgnoringModifiers:charsNoMods - isARepeat:NO - keyCode:keyCode]; -} - -NSMenuItem* MenuItem(NSString* equiv, NSUInteger mask) { - NSMenuItem* item = [[[NSMenuItem alloc] initWithTitle:@"" - action:NULL - keyEquivalent:@""] autorelease]; - [item setKeyEquivalent:equiv]; - [item setKeyEquivalentModifierMask:mask]; - return item; -} - -std::ostream& operator<<(std::ostream& out, NSObject* obj) { - return out << base::SysNSStringToUTF8([obj description]); -} - -std::ostream& operator<<(std::ostream& out, NSMenuItem* item) { - return out << "NSMenuItem " << base::SysNSStringToUTF8([item keyEquivalent]); -} - -void ExpectKeyFiresItemEq(bool result, NSEvent* key, NSMenuItem* item, - bool compareCocoa) { - EXPECT_EQ(result, [item cr_firesForKeyEvent:key]) << key << '\n' << item; - - // Make sure that Cocoa does in fact agree with our expectations. However, - // in some cases cocoa behaves weirdly (if you create e.g. a new event that - // contains all fields of the event that you get when hitting cmd-a with a - // russion keyboard layout, the copy won't fire a menu item that has cmd-a as - // key equivalent, even though the original event would) and isn't a good - // oracle function. - if (compareCocoa) { - scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@"Menu!"]); - [menu setAutoenablesItems:NO]; - EXPECT_FALSE([menu performKeyEquivalent:key]); - [menu addItem:item]; - EXPECT_EQ(result, [menu performKeyEquivalent:key]) << key << '\n' << item; - } -} - -void ExpectKeyFiresItem( - NSEvent* key, NSMenuItem* item, bool compareCocoa = true) { - ExpectKeyFiresItemEq(true, key, item, compareCocoa); -} - -void ExpectKeyDoesntFireItem( - NSEvent* key, NSMenuItem* item, bool compareCocoa = true) { - ExpectKeyFiresItemEq(false, key, item, compareCocoa); -} - -TEST(NSMenuItemAdditionsTest, TestFiresForKeyEvent) { - // These test cases were built by writing a small test app that has a - // MainMenu.xib with a given key equivalent set in Interface Builder and a - // some code that prints both the key equivalent that fires a menu item and - // the menu item's key equivalent and modifier masks. I then pasted those - // below. This was done with a US layout, unless otherwise noted. In the - // comments, "z" always means the physical "z" key on a US layout no matter - // what character that key produces. - - NSMenuItem* item; - NSEvent* key; - unichar ch; - NSString* s; - - // Sanity - item = MenuItem(@"", 0); - EXPECT_TRUE([item isEnabled]); - - // a - key = KeyEvent(0x100, @"a", @"a", 0); - item = MenuItem(@"a", 0); - ExpectKeyFiresItem(key, item); - ExpectKeyDoesntFireItem(KeyEvent(0x20102, @"A", @"A", 0), item); - - // Disabled menu item - key = KeyEvent(0x100, @"a", @"a", 0); - item = MenuItem(@"a", 0); - [item setEnabled:NO]; - ExpectKeyDoesntFireItem(key, item, false); - - // shift-a - key = KeyEvent(0x20102, @"A", @"A", 0); - item = MenuItem(@"A", 0); - ExpectKeyFiresItem(key, item); - ExpectKeyDoesntFireItem(KeyEvent(0x100, @"a", @"a", 0), item); - - // cmd-opt-shift-a - key = KeyEvent(0x1a012a, @"\u00c5", @"A", 0); - item = MenuItem(@"A", 0x180000); - ExpectKeyFiresItem(key, item); - - // cmd-opt-a - key = KeyEvent(0x18012a, @"\u00e5", @"a", 0); - item = MenuItem(@"a", 0x180000); - ExpectKeyFiresItem(key, item); - - // cmd-= - key = KeyEvent(0x100110, @"=", @"=", 0x18); - item = MenuItem(@"=", 0x100000); - ExpectKeyFiresItem(key, item); - - // cmd-shift-= - key = KeyEvent(0x12010a, @"=", @"+", 0x18); - item = MenuItem(@"+", 0x100000); - ExpectKeyFiresItem(key, item); - - // Turns out Cocoa fires "+ 100108 + 18" if you hit cmd-= and the menu only - // has a cmd-+ shortcut. But that's transparent for |cr_firesForKeyEvent:|. - - // ctrl-3 - key = KeyEvent(0x40101, @"3", @"3", 0x14); - item = MenuItem(@"3", 0x40000); - ExpectKeyFiresItem(key, item); - - // return - key = KeyEvent(0, @"\r", @"\r", 0x24); - item = MenuItem(@"\r", 0); - ExpectKeyFiresItem(key, item); - - // shift-return - key = KeyEvent(0x20102, @"\r", @"\r", 0x24); - item = MenuItem(@"\r", 0x20000); - ExpectKeyFiresItem(key, item); - - // shift-left - ch = NSLeftArrowFunctionKey; - s = [NSString stringWithCharacters:&ch length:1]; - key = KeyEvent(0xa20102, s, s, 0x7b); - item = MenuItem(s, 0x20000); - ExpectKeyFiresItem(key, item); - - // shift-f1 (with a layout that needs the fn key down for f1) - ch = NSF1FunctionKey; - s = [NSString stringWithCharacters:&ch length:1]; - key = KeyEvent(0x820102, s, s, 0x7a); - item = MenuItem(s, 0x20000); - ExpectKeyFiresItem(key, item); - - // esc - // Turns out this doesn't fire. - key = KeyEvent(0x100, @"\e", @"\e", 0x35); - item = MenuItem(@"\e", 0); - ExpectKeyDoesntFireItem(key,item, false); - - // shift-esc - // Turns out this doesn't fire. - key = KeyEvent(0x20102, @"\e", @"\e", 0x35); - item = MenuItem(@"\e", 0x20000); - ExpectKeyDoesntFireItem(key,item, false); - - // cmd-esc - key = KeyEvent(0x100108, @"\e", @"\e", 0x35); - item = MenuItem(@"\e", 0x100000); - ExpectKeyFiresItem(key, item); - - // ctrl-esc - key = KeyEvent(0x40101, @"\e", @"\e", 0x35); - item = MenuItem(@"\e", 0x40000); - ExpectKeyFiresItem(key, item); - - // delete ("backspace") - key = KeyEvent(0x100, @"\x7f", @"\x7f", 0x33); - item = MenuItem(@"\x08", 0); - ExpectKeyFiresItem(key, item, false); - - // shift-delete - key = KeyEvent(0x20102, @"\x7f", @"\x7f", 0x33); - item = MenuItem(@"\x08", 0x20000); - ExpectKeyFiresItem(key, item, false); - - // forwarddelete (fn-delete / fn-backspace) - ch = NSDeleteFunctionKey; - s = [NSString stringWithCharacters:&ch length:1]; - key = KeyEvent(0x800100, s, s, 0x75); - item = MenuItem(@"\x7f", 0); - ExpectKeyFiresItem(key, item, false); - - // shift-forwarddelete (shift-fn-delete / shift-fn-backspace) - ch = NSDeleteFunctionKey; - s = [NSString stringWithCharacters:&ch length:1]; - key = KeyEvent(0x820102, s, s, 0x75); - item = MenuItem(@"\x7f", 0x20000); - ExpectKeyFiresItem(key, item, false); - - // fn-left - ch = NSHomeFunctionKey; - s = [NSString stringWithCharacters:&ch length:1]; - key = KeyEvent(0x800100, s, s, 0x73); - item = MenuItem(s, 0); - ExpectKeyFiresItem(key, item); - - // cmd-left - ch = NSLeftArrowFunctionKey; - s = [NSString stringWithCharacters:&ch length:1]; - key = KeyEvent(0xb00108, s, s, 0x7b); - item = MenuItem(s, 0x100000); - ExpectKeyFiresItem(key, item); - - // Hitting the "a" key with a russian keyboard layout -- does not fire - // a menu item that has "a" as key equiv. - key = KeyEvent(0x100, @"\u0444", @"\u0444", 0); - item = MenuItem(@"a", 0); - ExpectKeyDoesntFireItem(key,item); - - // cmd-a on a russion layout -- fires for a menu item with cmd-a as key equiv. - key = KeyEvent(0x100108, @"a", @"\u0444", 0); - item = MenuItem(@"a", 0x100000); - ExpectKeyFiresItem(key, item, false); - - // cmd-z on US layout - key = KeyEvent(0x100108, @"z", @"z", 6); - item = MenuItem(@"z", 0x100000); - ExpectKeyFiresItem(key, item); - - // cmd-y on german layout (has same keycode as cmd-z on us layout, shouldn't - // fire). - key = KeyEvent(0x100108, @"y", @"y", 6); - item = MenuItem(@"z", 0x100000); - ExpectKeyDoesntFireItem(key,item); - - // cmd-z on german layout - key = KeyEvent(0x100108, @"z", @"z", 0x10); - item = MenuItem(@"z", 0x100000); - ExpectKeyFiresItem(key, item); - - // fn-return (== enter) - key = KeyEvent(0x800100, @"\x3", @"\x3", 0x4c); - item = MenuItem(@"\r", 0); - ExpectKeyDoesntFireItem(key,item); - - // cmd-z on dvorak layout (so that the key produces ';') - key = KeyEvent(0x100108, @";", @";", 6); - ExpectKeyDoesntFireItem(key, MenuItem(@"z", 0x100000)); - ExpectKeyFiresItem(key, MenuItem(@";", 0x100000)); - - // cmd-z on dvorak qwerty layout (so that the key produces ';', but 'z' if - // cmd is down) - key = KeyEvent(0x100108, @"z", @";", 6); - ExpectKeyFiresItem(key, MenuItem(@"z", 0x100000), false); - ExpectKeyDoesntFireItem(key, MenuItem(@";", 0x100000), false); - - // cmd-shift-z on dvorak layout (so that we get a ':') - key = KeyEvent(0x12010a, @";", @":", 6); - ExpectKeyFiresItem(key, MenuItem(@":", 0x100000)); - ExpectKeyDoesntFireItem(key, MenuItem(@";", 0x100000)); - - // cmd-s with a serbian layout (just "s" produces something that looks a lot - // like "c" in some fonts, but is actually \u0441. cmd-s activates a menu item - // with key equivalent "s", not "c") - key = KeyEvent(0x100108, @"s", @"\u0441", 1); - ExpectKeyFiresItem(key, MenuItem(@"s", 0x100000), false); - ExpectKeyDoesntFireItem(key, MenuItem(@"c", 0x100000)); -} - -NSString* keyCodeToCharacter(NSUInteger keyCode, - EventModifiers modifiers, - TISInputSourceRef layout) { - CFDataRef uchr = (CFDataRef)TISGetInputSourceProperty( - layout, kTISPropertyUnicodeKeyLayoutData); - UCKeyboardLayout* keyLayout = (UCKeyboardLayout*)CFDataGetBytePtr(uchr); - - UInt32 deadKeyState = 0; - OSStatus err = noErr; - UniCharCount maxStringLength = 4, actualStringLength; - UniChar unicodeString[4]; - err = UCKeyTranslate(keyLayout, - (UInt16)keyCode, - kUCKeyActionDown, - modifiers, - LMGetKbdType(), - kUCKeyTranslateNoDeadKeysBit, - &deadKeyState, - maxStringLength, - &actualStringLength, - unicodeString); - assert(err == noErr); - - CFStringRef temp = CFStringCreateWithCharacters( - kCFAllocatorDefault, unicodeString, 1); - return [(NSString*)temp autorelease]; -} - -TEST(NSMenuItemAdditionsTest, TestMOnDifferentLayouts) { - // There's one key -- "m" -- that has the same keycode on most keyboard - // layouts. This function tests a menu item with cmd-m as key equivalent - // can be fired on all layouts. - NSMenuItem* item = MenuItem(@"m", 0x100000); - - NSDictionary* filter = [NSDictionary - dictionaryWithObject:(NSString*)kTISTypeKeyboardLayout - forKey:(NSString*)kTISPropertyInputSourceType]; - - // Docs say that including all layouts instead of just the active ones is - // slow, but there's no way around that. - NSArray* list = (NSArray*)TISCreateInputSourceList( - (CFDictionaryRef)filter, true); - for (id layout in list) { - TISInputSourceRef ref = (TISInputSourceRef)layout; - - NSUInteger keyCode = 0x2e; // "m" on a US layout and most other layouts. - - // On a few layouts, "m" has a different key code. - NSString* layoutId = (NSString*)TISGetInputSourceProperty( - ref, kTISPropertyInputSourceID); - if ([layoutId isEqualToString:@"com.apple.keylayout.Belgian"] || - [layoutId isEqualToString:@"com.apple.keylayout.French"] || - [layoutId isEqualToString:@"com.apple.keylayout.French-numerical"] || - [layoutId isEqualToString:@"com.apple.keylayout.Italian"]) { - keyCode = 0x29; - } else if ([layoutId isEqualToString:@"com.apple.keylayout.Turkish"]) { - keyCode = 0x28; - } else if ([layoutId isEqualToString:@"com.apple.keylayout.Dvorak-Left"]) { - keyCode = 0x16; - } else if ([layoutId isEqualToString:@"com.apple.keylayout.Dvorak-Right"]) { - keyCode = 0x1a; - } - - EventModifiers modifiers = cmdKey >> 8; - NSString* chars = keyCodeToCharacter(keyCode, modifiers, ref); - NSString* charsIgnoringMods = keyCodeToCharacter(keyCode, 0, ref); - NSEvent* key = KeyEvent(0x100000, chars, charsIgnoringMods, keyCode); - ExpectKeyFiresItem(key, item, false); - } - CFRelease(list); -} |