@@ -363,13 +363,15 @@ export default class ScrollableTerminal extends React.PureComponent<Props, State
363
363
remove : undefined ,
364
364
clear : undefined ,
365
365
onClick : undefined ,
366
+ onMouseDown : undefined ,
366
367
onFocus : undefined ,
367
368
onOutputRender : undefined ,
368
369
navigateTo : undefined ,
369
370
setActiveBlock : undefined ,
370
371
willFocusBlock : undefined ,
371
372
willRemoveBlock : undefined ,
372
- willUpdateCommand : undefined
373
+ willUpdateCommand : undefined ,
374
+ tabRefFor : undefined
373
375
}
374
376
375
377
const getBlockIndexFromEvent = ( evt : React . SyntheticEvent , doNotComplain = false ) => {
@@ -386,26 +388,33 @@ export default class ScrollableTerminal extends React.PureComponent<Props, State
386
388
387
389
state . remove = ( ) => this . removeSplit ( sbuuid )
388
390
state . clear = ( ) => this . clear ( sbuuid )
391
+
392
+ /**
393
+ * For inline-input clients, we want empty-space clicks to steal
394
+ * focus away from the other split, if we are switching splits;
395
+ * otherwise, we don't want empty-space clicks in the focused
396
+ * split to steal focus away from that split's active input
397
+ */
389
398
state . onClick = ( ) => {
390
399
if ( getSelectionText ( ) . length === 0 ) {
391
- const sbidx = this . findSplit ( this . state , sbuuid )
392
- if ( sbidx >= 0 ) {
393
- const scrollback = this . state . splits [ sbidx ]
394
- this . doFocus ( scrollback )
395
- }
400
+ this . doFocus ( state )
396
401
}
397
402
}
398
403
404
+ /**
405
+ * For bottom-input clients, we don't want empty-space clicks to
406
+ * steal focus away from the bottom input
407
+ */
408
+ state . onMouseDown = ( evt : React . MouseEvent < HTMLElement > ) => {
409
+ evt . preventDefault ( )
410
+ }
411
+
399
412
/** Output.tsx finished rendering something */
400
413
state . onOutputRender = ( ) => {
401
414
if ( ! this . props . noActiveInput ) {
402
415
// if we are using inline input, then scroll to the bottom
403
416
// whenever an output is rendered in this split
404
- const sbidx = this . findSplit ( this . state , sbuuid )
405
- if ( sbidx >= 0 ) {
406
- const scrollback = this . state . splits [ sbidx ]
407
- setTimeout ( ( ) => scrollback . facade . scrollToBottom ( ) )
408
- }
417
+ setTimeout ( ( ) => state . facade . scrollToBottom ( ) )
409
418
}
410
419
}
411
420
@@ -517,6 +526,34 @@ export default class ScrollableTerminal extends React.PureComponent<Props, State
517
526
}
518
527
}
519
528
529
+ state . tabRefFor = ( ref : HTMLElement ) => {
530
+ const scrollback = state
531
+ if ( ref ) {
532
+ ref [ 'facade' ] = scrollback . facade
533
+ scrollback . facade . getSize = getSize . bind ( ref )
534
+
535
+ scrollback . facade . splitCount = ( ) => this . state . splits . length
536
+ scrollback . facade . hasSideBySideTerminals = ( ) => {
537
+ return ! ! this . state . splits . find ( ( _ , sbidx ) => this . isASideBySide ( sbidx ) )
538
+ }
539
+
540
+ scrollback . facade . scrollToBottom = ( ) => {
541
+ ref . scrollTop = ref . scrollHeight
542
+ }
543
+
544
+ scrollback . facade . scrollToTop = ( ) => {
545
+ ref . scrollTop = 0
546
+ }
547
+
548
+ scrollback . facade . addClass = ( cls : string ) => {
549
+ ref . classList . add ( cls )
550
+ }
551
+ scrollback . facade . removeClass = ( cls : string ) => {
552
+ ref . classList . remove ( cls )
553
+ }
554
+ }
555
+ }
556
+
520
557
// prefetch command history; this helps with master history
521
558
History ( sbuuid )
522
559
@@ -1115,33 +1152,6 @@ export default class ScrollableTerminal extends React.PureComponent<Props, State
1115
1152
return this . theseAreSideBySide [ this . state . splits . length ] [ sbidx ]
1116
1153
}
1117
1154
1118
- private tabRefFor ( scrollback : ScrollbackState , ref : HTMLElement ) {
1119
- if ( ref ) {
1120
- ref [ 'facade' ] = scrollback . facade
1121
- scrollback . facade . getSize = getSize . bind ( ref )
1122
-
1123
- scrollback . facade . splitCount = ( ) => this . state . splits . length
1124
- scrollback . facade . hasSideBySideTerminals = ( ) => {
1125
- return ! ! this . state . splits . find ( ( _ , sbidx ) => this . isASideBySide ( sbidx ) )
1126
- }
1127
-
1128
- scrollback . facade . scrollToBottom = ( ) => {
1129
- ref . scrollTop = ref . scrollHeight
1130
- }
1131
-
1132
- scrollback . facade . scrollToTop = ( ) => {
1133
- ref . scrollTop = 0
1134
- }
1135
-
1136
- scrollback . facade . addClass = ( cls : string ) => {
1137
- ref . classList . add ( cls )
1138
- }
1139
- scrollback . facade . removeClass = ( cls : string ) => {
1140
- ref . classList . remove ( cls )
1141
- }
1142
- }
1143
- }
1144
-
1145
1155
private tabFor ( scrollback : ScrollbackState ) : KuiTab {
1146
1156
if ( ! scrollback . facade ) {
1147
1157
const { uuid } = scrollback
@@ -1308,8 +1318,9 @@ export default class ScrollableTerminal extends React.PureComponent<Props, State
1308
1318
data-is-focused = { sbidx === this . state . focusedIdx || undefined }
1309
1319
key = { tab . uuid }
1310
1320
data-scrollback-id = { tab . uuid }
1311
- ref = { ref => this . tabRefFor ( scrollback , ref ) }
1312
- onClick = { scrollback . onClick }
1321
+ ref = { scrollback . tabRefFor }
1322
+ onClick = { ! this . props . noActiveInput ? scrollback . onClick : undefined }
1323
+ onMouseDown = { this . props . noActiveInput ? scrollback . onMouseDown : undefined }
1313
1324
>
1314
1325
< React . Fragment >
1315
1326
{ this . state . splits . length > 1 && < SplitHeader onRemove = { scrollback . remove } onClear = { scrollback . clear } /> }
0 commit comments