diff options
Diffstat (limited to 'platform')
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]; |
