Skip to content

Commit 935b7de

Browse files
committed
Add ExtraWindowEventListener interface
1 parent 41a1941 commit 935b7de

4 files changed

Lines changed: 86 additions & 0 deletions

File tree

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
package com.facebook.react.bridge
9+
10+
import android.view.Window
11+
12+
/**
13+
* Listener for receiving extra window creation and destruction events.
14+
*
15+
* This allows modules to react to new windows being added or removed, such as Dialog windows
16+
* registered by Modal components. Modules like StatusBarModule can implement this interface to
17+
* apply their configuration to all active windows.
18+
*
19+
* Third-party libraries can both implement this listener and emit window events through
20+
* [ReactContext.onExtraWindowCreate] and [ReactContext.onExtraWindowDestroy].
21+
*/
22+
public interface ExtraWindowEventListener {
23+
24+
/** Called when a new [Window] is created (e.g. a Dialog window for a Modal). */
25+
public fun onExtraWindowCreate(window: Window)
26+
27+
/** Called when a [Window] is destroyed (e.g. on Dialog window dismiss). */
28+
public fun onExtraWindowDestroy(window: Window)
29+
}

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import android.content.Intent;
1616
import android.os.Bundle;
1717
import android.view.LayoutInflater;
18+
import android.view.Window;
1819
import androidx.annotation.NonNull;
1920
import androidx.annotation.Nullable;
2021
import com.facebook.common.logging.FLog;
@@ -48,6 +49,8 @@ public interface RCTDeviceEventEmitter extends JavaScriptModule {
4849
new CopyOnWriteArraySet<>();
4950
private final CopyOnWriteArraySet<ActivityEventListener> mActivityEventListeners =
5051
new CopyOnWriteArraySet<>();
52+
private final CopyOnWriteArraySet<ExtraWindowEventListener> mExtraWindowEventListeners =
53+
new CopyOnWriteArraySet<>();
5154
private final CopyOnWriteArraySet<WindowFocusChangeListener> mWindowFocusEventListeners =
5255
new CopyOnWriteArraySet<>();
5356
private final ScrollEndedListeners mScrollEndedListeners = new ScrollEndedListeners();
@@ -246,6 +249,14 @@ public void removeActivityEventListener(ActivityEventListener listener) {
246249
mActivityEventListeners.remove(listener);
247250
}
248251

252+
public void addExtraWindowEventListener(ExtraWindowEventListener listener) {
253+
mExtraWindowEventListeners.add(listener);
254+
}
255+
256+
public void removeExtraWindowEventListener(ExtraWindowEventListener listener) {
257+
mExtraWindowEventListeners.remove(listener);
258+
}
259+
249260
public void addWindowFocusChangeListener(WindowFocusChangeListener listener) {
250261
mWindowFocusEventListeners.add(listener);
251262
}
@@ -356,6 +367,30 @@ public void onActivityResult(
356367
}
357368
}
358369

370+
@ThreadConfined(UI)
371+
public void onExtraWindowCreate(Window window) {
372+
UiThreadUtil.assertOnUiThread();
373+
for (ExtraWindowEventListener listener : mExtraWindowEventListeners) {
374+
try {
375+
listener.onExtraWindowCreate(window);
376+
} catch (RuntimeException e) {
377+
handleException(e);
378+
}
379+
}
380+
}
381+
382+
@ThreadConfined(UI)
383+
public void onExtraWindowDestroy(Window window) {
384+
UiThreadUtil.assertOnUiThread();
385+
for (ExtraWindowEventListener listener : mExtraWindowEventListeners) {
386+
try {
387+
listener.onExtraWindowDestroy(window);
388+
} catch (RuntimeException e) {
389+
handleException(e);
390+
}
391+
}
392+
}
393+
359394
@ThreadConfined(UI)
360395
public void onWindowFocusChange(boolean hasFocus) {
361396
UiThreadUtil.assertOnUiThread();

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ package com.facebook.react.uimanager
1111

1212
import android.app.Activity
1313
import android.content.Context
14+
import android.view.Window
1415
import com.facebook.react.bridge.Callback
1516
import com.facebook.react.bridge.CatalystInstance
17+
import com.facebook.react.bridge.ExtraWindowEventListener
1618
import com.facebook.react.bridge.JavaScriptContextHolder
1719
import com.facebook.react.bridge.JavaScriptModule
1820
import com.facebook.react.bridge.LifecycleEventListener
@@ -67,6 +69,22 @@ public class ThemedReactContext(
6769
reactApplicationContext.removeLifecycleEventListener(listener)
6870
}
6971

72+
override fun addExtraWindowEventListener(listener: ExtraWindowEventListener) {
73+
reactApplicationContext.addExtraWindowEventListener(listener)
74+
}
75+
76+
override fun removeExtraWindowEventListener(listener: ExtraWindowEventListener) {
77+
reactApplicationContext.removeExtraWindowEventListener(listener)
78+
}
79+
80+
override fun onExtraWindowCreate(window: Window) {
81+
reactApplicationContext.onExtraWindowCreate(window)
82+
}
83+
84+
override fun onExtraWindowDestroy(window: Window) {
85+
reactApplicationContext.onExtraWindowDestroy(window)
86+
}
87+
7088
override fun hasCurrentActivity(): Boolean = reactApplicationContext.hasCurrentActivity()
7189

7290
override fun getCurrentActivity(): Activity? = reactApplicationContext.getCurrentActivity()

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,9 @@ public class ReactModalHostView(context: ThemedReactContext) :
196196
UiThreadUtil.assertOnUiThread()
197197

198198
dialog?.let { nonNullDialog ->
199+
nonNullDialog.window?.let { window ->
200+
(context as ThemedReactContext).onExtraWindowDestroy(window)
201+
}
199202
if (nonNullDialog.isShowing) {
200203
val dialogContext =
201204
ContextUtils.findContextOfType(nonNullDialog.context, Activity::class.java)
@@ -341,6 +344,7 @@ public class ReactModalHostView(context: ThemedReactContext) :
341344
newDialog.show()
342345
updateSystemAppearance()
343346
window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
347+
(context as ThemedReactContext).onExtraWindowCreate(window)
344348
}
345349
}
346350

0 commit comments

Comments
 (0)