Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 00af00c4 authored by Andrii Kulian's avatar Andrii Kulian Committed by Diego Vela
Browse files

Add RTL support in split activity organizer

Bug: 190433398
Test: Change locale to RLT, test in demo app
Change-Id: I941020c422d4fdf5bcb1a4f03f6fbd8b7aef30c3
parent 47a107ad
Loading
Loading
Loading
Loading
+71 −27
Original line number Original line Diff line number Diff line
@@ -19,11 +19,14 @@ package androidx.window.extensions.embedding;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;


import android.app.Activity;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IBinder;
import android.util.LayoutDirection;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowInsets;
import android.view.WindowMetrics;
import android.view.WindowMetrics;
import android.window.TaskFragmentCreationParams;
import android.window.TaskFragmentCreationParams;
@@ -40,13 +43,13 @@ import java.util.concurrent.Executor;
 * {@link SplitController}.
 * {@link SplitController}.
 */
 */
class SplitPresenter extends JetpackTaskFragmentOrganizer {
class SplitPresenter extends JetpackTaskFragmentOrganizer {
    private static final int POSITION_LEFT = 0;
    private static final int POSITION_START = 0;
    private static final int POSITION_RIGHT = 1;
    private static final int POSITION_END = 1;
    private static final int POSITION_FILL = 2;
    private static final int POSITION_FILL = 2;


    @IntDef(value = {
    @IntDef(value = {
            POSITION_LEFT,
            POSITION_START,
            POSITION_RIGHT,
            POSITION_END,
            POSITION_FILL,
            POSITION_FILL,
    })
    })
    private @interface Position {}
    private @interface Position {}
@@ -94,13 +97,15 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        final WindowContainerTransaction wct = new WindowContainerTransaction();


        final Rect parentBounds = getParentContainerBounds(primaryActivity);
        final Rect parentBounds = getParentContainerBounds(primaryActivity);
        final Rect primaryRectBounds = getBoundsForPosition(POSITION_LEFT, parentBounds, rule);
        final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule,
                isLtr(primaryActivity, rule));
        final TaskFragmentContainer primaryContainer = prepareContainerForActivity(wct,
        final TaskFragmentContainer primaryContainer = prepareContainerForActivity(wct,
                primaryActivity, primaryRectBounds, null);
                primaryActivity, primaryRectBounds, null);


        // Create new empty task fragment
        // Create new empty task fragment
        TaskFragmentContainer secondaryContainer = mController.newContainer(null);
        final TaskFragmentContainer secondaryContainer = mController.newContainer(null);
        final Rect secondaryRectBounds = getBoundsForPosition(POSITION_RIGHT, parentBounds, rule);
        final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds,
                rule, isLtr(primaryActivity, rule));
        createTaskFragment(wct, secondaryContainer.getTaskFragmentToken(),
        createTaskFragment(wct, secondaryContainer.getTaskFragmentToken(),
                primaryActivity.getActivityToken(), secondaryRectBounds,
                primaryActivity.getActivityToken(), secondaryRectBounds,
                WINDOWING_MODE_MULTI_WINDOW);
                WINDOWING_MODE_MULTI_WINDOW);
@@ -133,11 +138,13 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        final WindowContainerTransaction wct = new WindowContainerTransaction();


        final Rect parentBounds = getParentContainerBounds(primaryActivity);
        final Rect parentBounds = getParentContainerBounds(primaryActivity);
        final Rect primaryRectBounds = getBoundsForPosition(POSITION_LEFT, parentBounds, rule);
        final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule,
                isLtr(primaryActivity, rule));
        final TaskFragmentContainer primaryContainer = prepareContainerForActivity(wct,
        final TaskFragmentContainer primaryContainer = prepareContainerForActivity(wct,
                primaryActivity, primaryRectBounds, null);
                primaryActivity, primaryRectBounds, null);


        final Rect secondaryRectBounds = getBoundsForPosition(POSITION_RIGHT, parentBounds, rule);
        final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds, rule,
                isLtr(primaryActivity, rule));
        final TaskFragmentContainer secondaryContainer = prepareContainerForActivity(wct,
        final TaskFragmentContainer secondaryContainer = prepareContainerForActivity(wct,
                secondaryActivity, secondaryRectBounds, primaryContainer);
                secondaryActivity, secondaryRectBounds, primaryContainer);


