summaryrefslogtreecommitdiffstats
path: root/platform
diff options
context:
space:
mode:
Diffstat (limited to 'platform')
-rw-r--r--platform/android/android_input_handler.cpp4
-rw-r--r--platform/android/android_input_handler.h2
-rw-r--r--platform/android/detect.py2
-rw-r--r--platform/android/java/app/build.gradle6
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java7
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt68
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java158
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java10
-rw-r--r--platform/android/java_godot_lib_jni.cpp8
-rw-r--r--platform/ios/detect.py2
-rw-r--r--platform/ios/display_server_ios.mm7
-rw-r--r--platform/ios/export/export_plugin.cpp52
-rw-r--r--platform/ios/view_controller.mm12
-rw-r--r--platform/linuxbsd/freedesktop_portal_desktop.cpp9
-rw-r--r--platform/linuxbsd/joypad_linux.cpp6
-rw-r--r--platform/linuxbsd/wayland/display_server_wayland.cpp18
-rw-r--r--platform/linuxbsd/wayland/display_server_wayland.h2
-rw-r--r--platform/linuxbsd/wayland/wayland_thread.h3
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp69
-rw-r--r--platform/linuxbsd/x11/display_server_x11.h2
-rw-r--r--platform/macos/display_server_macos.h2
-rw-r--r--platform/macos/display_server_macos.mm34
-rw-r--r--platform/macos/godot_content_view.mm33
-rw-r--r--platform/macos/godot_status_item.mm5
-rw-r--r--platform/web/detect.py2
-rw-r--r--platform/web/display_server_web.cpp76
-rw-r--r--platform/web/display_server_web.h1
-rw-r--r--platform/web/emscripten_helpers.py1
-rw-r--r--platform/web/javascript_bridge_singleton.cpp2
-rw-r--r--platform/web/js/libs/library_godot_input.js17
-rw-r--r--platform/windows/SCsub2
-rw-r--r--platform/windows/display_server_windows.cpp206
-rw-r--r--platform/windows/display_server_windows.h18
-rw-r--r--platform/windows/windows_utils.cpp4
34 files changed, 529 insertions, 321 deletions
diff --git a/platform/android/android_input_handler.cpp b/platform/android/android_input_handler.cpp
index 373dd399e4..41edc35276 100644
--- a/platform/android/android_input_handler.cpp
+++ b/platform/android/android_input_handler.cpp
@@ -176,6 +176,8 @@ void AndroidInputHandler::process_touch_event(int p_event, int p_pointer, const
for (int i = 0; i < p_points.size(); i++) {
touch.write[i].id = p_points[i].id;
touch.write[i].pos = p_points[i].pos;
+ touch.write[i].pressure = p_points[i].pressure;
+ touch.write[i].tilt = p_points[i].tilt;
}
//send touch
@@ -208,6 +210,8 @@ void AndroidInputHandler::process_touch_event(int p_event, int p_pointer, const
ev->set_position(p_points[idx].pos);
ev->set_relative(p_points[idx].pos - touch[i].pos);
ev->set_relative_screen_position(ev->get_relative());
+ ev->set_pressure(p_points[idx].pressure);
+ ev->set_tilt(p_points[idx].tilt);
Input::get_singleton()->parse_input_event(ev);
touch.write[i].pos = p_points[idx].pos;
}
diff --git a/platform/android/android_input_handler.h b/platform/android/android_input_handler.h
index 78a484cf05..e3365d8cb8 100644
--- a/platform/android/android_input_handler.h
+++ b/platform/android/android_input_handler.h
@@ -42,6 +42,8 @@ public:
struct TouchPos {
int id = 0;
Point2 pos;
+ float pressure = 0;
+ Vector2 tilt;
};
struct MouseEventInfo {
diff --git a/platform/android/detect.py b/platform/android/detect.py
index ed0ceb5862..0b182aca90 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -68,7 +68,7 @@ def get_min_target_api():
def get_flags():
return {
- "arch": "arm64", # Default for convenience.
+ "arch": "arm64",
"target": "template_debug",
"supported": ["mono"],
}
diff --git a/platform/android/java/app/build.gradle b/platform/android/java/app/build.gradle
index b83ef1471c..bde6a93c86 100644
--- a/platform/android/java/app/build.gradle
+++ b/platform/android/java/app/build.gradle
@@ -124,6 +124,12 @@ android {
// - https://stackoverflow.com/a/44704840
useLegacyPackaging shouldUseLegacyPackaging()
}
+
+ // Always select Godot's version of libc++_shared.so in case deps have their own
+ pickFirst 'lib/x86/libc++_shared.so'
+ pickFirst 'lib/x86_64/libc++_shared.so'
+ pickFirst 'lib/armeabi-v7a/libc++_shared.so'
+ pickFirst 'lib/arm64-v8a/libc++_shared.so'
}
signingConfigs {
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
index dc8a0e54bb..c085bb8886 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
@@ -266,8 +266,13 @@ public class GodotEditText extends EditText {
boolean hasHardwareKeyboard() {
Configuration config = getResources().getConfiguration();
- return config.keyboard != Configuration.KEYBOARD_NOKEYS &&
+ boolean hasHardwareKeyboardConfig = config.keyboard != Configuration.KEYBOARD_NOKEYS &&
config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO;
+ if (hasHardwareKeyboardConfig) {
+ return true;
+ }
+
+ return mRenderView.getInputHandler().hasHardwareKeyboard();
}
// ===========================================================
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt
index cfbbcf7d0e..49b34a5229 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt
@@ -65,7 +65,7 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi
private var lastDragY: Float = 0.0f
override fun onDown(event: MotionEvent): Boolean {
- GodotInputHandler.handleMotionEvent(event.source, MotionEvent.ACTION_DOWN, event.buttonState, event.x, event.y, nextDownIsDoubleTap)
+ GodotInputHandler.handleMotionEvent(event, MotionEvent.ACTION_DOWN, nextDownIsDoubleTap)
nextDownIsDoubleTap = false
return true
}
@@ -85,20 +85,14 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi
}
// Cancel the previous down event
- GodotInputHandler.handleMotionEvent(
- event.source,
- MotionEvent.ACTION_CANCEL,
- event.buttonState,
- event.x,
- event.y
- )
+ GodotInputHandler.handleMotionEvent(event, MotionEvent.ACTION_CANCEL)
// Turn a context click into a single tap right mouse button click.
GodotInputHandler.handleMouseEvent(
+ event,
MotionEvent.ACTION_DOWN,
MotionEvent.BUTTON_SECONDARY,
- event.x,
- event.y
+ false
)
contextClickInProgress = true
}
@@ -110,16 +104,7 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi
if (!hasCapture) {
// Dispatch a mouse relative ACTION_UP event to signal the end of the capture
- GodotInputHandler.handleMouseEvent(
- MotionEvent.ACTION_UP,
- 0,
- 0f,
- 0f,
- 0f,
- 0f,
- false,
- true
- )
+ GodotInputHandler.handleMouseEvent(MotionEvent.ACTION_UP, true)
}
pointerCaptureInProgress = hasCapture
}
@@ -142,26 +127,11 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi
return true
}
- val sourceMouseRelative = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE)
- } else {
- false
- }
-
if (pointerCaptureInProgress || dragInProgress || contextClickInProgress) {
if (contextClickInProgress || GodotInputHandler.isMouseEvent(event)) {
// This may be an ACTION_BUTTON_RELEASE event which we don't handle,
// so we convert it to an ACTION_UP event.
- GodotInputHandler.handleMouseEvent(
- MotionEvent.ACTION_UP,
- event.buttonState,
- event.x,
- event.y,
- 0f,
- 0f,
- false,
- sourceMouseRelative
- )
+ GodotInputHandler.handleMouseEvent(event, MotionEvent.ACTION_UP)
} else {
GodotInputHandler.handleTouchEvent(event)
}
@@ -178,21 +148,7 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi
private fun onActionMove(event: MotionEvent): Boolean {
if (contextClickInProgress) {
- val sourceMouseRelative = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE)
- } else {
- false
- }
- GodotInputHandler.handleMouseEvent(
- event.actionMasked,
- MotionEvent.BUTTON_SECONDARY,
- event.x,
- event.y,
- 0f,
- 0f,
- false,
- sourceMouseRelative
- )
+ GodotInputHandler.handleMouseEvent(event, event.actionMasked, MotionEvent.BUTTON_SECONDARY, false)
return true
} else if (!scaleInProgress) {
// The 'onScroll' event is triggered with a long delay.
@@ -213,7 +169,7 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi
if (event.actionMasked == MotionEvent.ACTION_UP) {
nextDownIsDoubleTap = false
GodotInputHandler.handleMotionEvent(event)
- } else if (event.actionMasked == MotionEvent.ACTION_MOVE && panningAndScalingEnabled == false) {
+ } else if (event.actionMasked == MotionEvent.ACTION_MOVE && !panningAndScalingEnabled) {
GodotInputHandler.handleMotionEvent(event)
}
@@ -235,13 +191,7 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi
if (dragInProgress || lastDragX != 0.0f || lastDragY != 0.0f) {
if (originEvent != null) {
// Cancel the drag
- GodotInputHandler.handleMotionEvent(
- originEvent.source,
- MotionEvent.ACTION_CANCEL,
- originEvent.buttonState,
- originEvent.x,
- originEvent.y
- )
+ GodotInputHandler.handleMotionEvent(originEvent, MotionEvent.ACTION_CANCEL)
}
dragInProgress = false
lastDragX = 0.0f
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
index fe971cf442..43ae71f8e1 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
@@ -62,6 +62,7 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
private final SparseIntArray mJoystickIds = new SparseIntArray(4);
private final SparseArray<Joystick> mJoysticksDevices = new SparseArray<>(4);
+ private final HashSet<Integer> mHardwareKeyboardIds = new HashSet<>();
private final GodotRenderView mRenderView;
private final InputManager mInputManager;
@@ -114,6 +115,10 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
rotaryInputAxis = axis;
}
+ boolean hasHardwareKeyboard() {
+ return !mHardwareKeyboardIds.isEmpty();
+ }
+
private boolean isKeyEventGameDevice(int source) {
// Note that keyboards are often (SOURCE_KEYBOARD | SOURCE_DPAD)
if (source == (InputDevice.SOURCE_KEYBOARD | InputDevice.SOURCE_DPAD))
@@ -195,7 +200,7 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
}
public boolean onTouchEvent(final MotionEvent event) {
- lastSeenToolType = event.getToolType(0);
+ lastSeenToolType = getEventToolType(event);
this.scaleGestureDetector.onTouchEvent(event);
if (this.gestureDetector.onTouchEvent(event)) {
@@ -221,7 +226,7 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
}
public boolean onGenericMotionEvent(MotionEvent event) {
- lastSeenToolType = event.getToolType(0);
+ lastSeenToolType = getEventToolType(event);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && gestureDetector.onGenericMotionEvent(event)) {
// The gesture detector has handled the event.
@@ -310,11 +315,17 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
return;
}
- int sources = device.getSources();
+ // Device may be an external keyboard; store the device id
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q &&
+ device.supportsSource(InputDevice.SOURCE_KEYBOARD) &&
+ device.isExternal() &&
+ device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
+ mHardwareKeyboardIds.add(deviceId);
+ }
// Device may not be a joystick or gamepad
- if ((sources & InputDevice.SOURCE_GAMEPAD) != InputDevice.SOURCE_GAMEPAD &&
- (sources & InputDevice.SOURCE_JOYSTICK) != InputDevice.SOURCE_JOYSTICK) {
+ if (!device.supportsSource(InputDevice.SOURCE_GAMEPAD) &&
+ !device.supportsSource(InputDevice.SOURCE_JOYSTICK)) {
return;
}
@@ -359,6 +370,8 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
@Override
public void onInputDeviceRemoved(int deviceId) {
+ mHardwareKeyboardIds.remove(deviceId);
+
// Check if the device has not been already removed
if (mJoystickIds.indexOfKey(deviceId) < 0) {
return;
@@ -440,50 +453,65 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
return button;
}
- static boolean isMouseEvent(MotionEvent event) {
- return isMouseEvent(event.getSource());
+ private static int getEventToolType(MotionEvent event) {
+ return event.getPointerCount() > 0 ? event.getToolType(0) : MotionEvent.TOOL_TYPE_UNKNOWN;
}
- private static boolean isMouseEvent(int eventSource) {
- boolean mouseSource = ((eventSource & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) || ((eventSource & InputDevice.SOURCE_STYLUS) == InputDevice.SOURCE_STYLUS);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- mouseSource = mouseSource || ((eventSource & InputDevice.SOURCE_MOUSE_RELATIVE) == InputDevice.SOURCE_MOUSE_RELATIVE);
+ static boolean isMouseEvent(MotionEvent event) {
+ int toolType = getEventToolType(event);
+ int eventSource = event.getSource();
+
+ switch (toolType) {
+ case MotionEvent.TOOL_TYPE_FINGER:
+ return false;
+
+ case MotionEvent.TOOL_TYPE_MOUSE:
+ case MotionEvent.TOOL_TYPE_STYLUS:
+ case MotionEvent.TOOL_TYPE_ERASER:
+ return true;
+
+ case MotionEvent.TOOL_TYPE_UNKNOWN:
+ default:
+ boolean mouseSource =
+ ((eventSource & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) ||
+ ((eventSource & (InputDevice.SOURCE_TOUCHSCREEN | InputDevice.SOURCE_STYLUS)) == InputDevice.SOURCE_STYLUS);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ mouseSource = mouseSource ||
+ ((eventSource & InputDevice.SOURCE_MOUSE_RELATIVE) == InputDevice.SOURCE_MOUSE_RELATIVE);
+ }
+ return mouseSource;
}
- return mouseSource;
}
static boolean handleMotionEvent(final MotionEvent event) {
- if (isMouseEvent(event)) {
- return handleMouseEvent(event);
- }
-
- return handleTouchEvent(event);
+ return handleMotionEvent(event, event.getActionMasked());
}
- static boolean handleMotionEvent(int eventSource, int eventAction, int buttonsMask, float x, float y) {
- return handleMotionEvent(eventSource, eventAction, buttonsMask, x, y, false);
+ static boolean handleMotionEvent(final MotionEvent event, int eventActionOverride) {
+ return handleMotionEvent(event, eventActionOverride, false);
}
- static boolean handleMotionEvent(int eventSource, int eventAction, int buttonsMask, float x, float y, boolean doubleTap) {
- return handleMotionEvent(eventSource, eventAction, buttonsMask, x, y, 0, 0, doubleTap);
+ static boolean handleMotionEvent(final MotionEvent event, int eventActionOverride, boolean doubleTap) {
+ if (isMouseEvent(event)) {
+ return handleMouseEvent(event, eventActionOverride, doubleTap);
+ }
+ return handleTouchEvent(event, eventActionOverride, doubleTap);
}
- static boolean handleMotionEvent(int eventSource, int eventAction, int buttonsMask, float x, float y, float deltaX, float deltaY, boolean doubleTap) {
- if (isMouseEvent(eventSource)) {
- return handleMouseEvent(eventAction, buttonsMask, x, y, deltaX, deltaY, doubleTap, false);
- }
+ private static float getEventTiltX(MotionEvent event) {
+ // Orientation is returned as a radian value between 0 to pi clockwise or 0 to -pi counterclockwise.
+ final float orientation = event.getOrientation();
- return handleTouchEvent(eventAction, x, y, doubleTap);
- }
+ // Tilt is zero is perpendicular to the screen and pi/2 is flat on the surface.
+ final float tilt = event.getAxisValue(MotionEvent.AXIS_TILT);
- static boolean handleMouseEvent(final MotionEvent event) {
- final int eventAction = event.getActionMasked();
- final float x = event.getX();
- final float y = event.getY();
- final int buttonsMask = event.getButtonState();
+ float tiltMult = (float)Math.sin(tilt);
- final float pressure = event.getPressure();
+ // To be consistent with expected tilt.
+ return (float)-Math.sin(orientation) * tiltMult;
+ }
+ private static float getEventTiltY(MotionEvent event) {
// Orientation is returned as a radian value between 0 to pi clockwise or 0 to -pi counterclockwise.
final float orientation = event.getOrientation();
@@ -493,8 +521,26 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
float tiltMult = (float)Math.sin(tilt);
// To be consistent with expected tilt.
- final float tiltX = (float)-Math.sin(orientation) * tiltMult;
- final float tiltY = (float)Math.cos(orientation) * tiltMult;
+ return (float)Math.cos(orientation) * tiltMult;
+ }
+
+ static boolean handleMouseEvent(final MotionEvent event) {
+ return handleMouseEvent(event, event.getActionMasked());
+ }
+
+ static boolean handleMouseEvent(final MotionEvent event, int eventActionOverride) {
+ return handleMouseEvent(event, eventActionOverride, false);
+ }
+
+ static boolean handleMouseEvent(final MotionEvent event, int eventActionOverride, boolean doubleTap) {
+ return handleMouseEvent(event, eventActionOverride, event.getButtonState(), doubleTap);
+ }
+
+ static boolean handleMouseEvent(final MotionEvent event, int eventActionOverride, int buttonMaskOverride, boolean doubleTap) {
+ final float x = event.getX();
+ final float y = event.getY();
+
+ final float pressure = event.getPressure();
float verticalFactor = 0;
float horizontalFactor = 0;
@@ -516,15 +562,11 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
sourceMouseRelative = event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE);
}
- return handleMouseEvent(eventAction, buttonsMask, x, y, horizontalFactor, verticalFactor, false, sourceMouseRelative, pressure, tiltX, tiltY);
+ return handleMouseEvent(eventActionOverride, buttonMaskOverride, x, y, horizontalFactor, verticalFactor, doubleTap, sourceMouseRelative, pressure, getEventTiltX(event), getEventTiltY(event));
}
- static boolean handleMouseEvent(int eventAction, int buttonsMask, float x, float y) {
- return handleMouseEvent(eventAction, buttonsMask, x, y, 0, 0, false, false);
- }
-
- static boolean handleMouseEvent(int eventAction, int buttonsMask, float x, float y, float deltaX, float deltaY, boolean doubleClick, boolean sourceMouseRelative) {
- return handleMouseEvent(eventAction, buttonsMask, x, y, deltaX, deltaY, doubleClick, sourceMouseRelative, 1, 0, 0);
+ static boolean handleMouseEvent(int eventAction, boolean sourceMouseRelative) {
+ return handleMouseEvent(eventAction, 0, 0f, 0f, 0f, 0f, false, sourceMouseRelative, 1f, 0f, 0f);
}
static boolean handleMouseEvent(int eventAction, int buttonsMask, float x, float y, float deltaX, float deltaY, boolean doubleClick, boolean sourceMouseRelative, float pressure, float tiltX, float tiltY) {
@@ -563,37 +605,39 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
}
static boolean handleTouchEvent(final MotionEvent event) {
+ return handleTouchEvent(event, event.getActionMasked());
+ }
+
+ static boolean handleTouchEvent(final MotionEvent event, int eventActionOverride) {
+ return handleTouchEvent(event, eventActionOverride, false);
+ }
+
+ static boolean handleTouchEvent(final MotionEvent event, int eventActionOverride, boolean doubleTap) {
final int pointerCount = event.getPointerCount();
if (pointerCount == 0) {
return true;
}
- final float[] positions = new float[pointerCount * 3]; // pointerId1, x1, y1, pointerId2, etc...
+ final float[] positions = new float[pointerCount * 6]; // pointerId1, x1, y1, pressure1, tiltX1, tiltY1, pointerId2, etc...
for (int i = 0; i < pointerCount; i++) {
- positions[i * 3 + 0] = event.getPointerId(i);
- positions[i * 3 + 1] = event.getX(i);
- positions[i * 3 + 2] = event.getY(i);
+ positions[i * 6 + 0] = event.getPointerId(i);
+ positions[i * 6 + 1] = event.getX(i);
+ positions[i * 6 + 2] = event.getY(i);
+ positions[i * 6 + 3] = event.getPressure(i);
+ positions[i * 6 + 4] = getEventTiltX(event);
+ positions[i * 6 + 5] = getEventTiltY(event);
}
- final int action = event.getActionMasked();
final int actionPointerId = event.getPointerId(event.getActionIndex());
- return handleTouchEvent(action, actionPointerId, pointerCount, positions, false);
- }
-
- static boolean handleTouchEvent(int eventAction, float x, float y, boolean doubleTap) {
- return handleTouchEvent(eventAction, 0, 1, new float[] { 0, x, y }, doubleTap);
- }
-
- static boolean handleTouchEvent(int eventAction, int actionPointerId, int pointerCount, float[] positions, boolean doubleTap) {
- switch (eventAction) {
+ switch (eventActionOverride) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_DOWN: {
- GodotLib.dispatchTouchEvent(eventAction, actionPointerId, pointerCount, positions, doubleTap);
+ GodotLib.dispatchTouchEvent(eventActionOverride, actionPointerId, pointerCount, positions, doubleTap);
return true;
}
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java
index 9df890e6bd..4e8e82a70a 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java
@@ -125,7 +125,7 @@ public final class PermissionsUtil {
}
activity.requestPermissions(requestedPermissions.toArray(new String[0]), REQUEST_ALL_PERMISSION_REQ_CODE);
- return true;
+ return false;
}
/**
@@ -281,8 +281,9 @@ public final class PermissionsUtil {
public static boolean hasManifestPermission(Context context, String permission) {
try {
for (String p : getManifestPermissions(context)) {
- if (permission.equals(p))
+ if (permission.equals(p)) {
return true;
+ }
}
} catch (PackageManager.NameNotFoundException ignored) {
}
@@ -299,8 +300,9 @@ public final class PermissionsUtil {
public static ArrayList<String> getManifestPermissions(Context context) throws PackageManager.NameNotFoundException {
PackageManager packageManager = context.getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS);
- if (packageInfo.requestedPermissions == null)
- return new ArrayList<String>();
+ if (packageInfo.requestedPermissions == null) {
+ return new ArrayList<>();
+ }
return new ArrayList<>(Arrays.asList(packageInfo.requestedPermissions));
}
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index 93743c4e35..40068745d6 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -298,11 +298,13 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_dispatchTouchEvent(JN
Vector<AndroidInputHandler::TouchPos> points;
for (int i = 0; i < pointer_count; i++) {
- jfloat p[3];
- env->GetFloatArrayRegion(position, i * 3, 3, p);
+ jfloat p[6];
+ env->GetFloatArrayRegion(position, i * 6, 6, p);
AndroidInputHandler::TouchPos tp;
- tp.pos = Point2(p[1], p[2]);
tp.id = (int)p[0];
+ tp.pos = Point2(p[1], p[2]);
+ tp.pressure = p[3];
+ tp.tilt = Vector2(p[4], p[5]);
points.push_back(tp);
}
diff --git a/platform/ios/detect.py b/platform/ios/detect.py
index 35e1b9cd6d..53b367a0a7 100644
--- a/platform/ios/detect.py
+++ b/platform/ios/detect.py
@@ -48,7 +48,7 @@ def get_doc_path():
def get_flags():
return {
- "arch": "arm64", # Default for convenience.
+ "arch": "arm64",
"target": "template_debug",
"use_volk": False,
"supported": ["mono"],
diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm
index 5d7af25f28..a454dd5ba0 100644
--- a/platform/ios/display_server_ios.mm
+++ b/platform/ios/display_server_ios.mm
@@ -399,7 +399,12 @@ void DisplayServerIOS::set_system_theme_change_callback(const Callable &p_callab
void DisplayServerIOS::emit_system_theme_changed() {
if (system_theme_changed.is_valid()) {
- system_theme_changed.call();
+ Variant ret;
+ Callable::CallError ce;
+ system_theme_changed.callp(nullptr, 0, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT(vformat("Failed to execute system theme changed callback: %s.", Variant::get_callable_error_text(system_theme_changed, nullptr, 0, ce)));
+ }
}
}
diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp
index 6a452f08fa..2194804b3b 100644
--- a/platform/ios/export/export_plugin.cpp
+++ b/platform/ios/export/export_plugin.cpp
@@ -541,6 +541,44 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
}
strnew += lines[i].replace("$interface_orientations", orientations);
+ } else if (lines[i].contains("$ipad_interface_orientations")) {
+ String orientations;
+ const DisplayServer::ScreenOrientation screen_orientation =
+ DisplayServer::ScreenOrientation(int(GLOBAL_GET("display/window/handheld/orientation")));
+
+ switch (screen_orientation) {
+ case DisplayServer::SCREEN_LANDSCAPE:
+ orientations += "<string>UIInterfaceOrientationLandscapeRight</string>\n";
+ break;
+ case DisplayServer::SCREEN_PORTRAIT:
+ orientations += "<string>UIInterfaceOrientationPortrait</string>\n";
+ break;
+ case DisplayServer::SCREEN_REVERSE_LANDSCAPE:
+ orientations += "<string>UIInterfaceOrientationLandscapeLeft</string>\n";
+ break;
+ case DisplayServer::SCREEN_REVERSE_PORTRAIT:
+ orientations += "<string>UIInterfaceOrientationPortraitUpsideDown</string>\n";
+ break;
+ case DisplayServer::SCREEN_SENSOR_LANDSCAPE:
+ // Allow both landscape orientations depending on sensor direction.
+ orientations += "<string>UIInterfaceOrientationLandscapeLeft</string>\n";
+ orientations += "<string>UIInterfaceOrientationLandscapeRight</string>\n";
+ break;
+ case DisplayServer::SCREEN_SENSOR_PORTRAIT:
+ // Allow both portrait orientations depending on sensor direction.
+ orientations += "<string>UIInterfaceOrientationPortrait</string>\n";
+ orientations += "<string>UIInterfaceOrientationPortraitUpsideDown</string>\n";
+ break;
+ case DisplayServer::SCREEN_SENSOR:
+ // Allow all screen orientations depending on sensor direction.
+ orientations += "<string>UIInterfaceOrientationLandscapeLeft</string>\n";
+ orientations += "<string>UIInterfaceOrientationLandscapeRight</string>\n";
+ orientations += "<string>UIInterfaceOrientationPortrait</string>\n";
+ orientations += "<string>UIInterfaceOrientationPortraitUpsideDown</string>\n";
+ break;
+ }
+
+ strnew += lines[i].replace("$ipad_interface_orientations", orientations);
} else if (lines[i].contains("$camera_usage_description")) {
String description = p_preset->get("privacy/camera_usage_description");
strnew += lines[i].replace("$camera_usage_description", description) + "\n";
@@ -1319,12 +1357,7 @@ void EditorExportPlatformIOS::_add_assets_to_project(const String &p_out_dir, co
String type;
if (asset.exported_path.ends_with(".framework")) {
- int total_libs = 0;
- int static_libs = 0;
- int dylibs = 0;
- int frameworks = 0;
- _check_xcframework_content(p_out_dir.path_join(asset.exported_path), total_libs, static_libs, dylibs, frameworks);
- if (asset.should_embed && (static_libs != total_libs)) {
+ if (asset.should_embed) {
additional_asset_info_format += "$framework_id = {isa = PBXBuildFile; fileRef = $ref_id; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };\n";
framework_id = (++current_id).str();
pbx_embeded_frameworks += framework_id + ",\n";
@@ -1332,7 +1365,12 @@ void EditorExportPlatformIOS::_add_assets_to_project(const String &p_out_dir, co
type = "wrapper.framework";
} else if (asset.exported_path.ends_with(".xcframework")) {
- if (asset.should_embed) {
+ int total_libs = 0;
+ int static_libs = 0;
+ int dylibs = 0;
+ int frameworks = 0;
+ _check_xcframework_content(p_out_dir.path_join(asset.exported_path), total_libs, static_libs, dylibs, frameworks);
+ if (asset.should_embed && static_libs != total_libs) {
additional_asset_info_format += "$framework_id = {isa = PBXBuildFile; fileRef = $ref_id; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };\n";
framework_id = (++current_id).str();
pbx_embeded_frameworks += framework_id + ",\n";
diff --git a/platform/ios/view_controller.mm b/platform/ios/view_controller.mm
index 6f6c04c2c8..787e767109 100644
--- a/platform/ios/view_controller.mm
+++ b/platform/ios/view_controller.mm
@@ -258,7 +258,11 @@
case DisplayServer::SCREEN_PORTRAIT:
return UIInterfaceOrientationMaskPortrait;
case DisplayServer::SCREEN_REVERSE_LANDSCAPE:
- return UIInterfaceOrientationMaskLandscapeRight;
+ if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
+ return UIInterfaceOrientationMaskLandscapeLeft;
+ } else {
+ return UIInterfaceOrientationMaskLandscapeRight;
+ }
case DisplayServer::SCREEN_REVERSE_PORTRAIT:
return UIInterfaceOrientationMaskPortraitUpsideDown;
case DisplayServer::SCREEN_SENSOR_LANDSCAPE:
@@ -268,7 +272,11 @@
case DisplayServer::SCREEN_SENSOR:
return UIInterfaceOrientationMaskAll;
case DisplayServer::SCREEN_LANDSCAPE:
- return UIInterfaceOrientationMaskLandscapeLeft;
+ if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
+ return UIInterfaceOrientationMaskLandscapeRight;
+ } else {
+ return UIInterfaceOrientationMaskLandscapeLeft;
+ }
}
}
diff --git a/platform/linuxbsd/freedesktop_portal_desktop.cpp b/platform/linuxbsd/freedesktop_portal_desktop.cpp
index e65404a531..671da7fc2a 100644
--- a/platform/linuxbsd/freedesktop_portal_desktop.cpp
+++ b/platform/linuxbsd/freedesktop_portal_desktop.cpp
@@ -591,13 +591,18 @@ void FreeDesktopPortalDesktop::_thread_monitor(void *p_ud) {
dbus_connection_read_write(portal->monitor_connection, 0);
}
- usleep(50000);
+ OS::get_singleton()->delay_usec(50'000);
}
}
void FreeDesktopPortalDesktop::_system_theme_changed_callback() {
if (system_theme_changed.is_valid()) {
- system_theme_changed.call();
+ Variant ret;
+ Callable::CallError ce;
+ system_theme_changed.callp(nullptr, 0, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT(vformat("Failed to execute system theme changed callback: %s.", Variant::get_callable_error_text(system_theme_changed, nullptr, 0, ce)));
+ }
}
}
diff --git a/platform/linuxbsd/joypad_linux.cpp b/platform/linuxbsd/joypad_linux.cpp
index 6e546c4531..3534c1afee 100644
--- a/platform/linuxbsd/joypad_linux.cpp
+++ b/platform/linuxbsd/joypad_linux.cpp
@@ -225,7 +225,7 @@ void JoypadLinux::monitor_joypads(udev *p_udev) {
udev_device_unref(dev);
}
}
- usleep(50000);
+ OS::get_singleton()->delay_usec(50'000);
}
udev_monitor_unref(mon);
}
@@ -250,7 +250,7 @@ void JoypadLinux::monitor_joypads() {
}
}
closedir(input_directory);
- usleep(1000000); // 1s
+ OS::get_singleton()->delay_usec(1'000'000);
}
}
@@ -508,7 +508,7 @@ void JoypadLinux::joypad_events_thread_run() {
}
}
if (no_events) {
- usleep(10000); // 10ms
+ OS::get_singleton()->delay_usec(10'000);
}
}
}
diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp
index ce8a53a856..12d3a6fd2f 100644
--- a/platform/linuxbsd/wayland/display_server_wayland.cpp
+++ b/platform/linuxbsd/wayland/display_server_wayland.cpp
@@ -1137,7 +1137,14 @@ void DisplayServerWayland::process_events() {
WindowData wd = main_window;
if (wd.drop_files_callback.is_valid()) {
- wd.drop_files_callback.call(dropfiles_msg->files);
+ Variant v_files = dropfiles_msg->files;
+ const Variant *v_args[1] = { &v_files };
+ Variant ret;
+ Callable::CallError ce;
+ wd.drop_files_callback.callp((const Variant **)&v_args, 1, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT(vformat("Failed to execute drop files callback: %s.", Variant::get_callable_error_text(wd.drop_files_callback, v_args, 1, ce)));
+ }
}
}
}
@@ -1209,6 +1216,15 @@ void DisplayServerWayland::set_context(Context p_context) {
wayland_thread.window_set_app_id(MAIN_WINDOW_ID, app_id);
}
+bool DisplayServerWayland::is_window_transparency_available() const {
+#if defined(RD_ENABLED)
+ if (rendering_device && !rendering_device->is_composite_alpha_supported()) {
+ return false;
+ }
+#endif
+ return OS::get_singleton()->is_layered_allowed();
+}
+
Vector<String> DisplayServerWayland::get_rendering_drivers_func() {
Vector<String> drivers;
diff --git a/platform/linuxbsd/wayland/display_server_wayland.h b/platform/linuxbsd/wayland/display_server_wayland.h
index 38ecbd703d..c24eb0ee62 100644
--- a/platform/linuxbsd/wayland/display_server_wayland.h
+++ b/platform/linuxbsd/wayland/display_server_wayland.h
@@ -280,6 +280,8 @@ public:
virtual void set_context(Context p_context) override;
+ virtual bool is_window_transparency_available() const override;
+
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Point2i *p_position, const Size2i &p_resolution, int p_screen, Context p_context, Error &r_error);
static Vector<String> get_rendering_drivers_func();
diff --git a/platform/linuxbsd/wayland/wayland_thread.h b/platform/linuxbsd/wayland/wayland_thread.h
index d35a5b7139..0756b6b0ea 100644
--- a/platform/linuxbsd/wayland/wayland_thread.h
+++ b/platform/linuxbsd/wayland/wayland_thread.h
@@ -43,6 +43,9 @@
#else
#include <wayland-client-core.h>
#include <wayland-cursor.h>
+#ifdef GLES3_ENABLED
+#include <wayland-egl.h>
+#endif
#include <xkbcommon/xkbcommon.h>
#endif // SOWRAP_ENABLED
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index 2c07acf94f..34b6d0219a 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -502,7 +502,34 @@ Point2i DisplayServerX11::mouse_get_position() const {
}
BitField<MouseButtonMask> DisplayServerX11::mouse_get_button_state() const {
- return last_button_state;
+ int number_of_screens = XScreenCount(x11_display);
+ for (int i = 0; i < number_of_screens; i++) {
+ Window root, child;
+ int root_x, root_y, win_x, win_y;
+ unsigned int mask;
+ if (XQueryPointer(x11_display, XRootWindow(x11_display, i), &root, &child, &root_x, &root_y, &win_x, &win_y, &mask)) {
+ BitField<MouseButtonMask> last_button_state = 0;
+
+ if (mask & Button1Mask) {
+ last_button_state.set_flag(MouseButtonMask::LEFT);
+ }
+ if (mask & Button2Mask) {
+ last_button_state.set_flag(MouseButtonMask::MIDDLE);
+ }
+ if (mask & Button3Mask) {
+ last_button_state.set_flag(MouseButtonMask::RIGHT);
+ }
+ if (mask & Button4Mask) {
+ last_button_state.set_flag(MouseButtonMask::MB_XBUTTON1);
+ }
+ if (mask & Button5Mask) {
+ last_button_state.set_flag(MouseButtonMask::MB_XBUTTON2);
+ }
+
+ return last_button_state;
+ }
+ }
+ return 0;
}
void DisplayServerX11::clipboard_set(const String &p_text) {
@@ -2269,7 +2296,7 @@ void DisplayServerX11::window_set_size(const Size2i p_size, WindowID p_window) {
break;
}
- usleep(10000);
+ OS::get_singleton()->delay_usec(10'000);
}
// Keep rendering context window size in sync
@@ -2544,7 +2571,7 @@ void DisplayServerX11::_set_wm_maximized(WindowID p_window, bool p_enabled) {
// Give up after 0.5s, it's not going to happen on this WM.
// https://github.com/godotengine/godot/issues/19978
for (int attempt = 0; window_get_mode(p_window) != WINDOW_MODE_MAXIMIZED && attempt < 50; attempt++) {
- usleep(10000);
+ OS::get_singleton()->delay_usec(10'000);
}
}
wd.maximized = p_enabled;
@@ -3351,18 +3378,6 @@ void DisplayServerX11::_get_key_modifier_state(unsigned int p_x11_state, Ref<Inp
state->set_meta_pressed((p_x11_state & Mod4Mask));
}
-BitField<MouseButtonMask> DisplayServerX11::_get_mouse_button_state(MouseButton p_x11_button, int p_x11_type) {
- MouseButtonMask mask = mouse_button_to_mask(p_x11_button);
-
- if (p_x11_type == ButtonPress) {
- last_button_state.set_flag(mask);
- } else {
- last_button_state.clear_flag(mask);
- }
-
- return last_button_state;
-}
-
void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, LocalVector<XEvent> &p_events, uint32_t &p_event_index, bool p_echo) {
WindowData &wd = windows[p_window];
// X11 functions don't know what const is
@@ -4206,7 +4221,10 @@ void DisplayServerX11::popup_close(WindowID p_window) {
WindowID win_id = E->get();
popup_list.erase(E);
- _send_window_event(windows[win_id], DisplayServerX11::WINDOW_EVENT_CLOSE_REQUEST);
+ if (win_id != p_window) {
+ // Only request close on related windows, not this window. We are already processing it.
+ _send_window_event(windows[win_id], DisplayServerX11::WINDOW_EVENT_CLOSE_REQUEST);
+ }
E = F;
}
}
@@ -4747,12 +4765,20 @@ void DisplayServerX11::process_events() {
} else if (mb->get_button_index() == MouseButton::MIDDLE) {
mb->set_button_index(MouseButton::RIGHT);
}
- mb->set_button_mask(_get_mouse_button_state(mb->get_button_index(), event.xbutton.type));
mb->set_position(Vector2(event.xbutton.x, event.xbutton.y));
mb->set_global_position(mb->get_position());
mb->set_pressed((event.type == ButtonPress));
+ if (mb->is_pressed() && mb->get_button_index() >= MouseButton::WHEEL_UP && mb->get_button_index() <= MouseButton::WHEEL_RIGHT) {
+ MouseButtonMask mask = mouse_button_to_mask(mb->get_button_index());
+ BitField<MouseButtonMask> scroll_mask = mouse_get_button_state();
+ scroll_mask.set_flag(mask);
+ mb->set_button_mask(scroll_mask);
+ } else {
+ mb->set_button_mask(mouse_get_button_state());
+ }
+
const WindowData &wd = windows[window_id];
if (event.type == ButtonPress) {
@@ -5008,7 +5034,14 @@ void DisplayServerX11::process_events() {
}
if (windows[window_id].drop_files_callback.is_valid()) {
- windows[window_id].drop_files_callback.call(files);
+ Variant v_files = files;
+ const Variant *v_args[1] = { &v_files };
+ Variant ret;
+ Callable::CallError ce;
+ windows[window_id].drop_files_callback.callp((const Variant **)&v_args, 1, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT(vformat("Failed to execute drop files callback: %s.", Variant::get_callable_error_text(windows[window_id].drop_files_callback, v_args, 1, ce)));
+ }
}
//Reply that all is well.
diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h
index 7c69df3df0..f0b1811986 100644
--- a/platform/linuxbsd/x11/display_server_x11.h
+++ b/platform/linuxbsd/x11/display_server_x11.h
@@ -263,7 +263,6 @@ class DisplayServerX11 : public DisplayServer {
Point2i last_click_pos = Point2i(-100, -100);
uint64_t last_click_ms = 0;
MouseButton last_click_button_index = MouseButton::NONE;
- BitField<MouseButtonMask> last_button_state;
bool app_focused = false;
uint64_t time_since_no_focus = 0;
@@ -292,7 +291,6 @@ class DisplayServerX11 : public DisplayServer {
Rect2i _screen_get_rect(int p_screen) const;
- BitField<MouseButtonMask> _get_mouse_button_state(MouseButton p_x11_button, int p_x11_type);
void _get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state);
void _flush_mouse_motion();
diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h
index 608c34edc6..b4741dc08f 100644
--- a/platform/macos/display_server_macos.h
+++ b/platform/macos/display_server_macos.h
@@ -164,7 +164,6 @@ private:
CGEventSourceRef event_source;
MouseMode mouse_mode = MOUSE_MODE_VISIBLE;
- BitField<MouseButtonMask> last_button_state;
bool drop_events = false;
bool in_dispatch_input_event = false;
@@ -302,7 +301,6 @@ public:
bool update_mouse_wrap(WindowData &p_wd, NSPoint &r_delta, NSPoint &r_mpos, NSTimeInterval p_timestamp);
virtual void warp_mouse(const Point2i &p_position) override;
virtual Point2i mouse_get_position() const override;
- void mouse_set_button_state(BitField<MouseButtonMask> p_state);
virtual BitField<MouseButtonMask> mouse_get_button_state() const override;
virtual void clipboard_set(const String &p_text) override;
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index db71c48eff..50313cfe67 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -907,7 +907,12 @@ void DisplayServerMacOS::set_system_theme_change_callback(const Callable &p_call
void DisplayServerMacOS::emit_system_theme_changed() {
if (system_theme_changed.is_valid()) {
- system_theme_changed.call();
+ Variant ret;
+ Callable::CallError ce;
+ system_theme_changed.callp(nullptr, 0, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT(vformat("Failed to execute system theme changed callback: %s.", Variant::get_callable_error_text(system_theme_changed, nullptr, 0, ce)));
+ }
}
}
@@ -1416,11 +1421,25 @@ Point2i DisplayServerMacOS::mouse_get_position() const {
return Vector2i();
}
-void DisplayServerMacOS::mouse_set_button_state(BitField<MouseButtonMask> p_state) {
- last_button_state = p_state;
-}
-
BitField<MouseButtonMask> DisplayServerMacOS::mouse_get_button_state() const {
+ BitField<MouseButtonMask> last_button_state = 0;
+
+ NSUInteger buttons = [NSEvent pressedMouseButtons];
+ if (buttons & (1 << 0)) {
+ last_button_state.set_flag(MouseButtonMask::LEFT);
+ }
+ if (buttons & (1 << 1)) {
+ last_button_state.set_flag(MouseButtonMask::RIGHT);
+ }
+ if (buttons & (1 << 2)) {
+ last_button_state.set_flag(MouseButtonMask::MIDDLE);
+ }
+ if (buttons & (1 << 3)) {
+ last_button_state.set_flag(MouseButtonMask::MB_XBUTTON1);
+ }
+ if (buttons & (1 << 4)) {
+ last_button_state.set_flag(MouseButtonMask::MB_XBUTTON2);
+ }
return last_button_state;
}
@@ -3448,7 +3467,10 @@ void DisplayServerMacOS::popup_close(WindowID p_window) {
WindowID win_id = E->get();
popup_list.erase(E);
- send_window_event(windows[win_id], DisplayServerMacOS::WINDOW_EVENT_CLOSE_REQUEST);
+ if (win_id != p_window) {
+ // Only request close on related windows, not this window. We are already processing it.
+ send_window_event(windows[win_id], DisplayServerMacOS::WINDOW_EVENT_CLOSE_REQUEST);
+ }
E = F;
}
if (!was_empty && popup_list.is_empty()) {
diff --git a/platform/macos/godot_content_view.mm b/platform/macos/godot_content_view.mm
index 68a7288ad4..77f3a28ae7 100644
--- a/platform/macos/godot_content_view.mm
+++ b/platform/macos/godot_content_view.mm
@@ -323,7 +323,14 @@
NSString *file = [NSURL URLWithString:url].path;
files.push_back(String::utf8([file UTF8String]));
}
- wd.drop_files_callback.call(files);
+ Variant v_files = files;
+ const Variant *v_args[1] = { &v_files };
+ Variant ret;
+ Callable::CallError ce;
+ wd.drop_files_callback.callp((const Variant **)&v_args, 1, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT(vformat("Failed to execute drop files callback: %s.", Variant::get_callable_error_text(wd.drop_files_callback, v_args, 1, ce)));
+ }
}
return NO;
@@ -363,16 +370,6 @@
}
DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
- BitField<MouseButtonMask> last_button_state = ds->mouse_get_button_state();
-
- MouseButtonMask mask = mouse_button_to_mask(index);
-
- if (pressed) {
- last_button_state.set_flag(mask);
- } else {
- last_button_state.clear_flag(mask);
- }
- ds->mouse_set_button_state(last_button_state);
Ref<InputEventMouseButton> mb;
mb.instantiate();
@@ -387,7 +384,7 @@
mb->set_pressed(pressed);
mb->set_position(wd.mouse_pos);
mb->set_global_position(wd.mouse_pos);
- mb->set_button_mask(last_button_state);
+ mb->set_button_mask(ds->mouse_get_button_state());
if (!outofstream && index == MouseButton::LEFT && pressed) {
mb->set_double_click([event clickCount] == 2);
}
@@ -738,7 +735,6 @@
DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
MouseButtonMask mask = mouse_button_to_mask(button);
- BitField<MouseButtonMask> last_button_state = ds->mouse_get_button_state();
Ref<InputEventMouseButton> sc;
sc.instantiate();
@@ -750,9 +746,9 @@
sc->set_pressed(true);
sc->set_position(wd.mouse_pos);
sc->set_global_position(wd.mouse_pos);
- last_button_state.set_flag(mask);
- sc->set_button_mask(last_button_state);
- ds->mouse_set_button_state(last_button_state);
+ BitField<MouseButtonMask> scroll_mask = ds->mouse_get_button_state();
+ scroll_mask.set_flag(mask);
+ sc->set_button_mask(scroll_mask);
Input::get_singleton()->parse_input_event(sc);
@@ -763,9 +759,8 @@
sc->set_pressed(false);
sc->set_position(wd.mouse_pos);
sc->set_global_position(wd.mouse_pos);
- last_button_state.clear_flag(mask);
- sc->set_button_mask(last_button_state);
- ds->mouse_set_button_state(last_button_state);
+ scroll_mask.clear_flag(mask);
+ sc->set_button_mask(scroll_mask);
Input::get_singleton()->parse_input_event(sc);
}
diff --git a/platform/macos/godot_status_item.mm b/platform/macos/godot_status_item.mm
index 0990a16b2b..1b16d496a2 100644
--- a/platform/macos/godot_status_item.mm
+++ b/platform/macos/godot_status_item.mm
@@ -66,10 +66,13 @@
if (cb.is_valid()) {
Variant v_button = index;
Variant v_pos = ds->mouse_get_position();
- Variant *v_args[2] = { &v_button, &v_pos };
+ const Variant *v_args[2] = { &v_button, &v_pos };
Variant ret;
Callable::CallError ce;
cb.callp((const Variant **)&v_args, 2, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT(vformat("Failed to execute status indicator callback: %s.", Variant::get_callable_error_text(cb, v_args, 2, ce)));
+ }
}
}
diff --git a/platform/web/detect.py b/platform/web/detect.py
index 3df8cbad7c..c6568625c1 100644
--- a/platform/web/detect.py
+++ b/platform/web/detect.py
@@ -181,7 +181,7 @@ def configure(env: "SConsEnvironment"):
# Use TempFileMunge since some AR invocations are too long for cmd.exe.
# Use POSIX-style paths, required with TempFileMunge.
env["ARCOM_POSIX"] = env["ARCOM"].replace("$TARGET", "$TARGET.posix").replace("$SOURCES", "$SOURCES.posix")
- env["ARCOM"] = "${TEMPFILE(ARCOM_POSIX)}"
+ env["ARCOM"] = "${TEMPFILE('$ARCOM_POSIX','$ARCOMSTR')}"
# All intermediate files are just object files.
env["OBJPREFIX"] = ""
diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp
index 0420a01533..fab92b1894 100644
--- a/platform/web/display_server_web.cpp
+++ b/platform/web/display_server_web.cpp
@@ -70,7 +70,7 @@ bool DisplayServerWeb::check_size_force_redraw() {
void DisplayServerWeb::fullscreen_change_callback(int p_fullscreen) {
#ifdef PROXY_TO_PTHREAD_ENABLED
if (!Thread::is_main_thread()) {
- callable_mp_static(DisplayServerWeb::_fullscreen_change_callback).bind(p_fullscreen).call_deferred();
+ callable_mp_static(DisplayServerWeb::_fullscreen_change_callback).call_deferred(p_fullscreen);
return;
}
#endif
@@ -96,7 +96,7 @@ void DisplayServerWeb::drop_files_js_callback(const char **p_filev, int p_filec)
#ifdef PROXY_TO_PTHREAD_ENABLED
if (!Thread::is_main_thread()) {
- callable_mp_static(DisplayServerWeb::_drop_files_js_callback).bind(files).call_deferred();
+ callable_mp_static(DisplayServerWeb::_drop_files_js_callback).call_deferred(files);
return;
}
#endif
@@ -112,7 +112,14 @@ void DisplayServerWeb::_drop_files_js_callback(const Vector<String> &p_files) {
if (!ds->drop_files_callback.is_valid()) {
return;
}
- ds->drop_files_callback.call(p_files);
+ Variant v_files = p_files;
+ const Variant *v_args[1] = { &v_files };
+ Variant ret;
+ Callable::CallError ce;
+ ds->drop_files_callback.callp((const Variant **)&v_args, 1, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT(vformat("Failed to execute drop files callback: %s.", Variant::get_callable_error_text(ds->drop_files_callback, v_args, 1, ce)));
+ }
}
// Web quit request callback.
@@ -161,7 +168,7 @@ void DisplayServerWeb::key_callback(int p_pressed, int p_repeat, int p_modifiers
#ifdef PROXY_TO_PTHREAD_ENABLED
if (!Thread::is_main_thread()) {
- callable_mp_static(DisplayServerWeb::_key_callback).bind(code, key, p_pressed, p_repeat, p_modifiers).call_deferred();
+ callable_mp_static(DisplayServerWeb::_key_callback).call_deferred(code, key, p_pressed, p_repeat, p_modifiers);
return;
}
#endif
@@ -214,7 +221,7 @@ void DisplayServerWeb::_key_callback(const String &p_key_event_code, const Strin
int DisplayServerWeb::mouse_button_callback(int p_pressed, int p_button, double p_x, double p_y, int p_modifiers) {
#ifdef PROXY_TO_PTHREAD_ENABLED
if (!Thread::is_main_thread()) {
- callable_mp_static(DisplayServerWeb::_mouse_button_callback).bind(p_pressed, p_button, p_x, p_y, p_modifiers).call_deferred();
+ callable_mp_static(DisplayServerWeb::_mouse_button_callback).call_deferred(p_pressed, p_button, p_x, p_y, p_modifiers);
return true;
}
#endif
@@ -301,7 +308,7 @@ int DisplayServerWeb::_mouse_button_callback(int p_pressed, int p_button, double
void DisplayServerWeb::mouse_move_callback(double p_x, double p_y, double p_rel_x, double p_rel_y, int p_modifiers) {
#ifdef PROXY_TO_PTHREAD_ENABLED
if (!Thread::is_main_thread()) {
- callable_mp_static(DisplayServerWeb::_mouse_move_callback).bind(p_x, p_y, p_rel_x, p_rel_y, p_modifiers).call_deferred();
+ callable_mp_static(DisplayServerWeb::_mouse_move_callback).call_deferred(p_x, p_y, p_rel_x, p_rel_y, p_modifiers);
return;
}
#endif
@@ -394,7 +401,7 @@ void DisplayServerWeb::update_voices_callback(int p_size, const char **p_voice)
#ifdef PROXY_TO_PTHREAD_ENABLED
if (!Thread::is_main_thread()) {
- callable_mp_static(DisplayServerWeb::_update_voices_callback).bind(voices).call_deferred();
+ callable_mp_static(DisplayServerWeb::_update_voices_callback).call_deferred(voices);
return;
}
#endif
@@ -461,7 +468,7 @@ void DisplayServerWeb::tts_stop() {
void DisplayServerWeb::js_utterance_callback(int p_event, int p_id, int p_pos) {
#ifdef PROXY_TO_PTHREAD_ENABLED
if (!Thread::is_main_thread()) {
- callable_mp_static(DisplayServerWeb::_js_utterance_callback).bind(p_event, p_id, p_pos).call_deferred();
+ callable_mp_static(DisplayServerWeb::_js_utterance_callback).call_deferred(p_event, p_id, p_pos);
return;
}
#endif
@@ -591,7 +598,7 @@ Point2i DisplayServerWeb::mouse_get_position() const {
int DisplayServerWeb::mouse_wheel_callback(double p_delta_x, double p_delta_y) {
#ifdef PROXY_TO_PTHREAD_ENABLED
if (!Thread::is_main_thread()) {
- callable_mp_static(DisplayServerWeb::_mouse_wheel_callback).bind(p_delta_x, p_delta_y).call_deferred();
+ callable_mp_static(DisplayServerWeb::_mouse_wheel_callback).call_deferred(p_delta_x, p_delta_y);
return true;
}
#endif
@@ -654,7 +661,7 @@ int DisplayServerWeb::_mouse_wheel_callback(double p_delta_x, double p_delta_y)
void DisplayServerWeb::touch_callback(int p_type, int p_count) {
#ifdef PROXY_TO_PTHREAD_ENABLED
if (!Thread::is_main_thread()) {
- callable_mp_static(DisplayServerWeb::_touch_callback).bind(p_type, p_count).call_deferred();
+ callable_mp_static(DisplayServerWeb::_touch_callback).call_deferred(p_type, p_count);
return;
}
#endif
@@ -712,7 +719,7 @@ void DisplayServerWeb::vk_input_text_callback(const char *p_text, int p_cursor)
#ifdef PROXY_TO_PTHREAD_ENABLED
if (!Thread::is_main_thread()) {
- callable_mp_static(DisplayServerWeb::_vk_input_text_callback).bind(text, p_cursor).call_deferred();
+ callable_mp_static(DisplayServerWeb::_vk_input_text_callback).call_deferred(text, p_cursor);
return;
}
#endif
@@ -774,7 +781,7 @@ void DisplayServerWeb::gamepad_callback(int p_index, int p_connected, const char
#ifdef PROXY_TO_PTHREAD_ENABLED
if (!Thread::is_main_thread()) {
- callable_mp_static(DisplayServerWeb::_gamepad_callback).bind(p_index, p_connected, id, guid).call_deferred();
+ callable_mp_static(DisplayServerWeb::_gamepad_callback).call_deferred(p_index, p_connected, id, guid);
return;
}
#endif
@@ -797,7 +804,7 @@ void DisplayServerWeb::ime_callback(int p_type, const char *p_text) {
#ifdef PROXY_TO_PTHREAD_ENABLED
if (!Thread::is_main_thread()) {
- callable_mp_static(DisplayServerWeb::_ime_callback).bind(p_type, text).call_deferred();
+ callable_mp_static(DisplayServerWeb::_ime_callback).call_deferred(p_type, text);
return;
}
#endif
@@ -866,6 +873,9 @@ void DisplayServerWeb::_ime_callback(int p_type, const String &p_text) {
default:
break;
}
+
+ ds->process_keys();
+ Input::get_singleton()->flush_buffered_events();
}
void DisplayServerWeb::window_set_ime_active(const bool p_active, WindowID p_window) {
@@ -927,7 +937,7 @@ void DisplayServerWeb::update_clipboard_callback(const char *p_text) {
#ifdef PROXY_TO_PTHREAD_ENABLED
if (!Thread::is_main_thread()) {
- callable_mp_static(DisplayServerWeb::_update_clipboard_callback).bind(text).call_deferred();
+ callable_mp_static(DisplayServerWeb::_update_clipboard_callback).call_deferred(text);
return;
}
#endif
@@ -953,7 +963,7 @@ String DisplayServerWeb::clipboard_get() const {
void DisplayServerWeb::send_window_event_callback(int p_notification) {
#ifdef PROXY_TO_PTHREAD_ENABLED
if (!Thread::is_main_thread()) {
- callable_mp_static(DisplayServerWeb::_send_window_event_callback).bind(p_notification).call_deferred();
+ callable_mp_static(DisplayServerWeb::_send_window_event_callback).call_deferred(p_notification);
return;
}
#endif
@@ -1353,29 +1363,33 @@ DisplayServer::VSyncMode DisplayServerWeb::window_get_vsync_mode(WindowID p_vsyn
}
void DisplayServerWeb::process_events() {
+ process_keys();
Input::get_singleton()->flush_buffered_events();
if (godot_js_input_gamepad_sample() == OK) {
process_joypads();
- for (int i = 0; i < key_event_pos; i++) {
- const DisplayServerWeb::KeyEvent &ke = key_event_buffer[i];
+ }
+}
- Ref<InputEventKey> ev;
- ev.instantiate();
- ev->set_pressed(ke.pressed);
- ev->set_echo(ke.echo);
- ev->set_keycode(ke.keycode);
- ev->set_physical_keycode(ke.physical_keycode);
- ev->set_key_label(ke.key_label);
- ev->set_unicode(ke.unicode);
- ev->set_location(ke.location);
- if (ke.raw) {
- dom2godot_mod(ev, ke.mod, ke.keycode);
- }
+void DisplayServerWeb::process_keys() {
+ for (int i = 0; i < key_event_pos; i++) {
+ const DisplayServerWeb::KeyEvent &ke = key_event_buffer[i];
- Input::get_singleton()->parse_input_event(ev);
+ Ref<InputEventKey> ev;
+ ev.instantiate();
+ ev->set_pressed(ke.pressed);
+ ev->set_echo(ke.echo);
+ ev->set_keycode(ke.keycode);
+ ev->set_physical_keycode(ke.physical_keycode);
+ ev->set_key_label(ke.key_label);
+ ev->set_unicode(ke.unicode);
+ ev->set_location(ke.location);
+ if (ke.raw) {
+ dom2godot_mod(ev, ke.mod, ke.keycode);
}
- key_event_pos = 0;
+
+ Input::get_singleton()->parse_input_event(ev);
}
+ key_event_pos = 0;
}
int DisplayServerWeb::get_current_video_driver() const {
diff --git a/platform/web/display_server_web.h b/platform/web/display_server_web.h
index 276ca5210c..352b3fe523 100644
--- a/platform/web/display_server_web.h
+++ b/platform/web/display_server_web.h
@@ -145,6 +145,7 @@ private:
static void _drop_files_js_callback(const Vector<String> &p_files);
void process_joypads();
+ void process_keys();
static Vector<String> get_rendering_drivers_func();
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_window_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error);
diff --git a/platform/web/emscripten_helpers.py b/platform/web/emscripten_helpers.py
index 745b2457fa..2cee3e8110 100644
--- a/platform/web/emscripten_helpers.py
+++ b/platform/web/emscripten_helpers.py
@@ -123,7 +123,6 @@ def create_template_zip(env, js, wasm, worker, side):
zip_files,
ZIPROOT=zip_dir,
ZIPSUFFIX="${PROGSUFFIX}${ZIPSUFFIX}",
- ZIPCOMSTR="Archiving $SOURCES as $TARGET",
)
diff --git a/platform/web/javascript_bridge_singleton.cpp b/platform/web/javascript_bridge_singleton.cpp
index a2c83d2f2b..c4dbb405a3 100644
--- a/platform/web/javascript_bridge_singleton.cpp
+++ b/platform/web/javascript_bridge_singleton.cpp
@@ -262,7 +262,7 @@ void JavaScriptObjectImpl::callback(void *p_ref, int p_args_id, int p_argc) {
#ifdef PROXY_TO_PTHREAD_ENABLED
if (!Thread::is_main_thread()) {
- callable_mp_static(JavaScriptObjectImpl::_callback).bind(obj, arg).call_deferred();
+ callable_mp_static(JavaScriptObjectImpl::_callback).call_deferred(obj, arg);
return;
}
#endif
diff --git a/platform/web/js/libs/library_godot_input.js b/platform/web/js/libs/library_godot_input.js
index 1292c468f5..7ea89d553f 100644
--- a/platform/web/js/libs/library_godot_input.js
+++ b/platform/web/js/libs/library_godot_input.js
@@ -63,8 +63,15 @@ const GodotIME = {
ime_position: function (x, y) {
if (GodotIME.ime) {
- GodotIME.ime.style.left = `${x}px`;
- GodotIME.ime.style.top = `${y}px`;
+ const canvas = GodotConfig.canvas;
+ const rect = canvas.getBoundingClientRect();
+ const rw = canvas.width / rect.width;
+ const rh = canvas.height / rect.height;
+ const clx = (x / rw) + rect.x;
+ const cly = (y / rh) + rect.y;
+
+ GodotIME.ime.style.left = `${clx}px`;
+ GodotIME.ime.style.top = `${cly}px`;
}
},
@@ -99,10 +106,12 @@ const GodotIME = {
ime.style.background = 'none';
ime.style.opacity = 0.0;
ime.style.position = 'fixed';
+ ime.style.textAlign = 'left';
+ ime.style.fontSize = '1px';
ime.style.left = '0px';
ime.style.top = '0px';
- ime.style.width = '2px';
- ime.style.height = '2px';
+ ime.style.width = '100%';
+ ime.style.height = '40px';
ime.style.display = 'none';
ime.contentEditable = 'true';
diff --git a/platform/windows/SCsub b/platform/windows/SCsub
index 1c2bfb9b75..f2fb8616ae 100644
--- a/platform/windows/SCsub
+++ b/platform/windows/SCsub
@@ -50,6 +50,7 @@ def arrange_program_clean(prog):
res_file = "godot_res.rc"
res_target = "godot_res" + env["OBJSUFFIX"]
res_obj = env.RES(res_target, res_file)
+env.Depends(res_obj, "#core/version_generated.gen.h")
env.add_source_files(sources, common_win)
sources += res_obj
@@ -63,6 +64,7 @@ if env["windows_subsystem"] == "gui":
res_wrap_file = "godot_res_wrap.rc"
res_wrap_target = "godot_res_wrap" + env["OBJSUFFIX"]
res_wrap_obj = env_wrap.RES(res_wrap_target, res_wrap_file)
+ env_wrap.Depends(res_wrap_obj, "#core/version_generated.gen.h")
if env.msvc:
env_wrap.Append(LINKFLAGS=["/SUBSYSTEM:CONSOLE"])
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 03584977fe..c114adff84 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -660,6 +660,24 @@ Point2i DisplayServerWindows::mouse_get_position() const {
}
BitField<MouseButtonMask> DisplayServerWindows::mouse_get_button_state() const {
+ BitField<MouseButtonMask> last_button_state = 0;
+
+ if (GetAsyncKeyState(VK_LBUTTON) & (1 << 15)) {
+ last_button_state.set_flag(MouseButtonMask::LEFT);
+ }
+ if (GetAsyncKeyState(VK_RBUTTON) & (1 << 15)) {
+ last_button_state.set_flag(MouseButtonMask::RIGHT);
+ }
+ if (GetAsyncKeyState(VK_MBUTTON) & (1 << 15)) {
+ last_button_state.set_flag(MouseButtonMask::MIDDLE);
+ }
+ if (GetAsyncKeyState(VK_XBUTTON1) & (1 << 15)) {
+ last_button_state.set_flag(MouseButtonMask::MB_XBUTTON1);
+ }
+ if (GetAsyncKeyState(VK_XBUTTON2) & (1 << 15)) {
+ last_button_state.set_flag(MouseButtonMask::MB_XBUTTON2);
+ }
+
return last_button_state;
}
@@ -1832,24 +1850,6 @@ void DisplayServerWindows::window_set_size(const Size2i p_size, WindowID p_windo
int w = p_size.width;
int h = p_size.height;
-
- wd.width = w;
- wd.height = h;
-
-#if defined(RD_ENABLED)
- if (rendering_context) {
- rendering_context->window_set_size(p_window, w, h);
- }
-#endif
-#if defined(GLES3_ENABLED)
- if (gl_manager_native) {
- gl_manager_native->window_resize(p_window, w, h);
- }
- if (gl_manager_angle) {
- gl_manager_angle->window_resize(p_window, w, h);
- }
-#endif
-
RECT rect;
GetWindowRect(wd.hWnd, &rect);
@@ -3613,6 +3613,30 @@ void DisplayServerWindows::popup_close(WindowID p_window) {
}
}
+BitField<DisplayServerWindows::WinKeyModifierMask> DisplayServerWindows::_get_mods() const {
+ BitField<WinKeyModifierMask> mask;
+ static unsigned char keyboard_state[256];
+ if (GetKeyboardState((PBYTE)&keyboard_state)) {
+ if ((keyboard_state[VK_LSHIFT] & 0x80) || (keyboard_state[VK_RSHIFT] & 0x80)) {
+ mask.set_flag(WinKeyModifierMask::SHIFT);
+ }
+ if ((keyboard_state[VK_LCONTROL] & 0x80) || (keyboard_state[VK_RCONTROL] & 0x80)) {
+ mask.set_flag(WinKeyModifierMask::CTRL);
+ }
+ if ((keyboard_state[VK_LMENU] & 0x80) || (keyboard_state[VK_RMENU] & 0x80)) {
+ mask.set_flag(WinKeyModifierMask::ALT);
+ }
+ if ((keyboard_state[VK_RMENU] & 0x80)) {
+ mask.set_flag(WinKeyModifierMask::ALT_GR);
+ }
+ if ((keyboard_state[VK_LWIN] & 0x80) || (keyboard_state[VK_RWIN] & 0x80)) {
+ mask.set_flag(WinKeyModifierMask::META);
+ }
+ }
+
+ return mask;
+}
+
LRESULT DisplayServerWindows::MouseProc(int code, WPARAM wParam, LPARAM lParam) {
_THREAD_SAFE_METHOD_
@@ -3842,7 +3866,12 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
}
if (system_theme_changed.is_valid()) {
- system_theme_changed.call();
+ Variant ret;
+ Callable::CallError ce;
+ system_theme_changed.callp(nullptr, 0, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT(vformat("Failed to execute system theme changed callback: %s.", Variant::get_callable_error_text(system_theme_changed, nullptr, 0, ce)));
+ }
}
} break;
case WM_THEMECHANGED: {
@@ -3863,7 +3892,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
if (((lParam >> 16) <= 0) && !engine->is_project_manager_hint() && !engine->is_editor_hint() && !GLOBAL_GET("application/run/enable_alt_space_menu")) {
return 0;
}
- if (!alt_mem || !(GetAsyncKeyState(VK_SPACE) & (1 << 15))) {
+ if (!_get_mods().has_flag(WinKeyModifierMask::ALT) || !(GetAsyncKeyState(VK_SPACE) & (1 << 15))) {
return 0;
}
SendMessage(windows[window_id].hWnd, WM_SYSKEYUP, VK_SPACE, 0);
@@ -3897,10 +3926,13 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
} else if (indicators[iid].callback.is_valid()) {
Variant v_button = mb;
Variant v_pos = mouse_get_position();
- Variant *v_args[2] = { &v_button, &v_pos };
+ const Variant *v_args[2] = { &v_button, &v_pos };
Variant ret;
Callable::CallError ce;
indicators[iid].callback.callp((const Variant **)&v_args, 2, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT(vformat("Failed to execute status indicator callback: %s.", Variant::get_callable_error_text(indicators[iid].callback, v_args, 2, ce)));
+ }
}
}
return 0;
@@ -3946,20 +3978,22 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
RAWINPUT *raw = (RAWINPUT *)lpb;
+ const BitField<WinKeyModifierMask> &mods = _get_mods();
if (raw->header.dwType == RIM_TYPEKEYBOARD) {
if (raw->data.keyboard.VKey == VK_SHIFT) {
// If multiple Shifts are held down at the same time,
// Windows natively only sends a KEYUP for the last one to be released.
if (raw->data.keyboard.Flags & RI_KEY_BREAK) {
- if (GetAsyncKeyState(VK_SHIFT) < 0) {
+ if (!mods.has_flag(WinKeyModifierMask::SHIFT)) {
// A Shift is released, but another Shift is still held
ERR_BREAK(key_event_pos >= KEY_EVENT_BUFFER_SIZE);
KeyEvent ke;
ke.shift = false;
- ke.alt = alt_mem;
- ke.control = control_mem;
- ke.meta = meta_mem;
+ ke.altgr = mods.has_flag(WinKeyModifierMask::ALT_GR);
+ ke.alt = mods.has_flag(WinKeyModifierMask::ALT);
+ ke.control = mods.has_flag(WinKeyModifierMask::CTRL);
+ ke.meta = mods.has_flag(WinKeyModifierMask::META);
ke.uMsg = WM_KEYUP;
ke.window_id = window_id;
@@ -3976,13 +4010,14 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
mm.instantiate();
mm->set_window_id(window_id);
- mm->set_ctrl_pressed(control_mem);
- mm->set_shift_pressed(shift_mem);
- mm->set_alt_pressed(alt_mem);
+ mm->set_ctrl_pressed(mods.has_flag(WinKeyModifierMask::CTRL));
+ mm->set_shift_pressed(mods.has_flag(WinKeyModifierMask::SHIFT));
+ mm->set_alt_pressed(mods.has_flag(WinKeyModifierMask::ALT));
+ mm->set_meta_pressed(mods.has_flag(WinKeyModifierMask::META));
mm->set_pressure((raw->data.mouse.ulButtons & RI_MOUSE_LEFT_BUTTON_DOWN) ? 1.0f : 0.0f);
- mm->set_button_mask(last_button_state);
+ mm->set_button_mask(mouse_get_button_state());
Point2i c(windows[window_id].width / 2, windows[window_id].height / 2);
@@ -4073,18 +4108,20 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
break;
}
+ const BitField<WinKeyModifierMask> &mods = _get_mods();
Ref<InputEventMouseMotion> mm;
mm.instantiate();
mm->set_window_id(window_id);
- mm->set_ctrl_pressed(GetKeyState(VK_CONTROL) < 0);
- mm->set_shift_pressed(GetKeyState(VK_SHIFT) < 0);
- mm->set_alt_pressed(alt_mem);
+ mm->set_ctrl_pressed(mods.has_flag(WinKeyModifierMask::CTRL));
+ mm->set_shift_pressed(mods.has_flag(WinKeyModifierMask::SHIFT));
+ mm->set_alt_pressed(mods.has_flag(WinKeyModifierMask::ALT));
+ mm->set_meta_pressed(mods.has_flag(WinKeyModifierMask::META));
mm->set_pressure(windows[window_id].last_pressure);
mm->set_tilt(windows[window_id].last_tilt);
mm->set_pen_inverted(windows[window_id].last_pen_inverted);
- mm->set_button_mask(last_button_state);
+ mm->set_button_mask(mouse_get_button_state());
mm->set_position(Vector2(coords.x, coords.y));
mm->set_global_position(Vector2(coords.x, coords.y));
@@ -4223,11 +4260,13 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
mm->set_pen_inverted(pen_info.penFlags & (PEN_FLAG_INVERTED | PEN_FLAG_ERASER));
- mm->set_ctrl_pressed(GetKeyState(VK_CONTROL) < 0);
- mm->set_shift_pressed(GetKeyState(VK_SHIFT) < 0);
- mm->set_alt_pressed(alt_mem);
+ const BitField<WinKeyModifierMask> &mods = _get_mods();
+ mm->set_ctrl_pressed(mods.has_flag(WinKeyModifierMask::CTRL));
+ mm->set_shift_pressed(mods.has_flag(WinKeyModifierMask::SHIFT));
+ mm->set_alt_pressed(mods.has_flag(WinKeyModifierMask::ALT));
+ mm->set_meta_pressed(mods.has_flag(WinKeyModifierMask::META));
- mm->set_button_mask(last_button_state);
+ mm->set_button_mask(mouse_get_button_state());
POINT coords; // Client coords.
coords.x = GET_X_LPARAM(lParam);
@@ -4328,12 +4367,15 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
if (receiving_window_id == INVALID_WINDOW_ID) {
receiving_window_id = window_id;
}
+
+ const BitField<WinKeyModifierMask> &mods = _get_mods();
Ref<InputEventMouseMotion> mm;
mm.instantiate();
mm->set_window_id(receiving_window_id);
- mm->set_ctrl_pressed((wParam & MK_CONTROL) != 0);
- mm->set_shift_pressed((wParam & MK_SHIFT) != 0);
- mm->set_alt_pressed(alt_mem);
+ mm->set_ctrl_pressed(mods.has_flag(WinKeyModifierMask::CTRL));
+ mm->set_shift_pressed(mods.has_flag(WinKeyModifierMask::SHIFT));
+ mm->set_alt_pressed(mods.has_flag(WinKeyModifierMask::ALT));
+ mm->set_meta_pressed(mods.has_flag(WinKeyModifierMask::META));
if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[window_id].wtctx) {
// Note: WinTab sends both WT_PACKET and WM_xBUTTONDOWN/UP/MOUSEMOVE events, use mouse 1/0 pressure only when last_pressure was not updated recently.
@@ -4354,7 +4396,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
mm->set_tilt(windows[window_id].last_tilt);
mm->set_pen_inverted(windows[window_id].last_pen_inverted);
- mm->set_button_mask(last_button_state);
+ mm->set_button_mask(mouse_get_button_state());
mm->set_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
mm->set_global_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
@@ -4522,16 +4564,20 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
}
- mb->set_ctrl_pressed((wParam & MK_CONTROL) != 0);
- mb->set_shift_pressed((wParam & MK_SHIFT) != 0);
- mb->set_alt_pressed(alt_mem);
- // mb->is_alt_pressed()=(wParam&MK_MENU)!=0;
- if (mb->is_pressed()) {
- last_button_state.set_flag(mouse_button_to_mask(mb->get_button_index()));
+ const BitField<WinKeyModifierMask> &mods = _get_mods();
+ mb->set_ctrl_pressed(mods.has_flag(WinKeyModifierMask::CTRL));
+ mb->set_shift_pressed(mods.has_flag(WinKeyModifierMask::SHIFT));
+ mb->set_alt_pressed(mods.has_flag(WinKeyModifierMask::ALT));
+ mb->set_meta_pressed(mods.has_flag(WinKeyModifierMask::META));
+
+ if (mb->is_pressed() && mb->get_button_index() >= MouseButton::WHEEL_UP && mb->get_button_index() <= MouseButton::WHEEL_RIGHT) {
+ MouseButtonMask mask = mouse_button_to_mask(mb->get_button_index());
+ BitField<MouseButtonMask> scroll_mask = mouse_get_button_state();
+ scroll_mask.set_flag(mask);
+ mb->set_button_mask(scroll_mask);
} else {
- last_button_state.clear_flag(mouse_button_to_mask(mb->get_button_index()));
+ mb->set_button_mask(mouse_get_button_state());
}
- mb->set_button_mask(last_button_state);
mb->set_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
@@ -4545,7 +4591,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
SetCapture(hWnd);
}
} else {
- if (--pressrc <= 0 || last_button_state.is_empty()) {
+ if (--pressrc <= 0 || mouse_get_button_state().is_empty()) {
if (mouse_mode != MOUSE_MODE_CAPTURED) {
ReleaseCapture();
}
@@ -4570,8 +4616,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
// Send release for mouse wheel.
Ref<InputEventMouseButton> mbd = mb->duplicate();
mbd->set_window_id(window_id);
- last_button_state.clear_flag(mouse_button_to_mask(mbd->get_button_index()));
- mbd->set_button_mask(last_button_state);
+ mbd->set_button_mask(mouse_get_button_state());
mbd->set_pressed(false);
Input::get_singleton()->parse_input_event(mbd);
}
@@ -4641,6 +4686,14 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
rendering_context->window_set_size(window_id, window.width, window.height);
}
#endif
+#if defined(GLES3_ENABLED)
+ if (gl_manager_native) {
+ gl_manager_native->window_resize(window_id, window.width, window.height);
+ }
+ if (gl_manager_angle) {
+ gl_manager_angle->window_resize(window_id, window.width, window.height);
+ }
+#endif
}
if (!window.minimized && (!(window_pos_params->flags & SWP_NOMOVE) || window_pos_params->flags & SWP_FRAMECHANGED)) {
@@ -4693,19 +4746,6 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
case WM_KEYUP:
case WM_SYSKEYDOWN:
case WM_KEYDOWN: {
- if (wParam == VK_SHIFT) {
- shift_mem = (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN);
- }
- if (wParam == VK_CONTROL) {
- control_mem = (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN);
- }
- if (wParam == VK_MENU) {
- alt_mem = (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN);
- if (lParam & (1 << 24)) {
- gr_mem = alt_mem;
- }
- }
-
if (windows[window_id].ime_suppress_next_keyup && (uMsg == WM_KEYUP || uMsg == WM_SYSKEYUP)) {
windows[window_id].ime_suppress_next_keyup = false;
break;
@@ -4716,7 +4756,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
if (mouse_mode == MOUSE_MODE_CAPTURED) {
// When SetCapture is used, ALT+F4 hotkey is ignored by Windows, so handle it ourselves
- if (wParam == VK_F4 && alt_mem && (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN)) {
+ if (wParam == VK_F4 && _get_mods().has_flag(WinKeyModifierMask::ALT) && (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN)) {
_send_window_event(windows[window_id], WINDOW_EVENT_CLOSE_REQUEST);
}
}
@@ -4724,13 +4764,14 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
case WM_CHAR: {
ERR_BREAK(key_event_pos >= KEY_EVENT_BUFFER_SIZE);
+ const BitField<WinKeyModifierMask> &mods = _get_mods();
- // Make sure we don't include modifiers for the modifier key itself.
KeyEvent ke;
- ke.shift = (wParam != VK_SHIFT) ? shift_mem : false;
- ke.alt = (!(wParam == VK_MENU && (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN))) ? alt_mem : false;
- ke.control = (wParam != VK_CONTROL) ? control_mem : false;
- ke.meta = meta_mem;
+ ke.shift = mods.has_flag(WinKeyModifierMask::SHIFT);
+ ke.alt = mods.has_flag(WinKeyModifierMask::ALT);
+ ke.altgr = mods.has_flag(WinKeyModifierMask::ALT_GR);
+ ke.control = mods.has_flag(WinKeyModifierMask::CTRL);
+ ke.meta = mods.has_flag(WinKeyModifierMask::META);
ke.uMsg = uMsg;
ke.window_id = window_id;
@@ -4868,7 +4909,14 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
if (files.size() && windows[window_id].drop_files_callback.is_valid()) {
- windows[window_id].drop_files_callback.call(files);
+ Variant v_files = files;
+ const Variant *v_args[1] = { &v_files };
+ Variant ret;
+ Callable::CallError ce;
+ windows[window_id].drop_files_callback.callp((const Variant **)&v_args, 1, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT(vformat("Failed to execute drop files callback: %s.", Variant::get_callable_error_text(windows[window_id].drop_files_callback, v_args, 1, ce)));
+ }
}
} break;
default: {
@@ -4894,10 +4942,6 @@ void DisplayServerWindows::_process_activate_event(WindowID p_window_id) {
WindowData &wd = windows[p_window_id];
if (wd.activate_state == WA_ACTIVE || wd.activate_state == WA_CLICKACTIVE) {
last_focused_window = p_window_id;
- alt_mem = false;
- control_mem = false;
- shift_mem = false;
- gr_mem = false;
_set_mouse_mode_impl(mouse_mode);
if (!IsIconic(wd.hWnd)) {
SetFocus(wd.hWnd);
@@ -4909,7 +4953,6 @@ void DisplayServerWindows::_process_activate_event(WindowID p_window_id) {
track_mouse_leave_event(wd.hWnd);
// Release capture unconditionally because it can be set due to dragging, in addition to captured mode.
ReleaseCapture();
- alt_mem = false;
wd.window_focused = false;
_send_window_event(wd, WINDOW_EVENT_FOCUS_OUT);
}
@@ -4980,7 +5023,7 @@ void DisplayServerWindows::_process_key_events() {
k->set_physical_keycode(physical_keycode);
k->set_key_label(key_label);
k->set_unicode(fix_unicode(unicode));
- if (k->get_unicode() && gr_mem) {
+ if (k->get_unicode() && ke.altgr) {
k->set_alt_pressed(false);
k->set_ctrl_pressed(false);
}
@@ -5056,7 +5099,7 @@ void DisplayServerWindows::_process_key_events() {
}
k->set_unicode(fix_unicode(unicode));
}
- if (k->get_unicode() && gr_mem) {
+ if (k->get_unicode() && ke.altgr) {
k->set_alt_pressed(false);
k->set_ctrl_pressed(false);
}
@@ -5522,11 +5565,6 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
drop_events = false;
key_event_pos = 0;
- alt_mem = false;
- gr_mem = false;
- shift_mem = false;
- control_mem = false;
- meta_mem = false;
hInstance = static_cast<OS_Windows *>(OS::get_singleton())->get_hinstance();
pressrc = 0;
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index 9a4eeba486..0f649b76d7 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -337,7 +337,7 @@ class DisplayServerWindows : public DisplayServer {
struct KeyEvent {
WindowID window_id;
- bool alt, shift, control, meta;
+ bool alt, shift, control, meta, altgr;
UINT uMsg;
WPARAM wParam;
LPARAM lParam;
@@ -478,12 +478,7 @@ class DisplayServerWindows : public DisplayServer {
MouseMode mouse_mode;
int restore_mouse_trails = 0;
- bool alt_mem = false;
- bool gr_mem = false;
- bool shift_mem = false;
- bool control_mem = false;
- bool meta_mem = false;
- BitField<MouseButtonMask> last_button_state;
+
bool use_raw_input = false;
bool drop_events = false;
bool in_dispatch_input_event = false;
@@ -519,6 +514,15 @@ class DisplayServerWindows : public DisplayServer {
LRESULT _handle_early_window_message(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
Point2i _get_screens_origin() const;
+ enum class WinKeyModifierMask {
+ ALT_GR = (1 << 1),
+ SHIFT = (1 << 2),
+ ALT = (1 << 3),
+ META = (1 << 4),
+ CTRL = (1 << 5),
+ };
+ BitField<WinKeyModifierMask> _get_mods() const;
+
Error _file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, bool p_options_in_cb);
public:
diff --git a/platform/windows/windows_utils.cpp b/platform/windows/windows_utils.cpp
index 147b8bcbae..9b53252b07 100644
--- a/platform/windows/windows_utils.cpp
+++ b/platform/windows/windows_utils.cpp
@@ -92,7 +92,7 @@ Error WindowsUtils::copy_and_rename_pdb(const String &p_dll_path) {
DWORD Offset;
};
- const DWORD nb10_magic = '01BN';
+ const DWORD nb10_magic = 0x3031424e; // "01BN" (little-endian)
struct CV_INFO_PDB20 {
CV_HEADER CvHeader; // CvHeader.Signature = "NB10"
DWORD Signature;
@@ -100,7 +100,7 @@ Error WindowsUtils::copy_and_rename_pdb(const String &p_dll_path) {
BYTE PdbFileName[1];
};
- const DWORD rsds_magic = 'SDSR';
+ const DWORD rsds_magic = 0x53445352; // "SDSR" (little-endian)
struct CV_INFO_PDB70 {
DWORD Signature; // "RSDS"
BYTE Guid[16];