commit 255492a02c4bc58c5a9347074934bb7651884f8e
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Thu Sep 9 23:21:33 2021 +0200

    Improvements for the PopupWindows: now they work:
    
    1) on Android 11, everywhere
    2) on Android 10,9,8.1,8.0 - in case of fullscreen and split-screen modes; pop-up mode still does not work.
    3) on Android <= 7.0 : there should be no pop-up mode, so they should be working in all cases

diff --git a/src/main/java/org/distorted/screens/RubikScreenPlay.java b/src/main/java/org/distorted/screens/RubikScreenPlay.java
index 332dc512..d2193cc5 100644
--- a/src/main/java/org/distorted/screens/RubikScreenPlay.java
+++ b/src/main/java/org/distorted/screens/RubikScreenPlay.java
@@ -22,8 +22,10 @@ package org.distorted.screens;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.graphics.drawable.BitmapDrawable;
+import android.os.Build;
 import android.os.Bundle;
 import android.util.TypedValue;
+import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.Button;
@@ -74,6 +76,9 @@ public class RubikScreenPlay extends RubikScreenBase
   private float mButtonSize, mMenuItemSize, mMenuTextSize;
   private int mColCount, mRowCount, mMaxRowCount;
   private LinearLayout mPlayLayout;
+  private int mUpperBarHeight;
+
+  private boolean mIsFullScreen;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -88,6 +93,7 @@ public class RubikScreenPlay extends RubikScreenBase
     {
     float width = act.getScreenWidthInPixels();
     float height= act.getScreenHeightInPixels();
+    mUpperBarHeight = act.getHeightUpperBar();
 
     mMenuTextSize = width*RubikActivity.MENU_MED_TEXT_SIZE;
     mButtonSize   = width*RubikActivity.BUTTON_TEXT_SIZE;
@@ -121,7 +127,6 @@ public class RubikScreenPlay extends RubikScreenBase
   private void setupObjectButton(final RubikActivity act, final float width)
     {
     final int margin  = (int)(width*RubikActivity.MARGIN);
-    final int upperBarHeight = act.getHeightUpperBar();
     final int icon = RubikActivity.getDrawable(R.drawable.ui_small_cube_menu,R.drawable.ui_medium_cube_menu, R.drawable.ui_big_cube_menu, R.drawable.ui_huge_cube_menu);
 
     mObjButton = new TransparentImageButton(act, icon, width,LinearLayout.LayoutParams.MATCH_PARENT);
@@ -136,13 +141,7 @@ public class RubikScreenPlay extends RubikScreenBase
           int rowCount = Math.min(mMaxRowCount,mRowCount);
           View popupView = mObjectPopup.getContentView();
           popupView.setSystemUiVisibility(RubikActivity.FLAGS);
-
-          view.getLocationOnScreen(mLocation);
-          final int x = mLocation[0];
-          final int y = mLocation[1]+upperBarHeight+margin;
-
-          mObjectPopup.showAsDropDown(view);
-          mObjectPopup.update(x,y,mObjectSize*mColCount,mObjectSize*rowCount);
+          displayPopup(act,view,mObjectPopup,mObjectSize*mColCount,mObjectSize*rowCount,margin,margin);
           }
         }
       });
@@ -153,8 +152,7 @@ public class RubikScreenPlay extends RubikScreenBase
   private void setupPlayButton(final RubikActivity act, final float width, final float height)
     {
     final int margin   = (int)(width*RubikActivity.MARGIN);
-    final int upperBarHeight = act.getHeightUpperBar();
-    final int maxHeight= (int)(0.9f*(height-upperBarHeight) );
+    final int maxHeight= (int)(0.9f*(height-mUpperBarHeight) );
 
     mPlayButton = new TransparentButton(act, R.string.play, mButtonSize, width);
 
@@ -167,20 +165,12 @@ public class RubikScreenPlay extends RubikScreenBase
           {
           View popupView = mPlayPopup.getContentView();
           popupView.setSystemUiVisibility(RubikActivity.FLAGS);
-
-          view.getLocationOnScreen(mLocation);
-          int width = view.getWidth();
-
           final int sizeIndex = ObjectList.getSizeIndex(mObject,mSize);
           final int dbLevel = ObjectList.getDBLevel(mObject, sizeIndex);
           final int levelsShown = Math.min(dbLevel,LEVELS_SHOWN);
           final int popupHeight = (int)(levelsShown*(mMenuItemSize+margin)+3*margin+mMenuItemSize*(LAST_BUTTON-1.0f));
-          final int realHeight  = Math.min(popupHeight,maxHeight);
-          final int x = mLocation[0]+width-mPlayLayoutWidth;
-          final int y = mLocation[1]+upperBarHeight+margin;
-
-          mPlayPopup.showAsDropDown(view);
-          mPlayPopup.update(x,y,mPlayLayoutWidth,realHeight);
+          final int realHeight = Math.min(popupHeight,maxHeight);
+          displayPopup(act,view,mPlayPopup,mPlayLayoutWidth,realHeight,margin,margin);
           }
         }
       });
