@capgo/capacitor-screen-orientation 8.1.21 → 8.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +347 -9
- package/android/build.gradle +2 -0
- package/android/src/main/java/ee/forgr/capacitor/screenorientation/CapacitorScreenOrientationPlugin.java +211 -1
- package/android/src/main/java/ee/forgr/capacitor/screenorientation/FoldLayout.java +176 -0
- package/dist/docs.json +809 -37
- package/dist/esm/definitions.d.ts +375 -0
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +15 -1
- package/dist/esm/web.js +52 -0
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +54 -1
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +54 -1
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/CapacitorScreenOrientationPlugin/CapacitorScreenOrientationPlugin.swift +128 -1
- package/ios/Sources/CapacitorScreenOrientationPlugin/IPhoneDuoFold.swift +258 -0
- package/package.json +1 -1
|
@@ -7,23 +7,60 @@ import android.hardware.Sensor;
|
|
|
7
7
|
import android.hardware.SensorEvent;
|
|
8
8
|
import android.hardware.SensorEventListener;
|
|
9
9
|
import android.hardware.SensorManager;
|
|
10
|
+
import android.os.Build;
|
|
11
|
+
import android.os.Handler;
|
|
12
|
+
import android.os.Looper;
|
|
10
13
|
import android.view.Surface;
|
|
11
14
|
import com.getcapacitor.JSObject;
|
|
12
15
|
import com.getcapacitor.Plugin;
|
|
13
16
|
import com.getcapacitor.PluginCall;
|
|
14
17
|
import com.getcapacitor.PluginMethod;
|
|
15
18
|
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
19
|
+
import java.util.ArrayList;
|
|
20
|
+
import java.util.List;
|
|
21
|
+
import java.util.concurrent.Executor;
|
|
22
|
+
import org.json.JSONObject;
|
|
16
23
|
|
|
17
24
|
@CapacitorPlugin(name = "CapacitorScreenOrientation")
|
|
18
25
|
public class CapacitorScreenOrientationPlugin extends Plugin implements SensorEventListener {
|
|
19
26
|
|
|
20
|
-
private final String pluginVersion = "8.
|
|
27
|
+
private final String pluginVersion = "8.3.0";
|
|
21
28
|
private int currentOrientation;
|
|
22
29
|
private SensorManager sensorManager;
|
|
23
30
|
private Sensor accelerometer;
|
|
24
31
|
private boolean isTrackingMotion = false;
|
|
25
32
|
private String currentPhysicalOrientation = "portrait-primary";
|
|
26
33
|
private String lastNotifiedOrientation = null;
|
|
34
|
+
private FoldLayout foldLayout;
|
|
35
|
+
private Sensor hingeSensor;
|
|
36
|
+
private boolean hingeRegistered = false;
|
|
37
|
+
private Float lastHingeAngle = null;
|
|
38
|
+
private String lastSizeClassKey = null;
|
|
39
|
+
private final List<PluginCall> pendingHingeCalls = new ArrayList<>();
|
|
40
|
+
private final Handler mainHandler = new Handler(Looper.getMainLooper());
|
|
41
|
+
private final SensorEventListener hingeListener = new SensorEventListener() {
|
|
42
|
+
@Override
|
|
43
|
+
public void onSensorChanged(SensorEvent event) {
|
|
44
|
+
if (event.values.length == 0) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
float angle = Math.max(0f, Math.min(360f, event.values[0]));
|
|
48
|
+
boolean unchanged = lastHingeAngle != null && Math.abs(lastHingeAngle - angle) < 0.5f;
|
|
49
|
+
lastHingeAngle = angle;
|
|
50
|
+
if (unchanged && pendingHingeCalls.isEmpty()) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
JSObject payload = hingePayload(angle);
|
|
54
|
+
notifyListeners("hingeAngleChange", payload);
|
|
55
|
+
resolvePendingHinge(payload);
|
|
56
|
+
if (!hasListeners("hingeAngleChange")) {
|
|
57
|
+
stopHingeTracking();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@Override
|
|
62
|
+
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
|
|
63
|
+
};
|
|
27
64
|
|
|
28
65
|
@Override
|
|
29
66
|
public void load() {
|
|
@@ -34,12 +71,26 @@ public class CapacitorScreenOrientationPlugin extends Plugin implements SensorEv
|
|
|
34
71
|
sensorManager = (SensorManager) getActivity().getSystemService(Context.SENSOR_SERVICE);
|
|
35
72
|
if (sensorManager != null) {
|
|
36
73
|
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
|
74
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
75
|
+
hingeSensor = sensorManager.getDefaultSensor(Sensor.TYPE_HINGE_ANGLE);
|
|
76
|
+
}
|
|
37
77
|
}
|
|
78
|
+
|
|
79
|
+
Executor executor = mainHandler::post;
|
|
80
|
+
foldLayout = new FoldLayout(getActivity(), bridge.getWebView(), executor, (state) -> {
|
|
81
|
+
notifyListeners("foldStateChange", state);
|
|
82
|
+
notifySizeClassIfChanged();
|
|
83
|
+
});
|
|
84
|
+
notifySizeClassIfChanged();
|
|
38
85
|
}
|
|
39
86
|
|
|
40
87
|
@Override
|
|
41
88
|
protected void handleOnDestroy() {
|
|
42
89
|
stopMotionTracking();
|
|
90
|
+
stopHingeTracking();
|
|
91
|
+
if (foldLayout != null) {
|
|
92
|
+
foldLayout.stop();
|
|
93
|
+
}
|
|
43
94
|
super.handleOnDestroy();
|
|
44
95
|
}
|
|
45
96
|
|
|
@@ -47,6 +98,8 @@ public class CapacitorScreenOrientationPlugin extends Plugin implements SensorEv
|
|
|
47
98
|
protected void handleOnConfigurationChanged(Configuration newConfig) {
|
|
48
99
|
super.handleOnConfigurationChanged(newConfig);
|
|
49
100
|
|
|
101
|
+
notifySizeClassIfChanged();
|
|
102
|
+
|
|
50
103
|
// Skip system orientation changes when motion tracking is active
|
|
51
104
|
// to avoid duplicate events
|
|
52
105
|
if (isTrackingMotion) {
|
|
@@ -59,6 +112,101 @@ public class CapacitorScreenOrientationPlugin extends Plugin implements SensorEv
|
|
|
59
112
|
}
|
|
60
113
|
}
|
|
61
114
|
|
|
115
|
+
@PluginMethod(returnType = PluginMethod.RETURN_NONE)
|
|
116
|
+
@Override
|
|
117
|
+
public void addListener(PluginCall call) {
|
|
118
|
+
super.addListener(call);
|
|
119
|
+
String eventName = call.getString("eventName");
|
|
120
|
+
if ("hingeAngleChange".equals(eventName)) {
|
|
121
|
+
mainHandler.post(this::startHingeTracking);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@PluginMethod(returnType = PluginMethod.RETURN_NONE)
|
|
126
|
+
@Override
|
|
127
|
+
public void removeListener(PluginCall call) {
|
|
128
|
+
super.removeListener(call);
|
|
129
|
+
if (!hasListeners("hingeAngleChange")) {
|
|
130
|
+
mainHandler.post(this::stopHingeTracking);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@PluginMethod
|
|
135
|
+
@Override
|
|
136
|
+
public void removeAllListeners(PluginCall call) {
|
|
137
|
+
super.removeAllListeners(call);
|
|
138
|
+
mainHandler.post(this::stopHingeTracking);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@PluginMethod
|
|
142
|
+
public void isDeviceFoldable(PluginCall call) {
|
|
143
|
+
JSObject result = new JSObject();
|
|
144
|
+
result.put("foldable", foldLayout != null && foldLayout.isFoldable());
|
|
145
|
+
result.put("supportsTabletop", foldLayout != null && foldLayout.supportsTabletop());
|
|
146
|
+
call.resolve(result);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
@PluginMethod
|
|
150
|
+
public void getFoldState(PluginCall call) {
|
|
151
|
+
call.resolve(foldLayout == null ? flatFold() : foldLayout.currentState());
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
@PluginMethod
|
|
155
|
+
public void getHingeAngle(PluginCall call) {
|
|
156
|
+
mainHandler.post(() -> {
|
|
157
|
+
if (hingeRegistered && lastHingeAngle != null) {
|
|
158
|
+
call.resolve(hingePayload(lastHingeAngle));
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (hingeSensor == null) {
|
|
162
|
+
call.resolve(hingePayload(null));
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
pendingHingeCalls.add(call);
|
|
166
|
+
startHingeTracking();
|
|
167
|
+
mainHandler.postDelayed(
|
|
168
|
+
() -> {
|
|
169
|
+
if (!pendingHingeCalls.contains(call)) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
pendingHingeCalls.remove(call);
|
|
173
|
+
call.resolve(hingePayload(null));
|
|
174
|
+
if (!hasListeners("hingeAngleChange") && pendingHingeCalls.isEmpty()) {
|
|
175
|
+
stopHingeTracking();
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
800
|
|
179
|
+
);
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
@PluginMethod
|
|
184
|
+
public void getSizeClass(PluginCall call) {
|
|
185
|
+
call.resolve(currentSizeClass());
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
@PluginMethod
|
|
189
|
+
public void getReservedRegions(PluginCall call) {
|
|
190
|
+
JSObject result = new JSObject();
|
|
191
|
+
result.put("regions", new org.json.JSONArray());
|
|
192
|
+
call.resolve(result);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
@PluginMethod
|
|
196
|
+
public void getBarPlacement(PluginCall call) {
|
|
197
|
+
JSObject result = new JSObject();
|
|
198
|
+
result.put("verticalBarEdge", JSONObject.NULL);
|
|
199
|
+
result.put("inset", 0);
|
|
200
|
+
call.resolve(result);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@PluginMethod
|
|
204
|
+
public void setVerticalBarBehavior(PluginCall call) {
|
|
205
|
+
JSObject result = new JSObject();
|
|
206
|
+
result.put("applied", false);
|
|
207
|
+
call.resolve(result);
|
|
208
|
+
}
|
|
209
|
+
|
|
62
210
|
@PluginMethod
|
|
63
211
|
public void orientation(final PluginCall call) {
|
|
64
212
|
try {
|
|
@@ -198,6 +346,68 @@ public class CapacitorScreenOrientationPlugin extends Plugin implements SensorEv
|
|
|
198
346
|
}
|
|
199
347
|
}
|
|
200
348
|
|
|
349
|
+
private JSObject currentSizeClass() {
|
|
350
|
+
if (foldLayout != null) {
|
|
351
|
+
return foldLayout.sizeClass();
|
|
352
|
+
}
|
|
353
|
+
return FoldLayout.sizeClassOf(0f, 0f);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
private void notifySizeClassIfChanged() {
|
|
357
|
+
JSObject sizeClass = currentSizeClass();
|
|
358
|
+
String key = sizeClass.toString();
|
|
359
|
+
if (key.equals(lastSizeClassKey)) {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
lastSizeClassKey = key;
|
|
363
|
+
notifyListeners("sizeClassChange", sizeClass);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
private void startHingeTracking() {
|
|
367
|
+
if (hingeRegistered || hingeSensor == null || sensorManager == null) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
hingeRegistered = true;
|
|
371
|
+
sensorManager.registerListener(hingeListener, hingeSensor, SensorManager.SENSOR_DELAY_NORMAL, mainHandler);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
private void stopHingeTracking() {
|
|
375
|
+
if (!hingeRegistered || sensorManager == null) {
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
hingeRegistered = false;
|
|
379
|
+
sensorManager.unregisterListener(hingeListener);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
private void resolvePendingHinge(JSObject payload) {
|
|
383
|
+
if (pendingHingeCalls.isEmpty()) {
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
List<PluginCall> pending = new ArrayList<>(pendingHingeCalls);
|
|
387
|
+
pendingHingeCalls.clear();
|
|
388
|
+
for (PluginCall call : pending) {
|
|
389
|
+
call.resolve(payload);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
private static JSObject hingePayload(Float angle) {
|
|
394
|
+
JSObject result = new JSObject();
|
|
395
|
+
if (angle == null) {
|
|
396
|
+
result.put("angle", JSONObject.NULL);
|
|
397
|
+
} else {
|
|
398
|
+
result.put("angle", angle.doubleValue());
|
|
399
|
+
}
|
|
400
|
+
return result;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
private static JSObject flatFold() {
|
|
404
|
+
JSObject state = new JSObject();
|
|
405
|
+
state.put("state", "flat");
|
|
406
|
+
state.put("isSeparating", false);
|
|
407
|
+
state.put("posture", "flat");
|
|
408
|
+
return state;
|
|
409
|
+
}
|
|
410
|
+
|
|
201
411
|
// Motion tracking methods
|
|
202
412
|
private void startMotionTracking() {
|
|
203
413
|
if (isTrackingMotion || accelerometer == null) {
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
package ee.forgr.capacitor.screenorientation;
|
|
2
|
+
|
|
3
|
+
import android.app.Activity;
|
|
4
|
+
import android.content.pm.PackageManager;
|
|
5
|
+
import android.graphics.Rect;
|
|
6
|
+
import android.os.Build;
|
|
7
|
+
import android.view.View;
|
|
8
|
+
import androidx.core.util.Consumer;
|
|
9
|
+
import androidx.window.java.layout.WindowInfoTrackerCallbackAdapter;
|
|
10
|
+
import androidx.window.layout.DisplayFeature;
|
|
11
|
+
import androidx.window.layout.FoldingFeature;
|
|
12
|
+
import androidx.window.layout.SupportedPosture;
|
|
13
|
+
import androidx.window.layout.WindowInfoTracker;
|
|
14
|
+
import androidx.window.layout.WindowLayoutInfo;
|
|
15
|
+
import androidx.window.layout.WindowMetricsCalculator;
|
|
16
|
+
import com.getcapacitor.JSObject;
|
|
17
|
+
import java.util.concurrent.Executor;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Reads Jetpack WindowManager fold state for the current activity.
|
|
21
|
+
* The hinge sensor itself stays in the plugin so it can run only while a listener is registered.
|
|
22
|
+
*/
|
|
23
|
+
final class FoldLayout implements Consumer<WindowLayoutInfo> {
|
|
24
|
+
|
|
25
|
+
interface Callback {
|
|
26
|
+
void onFoldState(JSObject state);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private final Activity activity;
|
|
30
|
+
private final View webView;
|
|
31
|
+
private final WindowInfoTrackerCallbackAdapter adapter;
|
|
32
|
+
private final Executor executor;
|
|
33
|
+
private final Callback callback;
|
|
34
|
+
private final boolean supportsTabletop;
|
|
35
|
+
private JSObject current = flatState();
|
|
36
|
+
private boolean sawFold = false;
|
|
37
|
+
|
|
38
|
+
FoldLayout(Activity activity, View webView, Executor executor, Callback callback) {
|
|
39
|
+
this.activity = activity;
|
|
40
|
+
this.webView = webView;
|
|
41
|
+
this.executor = executor;
|
|
42
|
+
this.callback = callback;
|
|
43
|
+
WindowInfoTracker tracker = WindowInfoTracker.getOrCreate(activity);
|
|
44
|
+
this.adapter = new WindowInfoTrackerCallbackAdapter(tracker);
|
|
45
|
+
this.supportsTabletop = supportsTabletop(tracker);
|
|
46
|
+
this.current = toFoldState(firstFold());
|
|
47
|
+
this.adapter.addWindowLayoutInfoListener(activity, executor, this);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private FoldingFeature firstFold() {
|
|
51
|
+
WindowLayoutInfo info;
|
|
52
|
+
try {
|
|
53
|
+
info = adapter.getCurrentWindowLayoutInfo(activity);
|
|
54
|
+
} catch (UnsupportedOperationException ignored) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
for (DisplayFeature feature : info.getDisplayFeatures()) {
|
|
58
|
+
if (feature instanceof FoldingFeature) {
|
|
59
|
+
sawFold = true;
|
|
60
|
+
return (FoldingFeature) feature;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
void stop() {
|
|
67
|
+
adapter.removeWindowLayoutInfoListener(this);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
JSObject currentState() {
|
|
71
|
+
return current;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
boolean isFoldable() {
|
|
75
|
+
if (sawFold || supportsTabletop) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
return (
|
|
79
|
+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R &&
|
|
80
|
+
activity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_SENSOR_HINGE_ANGLE)
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
boolean supportsTabletop() {
|
|
85
|
+
return supportsTabletop;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
JSObject sizeClass() {
|
|
89
|
+
Rect bounds = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(activity).getBounds();
|
|
90
|
+
float density = activity.getResources().getDisplayMetrics().density;
|
|
91
|
+
return sizeClassOf(bounds.width() / density, bounds.height() / density);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
static JSObject sizeClassOf(float widthDp, float heightDp) {
|
|
95
|
+
JSObject result = new JSObject();
|
|
96
|
+
result.put("horizontal", widthDp >= 600f ? "regular" : "compact");
|
|
97
|
+
result.put("vertical", heightDp >= 480f ? "regular" : "compact");
|
|
98
|
+
result.put("widthClass", widthClass(widthDp));
|
|
99
|
+
result.put("heightClass", heightDp >= 900f ? "expanded" : heightDp >= 480f ? "medium" : "compact");
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
@Override
|
|
104
|
+
public void accept(WindowLayoutInfo info) {
|
|
105
|
+
FoldingFeature fold = null;
|
|
106
|
+
for (DisplayFeature feature : info.getDisplayFeatures()) {
|
|
107
|
+
if (feature instanceof FoldingFeature) {
|
|
108
|
+
fold = (FoldingFeature) feature;
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (fold != null) {
|
|
113
|
+
sawFold = true;
|
|
114
|
+
}
|
|
115
|
+
current = toFoldState(fold);
|
|
116
|
+
callback.onFoldState(current);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private JSObject toFoldState(FoldingFeature fold) {
|
|
120
|
+
if (fold == null) {
|
|
121
|
+
return flatState();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
float density = activity.getResources().getDisplayMetrics().density;
|
|
125
|
+
int[] offset = new int[2];
|
|
126
|
+
webView.getLocationInWindow(offset);
|
|
127
|
+
JSObject bounds = boundsOf(fold.getBounds(), density, offset[0], offset[1]);
|
|
128
|
+
|
|
129
|
+
boolean halfOpened = FoldingFeature.State.HALF_OPENED.equals(fold.getState());
|
|
130
|
+
boolean horizontal = FoldingFeature.Orientation.HORIZONTAL.equals(fold.getOrientation());
|
|
131
|
+
|
|
132
|
+
JSObject state = new JSObject();
|
|
133
|
+
state.put("state", halfOpened ? "half-opened" : "flat");
|
|
134
|
+
state.put("isSeparating", fold.isSeparating());
|
|
135
|
+
state.put("posture", !halfOpened ? "flat" : horizontal ? "tabletop" : "book");
|
|
136
|
+
state.put("hingeOrientation", horizontal ? "horizontal" : "vertical");
|
|
137
|
+
state.put("hingeBounds", bounds);
|
|
138
|
+
if (FoldingFeature.OcclusionType.FULL.equals(fold.getOcclusionType())) {
|
|
139
|
+
state.put("occludedBounds", bounds);
|
|
140
|
+
}
|
|
141
|
+
return state;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private static JSObject boundsOf(Rect rect, float density, int offsetX, int offsetY) {
|
|
145
|
+
JSObject bounds = new JSObject();
|
|
146
|
+
bounds.put("x", Math.round((rect.left - offsetX) / density));
|
|
147
|
+
bounds.put("y", Math.round((rect.top - offsetY) / density));
|
|
148
|
+
bounds.put("width", Math.round(rect.width() / density));
|
|
149
|
+
bounds.put("height", Math.round(rect.height() / density));
|
|
150
|
+
return bounds;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
private static JSObject flatState() {
|
|
154
|
+
JSObject state = new JSObject();
|
|
155
|
+
state.put("state", "flat");
|
|
156
|
+
state.put("isSeparating", false);
|
|
157
|
+
state.put("posture", "flat");
|
|
158
|
+
return state;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
private static String widthClass(float widthDp) {
|
|
162
|
+
if (widthDp >= 1600f) return "extraLarge";
|
|
163
|
+
if (widthDp >= 1200f) return "large";
|
|
164
|
+
if (widthDp >= 840f) return "expanded";
|
|
165
|
+
if (widthDp >= 600f) return "medium";
|
|
166
|
+
return "compact";
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
private static boolean supportsTabletop(WindowInfoTracker tracker) {
|
|
170
|
+
try {
|
|
171
|
+
return tracker.getSupportedPostures().contains(SupportedPosture.TABLETOP);
|
|
172
|
+
} catch (RuntimeException ignored) {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|