Application: onDisplayOrientation and onDeviceOrientation events for iOS and Android

Device orientation is the orientation of the phone/tablet.

Display orientation is the orientation of what is rendered on the display.

By default, they should usually be the same. If orientation is locked, device orientation will update, but display orientation usually won't.
This commit is contained in:
Josh Tynjala
2024-11-08 16:16:59 -08:00
parent 2da06fa2af
commit 8f0b8f356e
17 changed files with 549 additions and 6 deletions

View File

@@ -319,6 +319,7 @@
<file name="src/system/JNI.cpp" if="android" />
<file name="src/system/Locale.cpp" unless="mac || ios" />
<file name="src/system/Locale.mm" if="mac || ios" />
<file name="src/system/OrientationEvent.cpp" />
<file name="src/system/SensorEvent.cpp" />
<file name="src/system/System.cpp" unless="ios" />
<file name="src/system/System.mm" if="ios" />

View File

@@ -0,0 +1,40 @@
#ifndef LIME_SYSTEM_ORIENTATION_EVENT_H
#define LIME_SYSTEM_ORIENTATION_EVENT_H
#include <system/CFFI.h>
#include <system/ValuePointer.h>
namespace lime {
enum OrientationEventType {
DISPLAY_ORIENTATION_CHANGE,
DEVICE_ORIENTATION_CHANGE
};
struct OrientationEvent {
hl_type* t;
int orientation;
int display;
OrientationEventType type;
static ValuePointer* callback;
static ValuePointer* eventObject;
OrientationEvent ();
static void Dispatch (OrientationEvent* event);
};
}
#endif

View File