@@ -192,7 +182,6 @@ public class RubikScreenPlay extends RubikScreenBase
     {
     final int margin  = (int)(width*RubikActivity.MARGIN);
     final int icon = RubikActivity.getDrawable(R.drawable.ui_small_menu,R.drawable.ui_medium_menu, R.drawable.ui_big_menu, R.drawable.ui_huge_menu);
-    final int upperBarHeight = act.getHeightUpperBar();
 
     mMenuButton = new TransparentImageButton(act, icon, width,LinearLayout.LayoutParams.MATCH_PARENT);
 
@@ -205,14 +194,7 @@ public class RubikScreenPlay extends RubikScreenBase
           {
           View popupView = mMenuPopup.getContentView();
           popupView.setSystemUiVisibility(RubikActivity.FLAGS);
-
-          view.getLocationOnScreen(mLocation);
-          int width = view.getWidth();
-          final int x = mLocation[0]+(width-mMenuLayoutWidth)/2;
-          final int y = mLocation[1]+upperBarHeight+margin;
-
-          mMenuPopup.showAsDropDown(view);
-          mMenuPopup.update(x,y,mMenuLayoutWidth,mMenuLayoutHeight);
+          displayPopup(act,view,mMenuPopup,mMenuLayoutWidth,mMenuLayoutHeight,(int)(-width/12),margin);
           }
         }
       });
@@ -228,8 +210,7 @@ public class RubikScreenPlay extends RubikScreenBase
     int cubeWidth = bd.getIntrinsicWidth();
     int margin = (int)(width*RubikActivity.LARGE_MARGIN);
     mObjectSize = (int)(cubeWidth + 2*margin + 0.5f);
-    int upperBarHeight  = act.getHeightUpperBar();
-    mMaxRowCount = (int)(0.9f*(height-upperBarHeight)/mObjectSize);
+    mMaxRowCount = (int)(0.9f*(height-mUpperBarHeight)/mObjectSize);
     GridLayout objectGrid = new GridLayout(act);
     mObjectPopup = new PopupWindow(act);
     mObjectPopup.setFocusable(true);
@@ -508,6 +489,34 @@ public class RubikScreenPlay extends RubikScreenBase
     return true;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// work around lame bugs in Android's version <= 10 pop-up and split-screen modes
+
+  private void displayPopup(RubikActivity act, View view, PopupWindow window, int w, int h, int xoff, int yoff)
+    {
+    View topLayout = act.findViewById(R.id.relativeLayout);
+    topLayout.getLocationOnScreen(mLocation);
+    mIsFullScreen = (mLocation[1]==0);
+
+    // if on Android 11 or we are fullscreen
+    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R || mIsFullScreen )
+      {
+      window.showAsDropDown(view, xoff, yoff, Gravity.CENTER);
+      window.update(view, w, h);
+      }
+    else  // Android 10 or below in pop-up mode or split-screen mode
+      {
+      view.getLocationOnScreen(mLocation);
+      int width  = view.getWidth();
+      int height = view.getHeight();
+      int x = mLocation[0]+(width-w)/2;
+      int y = mLocation[1]+height+yoff;
+
+      window.showAsDropDown(view);
+      window.update(x,y,w,h);
+      }
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private void adjustLevels(final RubikActivity act)