@@ -209,8 +216,10 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
    void startActivityToSide(@NonNull Activity launchingActivity, @NonNull Intent activityIntent,
    void startActivityToSide(@NonNull Activity launchingActivity, @NonNull Intent activityIntent,
            @Nullable Bundle activityOptions, @NonNull SplitRule rule) {
            @Nullable Bundle activityOptions, @NonNull SplitRule rule) {
        final Rect parentBounds = getParentContainerBounds(launchingActivity);
        final Rect parentBounds = getParentContainerBounds(launchingActivity);
        final Rect primaryRectBounds = getBoundsForPosition(POSITION_LEFT, parentBounds, rule);
        final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule,
        final Rect secondaryRectBounds = getBoundsForPosition(POSITION_RIGHT, parentBounds, rule);
                isLtr(launchingActivity, rule));
        final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds, rule,
                isLtr(launchingActivity, rule));


        TaskFragmentContainer primaryContainer = mController.getContainerWithActivity(
        TaskFragmentContainer primaryContainer = mController.getContainerWithActivity(
                launchingActivity.getActivityToken());
                launchingActivity.getActivityToken());
@@ -243,8 +252,15 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
        // Getting the parent bounds using the updated container - it will have the recent value.
        // Getting the parent bounds using the updated container - it will have the recent value.
        final Rect parentBounds = getParentContainerBounds(updatedContainer);
        final Rect parentBounds = getParentContainerBounds(updatedContainer);
        final SplitRule rule = splitContainer.getSplitRule();
        final SplitRule rule = splitContainer.getSplitRule();
        final Rect primaryRectBounds = getBoundsForPosition(POSITION_LEFT, parentBounds, rule);
        final Activity activity = splitContainer.getPrimaryContainer().getTopNonFinishingActivity();
        final Rect secondaryRectBounds = getBoundsForPosition(POSITION_RIGHT, parentBounds, rule);
        if (activity == null) {
            return;
        }
        final boolean isLtr = isLtr(activity, rule);
        final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule,
                isLtr);
        final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds, rule,
                isLtr);


        // If the task fragments are not registered yet, the positions will be updated after they
        // If the task fragments are not registered yet, the positions will be updated after they
        // are created again.
        // are created again.
@@ -300,29 +316,57 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {


    @NonNull
    @NonNull
    private Rect getBoundsForPosition(@Position int position, @NonNull Rect parentBounds,
    private Rect getBoundsForPosition(@Position int position, @NonNull Rect parentBounds,
            @NonNull SplitRule rule) {
            @NonNull SplitRule rule, boolean isLtr) {
        if (!shouldShowSideBySide(parentBounds, rule)) {
        if (!shouldShowSideBySide(parentBounds, rule)) {
            return new Rect();
            return new Rect();
        }
        }


        float splitRatio = rule.getSplitRatio();
        final float splitRatio = rule.getSplitRatio();
        final float rtlSplitRatio = 1 - splitRatio;
        switch (position) {
        switch (position) {
            case POSITION_LEFT:
            case POSITION_START:
                return isLtr ? getLeftContainerBounds(parentBounds, splitRatio)
                        : getRightContainerBounds(parentBounds, rtlSplitRatio);
            case POSITION_END:
                return isLtr ? getRightContainerBounds(parentBounds, splitRatio)
                        : getLeftContainerBounds(parentBounds, rtlSplitRatio);
            case POSITION_FILL:
                return parentBounds;
        }
        return parentBounds;
    }

    private Rect getLeftContainerBounds(@NonNull Rect parentBounds, float splitRatio) {
        return new Rect(
        return new Rect(
                parentBounds.left,
                parentBounds.left,
                parentBounds.top,
                parentBounds.top,
                (int) (parentBounds.left + parentBounds.width() * splitRatio),
                (int) (parentBounds.left + parentBounds.width() * splitRatio),
                parentBounds.bottom);
                parentBounds.bottom);
            case POSITION_RIGHT:
    }

    private Rect getRightContainerBounds(@NonNull Rect parentBounds, float splitRatio) {
        return new Rect(
        return new Rect(
                (int) (parentBounds.left + parentBounds.width() * splitRatio),
                (int) (parentBounds.left + parentBounds.width() * splitRatio),
                parentBounds.top,
                parentBounds.top,
                parentBounds.right,
                parentBounds.right,
                parentBounds.bottom);
                parentBounds.bottom);
            case POSITION_FILL:
                return parentBounds;
    }
    }
        return parentBounds;

    /**
     * Checks if a split with the provided rule should be displays in left-to-right layout
     * direction, either always or with the current configuration.
     */
    private boolean isLtr(@NonNull Context context, @NonNull SplitRule rule) {
        switch (rule.getLayoutDirection()) {
            case LayoutDirection.LOCALE:
                return context.getResources().getConfiguration().getLayoutDirection()
                        == View.LAYOUT_DIRECTION_LTR;
            case LayoutDirection.RTL:
                return false;
            case LayoutDirection.LTR:
            default:
                return true;
        }
    }
    }


    @NonNull
    @NonNull