From: Soren Stoutner Date: Mon, 23 Dec 2024 22:14:24 +0000 (-0700) Subject: Fix displaying under cutouts on all APIs. https://redmine.stoutner.com/issues/1238 X-Git-Tag: v3.19~3 X-Git-Url: https://gitweb.stoutner.com/?a=commitdiff_plain;h=66cd12ff83243a33e94639766859f5cc146ad596;p=PrivacyBrowserAndroid.git Fix displaying under cutouts on all APIs. https://redmine.stoutner.com/issues/1238 --- diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt index bf2c30a2..c57fce16 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt @@ -63,6 +63,8 @@ import android.view.MenuItem import android.view.MotionEvent import android.view.View import android.view.ViewGroup +import android.view.WindowInsets +import android.view.WindowInsetsController import android.view.WindowManager import android.view.inputmethod.InputMethodManager import android.webkit.CookieManager @@ -259,7 +261,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook private lateinit var bookmarksCursorAdapter: CursorAdapter private lateinit var bookmarksListView: ListView private lateinit var bookmarksDrawerPinnedImageView: ImageView + private lateinit var bookmarksFrameLayout: FrameLayout private lateinit var bookmarksTitleTextView: TextView + private lateinit var browserFrameLayout: FrameLayout private lateinit var coordinatorLayout: CoordinatorLayout private lateinit var cookieManager: CookieManager private lateinit var defaultFontSizeString: String @@ -285,6 +289,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook private lateinit var navigationRequestsMenuItem: MenuItem private lateinit var navigationScrollToBottomMenuItem: MenuItem private lateinit var navigationView: NavigationView + private lateinit var oldFullScreenVideoFrameLayout: FrameLayout private lateinit var optionsAddOrEditDomainMenuItem: MenuItem private lateinit var optionsBlockAllThirdPartyRequestsMenuItem: MenuItem private lateinit var optionsClearCookiesMenuItem: MenuItem @@ -327,7 +332,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook private lateinit var optionsWideViewportMenuItem: MenuItem private lateinit var proxyHelper: ProxyHelper private lateinit var redColorSpan: ForegroundColorSpan - private lateinit var rootFrameLayout: FrameLayout private lateinit var saveUrlString: String private lateinit var searchURL: String private lateinit var sharedPreferences: SharedPreferences @@ -338,6 +342,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook private lateinit var webViewDefaultUserAgent: String private lateinit var webViewThemeEntryValuesStringArray: Array private lateinit var webViewViewPager2: ViewPager2 + private lateinit var windowInsetsController: WindowInsetsController private lateinit var ultraList: ArrayList>> private lateinit var urlEditText: EditText private lateinit var urlRelativeLayout: RelativeLayout @@ -516,19 +521,14 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook val allowScreenshots = sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false) bottomAppBar = sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false) displayAdditionalAppBarIcons = sharedPreferences.getBoolean(getString(R.string.display_additional_app_bar_icons_key), false) - - // Displaying under cutouts currently only works on API < 35. - if (Build.VERSION.SDK_INT < 35) { - // Get the display under cutouts preference. - displayUnderCutouts = sharedPreferences.getBoolean(getString(R.string.display_under_cutouts_key), false) - - // Set the display under cutouts mode. This must be done here as it doesn't appear to work correctly if handled after the app is fully initialized. - if (displayUnderCutouts) { - if (Build.VERSION.SDK_INT >= 30) - window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS - else if (Build.VERSION.SDK_INT >= 28) - window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES - } + displayUnderCutouts = sharedPreferences.getBoolean(getString(R.string.display_under_cutouts_key), false) + + // Set the display under cutouts mode. This must be done here as it doesn't appear to work correctly if handled after the app is fully initialized. + if ((Build.VERSION.SDK_INT < 35) && displayUnderCutouts) { + if (Build.VERSION.SDK_INT >= 30) + window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS + else if (Build.VERSION.SDK_INT >= 28) + window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES } // Get the entry values string arrays. @@ -589,7 +589,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook setContentView(R.layout.main_framelayout_top_appbar) // Get handles for the views. - rootFrameLayout = findViewById(R.id.root_framelayout) + browserFrameLayout = findViewById(R.id.browser_framelayout) drawerLayout = findViewById(R.id.drawerlayout) coordinatorLayout = findViewById(R.id.coordinatorlayout) appBarLayout = findViewById(R.id.appbar_layout) @@ -602,11 +602,27 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook swipeRefreshLayout = findViewById(R.id.swiperefreshlayout) webViewViewPager2 = findViewById(R.id.webview_viewpager2) navigationView = findViewById(R.id.navigationview) + bookmarksFrameLayout = findViewById(R.id.bookmarks_framelayout) bookmarksListView = findViewById(R.id.bookmarks_drawer_listview) bookmarksTitleTextView = findViewById(R.id.bookmarks_title_textview) bookmarksDrawerPinnedImageView = findViewById(R.id.bookmarks_drawer_pinned_imageview) + oldFullScreenVideoFrameLayout = findViewById(R.id.old_full_screen_video_framelayout) fullScreenVideoFrameLayout = findViewById(R.id.full_screen_video_framelayout) + // Get a handle for the window inset controller. + if (Build.VERSION.SDK_INT >= 30) + windowInsetsController = browserFrameLayout.windowInsetsController!! + + // Set the layout to fit the system windows according to the API. + if (Build.VERSION.SDK_INT >= 35) { + // Set the browser frame layout to fit system windows. + browserFrameLayout.fitsSystemWindows = true + } else { + // Set the layouts to fit system windows. + coordinatorLayout.fitsSystemWindows = true + bookmarksFrameLayout.fitsSystemWindows = true + } + // Get a handle for the navigation menu. val navigationMenu = navigationView.menu @@ -890,8 +906,8 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook if (proxyMode != ProxyHelper.NONE) applyProxy(false) - // Reapply any system UI flags. - if (displayingFullScreenVideo || inFullScreenBrowsingMode) { // The system is displaying a website or a video in full screen mode. + // Reapply any system UI flags on older APIs. + if ((Build.VERSION.SDK_INT < 30) && (displayingFullScreenVideo || inFullScreenBrowsingMode)) { // The system is displaying a website or a video in full screen mode. /* Hide the system bars. * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. @@ -899,9 +915,8 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. */ - // The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30. @Suppress("DEPRECATION") - rootFrameLayout.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + browserFrameLayout.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY } // Show any pending dialogs. @@ -3020,6 +3035,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook proxyMode = sharedPreferences.getString(getString(R.string.proxy_key), getString(R.string.proxy_default_value))!! fullScreenBrowsingModeEnabled = sharedPreferences.getBoolean(getString(R.string.full_screen_browsing_mode_key), false) hideAppBar = sharedPreferences.getBoolean(getString(R.string.hide_app_bar_key), true) + displayUnderCutouts = sharedPreferences.getBoolean(getString(R.string.display_under_cutouts_key), false) val downloadProvider = sharedPreferences.getString(getString(R.string.download_provider_key), getString(R.string.download_provider_default_value))!! scrollAppBar = sharedPreferences.getBoolean(getString(R.string.scroll_app_bar_key), false) sortBookmarksAlphabetically = sharedPreferences.getBoolean(getString(R.string.sort_bookmarks_alphabetically_key), false) @@ -3111,8 +3127,12 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook } } + // Force an exit of full screen browsing mode if it is now disabled in settings. + if (!fullScreenBrowsingModeEnabled) + inFullScreenBrowsingMode = false + // Update the full screen browsing mode settings. - if (fullScreenBrowsingModeEnabled && inFullScreenBrowsingMode) { // Privacy Browser is currently in full screen browsing mode. + if (inFullScreenBrowsingMode) { // Privacy Browser is currently in full screen browsing mode. // Update the visibility of the app bar, which might have changed in the settings. if (hideAppBar) { // Hide the tab linear layout. @@ -3128,29 +3148,37 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook appBar.show() } - /* Hide the system bars. - * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. - * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. - * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. - * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. - */ + // Re-enforce the fullscreen flags if the API < 30. + if (Build.VERSION.SDK_INT < 30) { + /* Hide the system bars. + * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. + * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. + * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. + * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. + */ - // The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30. - @Suppress("DEPRECATION") - rootFrameLayout.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + @Suppress("DEPRECATION") + window.addFlags(View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) + } } else { // Privacy Browser is not in full screen browsing mode. - // Reset the full screen tracker, which could be true if Privacy Browser was in full screen mode before entering settings and full screen browsing was disabled. - inFullScreenBrowsingMode = false - // Show the tab linear layout. tabsLinearLayout.visibility = View.VISIBLE // Show the app bar. appBar.show() - // Remove the `SYSTEM_UI` flags from the root frame layout. The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30. - @Suppress("DEPRECATION") - rootFrameLayout.systemUiVisibility = 0 + // Remove the fullscreen flags if the API < 30. + if (Build.VERSION.SDK_INT < 30) { + /* Show the system bars. + * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. + * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. + * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. + * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. + */ + + @Suppress("DEPRECATION") + window.clearFlags(View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) + } } // Load the bookmarks folder. @@ -4108,33 +4136,58 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook } private fun exitFullScreenVideo() { - // Re-enable the screen timeout. - fullScreenVideoFrameLayout.keepScreenOn = false - // Unset the full screen video flag. displayingFullScreenVideo = false - // Remove all the views from the full screen video frame layout. - fullScreenVideoFrameLayout.removeAllViews() + // Hide the full screen video according to the API and display under cutouts status. + if ((Build.VERSION.SDK_INT < 35) && displayUnderCutouts) { // The device is running API < 35 and display under cutouts is enabled. + // Re-enable the screen timeout. + oldFullScreenVideoFrameLayout.keepScreenOn = false + + // Remove all the views from the full screen video frame layout. + oldFullScreenVideoFrameLayout.removeAllViews() + + // Hide the full screen video frame layout. + oldFullScreenVideoFrameLayout.visibility = View.GONE + } else { // The device is running API >= 35 or display under cutouts is disabled. + // Re-enable the screen timeout. + fullScreenVideoFrameLayout.keepScreenOn = false - // Hide the full screen video frame layout. - fullScreenVideoFrameLayout.visibility = View.GONE + // Remove all the views from the full screen video frame layout. + fullScreenVideoFrameLayout.removeAllViews() + + // Hide the full screen video frame layout. + fullScreenVideoFrameLayout.visibility = View.GONE + } // Enable the sliding drawers. drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) - // Show the coordinator layout. - coordinatorLayout.visibility = View.VISIBLE + // Show the browser view according to the API and display under cutouts status. + if ((Build.VERSION.SDK_INT < 35) && displayUnderCutouts) { // The device is running API < 35 and display under cutouts is enabled. + // Display the app bar if it is not supposed to be hidden, the `||` ensures that `!hideAppBar` is only evaluated in `inFullScreenBrowsingMode == true`. + if (!inFullScreenBrowsingMode || !hideAppBar) { + // Show the tab linear layout. + tabsLinearLayout.visibility = View.VISIBLE - // Apply the appropriate full screen mode flags. - if (fullScreenBrowsingModeEnabled && inFullScreenBrowsingMode) { // Privacy Browser is currently in full screen browsing mode. - // Handle display under cutouts for API < 35. - if (Build.VERSION.SDK_INT < 35) { - // Disable fits system windows if display under cutouts is enabled. - if (displayUnderCutouts) - rootFrameLayout.fitsSystemWindows = false + // Show the app bar. + appBar.show() } + // Display the swipe refresh layout (which includes the WebView). + swipeRefreshLayout.visibility = View.VISIBLE + + // Enable fits system windows if not in full screen browsing mode. + if (!inFullScreenBrowsingMode) { + coordinatorLayout.fitsSystemWindows = true + bookmarksFrameLayout.fitsSystemWindows = true + } + } else { // The device is running API >= 35 or display under cutouts is disabled. + browserFrameLayout.visibility = View.VISIBLE + } + + // Apply the appropriate full screen mode flags. + if (inFullScreenBrowsingMode) { // Privacy Browser is currently in full screen browsing mode. // Hide the app bar if specified. if (hideAppBar) { // Hide the tab linear layout. @@ -4144,27 +4197,33 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook appBar.hide() } - /* Hide the system bars. - * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. - * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. - * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. - * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. - */ + if (Build.VERSION.SDK_INT < 30) { + /* Hide the system bars. + * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. + * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. + * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. + * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. + */ - // The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30. - @Suppress("DEPRECATION") - rootFrameLayout.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY - } else { // Switch to normal viewing mode. - // Handle display under cutouts for API < 35. - if (Build.VERSION.SDK_INT < 35) { - // Enable fits system windows if display under cutouts is enabled. - if (displayUnderCutouts) - rootFrameLayout.fitsSystemWindows = true + @Suppress("DEPRECATION") + window.addFlags(View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) } + } else { // Switch to normal viewing mode. + // Show the system bars according to the API. + if (Build.VERSION.SDK_INT >= 30) { + // Show the system bars. + windowInsetsController.show(WindowInsets.Type.systemBars()) + } else { + /* Show the system bars. + * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. + * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. + * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. + * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. + */ - // Remove the `SYSTEM_UI` flags from the root frame layout. The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30. - @Suppress("DEPRECATION") - rootFrameLayout.systemUiVisibility = 0 + @Suppress("DEPRECATION") + window.clearFlags(View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) + } } } @@ -4759,13 +4818,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook // Toggle the full screen browsing mode. if (inFullScreenBrowsingMode) { // Switch to full screen mode. - // Handle display under cutouts for API < 35. - if (Build.VERSION.SDK_INT < 35) { - // Disable fits system windows if display under cutouts is enabled. - if (displayUnderCutouts) - rootFrameLayout.fitsSystemWindows = false - } - // Hide the app bar if specified. if (hideAppBar) { // App bar hiding is enabled. // Close the find on page bar if it is visible. @@ -4811,24 +4863,51 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook } } - /* Hide the system bars. - * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. - * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. - * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. - * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. - */ + // Hide the system bars. + if (Build.VERSION.SDK_INT >= 30) { + // Set the system bars to display transiently when swiped. + windowInsetsController.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - // The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30. - @Suppress("DEPRECATION") - rootFrameLayout.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY - } else { // Switch to normal viewing mode. - // Handle display under cutouts for API < 35. - if (Build.VERSION.SDK_INT < 35) { - // Enable fits system windows if display under cutouts is enabled. - if (displayUnderCutouts) - rootFrameLayout.fitsSystemWindows = true + // Hide the system bars. + windowInsetsController.hide(WindowInsets.Type.systemBars()) + } else { + /* Hide the system bars. + * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. + * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. + * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. + * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. + */ + + @Suppress("DEPRECATION") + window.addFlags(View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) } + // Disable fits system windows according to the configuration. + if (displayUnderCutouts) { // Display under cutouts. + // Disable fits system windows according to the API. + if (Build.VERSION.SDK_INT >= 35) { // The device is running API >= 35. + // Disable fits system windows. + browserFrameLayout.fitsSystemWindows = false + + // Manually update the padding, which isn't done on API >= 35 + browserFrameLayout.setPadding(0, 0, 0, 0) + } else { // The device is running API < 35. + // Disable fits system windows. + coordinatorLayout.fitsSystemWindows = false + bookmarksFrameLayout.fitsSystemWindows = false + + // Remove any padding on the bookmarks frame layout. + bookmarksFrameLayout.setPadding(0, 0, 0, 0) + } + } else if (Build.VERSION.SDK_INT < 35) { // The device is running API < 35 and display under cutouts is disabled. + // Disable fits system windows to display under the navigation bar. + coordinatorLayout.fitsSystemWindows = false + bookmarksFrameLayout.fitsSystemWindows = false + + // Remove any padding on the bookmarks frame layout. + bookmarksFrameLayout.setPadding(0, 0, 0, 0) + } + } else { // Switch to normal viewing mode. // Show the app bar if it was hidden. if (hideAppBar) { // Show the tab linear layout. @@ -4865,9 +4944,36 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook } } - // Remove the `SYSTEM_UI` flags from the root frame layout. The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30. - @Suppress("DEPRECATION") - rootFrameLayout.systemUiVisibility = 0 + // Enable fits system windows if display under cutouts is enabled. + if (displayUnderCutouts) { + // Enable fits system windows according to the API. + if (Build.VERSION.SDK_INT >= 35) { + browserFrameLayout.fitsSystemWindows = true + } else { + coordinatorLayout.fitsSystemWindows = true + bookmarksFrameLayout.fitsSystemWindows = true + } + } else if (Build.VERSION.SDK_INT < 35) { // The device is running API < 35 and display under cutouts is disabled. + // Enable fits system windows. + coordinatorLayout.fitsSystemWindows = true + bookmarksFrameLayout.fitsSystemWindows = true + } + + // Show the system bars according to the API. + if (Build.VERSION.SDK_INT >= 30) { + // Show the system bars. + windowInsetsController.show(WindowInsets.Type.systemBars()) + } else { + /* Show the system bars. + * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. + * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. + * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. + * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. + */ + + @Suppress("DEPRECATION") + window.clearFlags(View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) + } } // Consume the double-tap. @@ -4994,21 +5100,6 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook swipeRefreshLayout.isEnabled = nestedScrollWebView.scrollY == 0 else // Disable swipe to refresh. swipeRefreshLayout.isEnabled = false - - // Reinforce the system UI visibility flags if in full screen browsing mode. - // This hides the status and navigation bars, which are displayed if other elements are shown, like dialog boxes, the options menu, or the keyboard. - if (inFullScreenBrowsingMode) { - /* Hide the system bars. - * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. - * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. - * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. - * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. - */ - - // The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30. - @Suppress("DEPRECATION") - rootFrameLayout.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY - } } // Set the web chrome client. @@ -5098,44 +5189,75 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook // Enter full screen video. override fun onShowCustomView(video: View, callback: CustomViewCallback) { - // Handle display under cutouts for API < 35. - if (Build.VERSION.SDK_INT < 35) { - // Disable fits system windows if display under cutouts is enabled. - if (displayUnderCutouts) - rootFrameLayout.fitsSystemWindows = false - } - // Set the full screen video flag. displayingFullScreenVideo = true // Hide the keyboard. inputMethodManager.hideSoftInputFromWindow(nestedScrollWebView.windowToken, 0) - // Hide the coordinator layout. - coordinatorLayout.visibility = View.GONE + // Hide the browser view according to the API. + if ((Build.VERSION.SDK_INT < 35) && displayUnderCutouts) { // The device is running API < 35 and display under cutouts is enabled. + // Hide the tab linear layout. + tabsLinearLayout.visibility = View.GONE - /* Hide the system bars. - * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. - * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. - * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. - * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. - */ + // Hide the app bar. + appBar.hide() - // The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30. - @Suppress("DEPRECATION") - rootFrameLayout.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + // Hide the swipe refresh layout (which includes the WebView). + swipeRefreshLayout.visibility = View.GONE + + // Disable fits system windows. + coordinatorLayout.fitsSystemWindows = false + bookmarksFrameLayout.fitsSystemWindows = false + + // Remove any padding from the bookmark frame layout + bookmarksFrameLayout.setPadding(0, 0, 0, 0) + } else { // The device is running API >= 35 or display under cutouts is disabled. + // Hide the browser view. + browserFrameLayout.visibility = View.GONE + } + + // Hide the system bars according to the API. + if (Build.VERSION.SDK_INT >= 30) { + // Set the system bars to show transiently when swiped. + windowInsetsController.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + + // Hide the system bars. + windowInsetsController.hide(WindowInsets.Type.systemBars()) + } else { + /* Hide the system bars. + * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. + * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. + * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. + * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. + */ + + @Suppress("DEPRECATION") + window.addFlags(View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) + } // Disable the sliding drawers. drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) - // Add the video view to the full screen video frame layout. - fullScreenVideoFrameLayout.addView(video) + if ((Build.VERSION.SDK_INT < 35) && displayUnderCutouts) { + // Add the video view to the full screen video frame layout. + oldFullScreenVideoFrameLayout.addView(video) - // Show the full screen video frame layout. - fullScreenVideoFrameLayout.visibility = View.VISIBLE + // Show the full screen video frame layout. + oldFullScreenVideoFrameLayout.visibility = View.VISIBLE - // Disable the screen timeout while the video is playing. YouTube does this automatically, but not all other videos do. - fullScreenVideoFrameLayout.keepScreenOn = true + // Disable the screen timeout while the video is playing. YouTube does this automatically, but not all other videos do. + oldFullScreenVideoFrameLayout.keepScreenOn = true + } else { + // Add the video view to the full screen video frame layout. + fullScreenVideoFrameLayout.addView(video) + + // Show the full screen video frame layout. + fullScreenVideoFrameLayout.visibility = View.VISIBLE + + // Disable the screen timeout while the video is playing. YouTube does this automatically, but not all other videos do. + fullScreenVideoFrameLayout.keepScreenOn = true + } } // Exit full screen video. @@ -5155,7 +5277,8 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook // Request an openable file. fileChooserIntent.addCategory(Intent.CATEGORY_OPENABLE) - // Set the file type to everything. The file chooser params cannot be used to create the intent because it only selects the first specified file type. See . + // Set the file type to everything. The file chooser params cannot be used to create the intent because it only selects the first specified file type. + // See . fileChooserIntent.type = "*/*" // Launch the file chooser intent. diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/SettingsActivity.kt b/app/src/main/java/com/stoutner/privacybrowser/activities/SettingsActivity.kt index 80c1f6f3..db10eb5a 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/SettingsActivity.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/SettingsActivity.kt @@ -1,20 +1,20 @@ -/* - * Copyright 2016-2022 Soren Stoutner . +/* SPDX-License-Identifier: GPL-3.0-or-later + * SPDX-FileCopyrightText: 2016-2024 Soren Stoutner * * This file is part of Privacy Browser Android . * - * Privacy Browser Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. * - * Privacy Browser Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. * - * You should have received a copy of the GNU General Public License - * along with Privacy Browser Android. If not, see . + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . */ package com.stoutner.privacybrowser.activities diff --git a/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.kt b/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.kt index 490faf46..0431e5a5 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.kt @@ -33,7 +33,6 @@ import android.widget.ArrayAdapter import androidx.appcompat.app.AppCompatDelegate import androidx.preference.Preference -import androidx.preference.PreferenceCategory import androidx.preference.PreferenceFragmentCompat import com.stoutner.privacybrowser.R @@ -168,7 +167,6 @@ class SettingsFragment : PreferenceFragmentCompat() { // Set the preference dependencies. domStoragePreference.dependency = getString(R.string.javascript_key) hideAppBarPreference.dependency = getString(R.string.full_screen_browsing_mode_key) - displayUnderCutoutsPreference.dependency = getString(R.string.full_screen_browsing_mode_key) // Get strings from the preferences. val userAgentName = sharedPreferences.getString(getString(R.string.user_agent_key), getString(R.string.user_agent_default_value)) @@ -182,15 +180,6 @@ class SettingsFragment : PreferenceFragmentCompat() { val fullScreenBrowsingMode = sharedPreferences.getBoolean(getString(R.string.full_screen_browsing_mode_key), false) val clearEverything = sharedPreferences.getBoolean(getString(R.string.clear_everything_key), true) - // Remove the display under cutouts preferences if the API is >= 35 as Google broke this functionality. - if (Build.VERSION.SDK_INT >= 35) { - // Get a handle for the full screen category. - val fullScreenCategory = findPreference(getString(R.string.full_screen_category_key))!! - - // Remove the display under cutouts preferences. - fullScreenCategory.removePreference(displayUnderCutoutsPreference) - } - // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list is disabled. fanboySocialBlockingListPreference.isEnabled = !fanboyAnnoyanceListEnabled @@ -926,13 +915,14 @@ class SettingsFragment : PreferenceFragmentCompat() { getString(R.string.display_under_cutouts_key) -> { // Update the icon. - if (sharedPreferences.getBoolean(getString(R.string.display_under_cutouts_key), true)) + if (sharedPreferences.getBoolean(getString(R.string.display_under_cutouts_key), false)) displayUnderCutoutsPreference.setIcon(R.drawable.display_under_cutouts_enabled) else displayUnderCutoutsPreference.setIcon(R.drawable.display_under_cutouts_disabled) - // Restart Privacy Browser. - restartPrivacyBrowser() + // Restart Privacy Browser if the API < 35. + if (Build.VERSION.SDK_INT < 35) + restartPrivacyBrowser() } getString(R.string.clear_everything_key) -> { diff --git a/app/src/main/res/layout-w900dp/bookmarks_drawer_bottom_appbar.xml b/app/src/main/res/layout-w900dp/bookmarks_drawer_bottom_appbar.xml index 952eab6e..fc4756e2 100644 --- a/app/src/main/res/layout-w900dp/bookmarks_drawer_bottom_appbar.xml +++ b/app/src/main/res/layout-w900dp/bookmarks_drawer_bottom_appbar.xml @@ -1,22 +1,23 @@ + You should have received a copy of the GNU General Public License along with + this program. If not, see . --> + You should have received a copy of the GNU General Public License along with + this program. If not, see . --> + You should have received a copy of the GNU General Public License along with + this program. If not, see . --> + android:layout_gravity="end" > + You should have received a copy of the GNU General Public License along with + this program. If not, see . --> . --> - + android:layout_width="match_parent" > - - - - - + android:layout_width="match_parent" > + + + + + - - - - - - - - + android:layout_width="match_parent" > - - - - + android:layout_width="match_parent" /> + - - - - - - + + android:theme="@style/PrivacyBrowserAppBar" + android:layout_gravity="bottom" + app:layout_dodgeInsetEdges="bottom" > - - - - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + android:layout_width="match_parent" > + + + + + + - - - - - - - - diff --git a/app/src/main/res/layout/main_framelayout_top_appbar.xml b/app/src/main/res/layout/main_framelayout_top_appbar.xml index 4bf59f5c..2a281a5e 100644 --- a/app/src/main/res/layout/main_framelayout_top_appbar.xml +++ b/app/src/main/res/layout/main_framelayout_top_appbar.xml @@ -19,185 +19,225 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . --> - + android:layout_width="match_parent" > - - - + android:layout_width="match_parent" > - - + + android:focusable="true" + android:focusableInTouchMode="true" > - - + + android:theme="@style/PrivacyBrowserAppBar" > - - + + - - + - - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + android:orientation="horizontal" + app:layout_scrollFlags="scroll|enterAlways|snap" > + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + - - - - - - - + + + + + + + - - - - + android:layout_width="match_parent" > + + + + + + - - - - - - - - diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 6800f074..c321e8c4 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -1,28 +1,27 @@ + You should have received a copy of the GNU General Public License along with + this program. If not, see . --> @@ -645,8 +644,6 @@ App-Leiste verstecken Versteckt die App-Leiste, die die URL enthält. Unter Aussparungen anzeigen - Zeigt die Internetseite unterhalb von Ausschnitten wie etwa Kamera-Einbuchtungen. - Ist diese Option aktiv, wrd Privacy Browser auch unterhalb der Tastatur dargestellt. Das Ändern dieser Einstellung startet Privacy Browser neu. Alles löschen Löscht Cookies, DOM-Storage, das Logcat Systemlogbuch und den WebView-Cache, sowie die gesamten “app_webview”- und “cache”-Ordner. Cookies löschen diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 65bcc8d3..05242908 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -1,24 +1,25 @@ + You should have received a copy of the GNU General Public License along with + this program. If not, see . --> @@ -642,8 +643,6 @@ Ocultar la barra de aplicaciones Ocultar la barra de aplicaciones que contiene la URL. Mostrar bajo los recortes - Mostrar el sitio web bajo los recortes, como las muescas de la cámara. Cuando está opción está activada, Navegador Privado también se dibujará bajo el teclado. - Al cambiar esta configuración se reiniciará Navegador Privado. Borrar todo Borra cookies, almacenamiento DOM, el logcat y la caché de WebView. A continuación borra manualmente los directorios “app_webview” y “cache”. Borrar cookies diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 3cb6f38f..afb0e201 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -1,24 +1,25 @@ + You should have received a copy of the GNU General Public License along with + this program. If not, see . --> @@ -636,8 +637,6 @@ Masquer la barre d\'application Masquer la barre d\'applications contenant l\'URL. Afficher sous les éléments découpés - Affiche le site web sous les éléments découpés, tels que les encoches d\'appareil photo. - Lorsque ce paramètre est activé, Privacy Browser sera également affiché sous le clavier. La modification de ce paramètre entraînera le redémarrage de Privacy Browser. Tout effacer Efface les cookies, le stockage DOM, le logcat et le cache de WebView. Supprime ensuite manuellement les répertoires entiers «app_webview» et «cache». Effacer les cookies diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 90f62100..7e70bca6 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -1,24 +1,25 @@ + You should have received a copy of the GNU General Public License along with + this program. If not, see . --> @@ -642,8 +643,6 @@ Nascondi la barra dell\'applicazione Nasconde la barra che contiene l\'URL. Visualizza sotto i ritagli dello schermo - Visualizza il sito web sotto i ritagli dello schermo come quello della fotocamera. - Quando questa opzione è abilitata, Privacy Browser sarà anche visualizzato sotto alla tastiera. La modifica di questa impostazione provoca il riavvio di Privacy Browser. Elimina tutto Cancella i cookies, il DOM storage, il logcat e la cache di WebView. Cancella completamente le cartelle “app_webview” e “cache”. Elimina i cookie diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index cf80c4f4..95b4e4fe 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -1,24 +1,25 @@ + You should have received a copy of the GNU General Public License along with + this program. If not, see . --> @@ -44,7 +45,7 @@ Adicionar aba Fechar aba Nova aba - Carregando... + Carregando… Erro:\u0020 %1$s Aplicar diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index aae2a01c..d581f172 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -1,22 +1,23 @@ + You should have received a copy of the GNU General Public License along with + this program. If not, see . --> @@ -638,8 +639,6 @@ Скрыть панель приложения Скрывает панель приложения, которая содержит URL. Отображение под вырезом - Отрисовывать сайт под вырезами, например, под камерой. Если эта опция включена, Privacy Browser также будет отображаться под клавиатурой. - Изменение этой настройки приведет к перезапуску Privacy Browser. Очистить все Очищает cookie, DOM-хранилище, logcat и кэш WebView. После этого вручную удаляет каталоги "app_webview" и "cache". Очистить cookie diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 358bf367..7a86538e 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -1,22 +1,23 @@ + You should have received a copy of the GNU General Public License along with + this program. If not, see . --> diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 441a17b3..3ae2ffc1 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -1,24 +1,25 @@ + You should have received a copy of the GNU General Public License along with + this program. If not, see . --> Hide the app bar that contains the URL. Display under cutouts Draw the website under cutouts, like camera notches. When this is enabled, Privacy Browser will also be drawn under the keyboard. - Changing this setting will restart Privacy Browser. + Changing this setting will restart Privacy Browser on Android < 15. Clear everything Clears cookies, DOM storage, the logcat, and WebView’s cache. Then manually deletes the entire “app_webview” and “cache” directories. Clear cookies