Merge "Give Divider back its touch-region" into rvc-dev

This commit is contained in:
Evan Rosky
2020-05-01 00:11:36 +00:00
committed by Android (Google) Code Review
8 changed files with 104 additions and 11 deletions

View File

@@ -342,5 +342,5 @@ interface IWindowSession {
* Update the flags on an input channel associated with a particular surface.
*/
void updateInputChannel(in IBinder channelToken, int displayId, in SurfaceControl surface,
int flags);
int flags, in Region region);
}

View File

@@ -233,6 +233,14 @@ public class SurfaceControlViewHost {
return mViewRoot.mWindow;
}
/**
* @return the WindowlessWindowManager instance that this host is attached to.
* @hide
*/
public @NonNull WindowlessWindowManager getWindowlessWM() {
return mWm;
}
/**
* @hide
*/

View File

@@ -16,16 +16,19 @@
package android.view;
import android.annotation.Nullable;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.util.MergedConfiguration;
import java.util.HashMap;
import java.util.Objects;
/**
* A simplistic implementation of IWindowSession. Rather than managing Surfaces
@@ -42,6 +45,7 @@ public class WindowlessWindowManager implements IWindowSession {
WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
int mDisplayId;
IBinder mInputChannelToken;
Region mInputRegion;
State(SurfaceControl sc, WindowManager.LayoutParams p, int displayId,
IBinder inputChannelToken) {
mSurfaceControl = sc;
@@ -95,6 +99,30 @@ public class WindowlessWindowManager implements IWindowSession {
mResizeCompletionForWindow.put(window, callback);
}
protected void setTouchRegion(IBinder window, @Nullable Region region) {
State state;
synchronized (this) {
// Do everything while locked so that we synchronize with relayout. This should be a
// very infrequent operation.
state = mStateForWindow.get(window);
if (state == null) {
return;
}
if (Objects.equals(region, state.mInputRegion)) {
return;
}
state.mInputRegion = region != null ? new Region(region) : null;
if (state.mInputChannelToken != null) {
try {
mRealWm.updateInputChannel(state.mInputChannelToken, state.mDisplayId,
state.mSurfaceControl, state.mParams.flags, state.mInputRegion);
} catch (RemoteException e) {
Log.e(TAG, "Failed to update surface input channel: ", e);
}
}
}
}
/**
* IWindowSession implementation.
*/
@@ -234,7 +262,7 @@ public class WindowlessWindowManager implements IWindowSession {
&& state.mInputChannelToken != null) {
try {
mRealWm.updateInputChannel(state.mInputChannelToken, state.mDisplayId, sc,
attrs.flags);
attrs.flags, state.mInputRegion);
} catch (RemoteException e) {
Log.e(TAG, "Failed to update surface input channel: ", e);
}
@@ -409,7 +437,7 @@ public class WindowlessWindowManager implements IWindowSession {
@Override
public void updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface,
int flags) {
int flags, Region region) {
}
@Override

View File

@@ -29,6 +29,7 @@ import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.Region.Op;
import android.hardware.display.DisplayManager;
import android.os.Bundle;
@@ -338,12 +339,12 @@ public class DividerView extends FrameLayout implements OnTouchListener,
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (mFirstLayout) {
// Wait for first layout so that the ViewRootImpl surface has been created.
initializeSurfaceState();
mFirstLayout = false;
}
super.onLayout(changed, left, top, right, bottom);
int minimizeLeft = 0;
int minimizeTop = 0;
if (mDockSide == WindowManager.DOCKED_TOP) {
@@ -783,6 +784,20 @@ public class DividerView extends FrameLayout implements OnTouchListener,
setResizeDimLayer(t, false /* secondary */, 0.f /* alpha */);
t.apply();
mTiles.releaseTransaction(t);
// Get the actually-visible bar dimensions (relative to full window). This is a thin
// bar going through the center.
final Rect dividerBar = isHorizontalDivision()
? new Rect(0, mDividerInsets, mSplitLayout.mDisplayLayout.width(),
mDividerInsets + mDividerSize)
: new Rect(mDividerInsets, 0, mDividerInsets + mDividerSize,
mSplitLayout.mDisplayLayout.height());
final Region touchRegion = new Region(dividerBar);
// Add in the "draggable" portion. While not visible, this is an expanded area that the
// user can interact with.
touchRegion.union(new Rect(mHandle.getLeft(), mHandle.getTop(),
mHandle.getRight(), mHandle.getBottom()));
mWindowManager.setTouchRegion(touchRegion);
}
public void setMinimizedDockStack(boolean minimized, boolean isHomeStackResizable) {

View File

@@ -27,6 +27,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMA
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import android.graphics.PixelFormat;
import android.graphics.Region;
import android.os.Binder;
import android.view.View;
import android.view.WindowManager;
@@ -103,4 +104,12 @@ public class DividerWindowManager {
mSystemWindows.updateViewLayout(mView, mLp);
}
}
/** Sets the touch region to `touchRegion`. Use null to unset.*/
public void setTouchRegion(Region touchRegion) {
if (mView == null) {
return;
}
mSystemWindows.setTouchableRegion(mView, touchRegion);
}
}

