summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
Diffstat (limited to 'platform')
-rw-r--r--platform/iphone/ios.h11
-rw-r--r--platform/iphone/ios.mm99
-rw-r--r--platform/iphone/os_iphone.mm8
-rw-r--r--platform/linuxbsd/display_server_x11.cpp25
4 files changed, 135 insertions, 8 deletions
diff --git a/platform/iphone/ios.h b/platform/iphone/ios.h
index 03e663b05c..0607d7b395 100644
--- a/platform/iphone/ios.h
+++ b/platform/iphone/ios.h
@@ -32,15 +32,26 @@
#define IOS_H
#include "core/object/class_db.h"
+#import <CoreHaptics/CoreHaptics.h>
class iOS : public Object {
GDCLASS(iOS, Object);
static void _bind_methods();
+private:
+ CHHapticEngine *haptic_engine API_AVAILABLE(ios(13)) = nullptr;
+
+ CHHapticEngine *get_haptic_engine_instance() API_AVAILABLE(ios(13));
+ void start_haptic_engine();
+ void stop_haptic_engine();
+
public:
static void alert(const char *p_alert, const char *p_title);
+ bool supports_haptic_engine();
+ void vibrate_haptic_engine(float p_duration_seconds);
+
String get_model() const;
String get_rate_url(int p_app_id) const;
diff --git a/platform/iphone/ios.mm b/platform/iphone/ios.mm
index ad1ea70c10..cca28cc055 100644
--- a/platform/iphone/ios.mm
+++ b/platform/iphone/ios.mm
@@ -32,11 +32,110 @@
#import "app_delegate.h"
#import "view_controller.h"
+
+#import <CoreHaptics/CoreHaptics.h>
#import <UIKit/UIKit.h>
#include <sys/sysctl.h>
void iOS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_rate_url", "app_id"), &iOS::get_rate_url);
+ ClassDB::bind_method(D_METHOD("supports_haptic_engine"), &iOS::supports_haptic_engine);
+ ClassDB::bind_method(D_METHOD("start_haptic_engine"), &iOS::start_haptic_engine);
+ ClassDB::bind_method(D_METHOD("stop_haptic_engine"), &iOS::stop_haptic_engine);
+};
+
+bool iOS::supports_haptic_engine() {
+ if (@available(iOS 13, *)) {
+ id<CHHapticDeviceCapability> capabilities = [CHHapticEngine capabilitiesForHardware];
+ return capabilities.supportsHaptics;
+ }
+
+ return false;
+}
+
+CHHapticEngine *iOS::get_haptic_engine_instance() API_AVAILABLE(ios(13)) {
+ if (haptic_engine == nullptr) {
+ NSError *error = nullptr;
+ haptic_engine = [[CHHapticEngine alloc] initAndReturnError:&error];
+
+ if (!error) {
+ [haptic_engine setAutoShutdownEnabled:true];
+ } else {
+ haptic_engine = nullptr;
+ NSLog(@"Could not initialize haptic engine: %@", error);
+ }
+ }
+
+ return haptic_engine;
+}
+
+void iOS::vibrate_haptic_engine(float p_duration_seconds) API_AVAILABLE(ios(13)) {
+ if (@available(iOS 13, *)) { // We need the @available check every time to make the compiler happy...
+ if (supports_haptic_engine()) {
+ CHHapticEngine *haptic_engine = get_haptic_engine_instance();
+ if (haptic_engine) {
+ NSDictionary *hapticDict = @{
+ CHHapticPatternKeyPattern : @[
+ @{CHHapticPatternKeyEvent : @{
+ CHHapticPatternKeyEventType : CHHapticEventTypeHapticTransient,
+ CHHapticPatternKeyTime : @(CHHapticTimeImmediate),
+ CHHapticPatternKeyEventDuration : @(p_duration_seconds)
+ },
+ },
+ ],
+ };
+
+ NSError *error;
+ CHHapticPattern *pattern = [[CHHapticPattern alloc] initWithDictionary:hapticDict error:&error];
+
+ [[haptic_engine createPlayerWithPattern:pattern error:&error] startAtTime:0 error:&error];
+
+ NSLog(@"Could not vibrate using haptic engine: %@", error);
+ }
+
+ return;
+ }
+ }
+
+ NSLog(@"Haptic engine is not supported in this version of iOS");
+}
+
+void iOS::start_haptic_engine() {
+ if (@available(iOS 13, *)) {
+ if (supports_haptic_engine()) {
+ CHHapticEngine *haptic_engine = get_haptic_engine_instance();
+ if (haptic_engine) {
+ [haptic_engine startWithCompletionHandler:^(NSError *returnedError) {
+ if (returnedError) {
+ NSLog(@"Could not start haptic engine: %@", returnedError);
+ }
+ }];
+ }
+
+ return;
+ }
+ }
+
+ NSLog(@"Haptic engine is not supported in this version of iOS");
+}
+
+void iOS::stop_haptic_engine() {
+ if (@available(iOS 13, *)) {
+ if (supports_haptic_engine()) {
+ CHHapticEngine *haptic_engine = get_haptic_engine_instance();
+ if (haptic_engine) {
+ [haptic_engine stopWithCompletionHandler:^(NSError *returnedError) {
+ if (returnedError) {
+ NSLog(@"Could not stop haptic engine: %@", returnedError);
+ }
+ }];
+ }
+
+ return;
+ }
+ }
+
+ NSLog(@"Haptic engine is not supported in this version of iOS");
}
void iOS::alert(const char *p_alert, const char *p_title) {
diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm
index ea1bc0ef64..f7974c4b3d 100644
--- a/platform/iphone/os_iphone.mm
+++ b/platform/iphone/os_iphone.mm
@@ -298,8 +298,12 @@ String OSIPhone::get_processor_name() const {
}
void OSIPhone::vibrate_handheld(int p_duration_ms) {
- // iOS does not support duration for vibration
- AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
+ if (ios->supports_haptic_engine()) {
+ ios->vibrate_haptic_engine((float)p_duration_ms / 1000.f);
+ } else {
+ // iOS <13 does not support duration for vibration
+ AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
+ }
}
bool OSIPhone::_check_internal_feature_support(const String &p_feature) {
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index 7da30ac363..acc7d1bc30 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -670,17 +670,17 @@ void DisplayServerX11::_clipboard_transfer_ownership(Atom p_source, Window x11_w
int DisplayServerX11::get_screen_count() const {
_THREAD_SAFE_METHOD_
+ int count = 0;
// Using Xinerama Extension
int event_base, error_base;
- const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base);
- if (!ext_okay) {
- return 0;
+ if (XineramaQueryExtension(x11_display, &event_base, &error_base)) {
+ XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count);
+ XFree(xsi);
+ } else {
+ count = XScreenCount(x11_display);
}
- int count;
- XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count);
- XFree(xsi);
return count;
}
@@ -712,6 +712,19 @@ Rect2i DisplayServerX11::_screen_get_rect(int p_screen) const {
if (xsi) {
XFree(xsi);
}
+ } else {
+ int count = XScreenCount(x11_display);
+ if (p_screen < count) {
+ Window root = XRootWindow(x11_display, p_screen);
+ XWindowAttributes xwa;
+ XGetWindowAttributes(x11_display, root, &xwa);
+ rect.position.x = xwa.x;
+ rect.position.y = xwa.y;
+ rect.size.width = xwa.width;
+ rect.size.height = xwa.height;
+ } else {
+ ERR_PRINT("Invalid screen index: " + itos(p_screen) + "(count: " + itos(count) + ").");
+ }
}
return rect;