Skip to content

Commit

Permalink
fix orientation-change can not work normally (#16774)
Browse files Browse the repository at this point in the history
* fix orientation-change can not work normally
  • Loading branch information
bofeng-song authored Mar 22, 2024
1 parent 559bfc9 commit 5da2f9b
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 30 deletions.
32 changes: 27 additions & 5 deletions cocos/core/platform/macro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import { EDITOR, MINIGAME, NATIVE, PREVIEW, RUNTIME_BASED } from 'internal:constants';
import { legacyCC } from '../global-exports';
import { Settings, settings } from '../settings';
import { Orientation } from '../../../pal/screen-adapter/enum-type';

const SUPPORT_TEXTURE_FORMATS = ['.astc', '.pkm', '.pvr', '.webp', '.jpg', '.jpeg', '.bmp', '.png'];

Expand Down Expand Up @@ -903,11 +904,29 @@ interface Macro {
ORIENTATION_PORTRAIT: number;

/**
* @en Oriented horizontally
* @zh 横屏朝向
* @en Inverted portrait orientation, with the device bottom facing upward.
* @zh 倒置竖屏,设备底部朝上
*/
ORIENTATION_PORTRAIT_UPSIDE_DOWN: number;

/**
* @en Oriented horizontally. Users cannot directly listen to this value; they need to listen for ORIENTATION_LANDSCAPE_LEFT or ORIENTATION_LANDSCAPE_RIGHT.

Check warning on line 913 in cocos/core/platform/macro.ts

View workflow job for this annotation

GitHub Actions / Run ESLint

This line has a length of 160. Maximum allowed is 150
* @zh 横屏朝向, 外部不能直接监听该值,需要监听 ORIENTATION_LANDSCAPE_LEFT 或 ORIENTATION_LANDSCAPE_RIGHT
*/
ORIENTATION_LANDSCAPE: number;

/**
* @en Oriented horizontally, top side facing to the left. Supported only on mobile devices.
* @zh 水平方向,顶部朝向左侧;仅移动端支持
*/
ORIENTATION_LANDSCAPE_LEFT: number;

/**
* @en Oriented horizontally, top side facing to the right. Supported only on mobile devices.
* @zh 水平方向,顶部朝向右侧;仅移动端支持
*/
ORIENTATION_LANDSCAPE_RIGHT: number;

/**
* @en Oriented automatically
* @zh 自动适配朝向
Expand Down Expand Up @@ -1091,9 +1110,12 @@ const macro: Macro = {
DEG: 180 / Math.PI,
REPEAT_FOREVER: (Number.MAX_VALUE - 1),
FLT_EPSILON: 0.0000001192092896,
ORIENTATION_PORTRAIT: 1,
ORIENTATION_LANDSCAPE: 2,
ORIENTATION_AUTO: 3,
ORIENTATION_PORTRAIT: Orientation.PORTRAIT,
ORIENTATION_PORTRAIT_UPSIDE_DOWN: Orientation.PORTRAIT_UPSIDE_DOWN,
ORIENTATION_LANDSCAPE: Orientation.LANDSCAPE,
ORIENTATION_LANDSCAPE_LEFT: Orientation.LANDSCAPE_LEFT,
ORIENTATION_LANDSCAPE_RIGHT: Orientation.LANDSCAPE_RIGHT,
ORIENTATION_AUTO: Orientation.AUTO,
ENABLE_TILEDMAP_CULLING: true,
TOUCH_TIMEOUT: 5000,
ENABLE_TRANSPARENT_CANVAS: false,
Expand Down
7 changes: 4 additions & 3 deletions cocos/ui/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { MINIGAME, JSB, RUNTIME_BASED, EDITOR } from 'internal:constants';
import { screenAdapter } from 'pal/screen-adapter';
import { Eventify } from '../core/event';
import { Rect, Size, Vec2 } from '../core/math';
import { visibleRect, cclegacy, errorID, screen, macro, System } from '../core';
import { visibleRect, cclegacy, errorID, screen, macro, System, assert } from '../core';
import { Orientation } from '../../pal/screen-adapter/enum-type';
import { director } from '../game/director';
import { Settings, settings } from '../core/settings';
Expand Down Expand Up @@ -140,7 +140,6 @@ export class View extends Eventify(System) {

// For now, the engine UI is adapted to resolution size, instead of window size.
screen.on('window-resize', this._updateAdaptResult, this);
screen.on('orientation-change', this._updateAdaptResult, this);
screen.on('fullscreen-change', this._updateAdaptResult, this);
}

Expand Down Expand Up @@ -596,8 +595,10 @@ export class View extends Eventify(System) {
const w = this._designResolutionSize.width;
const h = this._designResolutionSize.height;

if (width > 0) {
if (width > 0 && height > 0) {
this.setDesignResolutionSize(w, h, this._resolutionPolicy);
} else {
assert(false, '_updateAdaptResult Invalid size.');
}

this.emit('canvas-resize');
Expand Down
19 changes: 18 additions & 1 deletion native/cocos/bindings/event/EventDispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ se::Object *jsKeyboardEventObj = nullptr;
se::Object *jsControllerEventArray = nullptr;
se::Object *jsControllerChangeEventArray = nullptr;
se::Object *jsResizeEventObj = nullptr;
se::Object *jsOrientationChangeObj = nullptr;
bool inited = false;
bool busListenerInited = false;

Expand Down Expand Up @@ -145,6 +146,12 @@ void EventDispatcher::destroy() {
jsResizeEventObj = nullptr;
}

if (jsOrientationChangeObj != nullptr) {
jsOrientationChangeObj->unroot();
jsOrientationChangeObj->decRef();
jsOrientationChangeObj = nullptr;
}

inited = false;
tickVal.setUndefined();
}
Expand Down Expand Up @@ -412,7 +419,17 @@ void EventDispatcher::dispatchResizeEvent(int width, int height, uint32_t window
}

void EventDispatcher::dispatchOrientationChangeEvent(int orientation) {
// Ts's logic is same as the 'onResize', so remove code here temporary.
se::AutoHandleScope scope;
if (!jsOrientationChangeObj) {
jsOrientationChangeObj = se::Object::createPlainObject();
jsOrientationChangeObj->root();
}

jsOrientationChangeObj->setProperty("orientation", se::Value(orientation));

se::ValueArray args;
args.emplace_back(se::Value(jsOrientationChangeObj));
EventDispatcher::doDispatchJsEvent("onOrientationChanged", args);
}

void EventDispatcher::dispatchEnterBackgroundEvent() {
Expand Down
27 changes: 26 additions & 1 deletion native/cocos/platform/android/AndroidPlatform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
#include "base/StringUtil.h"
#include "engine/EngineEvents.h"
#include "paddleboat.h"
#include "platform/java/jni/JniImp.h"
#include "platform/interfaces/modules/Device.h"

#define ABORT_GAME \
{ \
Expand Down Expand Up @@ -531,6 +533,7 @@ class GameInputProxy {
if (!_launched) {
_launched = true;

_androidPlatform->_rotation = getDeviceRotationJNI();
ISystemWindowInfo info;
info.width = ANativeWindow_getWidth(nativeWindow);
info.height = ANativeWindow_getHeight(nativeWindow);
Expand Down Expand Up @@ -626,13 +629,35 @@ class GameInputProxy {
events::WindowEvent::broadcast(ev);
break;
}
case APP_CMD_CONFIG_CHANGED:
case APP_CMD_CONFIG_CHANGED: {
CC_LOG_INFO("AndroidPlatform: APP_CMD_CONFIG_CHANGED");
int rotation = getDeviceRotationJNI();
if (_androidPlatform->_rotation != rotation) {
CC_LOG_INFO("AndroidPlatform: orientation-change");
_androidPlatform->_rotation = rotation;
int orientation = static_cast<int>(Device::Orientation::PORTRAIT);
switch (rotation) {
case 0: // ROTATION_0
orientation = static_cast<int>(Device::Orientation::PORTRAIT);
break;
case 1: // ROTATION_90
orientation = static_cast<int>(cc::Device::Orientation::LANDSCAPE_RIGHT);
break;
case 2: // ROTATION_180
orientation = static_cast<int>(cc::Device::Orientation::PORTRAIT_UPSIDE_DOWN);
break;
case 3: // ROTATION_270
orientation = static_cast<int>(cc::Device::Orientation::LANDSCAPE_LEFT);
break;
}
cc::events::Orientation::broadcast(orientation);
}
// Window was resized or some other configuration changed.
// Note: we don't handle this event because we check the surface dimensions
// every frame, so that's how we know it was resized. If you are NOT doing that,
// then you need to handle this event!
break;
}
case APP_CMD_LOW_MEMORY: {
// system told us we have low memory. So if we are not visible, let's
// cooperate by deallocating all of our graphic resources.
Expand Down
1 change: 1 addition & 0 deletions native/cocos/platform/android/AndroidPlatform.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,6 @@ class CC_DLL AndroidPlatform : public UniversalPlatform {
GameInputProxy *_inputProxy{nullptr};
android_app *_app{nullptr};
friend class GameInputProxy;
int _rotation{-1};
};
} // namespace cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

package com.cocos.lib;

import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.media.AudioManager;
Expand All @@ -45,13 +46,16 @@

public class CocosActivity extends GameActivity {
private static final String TAG = "CocosActivity";
private static final int INITIAL_ROTATION = -1;
private CocosWebViewHelper mWebViewHelper = null;
private CocosVideoHelper mVideoHelper = null;

private CocosSensorHandler mSensorHandler;
private List<CocosSurfaceView> mSurfaceViewArray;
private FrameLayout mRootLayout;

private int mRotation = INITIAL_ROTATION;



private native void onCreateNative();
Expand Down Expand Up @@ -172,6 +176,18 @@ protected void onStart() {
surfaceView.setVisibility(View.VISIBLE);
}
}
if (mRotation == INITIAL_ROTATION
&& getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
//onConfigurationChange can be triggered at the mode of 'sensor or fullSensor'. Here only handles the sensorLandscape mode.
mRotation = CocosHelper.getDeviceRotation();
mSurfaceView.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
int rotation = CocosHelper.getDeviceRotation();
if (mRotation != rotation) {
mRotation = rotation;
this.onConfigurationChangedNative(this.getGameActivityNativeHandle());
}
});
}
}

@Override
Expand Down
4 changes: 4 additions & 0 deletions native/cocos/platform/java/jni/JniCocosOrientationHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,16 @@ JNIEXPORT void JNICALL Java_com_cocos_lib_CocosOrientationHelper_nativeOnOrienta
switch (rotation) {
case 0: // ROTATION_0
orientation = (int)cc::Device::Orientation::PORTRAIT;
break;
case 1: // ROTATION_90
orientation = (int)cc::Device::Orientation::LANDSCAPE_RIGHT;
break;
case 2: // ROTATION_180
orientation = (int)cc::Device::Orientation::PORTRAIT_UPSIDE_DOWN;
break;
case 3: // ROTATION_270
orientation = (int)cc::Device::Orientation::LANDSCAPE_LEFT;
break;
}
// run callbacks in game thread?
cc::events::Orientation::broadcast(orientation);
Expand Down
2 changes: 1 addition & 1 deletion pal/screen-adapter/native/screen-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ class ScreenAdapter extends EventTarget {
this.emit('window-resize', event.width, event.height, event.windowId);
};
jsb.onOrientationChanged = (event): void => {
this.emit('orientation-change');
this.emit('orientation-change', this.orientation);
};
}
}
Expand Down
89 changes: 70 additions & 19 deletions pal/screen-adapter/web/screen-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -377,11 +377,21 @@ class ScreenAdapter extends EventTarget {
});

window.addEventListener('resize', (): void => {
if (!this.handleResizeEvent) {
return;
}
// if (!this.handleResizeEvent) {
// return;
// }
this._resizeFrame();
});

const adapter = this;
const notifyOrientationChange = (orientation): void => {
if (orientation === adapter._orientation) {
return;
}
adapter._orientation = orientation;
adapter.emit('orientation-change', orientation);
};

if (typeof window.matchMedia === 'function') {
const updateDPRChangeListener = (): void => {
const dpr = window.devicePixelRatio;
Expand All @@ -392,21 +402,53 @@ class ScreenAdapter extends EventTarget {
}, { once: true });
};
updateDPRChangeListener();
}
window.addEventListener('orientationchange', (): void => {
if (this._orientationChangeTimeoutId !== -1) {
clearTimeout(this._orientationChangeTimeoutId);
}
this._orientationChangeTimeoutId = setTimeout((): void => {
if (!this.handleResizeEvent) {
return;

const mediaQueryPortrait = window.matchMedia('(orientation: portrait)');
const mediaQueryLandscape = window.matchMedia('(orientation: landscape)');
const handleOrientationChange = (): void => {
let tmpOrientation = adapter._orientation;
const orientationType = screen.orientation.type;
if (mediaQueryPortrait.matches) {
if (orientationType === 'portrait-primary') {
tmpOrientation = Orientation.PORTRAIT;
} else {
tmpOrientation = Orientation.PORTRAIT_UPSIDE_DOWN;
}
} else {
if (orientationType === 'landscape-primary') {
tmpOrientation = Orientation.LANDSCAPE_LEFT;
} else if (orientationType === 'landscape-secondary') {
tmpOrientation = Orientation.LANDSCAPE_RIGHT;
}
}
this._updateFrameState();
this._resizeFrame();
this.emit('orientation-change', this.windowSize.width, this.windowSize.height);
this._orientationChangeTimeoutId = -1;
}, EVENT_TIMEOUT);
});
notifyOrientationChange(tmpOrientation);
};
mediaQueryPortrait.addEventListener('change', handleOrientationChange);
mediaQueryLandscape.addEventListener('change', handleOrientationChange);
} else {
const adapter = this;
const handleOrientationChange = (): void => {
let tmpOrientation = adapter._orientation;
switch (window.orientation) {
case 0:
tmpOrientation = Orientation.PORTRAIT;
break;
case 90:
// Handle landscape orientation, top side facing to the right
tmpOrientation = Orientation.LANDSCAPE_RIGHT;
break;
case -90:
// Handle landscape orientation, top side facing to the left
tmpOrientation = Orientation.LANDSCAPE_LEFT;
break;
case 180:
tmpOrientation = Orientation.PORTRAIT_UPSIDE_DOWN;
break;
}
notifyOrientationChange(tmpOrientation);
};
window.addEventListener('orientationchange', handleOrientationChange);
}
document.addEventListener(this._fn.fullscreenchange, () => {
this._onFullscreenChange?.();
this.emit('fullscreen-change', this.windowSize.width, this.windowSize.height);
Expand Down Expand Up @@ -440,7 +482,13 @@ class ScreenAdapter extends EventTarget {
this._gameFrame.style.width = `${sizeInCssPixels.width}px`;
this._gameFrame.style.height = `${sizeInCssPixels.height}px`;
} else {
const winWidth = window.innerWidth; const winHeight = window.innerHeight;
const winWidth = window.innerWidth;
let winHeight = window.innerHeight;
//On certain devices, window.innerHeight may not account for the height of the virtual keyboard, so dynamic calculation is necessary.
const inputHeight = document.body.scrollHeight - winHeight;
if (winHeight < inputHeight) {
winHeight += inputHeight;
}
if (this.isFrameRotated) {
this._gameFrame.style['-webkit-transform'] = 'rotate(90deg)';
this._gameFrame.style.transform = 'rotate(90deg)';
Expand Down Expand Up @@ -504,7 +552,10 @@ class ScreenAdapter extends EventTarget {
const height = window.innerHeight;
const isBrowserLandscape = width > height;
this.isFrameRotated = systemInfo.isMobile
&& ((isBrowserLandscape && orientation === Orientation.PORTRAIT) || (!isBrowserLandscape && orientation === Orientation.LANDSCAPE));
&& ((isBrowserLandscape && orientation === Orientation.PORTRAIT) ||
(!isBrowserLandscape && (orientation === Orientation.LANDSCAPE ||
orientation === Orientation.LANDSCAPE_LEFT ||
orientation === Orientation.LANDSCAPE_RIGHT)));
}
private _updateContainer (): void {
if (!this._gameContainer) {
Expand Down

0 comments on commit 5da2f9b

Please sign in to comment.