317 lines
12 KiB
Java
317 lines
12 KiB
Java
package com.warren.iwanttoheal;
|
|
|
|
import android.app.Presentation;
|
|
import android.content.Context;
|
|
import android.graphics.Color;
|
|
import android.hardware.display.DisplayManager;
|
|
import android.os.Bundle;
|
|
import android.view.Display;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.webkit.WebResourceRequest;
|
|
import android.webkit.WebResourceResponse;
|
|
import android.webkit.WebSettings;
|
|
import android.webkit.WebView;
|
|
import android.webkit.WebViewClient;
|
|
import android.widget.FrameLayout;
|
|
import com.getcapacitor.JSArray;
|
|
import com.getcapacitor.JSObject;
|
|
import com.getcapacitor.Plugin;
|
|
import com.getcapacitor.PluginCall;
|
|
import com.getcapacitor.PluginMethod;
|
|
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
|
|
@CapacitorPlugin(name = "DualScreen")
|
|
public class DualScreenPlugin extends Plugin {
|
|
|
|
private TopDisplayPresentation presentation;
|
|
|
|
@PluginMethod
|
|
public void getDisplays(PluginCall call) {
|
|
DisplayManager displayManager =
|
|
(DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE);
|
|
Display currentDisplay = getActivity().getDisplay();
|
|
JSArray displays = new JSArray();
|
|
|
|
for (Display display : displayManager.getDisplays()) {
|
|
displays.put(describeDisplay(display, currentDisplay));
|
|
}
|
|
|
|
JSObject result = new JSObject();
|
|
result.put("currentDisplayId", currentDisplay == null ? -1 : currentDisplay.getDisplayId());
|
|
result.put("displays", displays);
|
|
call.resolve(result);
|
|
}
|
|
|
|
@PluginMethod
|
|
public void openTopDisplay(PluginCall call) {
|
|
getActivity().runOnUiThread(() -> {
|
|
try {
|
|
DisplayLaunchPlan launchPlan = createLaunchPlan(call.getInt("displayId"));
|
|
if (launchPlan.targetDisplay == null) {
|
|
call.reject("No secondary Android display is available.");
|
|
return;
|
|
}
|
|
|
|
Display currentDisplay = getActivity().getDisplay();
|
|
if (
|
|
currentDisplay != null
|
|
&& currentDisplay.getDisplayId() == launchPlan.targetDisplay.getDisplayId()
|
|
) {
|
|
JSObject result = describeDisplay(currentDisplay, currentDisplay);
|
|
result.put("opened", true);
|
|
result.put("alreadyOnMainDisplay", true);
|
|
call.resolve(result);
|
|
return;
|
|
}
|
|
|
|
String gameUrl = bridge.getLocalUrl();
|
|
String topGameUrl = gameUrl + "/?display=top";
|
|
String controlsUrl = gameUrl + "/?display=bottom";
|
|
String targetUrl = launchPlan.targetIsTopDisplay ? topGameUrl : controlsUrl;
|
|
String currentUrl = launchPlan.currentIsTopDisplay ? topGameUrl : controlsUrl;
|
|
|
|
closePresentation();
|
|
presentation = new TopDisplayPresentation(
|
|
getActivity(),
|
|
launchPlan.targetDisplay,
|
|
targetUrl
|
|
);
|
|
presentation.setOnDismissListener(dialog -> {
|
|
presentation = null;
|
|
notifyListeners("displayDisconnected", new JSObject());
|
|
});
|
|
presentation.show();
|
|
bridge.getWebView().loadUrl(currentUrl);
|
|
|
|
JSObject result = describeDisplay(launchPlan.targetDisplay, getActivity().getDisplay());
|
|
result.put("opened", true);
|
|
result.put("presentationMode", true);
|
|
result.put("targetIsTopDisplay", launchPlan.targetIsTopDisplay);
|
|
result.put("currentIsTopDisplay", launchPlan.currentIsTopDisplay);
|
|
call.resolve(result);
|
|
} catch (Exception exception) {
|
|
closePresentation();
|
|
call.reject("Unable to open the upper display.", exception);
|
|
}
|
|
});
|
|
}
|
|
|
|
@PluginMethod
|
|
public void closeTopDisplay(PluginCall call) {
|
|
getActivity().runOnUiThread(() -> {
|
|
closePresentation();
|
|
call.resolve();
|
|
});
|
|
}
|
|
|
|
@Override
|
|
protected void handleOnDestroy() {
|
|
closePresentation();
|
|
}
|
|
|
|
private DisplayLaunchPlan createLaunchPlan(Integer requestedDisplayId) {
|
|
DisplayManager displayManager =
|
|
(DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE);
|
|
Display currentDisplay = getActivity().getDisplay();
|
|
int currentDisplayId = currentDisplay == null ? -1 : currentDisplay.getDisplayId();
|
|
Display topDisplay = largestDisplay(displayManager.getDisplays());
|
|
boolean currentIsTopDisplay =
|
|
topDisplay != null && topDisplay.getDisplayId() == currentDisplayId;
|
|
Display targetDisplay = null;
|
|
|
|
if (requestedDisplayId != null) {
|
|
Display requested = displayManager.getDisplay(requestedDisplayId);
|
|
if (
|
|
requested != null
|
|
&& requested.getDisplayId() != currentDisplayId
|
|
&& requested.getState() != Display.STATE_OFF
|
|
) {
|
|
targetDisplay = requested;
|
|
}
|
|
}
|
|
|
|
if (targetDisplay == null && currentIsTopDisplay) {
|
|
targetDisplay = smallestOtherDisplay(displayManager.getDisplays(), currentDisplayId);
|
|
}
|
|
|
|
if (targetDisplay == null && topDisplay != null && topDisplay.getDisplayId() != currentDisplayId) {
|
|
targetDisplay = topDisplay;
|
|
}
|
|
|
|
if (targetDisplay == null) {
|
|
targetDisplay = largestOtherDisplay(
|
|
displayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION),
|
|
currentDisplayId
|
|
);
|
|
}
|
|
|
|
if (targetDisplay == null) {
|
|
targetDisplay = largestOtherDisplay(displayManager.getDisplays(), currentDisplayId);
|
|
}
|
|
|
|
boolean targetIsTopDisplay =
|
|
topDisplay != null && targetDisplay != null
|
|
&& targetDisplay.getDisplayId() == topDisplay.getDisplayId();
|
|
return new DisplayLaunchPlan(targetDisplay, targetIsTopDisplay, currentIsTopDisplay);
|
|
}
|
|
|
|
private Display largestDisplay(Display[] displays) {
|
|
Display selected = null;
|
|
long selectedPixels = -1;
|
|
for (Display display : displays) {
|
|
if (display.getState() == Display.STATE_OFF) continue;
|
|
long pixels = pixelCount(display);
|
|
if (pixels > selectedPixels) {
|
|
selected = display;
|
|
selectedPixels = pixels;
|
|
}
|
|
}
|
|
return selected;
|
|
}
|
|
|
|
private Display largestOtherDisplay(Display[] displays, int currentDisplayId) {
|
|
Display selected = null;
|
|
long selectedPixels = -1;
|
|
for (Display display : displays) {
|
|
if (
|
|
display.getDisplayId() == currentDisplayId
|
|
|| display.getState() == Display.STATE_OFF
|
|
) {
|
|
continue;
|
|
}
|
|
long pixels = pixelCount(display);
|
|
if (pixels > selectedPixels) {
|
|
selected = display;
|
|
selectedPixels = pixels;
|
|
}
|
|
}
|
|
return selected;
|
|
}
|
|
|
|
private Display smallestOtherDisplay(Display[] displays, int currentDisplayId) {
|
|
Display selected = null;
|
|
long selectedPixels = Long.MAX_VALUE;
|
|
for (Display display : displays) {
|
|
if (
|
|
display.getDisplayId() == currentDisplayId
|
|
|| display.getState() == Display.STATE_OFF
|
|
) {
|
|
continue;
|
|
}
|
|
long pixels = pixelCount(display);
|
|
if (pixels < selectedPixels) {
|
|
selected = display;
|
|
selectedPixels = pixels;
|
|
}
|
|
}
|
|
return selected;
|
|
}
|
|
|
|
private long pixelCount(Display display) {
|
|
Display.Mode mode = display.getMode();
|
|
return (long) mode.getPhysicalWidth() * mode.getPhysicalHeight();
|
|
}
|
|
|
|
private JSObject describeDisplay(Display display, Display currentDisplay) {
|
|
Display.Mode mode = display.getMode();
|
|
JSObject result = new JSObject();
|
|
result.put("id", display.getDisplayId());
|
|
result.put("name", display.getName());
|
|
result.put("width", mode.getPhysicalWidth());
|
|
result.put("height", mode.getPhysicalHeight());
|
|
result.put("refreshRate", mode.getRefreshRate());
|
|
result.put(
|
|
"isCurrent",
|
|
currentDisplay != null && currentDisplay.getDisplayId() == display.getDisplayId()
|
|
);
|
|
result.put(
|
|
"isPresentation",
|
|
(display.getFlags() & Display.FLAG_PRESENTATION) == Display.FLAG_PRESENTATION
|
|
);
|
|
return result;
|
|
}
|
|
|
|
private void closePresentation() {
|
|
if (presentation == null) return;
|
|
presentation.setOnDismissListener(null);
|
|
presentation.dismiss();
|
|
presentation = null;
|
|
}
|
|
|
|
private final class DisplayLaunchPlan {
|
|
|
|
private final Display targetDisplay;
|
|
private final boolean targetIsTopDisplay;
|
|
private final boolean currentIsTopDisplay;
|
|
|
|
DisplayLaunchPlan(
|
|
Display targetDisplay,
|
|
boolean targetIsTopDisplay,
|
|
boolean currentIsTopDisplay
|
|
) {
|
|
this.targetDisplay = targetDisplay;
|
|
this.targetIsTopDisplay = targetIsTopDisplay;
|
|
this.currentIsTopDisplay = currentIsTopDisplay;
|
|
}
|
|
}
|
|
|
|
private final class TopDisplayPresentation extends Presentation {
|
|
|
|
private final String initialUrl;
|
|
|
|
TopDisplayPresentation(Context context, Display display, String initialUrl) {
|
|
super(context, display);
|
|
this.initialUrl = initialUrl;
|
|
}
|
|
|
|
@Override
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
getWindow().setBackgroundDrawableResource(android.R.color.black);
|
|
getWindow().getDecorView().setSystemUiVisibility(
|
|
View.SYSTEM_UI_FLAG_FULLSCREEN
|
|
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
|
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
|
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
|
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
|
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
|
);
|
|
|
|
FrameLayout container = new FrameLayout(getContext());
|
|
container.setBackgroundColor(Color.BLACK);
|
|
WebView webView = new WebView(getContext());
|
|
configureWebView(webView);
|
|
container.addView(
|
|
webView,
|
|
new FrameLayout.LayoutParams(
|
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
ViewGroup.LayoutParams.MATCH_PARENT
|
|
)
|
|
);
|
|
setContentView(container);
|
|
webView.loadUrl(initialUrl);
|
|
}
|
|
}
|
|
|
|
private void configureWebView(WebView webView) {
|
|
WebSettings settings = webView.getSettings();
|
|
settings.setJavaScriptEnabled(true);
|
|
settings.setDomStorageEnabled(true);
|
|
settings.setDatabaseEnabled(true);
|
|
settings.setMediaPlaybackRequiresUserGesture(false);
|
|
settings.setAllowFileAccess(true);
|
|
settings.setAllowContentAccess(true);
|
|
webView.setBackgroundColor(Color.BLACK);
|
|
webView.setWebViewClient(new WebViewClient() {
|
|
@Override
|
|
public WebResourceResponse shouldInterceptRequest(
|
|
WebView view,
|
|
WebResourceRequest request
|
|
) {
|
|
return bridge.getLocalServer().shouldInterceptRequest(request);
|
|
}
|
|
});
|
|
}
|
|
}
|