Skip to content

Commit

Permalink
Add support for display cutouts in manifest and add methods to retrie…
Browse files Browse the repository at this point in the history
…ve data (#2969)

* Fresh changes of the display-cutout functionality

* Fine tuning + added tools

* Updated lib

* Add missing None for default value while grabbing the sizes
  • Loading branch information
kuzeyron authored Feb 13, 2024
1 parent 4c5fff6 commit 9cd5220
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 0 deletions.
4 changes: 4 additions & 0 deletions doc/source/buildoptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ options (this list may not be exhaustive):
- ``--permission``: A permission that needs to be declared into the App ``AndroidManifest.xml``.
For multiple permissions, add multiple ``--permission`` arguments.
``--home-app`` Gives you the option to set your application as a home app (launcher) on your Android device.
``--display-cutout``: A display cutout is an area on some devices that extends into the display surface.
It allows for an edge-to-edge experience while providing space for important sensors on the front of the device.
(Available options are ``default``, ``shortEdges``, ``never`` and defaults to ``never``)
`Android documentation <https://developer.android.com/develop/ui/views/layout/display-cutout>`__.

.. Note ::
``--permission`` accepts the following syntaxes:
Expand Down
3 changes: 3 additions & 0 deletions pythonforandroid/bootstraps/common/build/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,9 @@ def create_argument_parser():
'launcher, rather than a single app.'))
ap.add_argument('--home-app', dest='home_app', action='store_true', default=False,
help=('Turn your application into a home app (launcher)'))
ap.add_argument('--display-cutout', dest='display_cutout', default='never',
help=('Enables display-cutout that renders around the area (notch) on '
'some devices that extends into the display surface'))
ap.add_argument('--permission', dest='permissions', action='append', default=[],
help='The permissions to give this app.', nargs='+')
ap.add_argument('--meta-data', dest='meta_data', action='append', default=[],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|fontScale|uiMode{% if args.min_sdk_version >= 8 %}|uiMode{% endif %}{% if args.min_sdk_version >= 13 %}|screenSize|smallestScreenSize{% endif %}{% if args.min_sdk_version >= 17 %}|layoutDirection{% endif %}{% if args.min_sdk_version >= 24 %}|density{% endif %}"
android:screenOrientation="{{ args.manifest_orientation }}"
android:exported="true"
android:theme="@style/KivySupportCutout"
{% if args.activity_launch_mode %}
android:launchMode="{{ args.activity_launch_mode }}"
{% endif %}
Expand Down
10 changes: 10 additions & 0 deletions pythonforandroid/bootstraps/qt/build/templates/strings.tmpl.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="KivySupportCutout">
<item name="android:windowNoTitle">true</item>
<!-- Display cutout is an area on some devices that extends into the display surface -->
{% if args.display_cutout != 'never'%}
<item name="android:windowLayoutInDisplayCutoutMode">{{ args.display_cutout }}</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:windowFullscreen">true</item>
{% endif %}
</style>
<string name="app_name">{{ args.name }}</string>
<string name="private_version">{{ private_version }}</string>
<string name="presplash_color">{{ args.presplash_color }}</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|fontScale|uiMode{% if args.min_sdk_version >= 8 %}|uiMode{% endif %}{% if args.min_sdk_version >= 13 %}|screenSize|smallestScreenSize{% endif %}{% if args.min_sdk_version >= 17 %}|layoutDirection{% endif %}{% if args.min_sdk_version >= 24 %}|density{% endif %}"
android:screenOrientation="{{ args.manifest_orientation }}"
android:exported="true"
android:theme="@style/KivySupportCutout"
{% if args.activity_launch_mode %}
android:launchMode="{{ args.activity_launch_mode }}"
{% endif %}
Expand Down
10 changes: 10 additions & 0 deletions pythonforandroid/bootstraps/sdl2/build/templates/strings.tmpl.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="KivySupportCutout">
<item name="android:windowNoTitle">true</item>
<!-- Display cutout is an area on some devices that extends into the display surface -->
{% if args.display_cutout != 'never'%}
<item name="android:windowLayoutInDisplayCutoutMode">{{ args.display_cutout }}</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:windowFullscreen">true</item>
{% endif %}
</style>
<string name="app_name">{{ args.name }}</string>
<string name="private_version">{{ private_version }}</string>
<string name="presplash_color">{{ args.presplash_color }}</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|fontScale|uiMode{% if args.min_sdk_version >= 8 %}|uiMode{% endif %}{% if args.min_sdk_version >= 13 %}|screenSize|smallestScreenSize{% endif %}{% if args.min_sdk_version >= 17 %}|layoutDirection{% endif %}{% if args.min_sdk_version >= 24 %}|density{% endif %}"
android:screenOrientation="{{ args.manifest_orientation }}"
android:exported="true"
android:theme="@style/KivySupportCutout"
{% if args.activity_launch_mode %}
android:launchMode="{{ args.activity_launch_mode }}"
{% endif %}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="KivySupportCutout">
<item name="android:windowNoTitle">true</item>
<!-- Display cutout is an area on some devices that extends into the display surface -->
{% if args.display_cutout != 'never'%}
<item name="android:windowLayoutInDisplayCutoutMode">{{ args.display_cutout }}</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:windowFullscreen">true</item>
{% endif %}
</style>
<string name="app_name">{{ args.name }}</string>
<string name="private_version">{{ private_version }}</string>
<string name="presplash_color">{{ args.presplash_color }}</string>
Expand Down
72 changes: 72 additions & 0 deletions pythonforandroid/recipes/android/src/android/display_cutout.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from jnius import autoclass
from kivy.core.window import Window

from android import mActivity

__all__ = ('get_cutout_pos', 'get_cutout_size', 'get_width_of_bar',
'get_height_of_bar', 'get_size_of_bar')


def _core_cutout():
decorview = mActivity.getWindow().getDecorView()
cutout = decorview.rootWindowInsets.displayCutout

return cutout.boundingRects.get(0)


def get_cutout_pos():
""" Get position of the display-cutout.
Returns integer for each positions (xy)
"""
try:
cutout = _core_cutout()
return int(cutout.left), Window.height - int(cutout.height())
except Exception:
# Doesn't have a camera builtin with the display
return 0, 0


def get_cutout_size():
""" Get the size (xy) of the front camera.
Returns size with float values
"""
try:
cutout = _core_cutout()
return float(cutout.width()), float(cutout.height())
except Exception:
# Doesn't have a camera builtin with the display
return 0., 0.


def get_height_of_bar(bar_target=None):
""" Get the height of either statusbar or navigationbar
bar_target = status or navigation and defaults to status
"""
bar_target = bar_target or 'status'

if bar_target not in ('status', 'navigation'):
raise Exception("bar_target must be 'status' or 'navigation'")

try:
displayMetrics = autoclass('android.util.DisplayMetrics')
mActivity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics())
resources = mActivity.getResources()
resourceId = resources.getIdentifier(f'{bar_target}_bar_height', 'dimen',
'android')

return float(max(resources.getDimensionPixelSize(resourceId), 0))
except Exception:
# Getting the size is not supported on older Androids
return 0.


def get_width_of_bar(bar_target=None):
" Get the width of the bar "
return Window.width


def get_size_of_bar(bar_target=None):
""" Get the size of either statusbar or navigationbar
bar_target = status or navigation and defaults to status
"""
return get_width_of_bar(), get_height_of_bar(bar_target)

0 comments on commit 9cd5220

Please sign in to comment.