@capgo/capacitor-updater 8.48.0 → 8.49.1

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.
@@ -19,10 +19,13 @@ import android.widget.ListView;
19
19
  import android.widget.ProgressBar;
20
20
  import com.getcapacitor.Bridge;
21
21
  import com.getcapacitor.BridgeActivity;
22
+ import com.getcapacitor.JSArray;
23
+ import com.getcapacitor.JSObject;
22
24
  import java.util.ArrayList;
23
25
  import java.util.List;
24
26
  import java.util.Map;
25
27
  import org.json.JSONArray;
28
+ import org.json.JSONObject;
26
29
 
27
30
  public class ShakeMenu implements ShakeDetector.Listener, ThreeFingerPinchDetector.Listener {
28
31
 
@@ -36,11 +39,13 @@ public class ShakeMenu implements ShakeDetector.Listener, ThreeFingerPinchDetect
36
39
  private ThreeFingerPinchDetector pinchDetector;
37
40
  private boolean isShowing = false;
38
41
  private Logger logger;
42
+ private String gesture;
39
43
 
40
44
  public ShakeMenu(CapacitorUpdaterPlugin plugin, BridgeActivity activity, Logger logger, String gesture) {
41
45
  this.plugin = plugin;
42
46
  this.activity = activity;
43
47
  this.logger = logger;
48
+ this.gesture = gesture;
44
49
 
45
50
  if (CapacitorUpdaterPlugin.SHAKE_MENU_GESTURE_THREE_FINGER_PINCH.equals(gesture)) {
46
51
  this.pinchDetector = new ThreeFingerPinchDetector(this, logger);
@@ -52,6 +57,10 @@ public class ShakeMenu implements ShakeDetector.Listener, ThreeFingerPinchDetect
52
57
  }
53
58
  }
54
59
 
60
+ public boolean usesGesture(String gesture) {
61
+ return this.gesture != null && this.gesture.equals(gesture);
62
+ }
63
+
55
64
  public void stop() {
56
65
  if (shakeDetector != null) {
57
66
  shakeDetector.stop();
@@ -114,21 +123,43 @@ public class ShakeMenu implements ShakeDetector.Listener, ThreeFingerPinchDetect
114
123
  }
115
124
  String appName = activity.getPackageManager().getApplicationLabel(activity.getApplicationInfo()).toString();
116
125
  String title = "Preview " + appName + " Menu";
117
- String message = "Reload the current preview or leave the test app.";
118
- String okButtonTitle = "Leave test app";
119
- String reloadButtonTitle = "Reload app";
120
- String cancelButtonTitle = "Close menu";
126
+ String message = "Reload, switch, or leave the current preview.";
127
+ List<String> actions = new ArrayList<>();
128
+ actions.add("Reload preview");
129
+ if (plugin.previewMenuPreviews().length() > 0) {
130
+ actions.add("Switch preview");
131
+ }
132
+ actions.add("Leave test app");
133
+ final boolean[] openingNestedSelector = { false };
134
+ final boolean[] previewActionRunning = { false };
121
135
 
122
136
  AlertDialog.Builder builder = new AlertDialog.Builder(activity);
123
137
  builder.setTitle(title);
124
138
  builder.setMessage(message);
125
-
126
- builder.setPositiveButton(okButtonTitle, null);
127
- builder.setNeutralButton(reloadButtonTitle, null);
139
+ builder.setItems(actions.toArray(new String[0]), (dialogInterface, which) -> {
140
+ AlertDialog dialog = (AlertDialog) dialogInterface;
141
+ String action = actions.get(which);
142
+ if ("Reload preview".equals(action)) {
143
+ previewActionRunning[0] = true;
144
+ logger.info("Reloading webview");
145
+ runPreviewMenuAction(dialog, "Could not reload the test app.", "Error reloading test app: ", () ->
146
+ plugin.reloadPreviewSessionFromShakeMenu()
147
+ );
148
+ } else if ("Switch preview".equals(action)) {
149
+ openingNestedSelector[0] = true;
150
+ dialog.dismiss();
151
+ showPreviewSelector();
152
+ } else {
153
+ previewActionRunning[0] = true;
154
+ runPreviewMenuAction(dialog, "Could not leave the test app.", "Error leaving test app: ", () ->
155
+ plugin.leavePreviewSessionFromShakeMenu()
156
+ );
157
+ }
158
+ });
128
159
 
129
160
  // Cancel button
130
161
  builder.setNegativeButton(
131
- cancelButtonTitle,
162
+ "Close menu",
132
163
  new DialogInterface.OnClickListener() {
133
164
  public void onClick(DialogInterface dialog, int id) {
134
165
  logger.info("Shake menu cancelled");
@@ -139,21 +170,12 @@ public class ShakeMenu implements ShakeDetector.Listener, ThreeFingerPinchDetect
139
170
  );
140
171
 
141
172
  AlertDialog dialog = builder.create();
142
- dialog.setOnDismissListener((dialogInterface) -> isShowing = false);
143
- dialog.show();
144
- dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener((view) -> {
145
- setPreviewMenuButtonsEnabled(dialog, false);
146
- runPreviewMenuAction(dialog, "Could not leave the test app.", "Error leaving test app: ", () ->
147
- plugin.leavePreviewSessionFromShakeMenu()
148
- );
149
- });
150
- dialog.getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener((view) -> {
151
- setPreviewMenuButtonsEnabled(dialog, false);
152
- logger.info("Reloading webview");
153
- runPreviewMenuAction(dialog, "Could not reload the test app.", "Error reloading test app: ", () ->
154
- plugin.reloadPreviewSessionFromShakeMenu()
155
- );
173
+ dialog.setOnDismissListener((dialogInterface) -> {
174
+ if (!openingNestedSelector[0] && !previewActionRunning[0]) {
175
+ isShowing = false;
176
+ }
156
177
  });
178
+ dialog.show();
157
179
  } catch (Exception e) {
158
180
  logger.error("Error showing shake menu: " + e.getMessage());
159
181
  isShowing = false;
@@ -165,29 +187,40 @@ public class ShakeMenu implements ShakeDetector.Listener, ThreeFingerPinchDetect
165
187
  try {
166
188
  String appName = activity.getPackageManager().getApplicationLabel(activity.getApplicationInfo()).toString();
167
189
  String title = "Preview " + appName + " Menu";
168
- String message = "Reload or leave the current preview, or switch update channel.";
169
- String[] actions = { "Reload preview", "Leave test app", "Switch channel" };
170
- final boolean[] openingChannelSelector = { false };
190
+ String message = "Reload, switch, or leave the current preview.";
191
+ List<String> actions = new ArrayList<>();
192
+ actions.add("Reload preview");
193
+ if (plugin.previewMenuPreviews().length() > 0) {
194
+ actions.add("Switch preview");
195
+ }
196
+ actions.add("Leave test app");
197
+ actions.add("Switch channel");
198
+ final boolean[] openingNestedSelector = { false };
171
199
  final boolean[] previewActionRunning = { false };
172
200
 
173
201
  AlertDialog.Builder builder = new AlertDialog.Builder(activity);
174
202
  builder.setTitle(title);
175
203
  builder.setMessage(message);
176
- builder.setItems(actions, (dialogInterface, which) -> {
204
+ builder.setItems(actions.toArray(new String[0]), (dialogInterface, which) -> {
177
205
  AlertDialog dialog = (AlertDialog) dialogInterface;
178
- if (which == 0) {
206
+ String action = actions.get(which);
207
+ if ("Reload preview".equals(action)) {
179
208
  previewActionRunning[0] = true;
180
209
  logger.info("Reloading webview");
181
210
  runPreviewMenuAction(dialog, "Could not reload the test app.", "Error reloading test app: ", () ->
182
211
  plugin.reloadPreviewSessionFromShakeMenu()
183
212
  );
184
- } else if (which == 1) {
213
+ } else if ("Leave test app".equals(action)) {
185
214
  previewActionRunning[0] = true;
186
215
  runPreviewMenuAction(dialog, "Could not leave the test app.", "Error leaving test app: ", () ->
187
216
  plugin.leavePreviewSessionFromShakeMenu()
188
217
  );
218
+ } else if ("Switch preview".equals(action)) {
219
+ openingNestedSelector[0] = true;
220
+ dialog.dismiss();
221
+ showPreviewSelector();
189
222
  } else {
190
- openingChannelSelector[0] = true;
223
+ openingNestedSelector[0] = true;
191
224
  dialog.dismiss();
192
225
  showChannelSelector();
193
226
  }
@@ -200,7 +233,7 @@ public class ShakeMenu implements ShakeDetector.Listener, ThreeFingerPinchDetect
200
233
 
201
234
  AlertDialog dialog = builder.create();
202
235
  dialog.setOnDismissListener((dialogInterface) -> {
203
- if (!openingChannelSelector[0] && !previewActionRunning[0]) {
236
+ if (!openingNestedSelector[0] && !previewActionRunning[0]) {
204
237
  isShowing = false;
205
238
  }
206
239
  });
@@ -235,6 +268,146 @@ public class ShakeMenu implements ShakeDetector.Listener, ThreeFingerPinchDetect
235
268
  dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setEnabled(enabled);
236
269
  }
237
270
 
271
+ private void showPreviewSelector() {
272
+ activity.runOnUiThread(() -> {
273
+ try {
274
+ JSArray previewsRaw = plugin.previewMenuPreviews();
275
+ List<JSObject> previews = new ArrayList<>();
276
+ for (int i = 0; i < previewsRaw.length(); i++) {
277
+ Object raw = previewsRaw.opt(i);
278
+ if (raw instanceof JSObject preview) {
279
+ previews.add(preview);
280
+ } else if (raw instanceof JSONObject json) {
281
+ previews.add(JSObject.fromJSONObject(json));
282
+ }
283
+ }
284
+
285
+ if (previews.isEmpty()) {
286
+ showError("No saved previews available on this device.");
287
+ return;
288
+ }
289
+
290
+ presentPreviewPicker(previews);
291
+ } catch (Exception e) {
292
+ logger.error("Error showing preview selector: " + e.getMessage());
293
+ isShowing = false;
294
+ }
295
+ });
296
+ }
297
+
298
+ private String previewLabel(JSObject preview) {
299
+ String name = preview.optString("name", "");
300
+ JSObject bundle = preview.getJSObject("bundle");
301
+ String version = bundle == null ? "" : bundle.optString("version", "");
302
+ String label = !name.isEmpty() ? name : (!version.isEmpty() ? version : preview.optString("id", "Preview"));
303
+ if (preview.optBoolean("isActive", false)) {
304
+ label += " (current)";
305
+ }
306
+ return label;
307
+ }
308
+
309
+ private void presentPreviewPicker(List<JSObject> previews) {
310
+ try {
311
+ AlertDialog.Builder builder = new AlertDialog.Builder(activity);
312
+ builder.setTitle("Select Preview");
313
+
314
+ LinearLayout layout = new LinearLayout(activity);
315
+ layout.setOrientation(LinearLayout.VERTICAL);
316
+ int padding = dpToPx(16);
317
+ layout.setPadding(padding, padding, padding, padding);
318
+
319
+ EditText searchField = new EditText(activity);
320
+ searchField.setHint("Search previews...");
321
+ searchField.setSingleLine(true);
322
+ layout.addView(searchField);
323
+
324
+ final List<JSObject> displayedPreviews = new ArrayList<>();
325
+ displayedPreviews.addAll(previews.subList(0, Math.min(5, previews.size())));
326
+ final ArrayAdapter<String> adapter = new ArrayAdapter<>(
327
+ activity,
328
+ android.R.layout.simple_list_item_1,
329
+ previewLabels(displayedPreviews)
330
+ );
331
+
332
+ ListView listView = new ListView(activity);
333
+ listView.setAdapter(adapter);
334
+ LinearLayout.LayoutParams listParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, dpToPx(250));
335
+ listView.setLayoutParams(listParams);
336
+ layout.addView(listView);
337
+
338
+ builder.setView(layout);
339
+ builder.setNegativeButton("Cancel", (dialog, which) -> {
340
+ dialog.dismiss();
341
+ isShowing = false;
342
+ });
343
+
344
+ AlertDialog dialog = builder.create();
345
+ dialog.setOnDismissListener((d) -> isShowing = false);
346
+
347
+ searchField.addTextChangedListener(
348
+ new TextWatcher() {
349
+ @Override
350
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
351
+
352
+ @Override
353
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
354
+
355
+ @Override
356
+ public void afterTextChanged(Editable s) {
357
+ String query = s.toString().toLowerCase();
358
+ displayedPreviews.clear();
359
+
360
+ for (JSObject preview : previews) {
361
+ if (previewLabel(preview).toLowerCase().contains(query)) {
362
+ displayedPreviews.add(preview);
363
+ if (displayedPreviews.size() >= 5) break;
364
+ }
365
+ }
366
+
367
+ adapter.clear();
368
+ adapter.addAll(previewLabels(displayedPreviews));
369
+ adapter.notifyDataSetChanged();
370
+ }
371
+ }
372
+ );
373
+
374
+ listView.setOnItemClickListener((parent, view, position, id) -> {
375
+ JSObject selectedPreview = displayedPreviews.get(position);
376
+ String previewId = selectedPreview.optString("id", "");
377
+ dialog.dismiss();
378
+ selectPreview(previewId);
379
+ });
380
+
381
+ dialog.show();
382
+ } catch (Exception e) {
383
+ logger.error("Error presenting preview picker: " + e.getMessage());
384
+ isShowing = false;
385
+ }
386
+ }
387
+
388
+ private List<String> previewLabels(List<JSObject> previews) {
389
+ List<String> labels = new ArrayList<>();
390
+ for (JSObject preview : previews) {
391
+ labels.add(previewLabel(preview));
392
+ }
393
+ return labels;
394
+ }
395
+
396
+ private void selectPreview(String previewId) {
397
+ new Thread(() -> {
398
+ try {
399
+ if (!plugin.setPreviewFromShakeMenu(previewId)) {
400
+ activity.runOnUiThread(() -> showError("Could not switch preview."));
401
+ }
402
+ } catch (Exception e) {
403
+ logger.error("Error switching preview: " + e.getMessage());
404
+ activity.runOnUiThread(() -> showError("Error switching preview: " + e.getMessage()));
405
+ } finally {
406
+ isShowing = false;
407
+ }
408
+ }).start();
409
+ }
410
+
238
411
  private void showConfiguredDefaultMenu() {
239
412
  activity.runOnUiThread(() -> {
240
413
  try {
@@ -6,27 +6,37 @@
6
6
 
7
7
  package ee.forgr.capacitor_updater;
8
8
 
9
+ import android.view.ActionMode;
10
+ import android.view.KeyEvent;
11
+ import android.view.KeyboardShortcutGroup;
12
+ import android.view.Menu;
13
+ import android.view.MenuItem;
9
14
  import android.view.MotionEvent;
15
+ import android.view.SearchEvent;
10
16
  import android.view.View;
11
- import com.getcapacitor.Bridge;
17
+ import android.view.Window;
18
+ import android.view.WindowManager;
19
+ import android.view.accessibility.AccessibilityEvent;
12
20
  import com.getcapacitor.BridgeActivity;
13
- import java.lang.reflect.Field;
21
+ import java.lang.ref.WeakReference;
22
+ import java.util.List;
14
23
 
15
- public class ThreeFingerPinchDetector implements View.OnTouchListener {
24
+ public class ThreeFingerPinchDetector {
16
25
 
17
26
  public interface Listener {
18
27
  void onThreeFingerPinchDetected();
19
28
  }
20
29
 
21
30
  private static final int REQUIRED_POINTER_COUNT = 3;
22
- private static final float MIN_SCALE_DELTA = 0.30f;
31
+ private static final float MIN_SCALE_DELTA = 0.12f;
23
32
  private static final long PINCH_TIMEOUT = 1000;
24
33
 
25
34
  private final Listener listener;
26
35
  private final Logger logger;
27
- private View targetView;
28
- private View.OnTouchListener previousOnTouchListener;
29
- private boolean touchListenerInstalled = false;
36
+ private Window targetWindow;
37
+ private Window.Callback previousWindowCallback;
38
+ private Window.Callback windowCallback;
39
+ private WeakReference<ThreeFingerPinchDetector> detectorReference;
30
40
  private float initialSpan = 0;
31
41
  private boolean tracking = false;
32
42
  private boolean triggered = false;
@@ -38,74 +48,68 @@ public class ThreeFingerPinchDetector implements View.OnTouchListener {
38
48
  }
39
49
 
40
50
  public void start(BridgeActivity activity) {
41
- if (targetView != null) {
51
+ if (targetWindow != null) {
42
52
  stop();
43
53
  }
44
54
 
45
- View view = null;
46
- Bridge bridge = activity.getBridge();
47
- if (bridge != null && bridge.getWebView() != null) {
48
- view = bridge.getWebView();
49
- }
50
- if (view == null && activity.getWindow() != null) {
51
- view = activity.getWindow().getDecorView().getRootView();
52
- }
53
- if (view == null) {
54
- logger.warn("Three finger pinch detector could not find a target view");
55
+ Window window = activity.getWindow();
56
+ if (window == null) {
57
+ logger.warn("Three finger pinch detector could not find a target window");
55
58
  return;
56
59
  }
57
60
 
58
- this.targetView = view;
59
- this.previousOnTouchListener = getCurrentOnTouchListener(view);
60
- if (this.previousOnTouchListener != this) {
61
- this.targetView.setOnTouchListener(this);
62
- this.touchListenerInstalled = true;
63
- }
61
+ this.targetWindow = window;
62
+ this.previousWindowCallback = window.getCallback();
63
+ this.detectorReference = new WeakReference<>(this);
64
+ this.windowCallback = new PinchWindowCallback(this.previousWindowCallback, this.detectorReference);
65
+ window.setCallback(this.windowCallback);
66
+ logger.info("Three finger pinch detector installed on activity window");
64
67
  }
65
68
 
66
69
  public void stop() {
67
- if (targetView != null) {
68
- View.OnTouchListener currentOnTouchListener = getCurrentOnTouchListener(targetView);
69
- if (touchListenerInstalled && (currentOnTouchListener == this || currentOnTouchListener == null)) {
70
- targetView.setOnTouchListener(previousOnTouchListener);
70
+ if (targetWindow != null) {
71
+ if (windowCallback instanceof PinchWindowCallback) {
72
+ ((PinchWindowCallback) windowCallback).disable();
71
73
  }
72
- targetView = null;
73
- previousOnTouchListener = null;
74
- touchListenerInstalled = false;
74
+ if (detectorReference != null) {
75
+ detectorReference.clear();
76
+ }
77
+ if (targetWindow.getCallback() == windowCallback) {
78
+ targetWindow.setCallback(previousWindowCallback);
79
+ }
80
+ targetWindow = null;
81
+ previousWindowCallback = null;
82
+ windowCallback = null;
83
+ detectorReference = null;
75
84
  }
76
85
  reset();
77
86
  }
78
87
 
79
- @Override
80
- public boolean onTouch(View view, MotionEvent event) {
81
- boolean consumedByPreviousListener = false;
82
- if (previousOnTouchListener != null && previousOnTouchListener != this) {
83
- consumedByPreviousListener = previousOnTouchListener.onTouch(view, event);
84
- }
85
-
88
+ private void handleTouch(MotionEvent event) {
86
89
  int action = event.getActionMasked();
87
90
  if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) {
88
91
  reset();
89
- return consumedByPreviousListener;
92
+ return;
90
93
  }
91
94
 
92
95
  if (event.getPointerCount() != REQUIRED_POINTER_COUNT) {
93
96
  if (action == MotionEvent.ACTION_POINTER_DOWN) {
94
97
  reset();
95
98
  }
96
- return consumedByPreviousListener;
99
+ return;
97
100
  }
98
101
 
99
102
  float span = calculateSpan(event);
100
103
  if (span <= 0) {
101
- return consumedByPreviousListener;
104
+ return;
102
105
  }
103
106
 
104
107
  if (!tracking || action == MotionEvent.ACTION_POINTER_DOWN) {
105
108
  initialSpan = span;
106
109
  tracking = true;
107
110
  triggered = false;
108
- return consumedByPreviousListener;
111
+ logger.info("Three finger pinch tracking started");
112
+ return;
109
113
  }
110
114
 
111
115
  if (!triggered && Math.abs(span - initialSpan) / initialSpan >= MIN_SCALE_DELTA) {
@@ -113,13 +117,12 @@ public class ThreeFingerPinchDetector implements View.OnTouchListener {
113
117
  if (currentTime - lastPinchTime > PINCH_TIMEOUT) {
114
118
  triggered = true;
115
119
  lastPinchTime = currentTime;
120
+ logger.info("Three finger pinch threshold reached");
116
121
  if (listener != null) {
117
122
  listener.onThreeFingerPinchDetected();
118
123
  }
119
124
  }
120
125
  }
121
-
122
- return consumedByPreviousListener;
123
126
  }
124
127
 
125
128
  private float calculateSpan(MotionEvent event) {
@@ -141,29 +144,180 @@ public class ThreeFingerPinchDetector implements View.OnTouchListener {
141
144
  return totalDistance / REQUIRED_POINTER_COUNT;
142
145
  }
143
146
 
144
- private View.OnTouchListener getCurrentOnTouchListener(View view) {
145
- try {
146
- Field listenerInfoField = View.class.getDeclaredField("mListenerInfo");
147
- listenerInfoField.setAccessible(true);
148
- Object listenerInfo = listenerInfoField.get(view);
149
- if (listenerInfo == null) {
150
- return null;
151
- }
152
- Field onTouchListenerField = listenerInfo.getClass().getDeclaredField("mOnTouchListener");
153
- onTouchListenerField.setAccessible(true);
154
- Object listener = onTouchListenerField.get(listenerInfo);
155
- if (listener instanceof View.OnTouchListener) {
156
- return (View.OnTouchListener) listener;
157
- }
158
- } catch (ReflectiveOperationException | RuntimeException exception) {
159
- logger.warn("Three finger pinch detector could not inspect the current touch listener: " + exception.getMessage());
160
- }
161
- return null;
162
- }
163
-
164
147
  private void reset() {
165
148
  initialSpan = 0;
166
149
  tracking = false;
167
150
  triggered = false;
168
151
  }
152
+
153
+ private static class PinchWindowCallback implements Window.Callback {
154
+
155
+ private final Window.Callback delegate;
156
+ private final WeakReference<ThreeFingerPinchDetector> detectorReference;
157
+ private boolean enabled = true;
158
+
159
+ PinchWindowCallback(Window.Callback delegate, WeakReference<ThreeFingerPinchDetector> detectorReference) {
160
+ this.delegate = delegate;
161
+ this.detectorReference = detectorReference;
162
+ }
163
+
164
+ void disable() {
165
+ enabled = false;
166
+ if (detectorReference != null) {
167
+ detectorReference.clear();
168
+ }
169
+ }
170
+
171
+ @Override
172
+ public boolean dispatchKeyEvent(KeyEvent event) {
173
+ return delegate != null && delegate.dispatchKeyEvent(event);
174
+ }
175
+
176
+ @Override
177
+ public boolean dispatchKeyShortcutEvent(KeyEvent event) {
178
+ return delegate != null && delegate.dispatchKeyShortcutEvent(event);
179
+ }
180
+
181
+ @Override
182
+ public boolean dispatchTouchEvent(MotionEvent event) {
183
+ boolean handled = delegate != null && delegate.dispatchTouchEvent(event);
184
+ if (enabled) {
185
+ ThreeFingerPinchDetector detector = detectorReference == null ? null : detectorReference.get();
186
+ if (detector != null) {
187
+ detector.handleTouch(event);
188
+ }
189
+ }
190
+ return handled;
191
+ }
192
+
193
+ @Override
194
+ public boolean dispatchTrackballEvent(MotionEvent event) {
195
+ return delegate != null && delegate.dispatchTrackballEvent(event);
196
+ }
197
+
198
+ @Override
199
+ public boolean dispatchGenericMotionEvent(MotionEvent event) {
200
+ return delegate != null && delegate.dispatchGenericMotionEvent(event);
201
+ }
202
+
203
+ @Override
204
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
205
+ return delegate != null && delegate.dispatchPopulateAccessibilityEvent(event);
206
+ }
207
+
208
+ @Override
209
+ public View onCreatePanelView(int featureId) {
210
+ return delegate == null ? null : delegate.onCreatePanelView(featureId);
211
+ }
212
+
213
+ @Override
214
+ public boolean onCreatePanelMenu(int featureId, Menu menu) {
215
+ return delegate != null && delegate.onCreatePanelMenu(featureId, menu);
216
+ }
217
+
218
+ @Override
219
+ public boolean onPreparePanel(int featureId, View view, Menu menu) {
220
+ return delegate != null && delegate.onPreparePanel(featureId, view, menu);
221
+ }
222
+
223
+ @Override
224
+ public boolean onMenuOpened(int featureId, Menu menu) {
225
+ return delegate != null && delegate.onMenuOpened(featureId, menu);
226
+ }
227
+
228
+ @Override
229
+ public boolean onMenuItemSelected(int featureId, MenuItem item) {
230
+ return delegate != null && delegate.onMenuItemSelected(featureId, item);
231
+ }
232
+
233
+ @Override
234
+ public void onWindowAttributesChanged(WindowManager.LayoutParams attrs) {
235
+ if (delegate != null) {
236
+ delegate.onWindowAttributesChanged(attrs);
237
+ }
238
+ }
239
+
240
+ @Override
241
+ public void onContentChanged() {
242
+ if (delegate != null) {
243
+ delegate.onContentChanged();
244
+ }
245
+ }
246
+
247
+ @Override
248
+ public void onWindowFocusChanged(boolean hasFocus) {
249
+ if (delegate != null) {
250
+ delegate.onWindowFocusChanged(hasFocus);
251
+ }
252
+ }
253
+
254
+ @Override
255
+ public void onAttachedToWindow() {
256
+ if (delegate != null) {
257
+ delegate.onAttachedToWindow();
258
+ }
259
+ }
260
+
261
+ @Override
262
+ public void onDetachedFromWindow() {
263
+ if (delegate != null) {
264
+ delegate.onDetachedFromWindow();
265
+ }
266
+ }
267
+
268
+ @Override
269
+ public void onPanelClosed(int featureId, Menu menu) {
270
+ if (delegate != null) {
271
+ delegate.onPanelClosed(featureId, menu);
272
+ }
273
+ }
274
+
275
+ @Override
276
+ public boolean onSearchRequested() {
277
+ return delegate != null && delegate.onSearchRequested();
278
+ }
279
+
280
+ @Override
281
+ public boolean onSearchRequested(SearchEvent searchEvent) {
282
+ return delegate != null && delegate.onSearchRequested(searchEvent);
283
+ }
284
+
285
+ @Override
286
+ public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
287
+ return delegate == null ? null : delegate.onWindowStartingActionMode(callback);
288
+ }
289
+
290
+ @Override
291
+ public ActionMode onWindowStartingActionMode(ActionMode.Callback callback, int type) {
292
+ return delegate == null ? null : delegate.onWindowStartingActionMode(callback, type);
293
+ }
294
+
295
+ @Override
296
+ public void onActionModeStarted(ActionMode mode) {
297
+ if (delegate != null) {
298
+ delegate.onActionModeStarted(mode);
299
+ }
300
+ }
301
+
302
+ @Override
303
+ public void onActionModeFinished(ActionMode mode) {
304
+ if (delegate != null) {
305
+ delegate.onActionModeFinished(mode);
306
+ }
307
+ }
308
+
309
+ @Override
310
+ public void onProvideKeyboardShortcuts(List<KeyboardShortcutGroup> data, Menu menu, int deviceId) {
311
+ if (delegate != null) {
312
+ delegate.onProvideKeyboardShortcuts(data, menu, deviceId);
313
+ }
314
+ }
315
+
316
+ @Override
317
+ public void onPointerCaptureChanged(boolean hasCapture) {
318
+ if (delegate != null) {
319
+ delegate.onPointerCaptureChanged(hasCapture);
320
+ }
321
+ }
322
+ }
169
323
  }