Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 4.10.14

* Adds opt out of `displayCutout` and `systemBars` Android inset changes. See
https://chromium.googlesource.com/chromium/src/+/HEAD/android_webview/docs/insets.md#opt_out

## 4.10.13

* Bumps androidx.webkit:webkit from 1.14.0 to 1.15.0.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2013 The Flutter Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Autogenerated from Pigeon (v26.1.4), do not edit directly.
// Autogenerated from Pigeon (v26.2.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")

Expand Down Expand Up @@ -708,6 +708,7 @@ private class AndroidWebkitLibraryPigeonProxyApiBaseCodec(
value is OverScrollMode ||
value is SslErrorType ||
value is MixedContentMode ||
value is WindowInsets ||
value == null) {
super.writeValue(stream, value)
return
Expand Down Expand Up @@ -1098,6 +1099,47 @@ enum class MixedContentMode(val raw: Int) {
}
}

/**
* Defines different types of sources causing window insets.
*
* See https://developer.android.com/reference/androidx/core/view/WindowInsetsCompat.Type
*/
enum class WindowInsets(val raw: Int) {
/**
* All system bars.
*
* Includes statusBars(), captionBar() as well as navigationBars(), systemOverlays(), but not
* ime().
*/
SYSTEM_BARS(0),
/** An inset type representing the area that used by DisplayCutout. */
DISPLAY_CUTOUT(1),
/** An insets type representing the window of a caption bar. */
CAPTION_BAR(2),
/** An insets type representing the window of an InputMethod. */
IME(3),
MANDATORY_SYSTEM_GESTURES(4),
/** An insets type representing any system bars for navigation. */
NAVIGATION_BARS(5),
/** An insets type representing any system bars for displaying status. */
STATUS_BARS(6),
/**
* An insets type representing the system gesture insets.
*
* The system gesture insets represent the area of a window where system gestures have priority
* and may consume some or all touch input, e.g. due to the a system bar occupying it, or it being
* reserved for touch-only gestures.
*/
SYSTEM_GESTURES(7),
TAPPABLE_ELEMENT(8);

companion object {
fun ofRaw(raw: Int): WindowInsets? {
return values().firstOrNull { it.raw == raw }
}
}
}

private open class AndroidWebkitLibraryPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
return when (type) {
Expand All @@ -1116,6 +1158,9 @@ private open class AndroidWebkitLibraryPigeonCodec : StandardMessageCodec() {
133.toByte() -> {
return (readValue(buffer) as Long?)?.let { MixedContentMode.ofRaw(it.toInt()) }
}
134.toByte() -> {
return (readValue(buffer) as Long?)?.let { WindowInsets.ofRaw(it.toInt()) }
}
else -> super.readValueOfType(type, buffer)
}
}
Expand All @@ -1142,6 +1187,10 @@ private open class AndroidWebkitLibraryPigeonCodec : StandardMessageCodec() {
stream.write(133)
writeValue(stream, value.raw.toLong())
}
is WindowInsets -> {
stream.write(134)
writeValue(stream, value.raw.toLong())
}
else -> super.writeValue(stream, value)
}
}
Expand Down Expand Up @@ -5316,6 +5365,18 @@ abstract class PigeonApiView(
/** Set the over-scroll mode for this view. */
abstract fun setOverScrollMode(pigeon_instance: android.view.View, mode: OverScrollMode)

/**
* Sets the listener to the native method `ViewCompat.setOnApplyWindowInsetsListener` to mark the
* passed insets to zero.
*
* This is a convenience method because `View.OnApplyWindowInsetsListener` requires implementing a
* callback that requires a synchronous return value.
*/
abstract fun setInsetListenerToSetInsetsToZero(
pigeon_instance: android.view.View,
insets: List<WindowInsets>
)

companion object {
@Suppress("LocalVariableName")
fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiView?) {
Expand Down Expand Up @@ -5460,6 +5521,30 @@ abstract class PigeonApiView(
channel.setMessageHandler(null)
}
}
run {
val channel =
BasicMessageChannel<Any?>(
binaryMessenger,
"dev.flutter.pigeon.webview_flutter_android.View.setInsetListenerToSetInsetsToZero",
codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val pigeon_instanceArg = args[0] as android.view.View
val insetsArg = args[1] as List<WindowInsets>
val wrapped: List<Any?> =
try {
api.setInsetListenerToSetInsetsToZero(pigeon_instanceArg, insetsArg)
listOf(null)
} catch (exception: Throwable) {
AndroidWebkitLibraryPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

import android.view.View;
import androidx.annotation.NonNull;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import java.util.List;

/**
* Flutter API implementation for `View`.
Expand Down Expand Up @@ -67,4 +71,55 @@ public void setOverScrollMode(@NonNull View pigeon_instance, @NonNull OverScroll
throw getPigeonRegistrar().createUnknownEnumException(OverScrollMode.UNKNOWN);
}
}

@Override
public void setInsetListenerToSetInsetsToZero(
@NonNull View pigeon_instance, @NonNull List<? extends WindowInsets> insets) {
if (insets.isEmpty()) {
ViewCompat.setOnApplyWindowInsetsListener(
pigeon_instance, (view, windowInsets) -> windowInsets);
return;
}

int typeMaskAccumulator = 0;
for (WindowInsets inset : insets) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add comment here that indicates why SYTEM_BARS and DISPLAY_CUTOUT where chosen and how to know when a new item should be added to this list.

Additionally why use the all caps ints instead of WindowInsets.Type.systemBars()?

switch (inset) {
case SYSTEM_BARS:
typeMaskAccumulator |= WindowInsetsCompat.Type.systemBars();
break;
case DISPLAY_CUTOUT:
typeMaskAccumulator |= WindowInsetsCompat.Type.displayCutout();
break;
case CAPTION_BAR:
typeMaskAccumulator |= WindowInsetsCompat.Type.captionBar();
break;
case IME:
typeMaskAccumulator |= WindowInsetsCompat.Type.ime();
break;
case MANDATORY_SYSTEM_GESTURES:
typeMaskAccumulator |= WindowInsetsCompat.Type.mandatorySystemGestures();
break;
case NAVIGATION_BARS:
typeMaskAccumulator |= WindowInsetsCompat.Type.navigationBars();
break;
case STATUS_BARS:
typeMaskAccumulator |= WindowInsetsCompat.Type.statusBars();
break;
case SYSTEM_GESTURES:
typeMaskAccumulator |= WindowInsetsCompat.Type.systemGestures();
break;
case TAPPABLE_ELEMENT:
typeMaskAccumulator |= WindowInsetsCompat.Type.tappableElement();
break;
}
}
final int insetsTypeMask = typeMaskAccumulator;

ViewCompat.setOnApplyWindowInsetsListener(
pigeon_instance,
(view, windowInsets) ->
new WindowInsetsCompat.Builder(windowInsets)
.setInsets(insetsTypeMask, Insets.NONE)
.build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,21 @@
package io.flutter.plugins.webviewflutter;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.view.View;
import androidx.core.graphics.Insets;
import androidx.core.view.OnApplyWindowInsetsListener;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import java.util.List;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.MockedStatic;

public class ViewTest {
@Test
Expand Down Expand Up @@ -82,4 +91,32 @@ public void setOverScrollMode() {

verify(instance).setOverScrollMode(View.OVER_SCROLL_ALWAYS);
}

@Test
public void setInsetListenerToSetInsetsToZero() {
final PigeonApiView api = new TestProxyApiRegistrar().getPigeonApiView();

final View instance = mock(View.class);
final WindowInsetsCompat originalInsets =
new WindowInsetsCompat.Builder()
.setInsets(WindowInsetsCompat.Type.systemBars(), Insets.of(1, 2, 3, 4))
.setInsets(WindowInsetsCompat.Type.displayCutout(), Insets.of(4, 5, 6, 7))
.build();

try (MockedStatic<ViewCompat> viewCompatMockedStatic = mockStatic(ViewCompat.class)) {
api.setInsetListenerToSetInsetsToZero(
instance, List.of(WindowInsets.SYSTEM_BARS, WindowInsets.DISPLAY_CUTOUT));

final ArgumentCaptor<OnApplyWindowInsetsListener> listenerCaptor =
ArgumentCaptor.forClass(OnApplyWindowInsetsListener.class);
viewCompatMockedStatic.verify(
() -> ViewCompat.setOnApplyWindowInsetsListener(eq(instance), listenerCaptor.capture()));

final WindowInsetsCompat newInsets =
listenerCaptor.getValue().onApplyWindowInsets(instance, originalInsets);

assertEquals(Insets.NONE, newInsets.getInsets(WindowInsetsCompat.Type.systemBars()));
assertEquals(Insets.NONE, newInsets.getInsets(WindowInsetsCompat.Type.displayCutout()));
}
}
}
Loading
Loading