@@ -40,6 +40,7 @@ namespace lime {
static bool GetIOSTablet ();
#endif
static int GetNumDisplays ();
static int GetDeviceOrientation ();
static std::wstring* GetPlatformLabel ();
static std::wstring* GetPlatformName ();
static std::wstring* GetPlatformVersion ();
@@ -53,6 +54,7 @@ namespace lime {
#if defined(HX_WINDOWS) && !defined (HX_WINRT)
static bool SetWindowsConsoleMode (int handleType, int mode);
#endif
static void EnableDeviceOrientationChange(bool enable);
private:

View File

@@ -26,6 +26,7 @@
#include <system/FileWatcher.h>
#include <system/JNI.h>
#include <system/Locale.h>
#include <system/OrientationEvent.h>
#include <system/SensorEvent.h>
#include <system/System.h>
#include <text/Font.h>
@@ -2594,6 +2595,23 @@ namespace lime {
}
void lime_orientation_event_manager_register (value callback, value eventObject) {
OrientationEvent::callback = new ValuePointer (callback);
OrientationEvent::eventObject = new ValuePointer (eventObject);
System::EnableDeviceOrientationChange(true);
}
HL_PRIM void HL_NAME(hl_orientation_event_manager_register) (vclosure* callback, OrientationEvent* eventObject) {
OrientationEvent::callback = new ValuePointer (callback);
OrientationEvent::eventObject = new ValuePointer ((vobj*)eventObject);
}
value lime_png_decode_bytes (value data, bool decodeData, value buffer) {
ImageBuffer imageBuffer (buffer);
@@ -2881,6 +2899,20 @@ namespace lime {
}
int lime_system_get_device_orientation () {
return System::GetDeviceOrientation();
}
HL_PRIM int HL_NAME(hl_system_get_device_orientation) () {
return System::GetDeviceOrientation();
}
value lime_system_get_platform_label () {
std::wstring* label = System::GetPlatformLabel ();
@@ -4017,6 +4049,7 @@ namespace lime {
DEFINE_PRIME2 (lime_lzma_decompress);
DEFINE_PRIME2v (lime_mouse_event_manager_register);
DEFINE_PRIME1v (lime_neko_execute);
DEFINE_PRIME2v (lime_orientation_event_manager_register);
DEFINE_PRIME3 (lime_png_decode_bytes);
DEFINE_PRIME3 (lime_png_decode_file);
DEFINE_PRIME2v (lime_render_event_manager_register);
@@ -4028,6 +4061,7 @@ namespace lime {
DEFINE_PRIME1 (lime_system_get_display);
DEFINE_PRIME0 (lime_system_get_ios_tablet);
DEFINE_PRIME0 (lime_system_get_num_displays);
DEFINE_PRIME0 (lime_system_get_device_orientation);
DEFINE_PRIME0 (lime_system_get_platform_label);
DEFINE_PRIME0 (lime_system_get_platform_name);
DEFINE_PRIME0 (lime_system_get_platform_version);
@@ -4097,6 +4131,7 @@ namespace lime {
#define _TJOYSTICK_EVENT _OBJ (_I32 _I32 _I32 _I32 _F64 _F64)
#define _TKEY_EVENT _OBJ (_F64 _I32 _I32 _I32)
#define _TMOUSE_EVENT _OBJ (_I32 _F64 _F64 _I32 _I32 _F64 _F64 _I32)
#define _TORIENTATION_EVENT _OBJ (_I32 _I32)
#define _TRECTANGLE _OBJ (_F64 _F64 _F64 _F64)
#define _TRENDER_EVENT _OBJ (_I32)
#define _TSENSOR_EVENT _OBJ (_I32 _F64 _F64 _F64 _I32)
@@ -4205,6 +4240,7 @@ namespace lime {
DEFINE_HL_PRIM (_TBYTES, hl_lzma_decompress, _TBYTES _TBYTES);
DEFINE_HL_PRIM (_VOID, hl_mouse_event_manager_register, _FUN (_VOID, _NO_ARG) _TMOUSE_EVENT);
// DEFINE_PRIME1v (lime_neko_execute);
DEFINE_HL_PRIM (_VOID, hl_orientation_event_manager_register, _FUN (_VOID, _NO_ARG) _TORIENTATION_EVENT);
DEFINE_HL_PRIM (_TIMAGEBUFFER, hl_png_decode_bytes, _TBYTES _BOOL _TIMAGEBUFFER);
DEFINE_HL_PRIM (_TIMAGEBUFFER, hl_png_decode_file, _STRING _BOOL _TIMAGEBUFFER);
DEFINE_HL_PRIM (_VOID, hl_render_event_manager_register, _FUN (_VOID, _NO_ARG) _TRENDER_EVENT);
@@ -4216,6 +4252,7 @@ namespace lime {
DEFINE_HL_PRIM (_DYN, hl_system_get_display, _I32);
DEFINE_HL_PRIM (_BOOL, hl_system_get_ios_tablet, _NO_ARG);
DEFINE_HL_PRIM (_I32, hl_system_get_num_displays, _NO_ARG);
DEFINE_HL_PRIM (_I32, hl_system_get_device_orientation, _NO_ARG);
DEFINE_HL_PRIM (_BYTES, hl_system_get_platform_label, _NO_ARG);
DEFINE_HL_PRIM (_BYTES, hl_system_get_platform_name, _NO_ARG);
DEFINE_HL_PRIM (_BYTES, hl_system_get_platform_version, _NO_ARG);

View File

@@ -53,6 +53,7 @@ namespace lime {
JoystickEvent joystickEvent;
KeyEvent keyEvent;
MouseEvent mouseEvent;
OrientationEvent orientationEvent;
RenderEvent renderEvent;
SensorEvent sensorEvent;
TextEvent textEvent;
@@ -183,6 +184,25 @@ namespace lime {
ProcessGamepadEvent (event);
break;
case SDL_DISPLAYEVENT:
switch (event->display.event) {
case SDL_DISPLAYEVENT_ORIENTATION:
// this is the orientation of what is rendered, which
// may not exactly match the orientation of the device,
// if the app was locked to portrait or landscape.
orientationEvent.type = DISPLAY_ORIENTATION_CHANGE;
orientationEvent.orientation = event->display.data1;
orientationEvent.display = event->display.display;
OrientationEvent::Dispatch (&orientationEvent);
break;
}
break;
case SDL_DROPFILE:
ProcessDropEvent (event);

View File

@@ -7,6 +7,7 @@
#include <app/ApplicationEvent.h>
#include <graphics/RenderEvent.h>
#include <system/ClipboardEvent.h>
#include <system/OrientationEvent.h>
#include <system/SensorEvent.h>
#include <ui/DropEvent.h>
#include <ui/GamepadEvent.h>
@@ -69,6 +70,7 @@ namespace lime {
Uint32 lastUpdate;
MouseEvent mouseEvent;
Uint32 nextUpdate;
OrientationEvent orientationEvent;
RenderEvent renderEvent;
SensorEvent sensorEvent;
TextEvent textEvent;

View File

@@ -52,6 +52,7 @@ namespace lime {
static int id_dpi;
static int id_height;
static int id_name;
static int id_orientation;
static int id_pixelFormat;
static int id_refreshRate;
static int id_supportedModes;
@@ -306,6 +307,7 @@ namespace lime {
id_dpi = val_id ("dpi");
id_height = val_id ("height");
id_name = val_id ("name");
id_orientation = val_id ("orientation");
id_pixelFormat = val_id ("pixelFormat");
id_refreshRate = val_id ("refreshRate");
id_supportedModes = val_id ("supportedModes");
@@ -335,6 +337,9 @@ namespace lime {
#endif
alloc_field (display, id_dpi, alloc_float (dpi));
SDL_DisplayOrientation orientation = SDL_GetDisplayOrientation(id);
alloc_field (display, id_orientation, alloc_int (orientation));
SDL_DisplayMode displayMode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 };
DisplayMode mode;
@@ -411,6 +416,7 @@ namespace lime {
const int id_dpi = hl_hash_utf8 ("dpi");
const int id_height = hl_hash_utf8 ("height");
const int id_name = hl_hash_utf8 ("name");
const int id_orientation = hl_hash_utf8 ("orientation");
const int id_pixelFormat = hl_hash_utf8 ("pixelFormat");
const int id_refreshRate = hl_hash_utf8 ("refreshRate");
const int id_supportedModes = hl_hash_utf8 ("supportedModes");
@@ -450,6 +456,9 @@ namespace lime {
#endif
hl_dyn_setf (display, id_dpi, dpi);
SDL_DisplayOrientation orientation = SDL_GetDisplayOrientation(id);
hl_dyn_seti (display, id_orientation, &hlt_i32, orientation);
SDL_DisplayMode displayMode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 };
DisplayMode mode;

View File

@@ -0,0 +1,64 @@
#include <system/CFFI.h>
#include <system/OrientationEvent.h>
namespace lime {
ValuePointer* OrientationEvent::callback = 0;
ValuePointer* OrientationEvent::eventObject = 0;
static int id_type;
static int id_orientation;
static int id_display;
static bool init = false;
OrientationEvent::OrientationEvent () {
orientation = 0; // SDL_ORIENTATION_UNKNOWN
display = 0;
type = DISPLAY_ORIENTATION_CHANGE;
}
void OrientationEvent::Dispatch (OrientationEvent* event) {
if (OrientationEvent::callback) {
if (OrientationEvent::eventObject->IsCFFIValue ()) {
if (!init) {
id_orientation = val_id ("orientation");
id_display = val_id ("display");
id_type = val_id ("type");
init = true;
}
value object = (value)OrientationEvent::eventObject->Get ();
alloc_field (object, id_orientation, alloc_int (event->orientation));
alloc_field (object, id_display, alloc_int (event->display));
alloc_field (object, id_type, alloc_int (event->type));
} else {
OrientationEvent* eventObject = (OrientationEvent*)OrientationEvent::eventObject->Get ();
eventObject->orientation = event->orientation;
eventObject->display = event->display;
eventObject->type = event->type;
}
OrientationEvent::callback->Call ();
}
}
}

View File

@@ -246,6 +246,15 @@ namespace lime {
}
#endif
int System::GetDeviceOrientation () {
return 0; // SDL_ORIENTATION_UNKNOWN
}
void System::EnableDeviceOrientationChange (bool enable) {
}
}

View File

@@ -4,10 +4,112 @@
#import <sys/utsname.h>
#include <system/System.h>
#include <system/OrientationEvent.h>
#ifdef IPHONE
@interface OrientationObserver: NSObject
- (id) init;
- (void) dealloc;
- (void) dispatchEventForDevice:(UIDevice *) device;
- (void) orientationChanged:(NSNotification *) notification;
@end
@implementation OrientationObserver {
}
- (void) dealloc
{
UIDevice * device = [UIDevice currentDevice];
// [device endGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
- (id) init
{
self = [super init];
if (!self)
{
return nil;
}
UIDevice * device = [UIDevice currentDevice];
// [device beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:device];
return self;
}
- (void) dispatchEventForCurrentDevice
{
UIDevice * device = [UIDevice currentDevice];
[self dispatchEventForDevice:device];
}
- (void) dispatchEventForDevice:(UIDevice *) device
{
int orientation = 0; // SDL_ORIENTATION_UNKNOWN
switch (device.orientation)
{
case UIDeviceOrientationLandscapeLeft:
orientation = 1; // SDL_ORIENTATION_LANDSCAPE
break;
case UIDeviceOrientationLandscapeRight:
orientation = 2; // SDL_ORIENTATION_LANDSCAPE_FLIPPED
break;
case UIDeviceOrientationPortrait:
orientation = 3; // SDL_ORIENTATION_PORTRAIT
break;
case UIDeviceOrientationPortraitUpsideDown:
orientation = 4; // SDL_ORIENTATION_PORTRAIT_FLIPPED
break;
default:
break;
};
lime::OrientationEvent event;
event.orientation = orientation;
event.display = -1;
event.type = lime::DEVICE_ORIENTATION_CHANGE;
lime::OrientationEvent::Dispatch(&event);
}
- (void) orientationChanged:(NSNotification *) notification
{
UIDevice * device = notification.object;
[self dispatchEventForDevice:device];
}
@end
#endif
namespace lime {
OrientationObserver* orientationObserver;
void System::GCEnterBlocking () {
@@ -84,6 +186,44 @@ namespace lime {
}
int System::GetDeviceOrientation () {
UIDevice * device = [UIDevice currentDevice];
int orientation = 0; // SDL_ORIENTATION_UNKNOWN
switch (device.orientation)
{
case UIDeviceOrientationLandscapeLeft:
orientation = 1; // SDL_ORIENTATION_LANDSCAPE
break;
case UIDeviceOrientationLandscapeRight:
orientation = 2; // SDL_ORIENTATION_LANDSCAPE_FLIPPED
break;
case UIDeviceOrientationPortrait:
orientation = 3; // SDL_ORIENTATION_PORTRAIT
break;
case UIDeviceOrientationPortraitUpsideDown:
orientation = 4; // SDL_ORIENTATION_PORTRAIT_FLIPPED
break;
default:
break;
};
return orientation;
}
std::wstring* System::GetDeviceModel () {
#ifdef IPHONE
@@ -133,6 +273,29 @@ namespace lime {
}
void System::EnableDeviceOrientationChange (bool enable) {
#ifdef IPHONE
if (enable && !orientationObserver)
{
orientationObserver = [[OrientationObserver alloc] init];
// SDL forces dispatch of a display orientation event immediately.
// for consistency, we should dispatch one for device orientation.
[orientationObserver dispatchEventForCurrentDevice];
}
else if (!enable && orientationObserver)
{
orientationObserver = nil;
}
#endif
}
void System::OpenFile (const char* path) {
OpenURL (path, NULL);