View File

@@ -23,7 +23,9 @@ import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.MergedConfiguration;
@@ -138,6 +140,23 @@ public class SystemWindows {
root.relayout((WindowManager.LayoutParams) params);
}
/**
* Sets the touchable region of a view's window. This will be cropped to the window size.
* @param view
* @param region
*/
public void setTouchableRegion(@NonNull View view, Region region) {
SurfaceControlViewHost root = mViewRoots.get(view);
if (root == null) {
return;
}
WindowlessWindowManager wwm = root.getWindowlessWM();
if (!(wwm instanceof SysUiWindowManager)) {
return;
}
((SysUiWindowManager) wwm).setTouchableRegionForWindow(view, region);
}
/**
* Adds a root for system-ui window management with no views. Only useful for IME.
*/
@@ -289,6 +308,14 @@ public class SystemWindows {
SurfaceControl getSurfaceControlForWindow(View rootView) {
return getSurfaceControl(rootView);
}
void setTouchableRegionForWindow(View rootView, Region region) {
IBinder token = rootView.getWindowToken();
if (token == null) {
return;
}
setTouchRegion(token, region);
}
}
class ContainerWindow extends IWindow.Stub {

View File

@@ -679,10 +679,10 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
@Override
public void updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface,
int flags) {
int flags, Region region) {
final long identity = Binder.clearCallingIdentity();
try {
mService.updateInputChannel(channelToken, displayId, surface, flags);
mService.updateInputChannel(channelToken, displayId, surface, flags, region);
} finally {
Binder.restoreCallingIdentity(identity);
}

View File

@@ -8030,7 +8030,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
updateInputChannel(clientChannel.getToken(), callingUid, callingPid, displayId, surface,
name, applicationHandle, flags);
name, applicationHandle, flags, null /* region */);
clientChannel.transferTo(outInputChannel);
clientChannel.dispose();
@@ -8042,7 +8042,7 @@ public class WindowManagerService extends IWindowManager.Stub
private void updateInputChannel(IBinder channelToken, int callingUid, int callingPid,
int displayId, SurfaceControl surface, String name,
InputApplicationHandle applicationHandle, int flags) {
InputApplicationHandle applicationHandle, int flags, Region region) {
InputWindowHandle h = new InputWindowHandle(applicationHandle, displayId);
h.token = channelToken;
h.name = name;
@@ -8062,7 +8062,13 @@ public class WindowManagerService extends IWindowManager.Stub
h.inputFeatures = 0;
h.replaceTouchableRegionWithCrop(null);
if (region == null) {
h.replaceTouchableRegionWithCrop(null);
} else {
h.touchableRegion.set(region);
h.replaceTouchableRegionWithCrop = false;
h.setTouchableRegionCrop(surface);
}
SurfaceControl.Transaction t = mTransactionFactory.get();
t.setInputWindowInfo(surface, h);
@@ -8076,7 +8082,7 @@ public class WindowManagerService extends IWindowManager.Stub
* is undefined.
*/
void updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface,
int flags) {
int flags, Region region) {
final InputApplicationHandle applicationHandle;
final String name;
final EmbeddedWindowController.EmbeddedWindow win;
@@ -8091,7 +8097,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
updateInputChannel(channelToken, win.mOwnerUid, win.mOwnerPid, displayId, surface, name,
applicationHandle, flags);
applicationHandle, flags, region);
}
/** Return whether layer tracing is enabled */