@@ -12,6 +12,12 @@ export class FocusOriginMonitor {
12
12
/** The focus origin that the next focus event is a result of. */
13
13
private _origin : FocusOrigin = null ;
14
14
15
+ /** A WeakMap used to track the last element focused via the FocusOriginMonitor. */
16
+ private _lastFocused = new WeakMap < Element , FocusOrigin > ( ) ;
17
+
18
+ /** Whether the window has just been focused. */
19
+ private _windowFocused = false ;
20
+
15
21
constructor ( ) {
16
22
// Listen to keydown and mousedown in the capture phase so we can detect them even if the user
17
23
// stops propagation.
@@ -20,6 +26,13 @@ export class FocusOriginMonitor {
20
26
'keydown' , ( ) => this . _setOriginForCurrentEventQueue ( 'keyboard' ) , true ) ;
21
27
document . addEventListener (
22
28
'mousedown' , ( ) => this . _setOriginForCurrentEventQueue ( 'mouse' ) , true ) ;
29
+
30
+ // Make a note of when the window regains focus, so we can restore the origin info for the
31
+ // focused element.
32
+ window . addEventListener ( 'focus' , ( ) => {
33
+ this . _windowFocused = true ;
34
+ setTimeout ( ( ) => this . _windowFocused = false , 0 ) ;
35
+ } ) ;
23
36
}
24
37
25
38
/** Register an element to receive focus classes. */
@@ -44,15 +57,26 @@ export class FocusOriginMonitor {
44
57
45
58
/** Handles focus events on a registered element. */
46
59
private _onFocus ( element : Element , renderer : Renderer , subject : Subject < FocusOrigin > ) {
47
- // If we couldn't detect a cause for the focus event, assume it was due to programmatically
48
- // setting the focus.
49
- this . _origin = this . _origin || 'program' ;
60
+ // If we couldn't detect a cause for the focus event, it's due to one of two reasons:
61
+ // 1) The window has just regained focus, in which case we want to restore the focused state of
62
+ // the element from before the window blurred.
63
+ // 2) The element was programmatically focused, in which case we should mark the origin as
64
+ // 'program'.
65
+ if ( ! this . _origin ) {
66
+ if ( this . _windowFocused && this . _lastFocused . has ( element ) ) {
67
+ this . _origin = this . _lastFocused . get ( element ) ;
68
+ } else {
69
+ this . _origin = 'program' ;
70
+ }
71
+ }
50
72
51
73
renderer . setElementClass ( element , 'cdk-focused' , true ) ;
52
74
renderer . setElementClass ( element , 'cdk-keyboard-focused' , this . _origin == 'keyboard' ) ;
53
75
renderer . setElementClass ( element , 'cdk-mouse-focused' , this . _origin == 'mouse' ) ;
54
76
renderer . setElementClass ( element , 'cdk-program-focused' , this . _origin == 'program' ) ;
77
+
55
78
subject . next ( this . _origin ) ;
79
+ this . _lastFocused = new WeakMap ( ) . set ( element , this . _origin ) ;
56
80
this . _origin = null ;
57
81
}
58
82
0 commit comments