Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / content / browser / cocoa / system_hotkey_map.mm
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.
4
5 #import "content/browser/cocoa/system_hotkey_map.h"
6
7 #pragma mark - NSDictionary Helper Functions
8
9 namespace {
10
11 // All 4 following functions return nil if the object doesn't exist, or isn't of
12 // the right class.
13 id ObjectForKey(NSDictionary* dict, NSString* key, Class aClass) {
14   id object = [dict objectForKey:key];
15   if (![object isKindOfClass:aClass])
16     return nil;
17   return object;
18 }
19
20 NSDictionary* DictionaryForKey(NSDictionary* dict, NSString* key) {
21   return ObjectForKey(dict, key, [NSDictionary class]);
22 }
23
24 NSArray* ArrayForKey(NSDictionary* dict, NSString* key) {
25   return ObjectForKey(dict, key, [NSArray class]);
26 }
27
28 NSNumber* NumberForKey(NSDictionary* dict, NSString* key) {
29   return ObjectForKey(dict, key, [NSNumber class]);
30 }
31
32 NSString* StringForKey(NSDictionary* dict, NSString* key) {
33   return ObjectForKey(dict, key, [NSString class]);
34 }
35
36 }  // namespace
37
38 #pragma mark - SystemHotkey
39
40 namespace content {
41
42 struct SystemHotkey {
43   unsigned short key_code;
44   NSUInteger modifiers;
45 };
46
47 #pragma mark - SystemHotkeyMap
48
49 SystemHotkeyMap::SystemHotkeyMap() {
50 }
51 SystemHotkeyMap::~SystemHotkeyMap() {
52 }
53
54 NSDictionary* SystemHotkeyMap::DictionaryFromData(NSData* data) {
55   if (!data)
56     return nil;
57
58   NSError* error = nil;
59   NSPropertyListFormat format;
60   NSDictionary* dictionary =
61       [NSPropertyListSerialization propertyListWithData:data
62                                                 options:0
63                                                  format:&format
64                                                   error:&error];
65
66   if (![dictionary isKindOfClass:[NSDictionary class]])
67     return nil;
68
69   return dictionary;
70 }
71
72 bool SystemHotkeyMap::ParseDictionary(NSDictionary* dictionary) {
73   system_hotkeys_.clear();
74
75   if (!dictionary)
76     return false;
77
78   NSDictionary* hotkey_dictionaries =
79       DictionaryForKey(dictionary, @"AppleSymbolicHotKeys");
80   if (!hotkey_dictionaries)
81     return false;
82
83   for (NSString* hotkey_system_effect in [hotkey_dictionaries allKeys]) {
84     if (![hotkey_system_effect isKindOfClass:[NSString class]])
85       continue;
86
87     NSDictionary* hotkey_dictionary =
88         [hotkey_dictionaries objectForKey:hotkey_system_effect];
89     if (![hotkey_dictionary isKindOfClass:[NSDictionary class]])
90       continue;
91
92     NSNumber* enabled = NumberForKey(hotkey_dictionary, @"enabled");
93     if (!enabled || enabled.boolValue == NO)
94       continue;
95
96     NSDictionary* value = DictionaryForKey(hotkey_dictionary, @"value");
97     if (!value)
98       continue;
99
100     NSString* type = StringForKey(value, @"type");
101     if (!type || ![type isEqualToString:@"standard"])
102       continue;
103
104     NSArray* parameters = ArrayForKey(value, @"parameters");
105     if (!parameters || [parameters count] != 3)
106       continue;
107
108     NSNumber* key_code = [parameters objectAtIndex:1];
109     if (![key_code isKindOfClass:[NSNumber class]])
110       continue;
111
112     NSNumber* modifiers = [parameters objectAtIndex:2];
113     if (![modifiers isKindOfClass:[NSNumber class]])
114       continue;
115
116     ReserveHotkey(key_code.unsignedShortValue,
117                   modifiers.unsignedIntegerValue,
118                   hotkey_system_effect);
119   }
120
121   return true;
122 }
123
124 bool SystemHotkeyMap::IsEventReserved(NSEvent* event) const {
125   return IsHotkeyReserved(event.keyCode, event.modifierFlags);
126 }
127
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)
134       return true;
135   }
136   return false;
137 }
138
139 void SystemHotkeyMap::ReserveHotkey(unsigned short key_code,
140                                     NSUInteger modifiers,
141                                     NSString* system_effect) {
142   ReserveHotkey(key_code, modifiers);
143
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);
148 }
149
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
153   // down.
154   NSUInteger required_modifiers =
155       NSControlKeyMask | NSCommandKeyMask | NSAlternateKeyMask;
156   if ((modifiers & required_modifiers) == 0)
157     return;
158
159   SystemHotkey hotkey;
160   hotkey.key_code = key_code;
161   hotkey.modifiers = modifiers;
162   system_hotkeys_.push_back(hotkey);
163 }
164
165 }  // namespace content