Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java +3 −1 Original line number Diff line number Diff line Loading @@ -255,6 +255,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { private final WindowContainerToken mTaskToken; private final DragPositioningCallback mDragPositioningCallback; private final DragDetector mDragDetector; private final int mDisplayId; private int mDragPointerId = -1; private boolean mIsDragging; Loading @@ -266,6 +267,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { mTaskToken = taskInfo.token; mDragPositioningCallback = dragPositioningCallback; mDragDetector = new DragDetector(this); mDisplayId = taskInfo.displayId; } @Override Loading @@ -274,7 +276,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { if (id == R.id.close_window) { mTaskOperations.closeTask(mTaskToken); } else if (id == R.id.back_button) { mTaskOperations.injectBackKey(); mTaskOperations.injectBackKey(mDisplayId); } else if (id == R.id.minimize_window) { mTaskOperations.minimizeTask(mTaskToken); } else if (id == R.id.maximize_window) { Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +3 −1 Original line number Diff line number Diff line Loading @@ -386,6 +386,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { private final DragPositioningCallback mDragPositioningCallback; private final DragDetector mDragDetector; private final GestureDetector mGestureDetector; private final int mDisplayId; /** * Whether to pilfer the next motion event to send cancellations to the windows below. Loading @@ -407,6 +408,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { mDragPositioningCallback = dragPositioningCallback; mDragDetector = new DragDetector(this); mGestureDetector = new GestureDetector(mContext, this); mDisplayId = taskInfo.displayId; mCloseMaximizeWindowRunnable = () -> { final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId); if (decoration == null) return; Loading @@ -432,7 +434,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { mTaskOperations.closeTask(mTaskToken, wct); } } else if (id == R.id.back_button) { mTaskOperations.injectBackKey(); mTaskOperations.injectBackKey(mDisplayId); } else if (id == R.id.caption_handle || id == R.id.open_menu_button) { if (!decoration.isHandleMenuActive()) { moveTaskToFront(decoration.mTaskInfo); Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java +5 −5 Original line number Diff line number Diff line Loading @@ -52,19 +52,19 @@ class TaskOperations { mSyncQueue = syncQueue; } void injectBackKey() { sendBackEvent(KeyEvent.ACTION_DOWN); sendBackEvent(KeyEvent.ACTION_UP); void injectBackKey(int displayId) { sendBackEvent(KeyEvent.ACTION_DOWN, displayId); sendBackEvent(KeyEvent.ACTION_UP, displayId); } private void sendBackEvent(int action) { private void sendBackEvent(int action, int displayId) { final long when = SystemClock.uptimeMillis(); final KeyEvent ev = new KeyEvent(when, when, action, KeyEvent.KEYCODE_BACK, 0 /* repeat */, 0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */, KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY, InputDevice.SOURCE_KEYBOARD); ev.setDisplayId(mContext.getDisplay().getDisplayId()); ev.setDisplayId(displayId); if (!mContext.getSystemService(InputManager.class) .injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC)) { Log.e(TAG, "Inject input event fail"); Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt +41 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.content.Context import android.graphics.Rect import android.hardware.display.DisplayManager import android.hardware.display.VirtualDisplay import android.hardware.input.InputManager import android.os.Handler import android.platform.test.annotations.EnableFlags import android.platform.test.annotations.RequiresFlagsEnabled Loading @@ -42,8 +43,10 @@ import android.view.InputChannel import android.view.InputMonitor import android.view.InsetsSource import android.view.InsetsState import android.view.KeyEvent import android.view.SurfaceControl import android.view.SurfaceView import android.view.View import android.view.WindowInsets.Type.navigationBars import android.view.WindowInsets.Type.statusBars import androidx.test.filters.SmallTest Loading @@ -51,6 +54,7 @@ import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession import com.android.dx.mockito.inline.extended.StaticMockitoSession import com.android.window.flags.Flags import com.android.wm.shell.R import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.ShellTestCase Loading @@ -61,6 +65,7 @@ import com.android.wm.shell.common.DisplayLayout import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.desktopmode.DesktopTasksController import com.android.wm.shell.freeform.FreeformTaskTransitionStarter import com.android.wm.shell.shared.DesktopModeStatus import com.android.wm.shell.sysui.KeyguardChangeListener import com.android.wm.shell.sysui.ShellCommandHandler Loading @@ -70,6 +75,7 @@ import com.android.wm.shell.transition.Transitions import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel.DesktopModeOnInsetsChangedListener import java.util.Optional import java.util.function.Supplier import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Rule import org.junit.Test Loading Loading @@ -278,6 +284,41 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { verify(mockInputMonitor, times(1)).dispose() } @Test fun testBackEventHasRightDisplayId() { val secondaryDisplay = createVirtualDisplay() ?: return val secondaryDisplayId = secondaryDisplay.display.displayId val task = createTask( displayId = secondaryDisplayId, windowingMode = WINDOWING_MODE_FREEFORM ) val windowDecor = setUpMockDecorationForTask(task) onTaskOpening(task) val onClickListenerCaptor = argumentCaptor<View.OnClickListener>() verify(windowDecor).setCaptionListeners( onClickListenerCaptor.capture(), any(), any(), any()) val onClickListener = onClickListenerCaptor.firstValue val view = mock(View::class.java) whenever(view.id).thenReturn(R.id.back_button) val inputManager = mock(InputManager::class.java) mContext.addMockSystemService(InputManager::class.java, inputManager) val freeformTaskTransitionStarter = mock(FreeformTaskTransitionStarter::class.java) desktopModeWindowDecorViewModel .setFreeformTaskTransitionStarter(freeformTaskTransitionStarter) onClickListener.onClick(view) val eventCaptor = argumentCaptor<KeyEvent>() verify(inputManager, times(2)).injectInputEvent(eventCaptor.capture(), anyInt()) assertEquals(secondaryDisplayId, eventCaptor.firstValue.displayId) assertEquals(secondaryDisplayId, eventCaptor.secondValue.displayId) } @Test fun testCaptionIsNotCreatedWhenKeyguardIsVisible() { val task = createTask(windowingMode = WINDOWING_MODE_FULLSCREEN, focused = true) Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java +3 −1 Original line number Diff line number Diff line Loading @@ -255,6 +255,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { private final WindowContainerToken mTaskToken; private final DragPositioningCallback mDragPositioningCallback; private final DragDetector mDragDetector; private final int mDisplayId; private int mDragPointerId = -1; private boolean mIsDragging; Loading @@ -266,6 +267,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { mTaskToken = taskInfo.token; mDragPositioningCallback = dragPositioningCallback; mDragDetector = new DragDetector(this); mDisplayId = taskInfo.displayId; } @Override Loading @@ -274,7 +276,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel { if (id == R.id.close_window) { mTaskOperations.closeTask(mTaskToken); } else if (id == R.id.back_button) { mTaskOperations.injectBackKey(); mTaskOperations.injectBackKey(mDisplayId); } else if (id == R.id.minimize_window) { mTaskOperations.minimizeTask(mTaskToken); } else if (id == R.id.maximize_window) { Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +3 −1 Original line number Diff line number Diff line Loading @@ -386,6 +386,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { private final DragPositioningCallback mDragPositioningCallback; private final DragDetector mDragDetector; private final GestureDetector mGestureDetector; private final int mDisplayId; /** * Whether to pilfer the next motion event to send cancellations to the windows below. Loading @@ -407,6 +408,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { mDragPositioningCallback = dragPositioningCallback; mDragDetector = new DragDetector(this); mGestureDetector = new GestureDetector(mContext, this); mDisplayId = taskInfo.displayId; mCloseMaximizeWindowRunnable = () -> { final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId); if (decoration == null) return; Loading @@ -432,7 +434,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { mTaskOperations.closeTask(mTaskToken, wct); } } else if (id == R.id.back_button) { mTaskOperations.injectBackKey(); mTaskOperations.injectBackKey(mDisplayId); } else if (id == R.id.caption_handle || id == R.id.open_menu_button) { if (!decoration.isHandleMenuActive()) { moveTaskToFront(decoration.mTaskInfo); Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java +5 −5 Original line number Diff line number Diff line Loading @@ -52,19 +52,19 @@ class TaskOperations { mSyncQueue = syncQueue; } void injectBackKey() { sendBackEvent(KeyEvent.ACTION_DOWN); sendBackEvent(KeyEvent.ACTION_UP); void injectBackKey(int displayId) { sendBackEvent(KeyEvent.ACTION_DOWN, displayId); sendBackEvent(KeyEvent.ACTION_UP, displayId); } private void sendBackEvent(int action) { private void sendBackEvent(int action, int displayId) { final long when = SystemClock.uptimeMillis(); final KeyEvent ev = new KeyEvent(when, when, action, KeyEvent.KEYCODE_BACK, 0 /* repeat */, 0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */, KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY, InputDevice.SOURCE_KEYBOARD); ev.setDisplayId(mContext.getDisplay().getDisplayId()); ev.setDisplayId(displayId); if (!mContext.getSystemService(InputManager.class) .injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC)) { Log.e(TAG, "Inject input event fail"); Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt +41 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.content.Context import android.graphics.Rect import android.hardware.display.DisplayManager import android.hardware.display.VirtualDisplay import android.hardware.input.InputManager import android.os.Handler import android.platform.test.annotations.EnableFlags import android.platform.test.annotations.RequiresFlagsEnabled Loading @@ -42,8 +43,10 @@ import android.view.InputChannel import android.view.InputMonitor import android.view.InsetsSource import android.view.InsetsState import android.view.KeyEvent import android.view.SurfaceControl import android.view.SurfaceView import android.view.View import android.view.WindowInsets.Type.navigationBars import android.view.WindowInsets.Type.statusBars import androidx.test.filters.SmallTest Loading @@ -51,6 +54,7 @@ import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession import com.android.dx.mockito.inline.extended.StaticMockitoSession import com.android.window.flags.Flags import com.android.wm.shell.R import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.ShellTestCase Loading @@ -61,6 +65,7 @@ import com.android.wm.shell.common.DisplayLayout import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.desktopmode.DesktopTasksController import com.android.wm.shell.freeform.FreeformTaskTransitionStarter import com.android.wm.shell.shared.DesktopModeStatus import com.android.wm.shell.sysui.KeyguardChangeListener import com.android.wm.shell.sysui.ShellCommandHandler Loading @@ -70,6 +75,7 @@ import com.android.wm.shell.transition.Transitions import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel.DesktopModeOnInsetsChangedListener import java.util.Optional import java.util.function.Supplier import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Rule import org.junit.Test Loading Loading @@ -278,6 +284,41 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() { verify(mockInputMonitor, times(1)).dispose() } @Test fun testBackEventHasRightDisplayId() { val secondaryDisplay = createVirtualDisplay() ?: return val secondaryDisplayId = secondaryDisplay.display.displayId val task = createTask( displayId = secondaryDisplayId, windowingMode = WINDOWING_MODE_FREEFORM ) val windowDecor = setUpMockDecorationForTask(task) onTaskOpening(task) val onClickListenerCaptor = argumentCaptor<View.OnClickListener>() verify(windowDecor).setCaptionListeners( onClickListenerCaptor.capture(), any(), any(), any()) val onClickListener = onClickListenerCaptor.firstValue val view = mock(View::class.java) whenever(view.id).thenReturn(R.id.back_button) val inputManager = mock(InputManager::class.java) mContext.addMockSystemService(InputManager::class.java, inputManager) val freeformTaskTransitionStarter = mock(FreeformTaskTransitionStarter::class.java) desktopModeWindowDecorViewModel .setFreeformTaskTransitionStarter(freeformTaskTransitionStarter) onClickListener.onClick(view) val eventCaptor = argumentCaptor<KeyEvent>() verify(inputManager, times(2)).injectInputEvent(eventCaptor.capture(), anyInt()) assertEquals(secondaryDisplayId, eventCaptor.firstValue.displayId) assertEquals(secondaryDisplayId, eventCaptor.secondValue.displayId) } @Test fun testCaptionIsNotCreatedWhenKeyguardIsVisible() { val task = createTask(windowingMode = WINDOWING_MODE_FULLSCREEN, focused = true) Loading