Screen position problem on landscape orientation with speaker cutout

Hi everyone,

I’m having a problem across all apps I build for Android, if the device I’m building for has a speaker cutout.

If the phone has one, like my Google Pixel 3XL, the main window is shifted to the left when I rotate the phone counter clockwise and it leaves a space the size of the speaker cutout to the right of the screen… when I rotate clockwise everything is fine.

I uploaded a video on which you can observe the problem here:

Does anyone know how to remedy this? So far I just locked screen rotation for my Android builds, but that is more of a hacky solution to the problem…

1 Like

After more investigation: the problem here is that the whole DocumentWindow seems to be shifted to the left, not only content. Is there a way to remedy this easily and shift the whole DocumentWindow? I could write the JNI needed to use the Android Window Insets class to figure out the speaker inlet size, but how would I then use the determined value to shift the entire window?

I’ve also ran into that exact problem multiple times, and got to this same conclusion… It seems like when there’s a cutout, juce gets confused as to where the origin is.

1 Like

but interestingly it does so only on Landscape orientation… on Portrait orientation the Speaker cutout just gets respected and the window starts on the right y position… because of that fact it seems like the fix should be simple enough, but I have no idea where to even look. The deeper I dig the more confused I get about any way to fix this… maybe @ed95 has a hot tip where to look or how to approach this? How is the DocumentWindow position managed on Android? Where is the cutout being managed for Portrait orientations?

2 Likes

same problem here!

So I’ve implemented all the JNI down to WindowInset.getDisplayCutout()

Unfortunately this is where it stops, because, as the documentation for it states, this will return null if it already has been “consumed” and this is what happens… instead of a DisplayCutout object i just get null. Meaning JUCE seems to consume that value but I can’t figure out where that happens…

I am also having the same problem and this seems to be a bug in juce_android_Windowing.cpp

Specifically “void setBounds (const Rectangle& userRect, bool isNowFullScreen) override” is fed with an incorrect rectangle object. (The width and height of the rectangle correctly take the safe area into account, but the x position does not.)

At the moment, I am still not sure who is supplying the incorrect rect. Will need to dig a little bit more.

Ok, I think I solved it. Using “android:windowLayoutInDisplayCutoutMode” is probably the most elegant solution at the moment. You can read more about android:windowLayoutInDisplayCutoutMode here: https://developer.android.com/guide/topics/display-cutout

  1. Create the following android style.xml file, and put it under a folder such as “./PlatformSpecificFiles/Android/res”

<?xml version=“1.0” encoding=“utf-8”?>
<resources>
<style name=“ActivityTheme"parent=”@android:style/Theme.NoTitleBar">
<item name=“android:windowLayoutInDisplayCutoutMode”>
shortEdges <!-- default, shortEdges, never –>
</item>
</style>
</resources>

(Note: JUCE forum does some weird quotation mark conversion when I post raw XML, make sure you replace all the quotation marks with " locally when copying this file.)

  1. Add “./PlatformSpecificFiles/Android/res” into Android exporter’s “Resource folders” field
  2. Change the “Android Theme” under the exporter to “@style/ActivityTheme”

This will prevent the app from drawing under the cut-off, and it works on all orientations.

4 Likes

oh wow, this is awesome @autumnrockdev ! I’ll test this next week! Thanks for figuring this out, this has been irking me for the longest time…

@vberthiaume check this out

2 Likes

@autumnrockdev

Edited

Does the xml file have to have a specific file name? I can’t get it to work, I always get that error:

<PathToMyJuceProj>/Builds/Android/app/src/main/AndroidManifest.xml:15:3-24:17: AAPT: error: resource style/ActivityTheme (aka <My.App.Identifier>:style/ActivityTheme) not found.

I’ve got my xml in a Folder <MyJuceProjDir>/Resources/Android and put that into the “Resource folders” field in Projucer, tried all possible numbers of ./ and ../ to make Android Studio find it, but I can’t seem to get it to work… (Also on your code block up there you have mixed up quotation marks (, "), which make the xml invalid, i fixed this locally of course)

Edited2

//EDIT:
So it turns out it doesn’t find it, when I specify the folder path under “Resource folders”, but I rather have to specify the xml file itself under Debug/Release reporters in the Extra Android XML Value Resources field.

It now finds the file and correctly applies the “No Title Bar” parent theme, so I know it works and finds the file. Unfortunately, neither the shortEdges nor the never options for the <item name="android:windowLayoutInDisplayCutoutMode"> element seem to do the trick for me… On counter clockwise landscape orientation my Google Pixel 3XL draws the Main Component below the speaker cutout :frowning:

// EDIT2:
I got it working :slight_smile: Turns out my previous hacky fixes for this problem killed the effects of the xml file.
So to summarise what I had to change to make your thingy work:

  • I had to put the xml file directly into the “Extra Android XML Value Resources” field directly on Debug/Release exporters, specifying the containing directory in the “Android Resources” field didn’t work for me.
  • I had to fix quotation symbols from your code block up there because there were different kinds mixed up, killing the xml format

Thanks again for sharing this, this has fixed a problem I had forever!

2 Likes

Welcome! :smiley:

Yeah, you have to replace all the quotation marks with " locally when copying the XML above, JUCE forum does some weird quotation mark conversion when I post raw XML.

Regarding the XML file name, the file has to be called styles.xml, and its parent folder has to be called values, otherwise, Android studio will not be able to find it.

For example:

My styles.xml is placed under [project folder]/PlatformSpecificFiles/Android/res/values/styles.xml

The path I fill into JUCE Android Exporter’s resource field is ./PlatformSpecificFiles/Android/res

What JUCE exporter does here is basically taking every file under “./PlatformSpecificFiles/Android/res” and copying them into the Android project’s res folder.

2 Likes