1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import "content/browser/cocoa/system_hotkey_map.h"
7 #pragma mark - NSDictionary Helper Functions
11 // All 4 following functions return nil if the object doesn't exist, or isn't of
13 id ObjectForKey(NSDictionary* dict, NSString* key, Class aClass) {
14 id object = [dict objectForKey:key];
15 if (![object isKindOfClass:aClass])
20 NSDictionary* DictionaryForKey(NSDictionary* dict, NSString* key) {
21 return ObjectForKey(dict, key, [NSDictionary class]);
24 NSArray* ArrayForKey(NSDictionary* dict, NSString* key) {
25 return ObjectForKey(dict, key, [NSArray class]);
28 NSNumber* NumberForKey(NSDictionary* dict, NSString* key) {
29 return ObjectForKey(dict, key, [NSNumber class]);
32 NSString* StringForKey(NSDictionary* dict, NSString* key) {
33 return ObjectForKey(dict, key, [NSString class]);
38 #pragma mark - SystemHotkey
43 unsigned short key_code;
47 #pragma mark - SystemHotkeyMap
49 SystemHotkeyMap::SystemHotkeyMap() {
51 SystemHotkeyMap::~SystemHotkeyMap() {
54 NSDictionary* SystemHotkeyMap::DictionaryFromData(NSData* data) {
59 NSPropertyListFormat format;
60 NSDictionary* dictionary =
61 [NSPropertyListSerialization propertyListWithData:data
66 if (![dictionary isKindOfClass:[NSDictionary class]])
72 bool SystemHotkeyMap::ParseDictionary(NSDictionary* dictionary) {
73 system_hotkeys_.clear();
78 NSDictionary* hotkey_dictionaries =
79 DictionaryForKey(dictionary, @"AppleSymbolicHotKeys");
80 if (!hotkey_dictionaries)
83 for (NSString* hotkey_system_effect in [hotkey_dictionaries allKeys]) {
84 if (![hotkey_system_effect isKindOfClass:[NSString class]])
87 NSDictionary* hotkey_dictionary =
88 [hotkey_dictionaries objectForKey:hotkey_system_effect];
89 if (![hotkey_dictionary isKindOfClass:[NSDictionary class]])
92 NSNumber* enabled = NumberForKey(hotkey_dictionary, @"enabled");
93 if (!enabled || enabled.boolValue == NO)
96 NSDictionary* value = DictionaryForKey(hotkey_dictionary, @"value");
100 NSString* type = StringForKey(value, @"type");
101 if (!type || ![type isEqualToString:@"standard"])
104 NSArray* parameters = ArrayForKey(value, @"parameters");
105 if (!parameters || [parameters count] != 3)
108 NSNumber* key_code = [parameters objectAtIndex:1];
109 if (![key_code isKindOfClass:[NSNumber class]])
112 NSNumber* modifiers = [parameters objectAtIndex:2];
113 if (![modifiers isKindOfClass:[NSNumber class]])
116 ReserveHotkey(key_code.unsignedShortValue,
117 modifiers.unsignedIntegerValue,
118 hotkey_system_effect);
124 bool SystemHotkeyMap::IsEventReserved(NSEvent* event) const {
125 return IsHotkeyReserved(event.keyCode, event.modifierFlags);
128 bool SystemHotkeyMap::IsHotkeyReserved(unsigned short key_code,
129 NSUInteger modifiers) const {
130 modifiers &= NSDeviceIndependentModifierFlagsMask;
131 std::vector<SystemHotkey>::const_iterator it;
132 for (it = system_hotkeys_.begin(); it != system_hotkeys_.end(); ++it) {
133 if (it->key_code == key_code && it->modifiers == modifiers)
139 void SystemHotkeyMap::ReserveHotkey(unsigned short key_code,
140 NSUInteger modifiers,
141 NSString* system_effect) {
142 ReserveHotkey(key_code, modifiers);
144 // If a hotkey exists for toggling through the windows of an application, then
145 // adding shift to that hotkey toggles through the windows backwards.
146 if ([system_effect isEqualToString:@"27"])
147 ReserveHotkey(key_code, modifiers | NSShiftKeyMask);
150 void SystemHotkeyMap::ReserveHotkey(unsigned short key_code,
151 NSUInteger modifiers) {
152 // Hotkeys require at least one of control, command, or alternate keys to be
154 NSUInteger required_modifiers =
155 NSControlKeyMask | NSCommandKeyMask | NSAlternateKeyMask;
156 if ((modifiers & required_modifiers) == 0)
160 hotkey.key_code = key_code;
161 hotkey.modifiers = modifiers;
162 system_hotkeys_.push_back(hotkey);
165 } // namespace content