@@ -30,66 +30,59 @@ mergeInto(LibraryManager.library, {
30
30
// text element used to capture input events
31
31
_inputelement : null ,
32
32
33
+ // current target of keyboard / input events
34
+ _inputtarget : null ,
35
+
33
36
// This function is used to call a function for each event
34
37
// type to handler mapping defined for LiveCode on Emscripten.
35
38
//
36
- // The <func> must take three arguments: the event type, the
37
- // handler function used to handle that event type, and a
38
- // boolean indicating whether the event handler should be
39
- // attached to the hidden input control.
39
+ // The <func> must take two arguments: the event type, and the
40
+ // handler function used to handle that event type.
40
41
_eventForEach : function ( func ) {
41
42
42
43
// Master mapping from event types to handler functions.
43
44
var mapping = [
44
- [ 'focus' , LiveCodeEvents . _handleFocusEvent , false ] ,
45
- [ 'blur' , LiveCodeEvents . _handleFocusEvent , false ] ,
45
+ [ 'focus' , LiveCodeEvents . _handleFocusEvent ] ,
46
+ [ 'blur' , LiveCodeEvents . _handleFocusEvent ] ,
46
47
47
- [ 'mousemove' , LiveCodeEvents . _handleMouseEvent , false ] ,
48
- [ 'mousedown' , LiveCodeEvents . _handleMouseEvent , false ] ,
49
- [ 'mouseup' , LiveCodeEvents . _handleMouseEvent , false ] ,
50
- [ 'mouseenter' , LiveCodeEvents . _handleMouseEvent , false ] ,
51
- [ 'mouseleave' , LiveCodeEvents . _handleMouseEvent , false ] ,
48
+ [ 'mousemove' , LiveCodeEvents . _handleMouseEvent ] ,
49
+ [ 'mousedown' , LiveCodeEvents . _handleMouseEvent ] ,
50
+ [ 'mouseup' , LiveCodeEvents . _handleMouseEvent ] ,
51
+ [ 'mouseenter' , LiveCodeEvents . _handleMouseEvent ] ,
52
+ [ 'mouseleave' , LiveCodeEvents . _handleMouseEvent ] ,
52
53
53
- [ 'keyup ' , LiveCodeEvents . _handleKeyboardEvent , true ] ,
54
- [ 'keydown' , LiveCodeEvents . _handleKeyboardEvent , true ] ,
54
+ [ 'contextmenu ' , LiveCodeEvents . _handleContextMenu ] ,
55
+ ] ;
55
56
56
- [ 'input' , LiveCodeEvents . _handleInput , true ] ,
57
- [ 'beforeinput' , LiveCodeEvents . _handleInput , true ] ,
57
+ var mapLength = mapping . length ;
58
+ for ( var i = 0 ; i < mapLength ; i ++ ) {
59
+ func ( mapping [ i ] [ 0 ] , mapping [ i ] [ 1 ] , mapping [ i ] [ 2 ] ) ;
60
+ }
61
+ } ,
58
62
59
- [ 'compositionstart' , LiveCodeEvents . _handleComposition , true ] ,
60
- [ 'compositionupdate' , LiveCodeEvents . _handleComposition , true ] ,
61
- [ 'compositionend' , LiveCodeEvents . _handleComposition , true ] ,
62
-
63
- [ 'contextmenu' , LiveCodeEvents . _handleContextMenu , false ] ,
63
+ _inputEventForEach : function ( pFunc ) {
64
+ var mapping = [
65
+ [ 'keyup' , LiveCodeEvents . _handleKeyboardEvent ] ,
66
+ [ 'keydown' , LiveCodeEvents . _handleKeyboardEvent ] ,
67
+
68
+ [ 'input' , LiveCodeEvents . _handleInput ] ,
69
+ [ 'beforeinput' , LiveCodeEvents . _handleInput ] ,
70
+
71
+ [ 'compositionstart' , LiveCodeEvents . _handleComposition ] ,
72
+ [ 'compositionupdate' , LiveCodeEvents . _handleComposition ] ,
73
+ [ 'compositionend' , LiveCodeEvents . _handleComposition ] ,
64
74
] ;
65
75
66
76
var mapLength = mapping . length ;
67
77
for ( var i = 0 ; i < mapLength ; i ++ ) {
68
- func ( mapping [ i ] [ 0 ] , mapping [ i ] [ 1 ] , mapping [ i ] [ 2 ] ) ;
78
+ pFunc ( mapping [ i ] [ 0 ] , mapping [ i ] [ 1 ] ) ;
69
79
}
70
80
} ,
71
81
72
82
addEventListeners : function ( pElement )
73
83
{
74
- // Create the hidden input element
75
- var tInput = document . createElement ( 'input' ) ;
76
- tInput . type = 'text' ;
77
- tInput . style . position = 'absolute' ;
78
- tInput . style . zIndex = 0 ;
79
- tInput . style . opacity = 0 ;
80
-
81
- LiveCodeEvents . _inputelement = tInput ;
82
- document . body . appendChild ( tInput ) ;
83
-
84
- LiveCodeEvents . _eventForEach ( function ( type , handler , addToInputField ) {
85
- if ( addToInputField )
86
- {
87
- tInput . addEventListener ( type , function ( e ) {
88
- handler ( e , pElement ) ;
89
- } ) ;
90
- }
91
- else
92
- pElement . addEventListener ( type , handler , true ) ;
84
+ LiveCodeEvents . _eventForEach ( function ( type , handler ) {
85
+ pElement . addEventListener ( type , handler , true ) ;
93
86
} ) ;
94
87
95
88
// Make sure the canvas is treated as focusable...
@@ -106,9 +99,6 @@ mergeInto(LibraryManager.library, {
106
99
LiveCodeEvents . _eventForEach ( function ( type , handler ) {
107
100
pElement . removeEventListener ( type , handler , true ) ;
108
101
} ) ;
109
-
110
- document . body . removeChild ( LiveCodeEvents . _inputelement ) ;
111
- LiveCodeEvents . _inputelements = null ;
112
102
} ,
113
103
114
104
initialize : function ( ) {
@@ -121,6 +111,20 @@ mergeInto(LibraryManager.library, {
121
111
document . addEventListener ( "mouseup" , LiveCodeEvents . _handleDocumentMouseEvent ) ;
122
112
document . addEventListener ( "mousemove" , LiveCodeEvents . _handleDocumentMouseEvent ) ;
123
113
114
+ // Create the hidden input element
115
+ var tInput = document . createElement ( 'input' ) ;
116
+ tInput . type = 'text' ;
117
+ tInput . style . position = 'absolute' ;
118
+ tInput . style . zIndex = 0 ;
119
+ tInput . style . opacity = 0 ;
120
+
121
+ LiveCodeEvents . _inputelement = tInput ;
122
+ document . body . appendChild ( tInput ) ;
123
+
124
+ LiveCodeEvents . _inputEventForEach ( function ( type , handler ) {
125
+ tInput . addEventListener ( type , handler ) ;
126
+ } ) ;
127
+
124
128
LiveCodeEvents . _initialised = true ;
125
129
} ,
126
130
@@ -129,6 +133,9 @@ mergeInto(LibraryManager.library, {
129
133
return ;
130
134
}
131
135
136
+ document . body . removeChild ( LiveCodeEvents . _inputelement ) ;
137
+ LiveCodeEvents . _inputelements = null ;
138
+
132
139
LiveCodeEvents . _initialised = false ; ;
133
140
} ,
134
141
@@ -167,24 +174,64 @@ mergeInto(LibraryManager.library, {
167
174
[ stack , owner ] ) ;
168
175
} ,
169
176
177
+ // When a LC canvas acquires focus, mark it as the current key focus target, then pass focus to the hidden input field
178
+ _setInputFocus : function ( pTarget ) {
179
+ if ( pTarget != LiveCodeEvents . _inputtarget )
180
+ {
181
+ if ( LiveCodeEvents . _inputtarget != null )
182
+ {
183
+ var tOldTarget = LiveCodeEvents . _inputtarget ;
184
+ LiveCodeEvents . _inputtarget = null ;
185
+ LiveCodeEvents . _postKeyFocus ( LiveCodeEvents . _getStackForCanvas ( tOldTarget ) , false ) ;
186
+ tOldTarget . blur ( ) ;
187
+ }
188
+
189
+ if ( pTarget != null )
190
+ {
191
+ LiveCodeEvents . _inputtarget = pTarget ;
192
+ LiveCodeEvents . _postKeyFocus ( LiveCodeEvents . _getStackForCanvas ( pTarget ) , true ) ;
193
+ }
194
+ }
195
+
196
+ if ( LiveCodeEvents . _inputelement != null )
197
+ LiveCodeEvents . _inputelement . focus ( { "preventScroll" : true } ) ;
198
+ } ,
199
+
170
200
_handleFocusEvent : function ( e ) {
171
201
LiveCodeAsync . delay ( function ( ) {
172
202
var stack = LiveCodeEvents . _getStackForCanvas ( e . target ) ;
203
+
204
+ // clear the current focus target when the hidden input field loses focus to a non-LC element.
205
+ if ( e . target == LiveCodeEvents . _inputelement &&
206
+ ( e . type == 'blur' || e . type == 'focusout' ) &&
207
+ LiveCodeEvents . _getStackForCanvas ( e . relatedTarget ) == null )
208
+ {
209
+ _setInputFocus ( null ) ;
210
+ return ;
211
+ }
212
+
173
213
// ignore events for non-lc elements
174
214
if ( ! stack )
175
215
return ;
176
216
177
217
switch ( e . type ) {
178
218
case 'focus' :
179
219
case 'focusin' :
180
- LiveCodeEvents . _postKeyFocus ( stack , true ) ;
181
-
182
- // direct key events to input element
183
- LiveCodeEvents . _inputelement . focus ( ) ;
220
+ LiveCodeEvents . _setInputFocus ( e . target ) ;
184
221
break ;
185
222
case 'blur' :
186
223
case 'focusout' :
187
- LiveCodeEvents . _postKeyFocus ( stack , false ) ;
224
+ // ignore passing focus to hidden input field
225
+ if ( e . relatedTarget == LiveCodeEvents . _inputelement )
226
+ return ;
227
+
228
+ // if losing focus to another LC stack don't remove focus here, as focus will
229
+ // be reassigned in the 'focusin' event sent to that stack canvas
230
+ var tFocusStack = LiveCodeEvents . _getStackForCanvas ( e . relatedTarget ) ;
231
+ if ( tFocusStack != null )
232
+ return ;
233
+
234
+ LiveCodeEvents . _setInputFocus ( null ) ;
188
235
break ;
189
236
default :
190
237
console . debug ( 'Unexpected focus event type: ' + e . type ) ;
@@ -531,14 +578,14 @@ mergeInto(LibraryManager.library, {
531
578
[ stack , modifiers , char_code , key_code , key_state ] ) ;
532
579
} ,
533
580
534
- _handleKeyboardEvent : function ( e , pCanvas ) {
581
+ _handleKeyboardEvent : function ( e ) {
535
582
LiveCodeAsync . delay ( function ( ) {
536
583
537
584
const kKeyStateDown = 0 ;
538
585
const kKeyStateUp = 1 ;
539
586
const kKeyStatePressed = 2 ;
540
587
541
- var stack = LiveCodeEvents . _getStackForCanvas ( pCanvas ) ;
588
+ var stack = LiveCodeEvents . _getStackForCanvas ( LiveCodeEvents . _inputtarget ) ;
542
589
/* TODO - reenable alt key detection
543
590
* As there is no direct way to tell the difference between an alt+<key>
544
591
* combination that produces a different character, and holding alt down
@@ -603,7 +650,7 @@ mergeInto(LibraryManager.library, {
603
650
[ stack , enabled , offset , chars , length ] ) ;
604
651
} ,
605
652
606
- _handleInput : function ( inputEvent , pCanvas ) {
653
+ _handleInput : function ( inputEvent ) {
607
654
console . debug ( 'Input event: ' + inputEvent . type + ' ' + inputEvent . data ) ;
608
655
} ,
609
656
@@ -612,15 +659,16 @@ mergeInto(LibraryManager.library, {
612
659
return [ buffer , string . length ] ;
613
660
} ,
614
661
615
- _handleComposition : function ( compositionEvent , pCanvas ) {
662
+ _handleComposition : function ( compositionEvent ) {
616
663
LiveCodeAsync . delay ( function ( ) {
617
664
// Stack that we're targeting
618
- var stack = LiveCodeEvents . _getStackForCanvas ( pCanvas ) ;
665
+ var stack = LiveCodeEvents . _getStackForCanvas ( LiveCodeEvents . _inputtarget ) ;
619
666
620
667
// ignore events for non-lc elements
621
668
if ( ! stack )
622
669
return ;
623
670
671
+ console . log ( 'composition event: ' + compositionEvent . type + " '" + compositionEvent . data + "'" ) ;
624
672
var encodedString ;
625
673
var chars , length ;
626
674
switch ( compositionEvent . type ) {
@@ -759,7 +807,8 @@ mergeInto(LibraryManager.library, {
759
807
case 'mousedown' :
760
808
// In the case of mouse down, specifically request
761
809
// keyboard focus
762
- e . target . focus ( ) ;
810
+ LiveCodeEvents . _setInputFocus ( target ) ;
811
+
763
812
LiveCodeEvents . _postMousePosition ( stack , e . timeStamp , mods , pos [ 0 ] , pos [ 1 ] ) ;
764
813
var state = LiveCodeEvents . _encodeMouseState ( e . type ) ;
765
814
LiveCodeEvents . _postMousePress ( stack , e . timeStamp , mods ,
0 commit comments