| OLD | NEW |
| (Empty) |
| 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 (function () { | |
| 6 | |
| 7 /** | |
| 8 * The possible states of the shift key. | |
| 9 * Unlocked is the default state. Locked for capslocked, pressed is a | |
| 10 * key-down and tapped for a key-down followed by an immediate key-up. | |
| 11 * @const | |
| 12 * @type {Enum} | |
| 13 */ | |
| 14 var KEY_STATES = { | |
| 15 PRESSED: "pressed", // Key-down on shift key. | |
| 16 LOCKED: "locked", // Key is capslocked. | |
| 17 UNLOCKED: "unlocked", // Default state. | |
| 18 TAPPED: "tapped", // Key-down followed by key-up. | |
| 19 CHORDING: "chording" // Key-down followed by other keys. | |
| 20 }; | |
| 21 | |
| 22 /** | |
| 23 * The pointerdown event on shiftkey that may eventually trigger chording | |
| 24 * state. pointerId and eventTarget are the two fields that is used now. | |
| 25 * @type {PointerEvent} | |
| 26 */ | |
| 27 var enterChordingEvent = undefined; | |
| 28 | |
| 29 /** | |
| 30 * Uses a closure to define one long press timer among all shift keys | |
| 31 * regardless of the layout they are in. | |
| 32 * @type {function} | |
| 33 */ | |
| 34 var shiftLongPressTimer = undefined; | |
| 35 | |
| 36 /** | |
| 37 * The current state of the shift key. | |
| 38 * @type {Enum} | |
| 39 */ | |
| 40 var state = KEY_STATES.UNLOCKED; | |
| 41 | |
| 42 Polymer('kb-shift-key', { | |
| 43 /** | |
| 44 * Defines how capslock effects keyset transition. We always transition | |
| 45 * from the lowerCaseKeysetId to the upperCaseKeysetId if capslock is | |
| 46 * on. | |
| 47 * @type {string} | |
| 48 */ | |
| 49 lowerCaseKeysetId: 'lower', | |
| 50 upperCaseKeysetId: 'upper', | |
| 51 | |
| 52 up: function(event) { | |
| 53 if (state == KEY_STATES.CHORDING && | |
| 54 event.pointerId != enterChordingEvent.pointerId) { | |
| 55 // Disables all other pointer events on shift keys when chording. | |
| 56 return; | |
| 57 } | |
| 58 switch (state) { | |
| 59 case KEY_STATES.PRESSED: | |
| 60 state = KEY_STATES.TAPPED; | |
| 61 break; | |
| 62 case KEY_STATES.CHORDING: | |
| 63 // Leaves chording only if the pointer that triggered it is | |
| 64 // released. | |
| 65 state = KEY_STATES.UNLOCKED; | |
| 66 break; | |
| 67 default: | |
| 68 break; | |
| 69 } | |
| 70 // When releasing the shift key, it is not the same shift key that was | |
| 71 // pressed. Updates the pointerId of the releasing shift key to make | |
| 72 // sure key-up event fires correctly in kb-key-base. | |
| 73 this.pointerId = enterChordingEvent.pointerId; | |
| 74 this.super([event]); | |
| 75 }, | |
| 76 | |
| 77 out: function(event) { | |
| 78 // Sliding off the shift key while chording is treated as a key-up. | |
| 79 // Note that we switch to a new keyset on shift keydown, and a finger | |
| 80 // movement on the new shift key will trigger this function being | |
| 81 // called on the old shift key. We should not end chording in that | |
| 82 // case. | |
| 83 if (state == KEY_STATES.CHORDING && | |
| 84 event.pointerId == enterChordingEvent.pointerId && | |
| 85 event.target != enterChordingEvent.target) { | |
| 86 state = KEY_STATES.UNLOCKED; | |
| 87 var detail = this.populateDetails('out'); | |
| 88 this.fire("key-out", detail); | |
| 89 } | |
| 90 }, | |
| 91 | |
| 92 down: function(event) { | |
| 93 // First transition state so that populateDetails generates | |
| 94 // correct data. | |
| 95 switch (state) { | |
| 96 case KEY_STATES.UNLOCKED: | |
| 97 state = KEY_STATES.PRESSED; | |
| 98 break; | |
| 99 case KEY_STATES.TAPPED: | |
| 100 case KEY_STATES.LOCKED: | |
| 101 state = KEY_STATES.UNLOCKED; | |
| 102 break; | |
| 103 case KEY_STATES.PRESSED: | |
| 104 case KEY_STATES.CHORDING: | |
| 105 // We pressed another shift key at the same time, | |
| 106 // so ignore second press. | |
| 107 return; | |
| 108 default: | |
| 109 console.error("Undefined shift key state: " + state); | |
| 110 break; | |
| 111 } | |
| 112 enterChordingEvent = event; | |
| 113 // Trigger parent behaviour. | |
| 114 this.super([event]); | |
| 115 this.fire('enable-sel'); | |
| 116 // Populate double click transition details. | |
| 117 var detail = {}; | |
| 118 detail.char = this.char || this.textContent; | |
| 119 detail.toKeyset = this.upperCaseKeysetId; | |
| 120 detail.nextKeyset = undefined; | |
| 121 detail.callback = this.onDoubleClick; | |
| 122 this.fire('enable-dbl', detail); | |
| 123 }, | |
| 124 | |
| 125 generateLongPressTimer: function() { | |
| 126 return this.async(function() { | |
| 127 var detail = this.populateDetails(); | |
| 128 if (state == KEY_STATES.LOCKED) { | |
| 129 // We don't care about the longpress if we are already | |
| 130 // capitalized. | |
| 131 return; | |
| 132 } else { | |
| 133 state = KEY_STATES.LOCKED; | |
| 134 detail.toKeyset = this.upperCaseKeysetId; | |
| 135 detail.nextKeyset = undefined; | |
| 136 } | |
| 137 this.fire('key-longpress', detail); | |
| 138 }, null, LONGPRESS_DELAY_MSEC); | |
| 139 }, | |
| 140 | |
| 141 // @return Whether the shift modifier is currently active. | |
| 142 isActive: function() { | |
| 143 return state != KEY_STATES.UNLOCKED; | |
| 144 }, | |
| 145 | |
| 146 /** | |
| 147 * Callback function for when a double click is triggered. | |
| 148 */ | |
| 149 onDoubleClick: function() { | |
| 150 state = KEY_STATES.LOCKED; | |
| 151 }, | |
| 152 | |
| 153 /** | |
| 154 * Notifies shift key that a non-control key was pressed down. | |
| 155 * A control key is defined as one of shift, control or alt. | |
| 156 */ | |
| 157 onNonControlKeyDown: function() { | |
| 158 switch (state) { | |
| 159 case (KEY_STATES.PRESSED): | |
| 160 state = KEY_STATES.CHORDING; | |
| 161 // Disable longpress timer. | |
| 162 clearTimeout(shiftLongPressTimer); | |
| 163 break; | |
| 164 default: | |
| 165 break; | |
| 166 } | |
| 167 }, | |
| 168 | |
| 169 /** | |
| 170 * Notifies key that a non-control keyed was typed. | |
| 171 * A control key is defined as one of shift, control or alt. | |
| 172 */ | |
| 173 onNonControlKeyTyped: function() { | |
| 174 if (state == KEY_STATES.TAPPED) | |
| 175 state = KEY_STATES.UNLOCKED; | |
| 176 }, | |
| 177 | |
| 178 /** | |
| 179 * Callback function for when a space is pressed after punctuation. | |
| 180 * @return {Object} The keyset transitions the keyboard should make. | |
| 181 */ | |
| 182 onSpaceAfterPunctuation: function() { | |
| 183 var detail = {}; | |
| 184 detail.toKeyset = this.upperCaseKeysetId; | |
| 185 detail.nextKeyset = this.lowerCaseKeysetId; | |
| 186 state = KEY_STATES.TAPPED; | |
| 187 return detail; | |
| 188 }, | |
| 189 | |
| 190 populateDetails: function(caller) { | |
| 191 var detail = this.super([caller]); | |
| 192 switch(state) { | |
| 193 case(KEY_STATES.LOCKED): | |
| 194 detail.toKeyset = this.upperCaseKeysetId; | |
| 195 break; | |
| 196 case(KEY_STATES.UNLOCKED): | |
| 197 detail.toKeyset = this.lowerCaseKeysetId; | |
| 198 break; | |
| 199 case(KEY_STATES.PRESSED): | |
| 200 detail.toKeyset = this.upperCaseKeysetId; | |
| 201 break; | |
| 202 case(KEY_STATES.TAPPED): | |
| 203 detail.toKeyset = this.upperCaseKeysetId; | |
| 204 detail.nextKeyset = this.lowerCaseKeysetId; | |
| 205 break; | |
| 206 case(KEY_STATES.CHORDING): | |
| 207 detail.toKeyset = this.lowerCaseKeysetId; | |
| 208 break; | |
| 209 default: | |
| 210 break; | |
| 211 } | |
| 212 return detail; | |
| 213 }, | |
| 214 | |
| 215 /** | |
| 216 * Resets the shift key state. | |
| 217 */ | |
| 218 reset: function() { | |
| 219 state = KEY_STATES.UNLOCKED; | |
| 220 }, | |
| 221 | |
| 222 /** | |
| 223 * Overrides longPressTimer for the shift key. | |
| 224 */ | |
| 225 get longPressTimer() { | |
| 226 return shiftLongPressTimer; | |
| 227 }, | |
| 228 | |
| 229 set longPressTimer(timer) { | |
| 230 shiftLongPressTimer = timer; | |
| 231 }, | |
| 232 | |
| 233 get state() { | |
| 234 return state; | |
| 235 }, | |
| 236 | |
| 237 get textKeyset() { | |
| 238 switch (state) { | |
| 239 case KEY_STATES.UNLOCKED: | |
| 240 return this.lowerCaseKeysetId; | |
| 241 default: | |
| 242 return this.upperCaseKeysetId; | |
| 243 } | |
| 244 }, | |
| 245 }); | |
| 246 })(); | |
| OLD | NEW |