Skip to content

Android: add auto-rotation support#594

Open
chofuhoyu wants to merge 9 commits into
koreader:masterfrom
chofuhoyu:feat/android-auto-rotation
Open

Android: add auto-rotation support#594
chofuhoyu wants to merge 9 commits into
koreader:masterfrom
chofuhoyu:feat/android-auto-rotation

Conversation

@chofuhoyu

@chofuhoyu chofuhoyu commented Jun 6, 2026

Copy link
Copy Markdown

This PR adds the Android-side changes needed for auto-rotation support in KOReader (see companion PR in the main repository).

Changes

  • AndroidManifest.xml: Change screenOrientation from nosensor to fullSensor, allowing Android to manage screen rotation via the accelerometer.
  • ActivityExtensions.kt: Add setAutoOrientation() extension and a sensor mode guard in setOrientationCompat that passes FULL_SENSOR and related constants through without remapping.
  • MainActivity.kt: Add setScreenAutoRotation(enabled) method to enable/disable auto mode via requestedOrientation.
  • LuaInterface.kt: Declare the new JNI method.
  • assets/android.lua: Add android.orientation.setAuto(enabled) binding.

Dependencies

This PR must be merged before the companion PR in koreader/koreader, which updates the luajit-launcher submodule pointer and implements the Lua-side auto-rotation UI and logic.

Companion PR: koreader/koreader#15507

Testing

  • Built and tested on an Android ARM64 device (Onyx Boox Leaf5)
  • Auto-rotation follows device orientation correctly
  • Manual rotation selection exits auto mode and locks to the selected orientation
  • Physical page-turn buttons follow rotation correctly in both modes

This change is Reviewable

- Change AndroidManifest.xml from nosensor to fullSensor
- Add setAutoOrientation() extension and sensor mode pass-through
- Add setScreenAutoRotation() method to MainActivity
- Add setScreenAutoRotation() to LuaInterface
- Add android.orientation.setAuto() JNI binding
@pazos

pazos commented Jun 9, 2026

Copy link
Copy Markdown
Member

thanks for the contribution!!! all is looking great!

Please see https://app.codacy.com/gh/koreader/android-luajit-launcher/pull-requests/594/issues#issue-272fb7d1f4c1bcb5b713ccf61077d2de

I agree with codacy this time :)

@pazos
pazos self-requested a review June 9, 2026 18:13
Comment thread app/src/main/AndroidManifest.xml
Extract the 7-branch OR condition in setOrientationCompat into a
well-named private function to satisfy detekt's complexity threshold.
When 'Lock auto rotation to current orientation' is enabled, use
Android's axis-specific sensor modes (SENSOR_PORTRAIT / SENSOR_LANDSCAPE)
instead of FULL_SENSOR. This lets the OS itself restrict rotation to
the same axis, fixing the lock being bypassed because FULL_SENSOR
rotated the screen before Lua's gyro filter could intervene.

- Add setLockedAutoOrientation() in ActivityExtensions.kt
- Add setScreenAutoRotationLocked() in MainActivity.kt and LuaInterface.kt
- Add android.orientation.setAutoLocked() binding in assets/android.lua
Comment thread app/src/main/java/org/koreader/launcher/extensions/ActivityExtensions.kt Outdated

@Frenzie Frenzie left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine by me. (Mind, only relevant if the others are too busy for the next week.)

…ping

screenIsLandscape was determined by comparing current display
width/height, but Display.getWidth()/getHeight() return dimensions
adjusted for the current rotation. On a native portrait device
started in landscape, this caused isLandscape=true, permanently
corrupting all orientation calculations.

Fix: account for Display.getRotation() when determining native
orientation. For ROTATION_90/270, width and height are swapped
relative to natural orientation, so invert the comparison.

Also fix getOrientationCompat mapping for both native portrait
and native landscape devices: ROTATION_90 and ROTATION_270
had incorrect DEVICE_ROTATED_* return values for both cases.
…ionCompat

Log evidence shows that for this native portrait device:
  REVERSE_LANDSCAPE(8) → ROTATION_270 (CCW), and
  LANDSCAPE(0) → ROTATION_90 (CW).

The swap in setOrientationCompat inverted these, so locking to CCW(3)
→ REVERSE_LANDSCAPE(8) → swap → LANDSCAPE(0) → CW(1), flipping the
device 180° from the intended orientation.

The Lua framebuffer already maps DEVICE_ROTATED_* to the correct
ASCREEN_ORIENTATION_* constants. No further remapping is needed
for native portrait devices.
@hugleo
hugleo self-requested a review June 13, 2026 14:15
@hugleo

hugleo commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

It might be worth testing on an emulator to verify that manual rotation still works as before on versions above 4.1, both with and without notch emulation. I can also test it on my devices and phone.

@chofuhoyu

Copy link
Copy Markdown
Author

It might be worth testing on an emulator to verify that manual rotation still works as before on versions above 4.1, both with and without notch emulation. I can also test it on my devices and phone.

Thanks. It needs more tests. Please let me know if you tried this patch on Android emulator, devices or phone, and whether it works fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants