AccessKit integration for macOS, Linux, and Windows.

This commit is contained in:
Pāvels Nadtočajevs 2025-03-21 09:54:55 +02:00
parent b106dfd4f9
commit 4310cb82b8
No known key found for this signature in database
GPG Key ID: 8413210218EF35D2
45 changed files with 23274 additions and 28 deletions

View File

@ -5,7 +5,7 @@ on:
# Global Settings
env:
GODOT_CPP_BRANCH: 4.4
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes strict_checks=yes
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes strict_checks=yes "accesskit_sdk_path=${{ github.workspace }}/accesskit-c-0.15.1/"
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
TSAN_OPTIONS: suppressions=${{ github.workspace }}/misc/error_suppressions/tsan.txt
@ -151,6 +151,17 @@ jobs:
# Targeting the oldest version we want to support to ensure it still builds.
dotnet-version: 8.0.100
- name: Download pre-built AccessKit
uses: dsaltares/fetch-gh-release-asset@1.1.2
with:
repo: AccessKit/accesskit-c
version: tags/0.15.1
file: accesskit-c-0.15.1.zip
target: accesskit-c-0.15.1/accesskit_c.zip
- name: Extract pre-built AccessKit
run: unzip -o accesskit-c-0.15.1/accesskit_c.zip
- name: Compilation
uses: ./.github/actions/godot-build
with:

View File

@ -4,7 +4,7 @@ on:
# Global Settings
env:
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes strict_checks=yes
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes strict_checks=yes "accesskit_sdk_path=${{ github.workspace }}/accesskit-c-0.15.1/"
jobs:
build-macos:
@ -43,6 +43,17 @@ jobs:
- name: Setup Python and SCons
uses: ./.github/actions/godot-deps
- name: Download pre-built AccessKit
uses: dsaltares/fetch-gh-release-asset@1.1.2
with:
repo: AccessKit/accesskit-c
version: tags/0.15.1
file: accesskit-c-0.15.1.zip
target: accesskit-c-0.15.1/accesskit_c.zip
- name: Extract pre-built AccessKit
run: unzip -o accesskit-c-0.15.1/accesskit_c.zip
- name: Setup Vulkan SDK
id: vulkan-sdk
run: |

View File

@ -5,7 +5,7 @@ on:
# Global Settings
# SCONS_CACHE for windows must be set in the build environment
env:
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes d3d12=yes strict_checks=yes "angle_libs=${{ github.workspace }}/"
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes d3d12=yes strict_checks=yes "angle_libs=${{ github.workspace }}/" "accesskit_sdk_path=${{ github.workspace }}/accesskit-c-0.15.1/"
SCONS_CACHE_MSVC_CONFIG: true
jobs:
@ -81,6 +81,17 @@ jobs:
- name: Extract pre-built ANGLE static libraries
run: Expand-Archive -Force angle/angle.zip ${{ github.workspace }}/
- name: Download pre-built AccessKit
uses: dsaltares/fetch-gh-release-asset@1.1.2
with:
repo: AccessKit/accesskit-c
version: tags/0.15.1
file: accesskit-c-0.15.1.zip
target: accesskit-c-0.15.1/accesskit_c.zip
- name: Extract pre-built AccessKit
run: unzip -o accesskit-c-0.15.1/accesskit_c.zip
- name: Compilation
uses: ./.github/actions/godot-build
with:

View File

@ -4,9 +4,7 @@ default_language_version:
exclude: |
(?x)^(
.*thirdparty/.*|
.*-so_wrap\.(h|c)|
.*-dll_wrap\.(h|c)|
.*-dylib_wrap\.(h|c)|
.*-(dll|dylib|so)_wrap\.[ch]|
platform/android/java/editor/src/main/java/com/android/.*|
platform/android/java/lib/src/com/google/.*
)$

View File

@ -163,6 +163,11 @@ Comment: Temporal Anti-Aliasing resolve implementation
Copyright: 2016, Panos Karabelas
License: Expat
Files: thirdparty/accesskit/*
Comment: AccessKit
Copyright: 2023, The AccessKit Authors.
License: Expat
Files: thirdparty/amd-fsr/*
Comment: AMD FidelityFX Super Resolution
Copyright: 2021, Advanced Micro Devices, Inc.

View File

@ -191,6 +191,8 @@ opts.Add(BoolVariable("use_volk", "Use the volk library to load the Vulkan loade
opts.Add(BoolVariable("disable_exceptions", "Force disabling exception handling code", True))
opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "")
opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
opts.Add(BoolVariable("accesskit", "Use AccessKit C SDK", True))
opts.Add(("accesskit_sdk_path", "Path to the AccessKit C SDK", ""))
# Advanced options
opts.Add(

View File

@ -26,9 +26,15 @@ if env["xaudio2"]:
print_error("Target platform '{}' does not support the XAudio2 audio driver".format(env["platform"]))
Exit(255)
SConscript("xaudio2/SCsub")
# Shared Apple platform drivers
if env["platform"] in ["macos", "ios"]:
SConscript("apple/SCsub")
# Accessibility
if env["accesskit"] and env["platform"] in ["macos", "windows", "linuxbsd"]:
SConscript("accesskit/SCsub")
# Midi drivers
SConscript("alsamidi/SCsub")
if env["platform"] in ["macos", "ios"]:

16
drivers/accesskit/SCsub Normal file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")
# Driver source files
env.add_source_files(env.drivers_sources, "accessibility_driver_accesskit.cpp")
if env["accesskit_sdk_path"] == "":
if env["platform"] == "windows":
env.add_source_files(env.drivers_sources, "dynwrappers/accesskit-dll_wrap.c")
if env["platform"] == "macos":
env.add_source_files(env.drivers_sources, "dynwrappers/accesskit-dylib_wrap.c")
if env["platform"] == "linuxbsd":
env.add_source_files(env.drivers_sources, "dynwrappers/accesskit-so_wrap.c")
env.Prepend(CPPPATH=["#thirdparty/accesskit/include"])

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,197 @@
/**************************************************************************/
/* accessibility_driver_accesskit.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifdef ACCESSKIT_ENABLED
#include "core/templates/rid_owner.h"
#include "servers/display_server.h"
#ifdef ACCESSKIT_DYNAMIC
#ifdef LINUXBSD_ENABLED
#include "drivers/accesskit/dynwrappers/accesskit-so_wrap.h"
#endif
#ifdef MACOS_ENABLED
#include "drivers/accesskit/dynwrappers/accesskit-dylib_wrap.h"
#endif
#ifdef WINDOWS_ENABLED
#include "drivers/accesskit/dynwrappers/accesskit-dll_wrap.h"
#endif
#else
#include <accesskit.h>
#endif
class AccessibilityDriverAccessKit : public AccessibilityDriver {
static AccessibilityDriverAccessKit *singleton;
struct AccessibilityElement {
HashMap<accesskit_action, Callable> actions;
DisplayServer::WindowID window_id = DisplayServer::INVALID_WINDOW_ID;
RID parent;
LocalVector<RID> children;
Vector3i run;
Variant meta;
String name;
String name_extra_info;
accesskit_role role = ACCESSKIT_ROLE_UNKNOWN;
accesskit_node *node = nullptr;
};
mutable RID_PtrOwner<AccessibilityElement> rid_owner;
struct WindowData {
// Adapter.
#ifdef WINDOWS_ENABLED
accesskit_windows_subclassing_adapter *adapter = nullptr;
#endif
#ifdef MACOS_ENABLED
accesskit_macos_subclassing_adapter *adapter = nullptr;
#endif
#ifdef LINUXBSD_ENABLED
accesskit_unix_adapter *adapter = nullptr;
#endif
RID root_id;
HashSet<RID> update;
};
RID focus;
HashMap<DisplayServer::WindowID, WindowData> windows;
HashMap<DisplayServer::AccessibilityRole, accesskit_role> role_map;
HashMap<DisplayServer::AccessibilityAction, accesskit_action> action_map;
_FORCE_INLINE_ accesskit_role _accessibility_role(DisplayServer::AccessibilityRole p_role) const;
_FORCE_INLINE_ accesskit_action _accessibility_action(DisplayServer::AccessibilityAction p_action) const;
void _free_recursive(WindowData *p_wd, const RID &p_id);
_FORCE_INLINE_ void _ensure_node(const RID &p_id, AccessibilityElement *p_ae);
static void _accessibility_action_callback(struct accesskit_action_request *p_request, void *p_user_data);
static accesskit_tree_update *_accessibility_initial_tree_update_callback(void *p_user_data);
static void _accessibility_deactivation_callback(void *p_user_data);
static accesskit_tree_update *_accessibility_build_tree_update(void *p_user_data);
bool in_accessibility_update = false;
Callable update_cb;
public:
Error init() override;
bool window_create(DisplayServer::WindowID p_window_id, void *p_handle) override;
void window_destroy(DisplayServer::WindowID p_window_id) override;
RID accessibility_create_element(DisplayServer::WindowID p_window_id, DisplayServer::AccessibilityRole p_role) override;
RID accessibility_create_sub_element(const RID &p_parent_rid, DisplayServer::AccessibilityRole p_role, int p_insert_pos = -1) override;
virtual RID accessibility_create_sub_text_edit_elements(const RID &p_parent_rid, const RID &p_shaped_text, float p_min_height, int p_insert_pos = -1) override;
bool accessibility_has_element(const RID &p_id) const override;
void accessibility_free_element(const RID &p_id) override;
void accessibility_element_set_meta(const RID &p_id, const Variant &p_meta) override;
Variant accessibility_element_get_meta(const RID &p_id) const override;
void accessibility_update_if_active(const Callable &p_callable) override;
void accessibility_update_set_focus(const RID &p_id) override;
RID accessibility_get_window_root(DisplayServer::WindowID p_window_id) const override;
void accessibility_set_window_rect(DisplayServer::WindowID p_window_id, const Rect2 &p_rect_out, const Rect2 &p_rect_in) override;
void accessibility_set_window_focused(DisplayServer::WindowID p_window_id, bool p_focused) override;
void accessibility_update_set_role(const RID &p_id, DisplayServer::AccessibilityRole p_role) override;
void accessibility_update_set_name(const RID &p_id, const String &p_name) override;
void accessibility_update_set_extra_info(const RID &p_id, const String &p_name_extra_info) override;
void accessibility_update_set_description(const RID &p_id, const String &p_description) override;
void accessibility_update_set_value(const RID &p_id, const String &p_value) override;
void accessibility_update_set_tooltip(const RID &p_id, const String &p_tooltip) override;
void accessibility_update_set_bounds(const RID &p_id, const Rect2 &p_rect) override;
void accessibility_update_set_transform(const RID &p_id, const Transform2D &p_transform) override;
void accessibility_update_add_child(const RID &p_id, const RID &p_child_id) override;
void accessibility_update_add_related_controls(const RID &p_id, const RID &p_related_id) override;
void accessibility_update_add_related_details(const RID &p_id, const RID &p_related_id) override;
void accessibility_update_add_related_described_by(const RID &p_id, const RID &p_related_id) override;
void accessibility_update_add_related_flow_to(const RID &p_id, const RID &p_related_id) override;
void accessibility_update_add_related_labeled_by(const RID &p_id, const RID &p_related_id) override;
void accessibility_update_add_related_radio_group(const RID &p_id, const RID &p_related_id) override;
void accessibility_update_set_active_descendant(const RID &p_id, const RID &p_other_id) override;
void accessibility_update_set_next_on_line(const RID &p_id, const RID &p_other_id) override;
void accessibility_update_set_previous_on_line(const RID &p_id, const RID &p_other_id) override;
void accessibility_update_set_member_of(const RID &p_id, const RID &p_group_id) override;
void accessibility_update_set_in_page_link_target(const RID &p_id, const RID &p_other_id) override;
void accessibility_update_set_error_message(const RID &p_id, const RID &p_other_id) override;
void accessibility_update_set_live(const RID &p_id, DisplayServer::AccessibilityLiveMode p_live) override;
void accessibility_update_add_action(const RID &p_id, DisplayServer::AccessibilityAction p_action, const Callable &p_callable) override;
void accessibility_update_add_custom_action(const RID &p_id, int p_action_id, const String &p_action_description) override;
void accessibility_update_set_table_row_count(const RID &p_id, int p_count) override;
void accessibility_update_set_table_column_count(const RID &p_id, int p_count) override;
void accessibility_update_set_table_row_index(const RID &p_id, int p_index) override;
void accessibility_update_set_table_column_index(const RID &p_id, int p_index) override;
void accessibility_update_set_table_cell_position(const RID &p_id, int p_row_index, int p_column_index) override;
void accessibility_update_set_table_cell_span(const RID &p_id, int p_row_span, int p_column_span) override;
void accessibility_update_set_list_item_count(const RID &p_id, int p_size) override;
void accessibility_update_set_list_item_index(const RID &p_id, int p_index) override;
void accessibility_update_set_list_item_level(const RID &p_id, int p_level) override;
void accessibility_update_set_list_item_selected(const RID &p_id, bool p_selected) override;
void accessibility_update_set_list_item_expanded(const RID &p_id, bool p_expanded) override;
void accessibility_update_set_popup_type(const RID &p_id, DisplayServer::AccessibilityPopupType p_popup) override;
void accessibility_update_set_checked(const RID &p_id, bool p_checekd) override;
void accessibility_update_set_num_value(const RID &p_id, double p_position) override;
void accessibility_update_set_num_range(const RID &p_id, double p_min, double p_max) override;
void accessibility_update_set_num_step(const RID &p_id, double p_step) override;
void accessibility_update_set_num_jump(const RID &p_id, double p_jump) override;
void accessibility_update_set_scroll_x(const RID &p_id, double p_position) override;
void accessibility_update_set_scroll_x_range(const RID &p_id, double p_min, double p_max) override;
void accessibility_update_set_scroll_y(const RID &p_id, double p_position) override;
void accessibility_update_set_scroll_y_range(const RID &p_id, double p_min, double p_max) override;
void accessibility_update_set_text_decorations(const RID &p_id, bool p_underline, bool p_strikethrough, bool p_overline) override;
void accessibility_update_set_text_align(const RID &p_id, HorizontalAlignment p_align) override;
void accessibility_update_set_text_selection(const RID &p_id, const RID &p_text_start_id, int p_start_char, const RID &p_text_end_id, int p_end_char) override;
void accessibility_update_set_flag(const RID &p_id, DisplayServer::AccessibilityFlags p_flag, bool p_value) override;
void accessibility_update_set_classname(const RID &p_id, const String &p_classname) override;
void accessibility_update_set_placeholder(const RID &p_id, const String &p_placeholder) override;
void accessibility_update_set_language(const RID &p_id, const String &p_language) override;
void accessibility_update_set_text_orientation(const RID &p_id, bool p_vertical) override;
void accessibility_update_set_list_orientation(const RID &p_id, bool p_vertical) override;
void accessibility_update_set_shortcut(const RID &p_id, const String &p_shortcut) override;
void accessibility_update_set_url(const RID &p_id, const String &p_url) override;
void accessibility_update_set_role_description(const RID &p_id, const String &p_description) override;
void accessibility_update_set_state_description(const RID &p_id, const String &p_description) override;
void accessibility_update_set_color_value(const RID &p_id, const Color &p_color) override;
void accessibility_update_set_background_color(const RID &p_id, const Color &p_color) override;
void accessibility_update_set_foreground_color(const RID &p_id, const Color &p_color) override;
AccessibilityDriverAccessKit();
~AccessibilityDriverAccessKit();
};
#endif // ACCESSKIT_ENABLED

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,7 @@ common_linuxbsd = [
"joypad_linux.cpp",
"freedesktop_portal_desktop.cpp",
"freedesktop_screensaver.cpp",
"freedesktop_at_spi_monitor.cpp",
]
if env["use_sowrap"]:

View File

@ -466,6 +466,24 @@ def configure(env: "SConsEnvironment"):
env.Append(CPPDEFINES=["WAYLAND_ENABLED"])
env.Append(LIBS=["rt"]) # Needed by glibc, used by _allocate_shm_file
if env["accesskit"]:
if env["accesskit_sdk_path"] != "":
env.Prepend(CPPPATH=[env["accesskit_sdk_path"] + "/include"])
if env["arch"] == "arm64":
env.Append(LIBPATH=[env["accesskit_sdk_path"] + "/lib/linux/arm64/static/"])
elif env["arch"] == "arm32":
env.Append(LIBPATH=[env["accesskit_sdk_path"] + "/lib/linux/arm32/static/"])
elif env["arch"] == "rv64":
env.Append(LIBPATH=[env["accesskit_sdk_path"] + "/lib/linux/riscv64gc/static/"])
elif env["arch"] == "x86_64":
env.Append(LIBPATH=[env["accesskit_sdk_path"] + "/lib/linux/x86_64/static/"])
elif env["arch"] == "x86_32":
env.Append(LIBPATH=[env["accesskit_sdk_path"] + "/lib/linux/x86/static/"])
env.Append(LIBS=["accesskit"])
else:
env.Append(CPPDEFINES=["ACCESSKIT_DYNAMIC"])
env.Append(CPPDEFINES=["ACCESSKIT_ENABLED"])
if env["vulkan"]:
env.Append(CPPDEFINES=["VULKAN_ENABLED", "RD_ENABLED"])
if not env["use_volk"]:

View File

@ -72,6 +72,11 @@ Error EditorExportPlatformLinuxBSD::export_project(const Ref<EditorExportPreset>
}
}
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (da->file_exists(template_path.get_base_dir().path_join("libaccesskit." + arch + ".so"))) {
da->copy(template_path.get_base_dir().path_join("libaccesskit." + arch + ".so"), p_path.get_base_dir().path_join("libaccesskit." + arch + ".so"), get_chmod_flags());
}
bool export_as_zip = p_path.ends_with("zip");
String pkg_name;

View File

@ -0,0 +1,157 @@
/**************************************************************************/
/* freedesktop_at_spi_monitor.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "freedesktop_at_spi_monitor.h"
#ifdef DBUS_ENABLED
#include "core/os/os.h"
#ifdef SOWRAP_ENABLED
#include "dbus-so_wrap.h"
#else
#include <dbus/dbus.h>
#endif
#include <unistd.h>
#define BUS_OBJECT_NAME "org.a11y.Bus"
#define BUS_OBJECT_PATH "/org/a11y/bus"
#define BUS_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties"
void FreeDesktopAtSPIMonitor::monitor_thread_func(void *p_userdata) {
FreeDesktopAtSPIMonitor *mon = (FreeDesktopAtSPIMonitor *)p_userdata;
DBusError error;
dbus_error_init(&error);
DBusConnection *bus = dbus_bus_get(DBUS_BUS_SESSION, &error);
if (dbus_error_is_set(&error)) {
dbus_error_free(&error);
mon->supported.clear();
return;
}
static const char *iface = "org.a11y.Status";
static const char *member = "IsEnabled";
while (!mon->exit_thread.is_set()) {
DBusMessage *message = dbus_message_new_method_call(BUS_OBJECT_NAME, BUS_OBJECT_PATH, BUS_INTERFACE_PROPERTIES, "Get");
dbus_message_append_args(
message,
DBUS_TYPE_STRING, &iface,
DBUS_TYPE_STRING, &member,
DBUS_TYPE_INVALID);
DBusMessage *reply = dbus_connection_send_with_reply_and_block(bus, message, 50, &error);
dbus_message_unref(message);
if (!dbus_error_is_set(&error)) {
DBusMessageIter iter, iter_variant, iter_struct;
dbus_bool_t result;
dbus_message_iter_init(reply, &iter);
dbus_message_iter_recurse(&iter, &iter_variant);
switch (dbus_message_iter_get_arg_type(&iter_variant)) {
case DBUS_TYPE_STRUCT: {
dbus_message_iter_recurse(&iter_variant, &iter_struct);
if (dbus_message_iter_get_arg_type(&iter_struct) == DBUS_TYPE_BOOLEAN) {
dbus_message_iter_get_basic(&iter_struct, &result);
if (result) {
mon->sr_enabled.set();
} else {
mon->sr_enabled.clear();
}
}
} break;
case DBUS_TYPE_BOOLEAN: {
dbus_message_iter_get_basic(&iter_variant, &result);
if (result) {
mon->sr_enabled.set();
} else {
mon->sr_enabled.clear();
}
} break;
default:
break;
}
dbus_message_unref(reply);
} else {
dbus_error_free(&error);
}
usleep(50000);
}
dbus_connection_unref(bus);
}
FreeDesktopAtSPIMonitor::FreeDesktopAtSPIMonitor() {
#ifdef SOWRAP_ENABLED
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
#else
int dylibloader_verbose = 0;
#endif
if (initialize_dbus(dylibloader_verbose) != 0) {
print_verbose("AT-SPI2: Failed to load DBus library!");
supported.clear();
return;
}
#endif
bool ver_ok = false;
int version_major = 0;
int version_minor = 0;
int version_rev = 0;
dbus_get_version(&version_major, &version_minor, &version_rev);
ver_ok = (version_major == 1 && version_minor >= 10) || (version_major > 1); // 1.10.0
print_verbose(vformat("AT-SPI2: DBus %d.%d.%d detected.", version_major, version_minor, version_rev));
if (!ver_ok) {
print_verbose("AT-SPI2: Unsupported DBus library version!");
supported.clear();
return;
}
supported.set();
sr_enabled.clear();
exit_thread.clear();
thread.start(FreeDesktopAtSPIMonitor::monitor_thread_func, this);
}
FreeDesktopAtSPIMonitor::~FreeDesktopAtSPIMonitor() {
exit_thread.set();
if (thread.is_started()) {
thread.wait_to_finish();
}
}
#endif // DBUS_ENABLED

View File

@ -0,0 +1,56 @@
/**************************************************************************/
/* freedesktop_at_spi_monitor.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifdef DBUS_ENABLED
#include "core/os/thread.h"
#include "core/os/thread_safe.h"
class FreeDesktopAtSPIMonitor {
private:
Thread thread;
SafeFlag exit_thread;
SafeFlag sr_enabled;
SafeFlag supported;
static void monitor_thread_func(void *p_userdata);
public:
FreeDesktopAtSPIMonitor();
~FreeDesktopAtSPIMonitor();
bool is_supported() { return supported.is_set(); }
bool is_active() { return sr_enabled.is_set(); }
};
#endif // DBUS_ENABLED

View File

@ -101,6 +101,11 @@ bool FreeDesktopPortalDesktop::try_parse_variant(DBusMessage *p_reply_message, R
return false;
}
dbus_message_iter_get_basic(&iter[2], r_value);
} else if (p_type == VAR_TYPE_BOOL) {
if (dbus_message_iter_get_arg_type(&iter[2]) != DBUS_TYPE_BOOLEAN) {
return false;
}
dbus_message_iter_get_basic(&iter[2], r_value);
}
return true;
}
@ -177,6 +182,18 @@ Color FreeDesktopPortalDesktop::get_appearance_accent_color() {
}
}
uint32_t FreeDesktopPortalDesktop::get_high_contrast() {
if (unsupported) {
return -1;
}
dbus_bool_t value = false;
if (read_setting("org.gnome.desktop.a11y.interface", "high-contrast", VAR_TYPE_BOOL, &value)) {
return value;
}
return -1;
}
static const char *cs_empty = "";
void FreeDesktopPortalDesktop::append_dbus_string(DBusMessageIter *p_iter, const String &p_string) {

View File

@ -46,6 +46,7 @@ private:
enum ReadVariantType {
VAR_TYPE_UINT32, // u
VAR_TYPE_BOOL, // b
VAR_TYPE_COLOR, // (ddd)
};
@ -135,6 +136,12 @@ public:
system_theme_changed = p_system_theme_changed;
}
// Retrieve high-contrast setting.
// -1: Unknown.
// 0: Disabled.
// 1: Enabled.
uint32_t get_high_contrast();
// org.freedesktop.portal.Screenshot methods.
bool color_picker(const String &p_xid, const Callable &p_callback);
};

View File

@ -39,6 +39,8 @@
#define DEBUG_LOG_WAYLAND(...)
#endif
#include "servers/rendering/dummy/rasterizer_dummy.h"
#ifdef VULKAN_ENABLED
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#endif
@ -50,6 +52,10 @@
#include "wayland/egl_manager_wayland_gles.h"
#endif
#ifdef ACCESSKIT_ENABLED
#include "drivers/accesskit/accessibility_driver_accesskit.h"
#endif
#define WAYLAND_MAX_FRAME_TIME_US (1'000'000)
String DisplayServerWayland::_get_app_id_from_context(Context p_context) {
@ -201,6 +207,12 @@ bool DisplayServerWayland::has_feature(Feature p_feature) const {
} break;
#endif
#ifdef ACCESSKIT_ENABLED
case FEATURE_ACCESSIBILITY_SCREEN_READER: {
return (accessibility_driver != nullptr);
} break;
#endif
default: {
return false;
}
@ -689,6 +701,16 @@ DisplayServer::WindowID DisplayServerWayland::create_sub_window(WindowMode p_mod
wd.flags = p_flags;
wd.vsync_mode = p_vsync_mode;
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver && !accessibility_driver->window_create(wd.id, nullptr)) {
if (OS::get_singleton()->is_stdout_verbose()) {
ERR_PRINT("Can't create an accessibility adapter for window, accessibility support disabled!");
}
memdelete(accessibility_driver);
accessibility_driver = nullptr;
}
#endif
// NOTE: Remember to clear its position if this window will be a toplevel. We
// can only know once we show it.
wd.rect = p_rect;
@ -840,6 +862,12 @@ void DisplayServerWayland::delete_sub_window(WindowID p_window_id) {
popup_menu_list.pop_back();
}
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver) {
accessibility_driver->window_destroy(p_window_id);
}
#endif
if (wd.visible) {
#ifdef VULKAN_ENABLED
if (rendering_device) {
@ -1284,6 +1312,22 @@ void DisplayServerWayland::window_set_ime_position(const Point2i &p_pos, Display
wayland_thread.window_set_ime_position(p_pos, p_window_id);
}
int DisplayServerWayland::accessibility_should_increase_contrast() const {
#ifdef DBUS_ENABLED
return portal_desktop->get_high_contrast();
#endif
return -1;
}
int DisplayServerWayland::accessibility_screen_reader_active() const {
#ifdef DBUS_ENABLED
if (atspi_monitor->is_supported()) {
return atspi_monitor->is_active();
}
#endif
return -1;
}
Point2i DisplayServerWayland::ime_get_selection() const {
return ime_selection;
}
@ -1557,14 +1601,24 @@ void DisplayServerWayland::process_events() {
}
Ref<WaylandThread::WindowEventMessage> winev_msg = msg;
if (winev_msg.is_valid()) {
if (winev_msg.is_valid() && windows.has(winev_msg->id)) {
_send_window_event(winev_msg->event, winev_msg->id);
if (winev_msg->event == WINDOW_EVENT_FOCUS_IN) {
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver) {
accessibility_driver->accessibility_set_window_focused(winev_msg->id, true);
}
#endif
if (OS::get_singleton()->get_main_loop()) {
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN);
}
} else if (winev_msg->event == WINDOW_EVENT_FOCUS_OUT) {
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver) {
accessibility_driver->accessibility_set_window_focused(winev_msg->id, false);
}
#endif
if (OS::get_singleton()->get_main_loop()) {
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT);
}
@ -1775,6 +1829,7 @@ Vector<String> DisplayServerWayland::get_rendering_drivers_func() {
drivers.push_back("opengl3");
drivers.push_back("opengl3_es");
#endif
drivers.push_back("dummy");
return drivers;
}
@ -1828,11 +1883,26 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
}
#endif
#ifdef ACCESSKIT_ENABLED
if (accessibility_get_mode() != DisplayServer::AccessibilityMode::ACCESSIBILITY_DISABLED) {
accessibility_driver = memnew(AccessibilityDriverAccessKit);
if (accessibility_driver->init() != OK) {
memdelete(accessibility_driver);
accessibility_driver = nullptr;
}
}
#endif
rendering_driver = p_rendering_driver;
bool driver_found = false;
String executable_name = OS::get_singleton()->get_executable_path().get_file();
if (rendering_driver == "dummy") {
RasterizerDummy::make_current();
driver_found = true;
}
#ifdef RD_ENABLED
#ifdef VULKAN_ENABLED
if (rendering_driver == "vulkan") {
@ -2021,6 +2091,7 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
#ifdef DBUS_ENABLED
portal_desktop = memnew(FreeDesktopPortalDesktop);
atspi_monitor = memnew(FreeDesktopAtSPIMonitor);
screensaver = memnew(FreeDesktopScreenSaver);
#endif // DBUS_ENABLED
@ -2045,12 +2116,17 @@ DisplayServerWayland::~DisplayServerWayland() {
if (!window_get_flag(WINDOW_FLAG_POPUP_WM_HINT, id)) {
toplevels.push_back(id);
#ifdef ACCESSKIT_ENABLED
} else if (accessibility_driver) {
accessibility_driver->window_destroy(id);
#endif
}
}
for (WindowID &id : toplevels) {
delete_sub_window(id);
}
windows.clear();
wayland_thread.destroy();
@ -2071,9 +2147,16 @@ DisplayServerWayland::~DisplayServerWayland() {
}
#endif
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver) {
memdelete(accessibility_driver);
}
#endif
#ifdef DBUS_ENABLED
if (portal_desktop) {
memdelete(portal_desktop);
memdelete(atspi_monitor);
memdelete(screensaver);
}
#endif

View File

@ -52,6 +52,7 @@
#endif
#ifdef DBUS_ENABLED
#include "freedesktop_at_spi_monitor.h"
#include "freedesktop_portal_desktop.h"
#include "freedesktop_screensaver.h"
#endif
@ -167,6 +168,7 @@ class DisplayServerWayland : public DisplayServer {
#if DBUS_ENABLED
FreeDesktopPortalDesktop *portal_desktop = nullptr;
FreeDesktopAtSPIMonitor *atspi_monitor = nullptr;
FreeDesktopScreenSaver *screensaver = nullptr;
bool screensaver_inhibited = false;
@ -307,6 +309,9 @@ public:
virtual void window_set_ime_active(const bool p_active, WindowID p_window_id = MAIN_WINDOW_ID) override;
virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window_id = MAIN_WINDOW_ID) override;
virtual int accessibility_should_increase_contrast() const override;
virtual int accessibility_screen_reader_active() const override;
virtual Point2i ime_get_selection() const override;
virtual String ime_get_text() const override;

View File

@ -39,9 +39,12 @@
#include "core/math/math_funcs.h"
#include "core/string/print_string.h"
#include "core/string/ustring.h"
#include "core/version.h"
#include "drivers/png/png_driver_common.h"
#include "main/main.h"
#include "servers/rendering/dummy/rasterizer_dummy.h"
#if defined(VULKAN_ENABLED)
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#endif
@ -50,6 +53,10 @@
#include "drivers/gles3/rasterizer_gles3.h"
#endif
#ifdef ACCESSKIT_ENABLED
#include "drivers/accesskit/accessibility_driver_accesskit.h"
#endif
#include <dlfcn.h>
#include <limits.h>
#include <stdio.h>
@ -169,6 +176,12 @@ bool DisplayServerX11::has_feature(Feature p_feature) const {
} break;
#endif
#ifdef ACCESSKIT_ENABLED
case FEATURE_ACCESSIBILITY_SCREEN_READER: {
return (accessibility_driver != nullptr);
} break;
#endif
default: {
return false;
}
@ -1943,6 +1956,12 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) {
}
#endif
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver) {
accessibility_driver->window_destroy(p_id);
}
#endif
if (wd.xic) {
XDestroyIC(wd.xic);
wd.xic = nullptr;
@ -3284,6 +3303,22 @@ void DisplayServerX11::window_set_ime_position(const Point2i &p_pos, WindowID p_
}
}
int DisplayServerX11::accessibility_should_increase_contrast() const {
#ifdef DBUS_ENABLED
return portal_desktop->get_high_contrast();
#endif
return -1;
}
int DisplayServerX11::accessibility_screen_reader_active() const {
#ifdef DBUS_ENABLED
if (atspi_monitor->is_supported()) {
return atspi_monitor->is_active();
}
#endif
return -1;
}
Point2i DisplayServerX11::ime_get_selection() const {
return im_selection;
}
@ -4931,6 +4966,11 @@ void DisplayServerX11::process_events() {
static unsigned int focus_order = 0;
wd.focus_order = ++focus_order;
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver) {
accessibility_driver->accessibility_set_window_focused(window_id, true);
}
#endif
_send_window_event(wd, WINDOW_EVENT_FOCUS_IN);
if (mouse_mode_grab) {
@ -4982,6 +5022,11 @@ void DisplayServerX11::process_events() {
wd.focused = false;
Input::get_singleton()->release_pressed_events();
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver) {
accessibility_driver->accessibility_set_window_focused(window_id, false);
}
#endif
_send_window_event(wd, WINDOW_EVENT_FOCUS_OUT);
if (mouse_mode_grab) {
@ -6083,6 +6128,7 @@ Vector<String> DisplayServerX11::get_rendering_drivers_func() {
drivers.push_back("opengl3");
drivers.push_back("opengl3_es");
#endif
drivers.push_back("dummy");
return drivers;
}
@ -6231,6 +6277,15 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
if (dead_tbl && xkb_loaded_v05p) {
wd.xkb_state = xkb_compose_state_new(dead_tbl, XKB_COMPOSE_STATE_NO_FLAGS);
}
#endif
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver && !accessibility_driver->window_create(id, nullptr)) {
if (OS::get_singleton()->is_stdout_verbose()) {
ERR_PRINT("Can't create an accessibility adapter for window, accessibility support disabled!");
}
memdelete(accessibility_driver);
accessibility_driver = nullptr;
}
#endif
// Enable receiving notification when the window is initialized (MapNotify)
// so the focus can be set at the right time.
@ -6818,6 +6873,16 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
}
#endif
#ifdef ACCESSKIT_ENABLED
if (accessibility_get_mode() != DisplayServer::AccessibilityMode::ACCESSIBILITY_DISABLED) {
accessibility_driver = memnew(AccessibilityDriverAccessKit);
if (accessibility_driver->init() != OK) {
memdelete(accessibility_driver);
accessibility_driver = nullptr;
}
}
#endif
//!!!!!!!!!!!!!!!!!!!!!!!!!!
//TODO - do Vulkan and OpenGL support checks, driver selection and fallback
rendering_driver = p_rendering_driver;
@ -6827,6 +6892,11 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
// Initialize context and rendering device.
if (rendering_driver == "dummy") {
RasterizerDummy::make_current();
driver_found = true;
}
#if defined(RD_ENABLED)
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
@ -7157,8 +7227,8 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
screen_set_keep_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on"));
portal_desktop = memnew(FreeDesktopPortalDesktop);
atspi_monitor = memnew(FreeDesktopAtSPIMonitor);
#endif // DBUS_ENABLED
XSetErrorHandler(&default_window_error_handler);
r_error = OK;
@ -7198,6 +7268,12 @@ DisplayServerX11::~DisplayServerX11() {
}
#endif
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver) {
accessibility_driver->window_destroy(E.key);
}
#endif
WindowData &wd = E.value;
if (wd.xic) {
XDestroyIC(wd.xic);
@ -7272,7 +7348,11 @@ DisplayServerX11::~DisplayServerX11() {
if (xmbstring) {
memfree(xmbstring);
}
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver) {
memdelete(accessibility_driver);
}
#endif
#ifdef SPEECHD_ENABLED
if (tts) {
memdelete(tts);
@ -7282,6 +7362,7 @@ DisplayServerX11::~DisplayServerX11() {
#ifdef DBUS_ENABLED
memdelete(screensaver);
memdelete(portal_desktop);
memdelete(atspi_monitor);
#endif
}

View File

@ -65,6 +65,7 @@
#endif
#if defined(DBUS_ENABLED)
#include "freedesktop_at_spi_monitor.h"
#include "freedesktop_portal_desktop.h"
#include "freedesktop_screensaver.h"
#endif
@ -159,6 +160,7 @@ class DisplayServerX11 : public DisplayServer {
#if defined(DBUS_ENABLED)
FreeDesktopPortalDesktop *portal_desktop = nullptr;
FreeDesktopAtSPIMonitor *atspi_monitor = nullptr;
#endif
struct WindowData {
@ -533,6 +535,9 @@ public:
virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID) override;
virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID) override;
virtual int accessibility_should_increase_contrast() const override;
virtual int accessibility_screen_reader_active() const override;
virtual Point2i ime_get_selection() const override;
virtual String ime_get_text() const override;

View File

@ -182,6 +182,18 @@ def configure(env: "SConsEnvironment"):
## Dependencies
if env["accesskit"]:
if env["accesskit_sdk_path"] != "":
env.Prepend(CPPPATH=[env["accesskit_sdk_path"] + "/include"])
if env["arch"] == "arm64" or env["arch"] == "universal":
env.Append(LINKFLAGS=["-L" + env["accesskit_sdk_path"] + "/lib/macos/arm64/static/"])
if env["arch"] == "x86_64" or env["arch"] == "universal":
env.Append(LINKFLAGS=["-L" + env["accesskit_sdk_path"] + "/lib/macos/x86_64/static/"])
env.Append(LINKFLAGS=["-laccesskit"])
else:
env.Append(CPPDEFINES=["ACCESSKIT_DYNAMIC"])
env.Append(CPPDEFINES=["ACCESSKIT_ENABLED"])
if env["builtin_libtheora"] and env["arch"] == "x86_64":
env["x86_libtheora_opt_gcc"] = True

View File

@ -425,6 +425,11 @@ public:
virtual void window_set_window_buttons_offset(const Vector2i &p_offset, WindowID p_window = MAIN_WINDOW_ID) override;
virtual Vector3i window_get_safe_title_margins(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual int accessibility_should_increase_contrast() const override;
virtual int accessibility_should_reduce_animation() const override;
virtual int accessibility_should_reduce_transparency() const override;
virtual int accessibility_screen_reader_active() const override;
virtual Point2i ime_get_selection() const override;
virtual String ime_get_text() const override;

View File

@ -30,6 +30,7 @@
#import "display_server_macos.h"
#import "godot_application_delegate.h"
#import "godot_button_view.h"
#import "godot_content_view.h"
#import "godot_menu_delegate.h"
@ -52,6 +53,8 @@
#include <AppKit/AppKit.h>
#include "servers/rendering/dummy/rasterizer_dummy.h"
#if defined(GLES3_ENABLED)
#include "drivers/gles3/rasterizer_gles3.h"
#endif
@ -60,6 +63,10 @@
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#endif
#if defined(ACCESSKIT_ENABLED)
#include "drivers/accesskit/accessibility_driver_accesskit.h"
#endif
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
#import <IOKit/IOCFPlugIn.h>
@ -68,14 +75,15 @@
#import <IOKit/hid/IOHIDLib.h>
DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect) {
WindowID id;
const float scale = screen_get_max_scale();
WindowID id = window_id_counter;
{
WindowData wd;
WindowData &wd = windows[id];
wd.window_delegate = [[GodotWindowDelegate alloc] init];
ERR_FAIL_NULL_V_MSG(wd.window_delegate, INVALID_WINDOW_ID, "Can't create a window delegate");
[wd.window_delegate setWindowID:window_id_counter];
[wd.window_delegate setWindowID:id];
int rq_screen = get_screen_from_rect(p_rect);
if (rq_screen < 0) {
@ -100,12 +108,15 @@ DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mod
backing:NSBackingStoreBuffered
defer:NO];
ERR_FAIL_NULL_V_MSG(wd.window_object, INVALID_WINDOW_ID, "Can't create a window");
[wd.window_object setWindowID:window_id_counter];
[wd.window_object setWindowID:id];
[wd.window_object setReleasedWhenClosed:NO];
wd.window_view = [[GodotContentView alloc] init];
ERR_FAIL_NULL_V_MSG(wd.window_view, INVALID_WINDOW_ID, "Can't create a window view");
[wd.window_view setWindowID:window_id_counter];
if (wd.window_view == nil) {
windows.erase(id);
ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Can't create a window view");
}
[wd.window_view setWindowID:id];
[wd.window_view setWantsLayer:TRUE];
[wd.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
@ -115,6 +126,16 @@ DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mod
[wd.window_object setRestorable:NO];
[wd.window_object setColorSpace:[NSColorSpace sRGBColorSpace]];
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver && !accessibility_driver->window_create(id, (__bridge void *)wd.window_object)) {
if (OS::get_singleton()->is_stdout_verbose()) {
ERR_PRINT("Can't create an accessibility adapter for window, accessibility support disabled!");
}
memdelete(accessibility_driver);
accessibility_driver = nullptr;
}
#endif
if ([wd.window_object respondsToSelector:@selector(setTabbingMode:)]) {
[wd.window_object setTabbingMode:NSWindowTabbingModeDisallowed];
}
@ -156,23 +177,43 @@ DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mod
}
#endif
Error err = rendering_context->window_create(window_id_counter, &wpd);
#ifdef ACCESSKIT_ENABLED
if (err != OK && accessibility_driver) {
accessibility_driver->window_destroy(id);
}
#endif
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, vformat("Can't create a %s context", rendering_driver));
rendering_context->window_set_size(window_id_counter, p_rect.size.width, p_rect.size.height);
rendering_context->window_set_vsync_mode(window_id_counter, p_vsync_mode);
}
#endif
#if defined(GLES3_ENABLED)
bool gl_failed = false;
if (gl_manager_legacy) {
Error err = gl_manager_legacy->window_create(window_id_counter, wd.window_view, p_rect.size.width, p_rect.size.height);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create an OpenGL context.");
if (err != OK) {
gl_failed = true;
}
}
if (gl_manager_angle) {
CALayer *layer = [(NSView *)wd.window_view layer];
Error err = gl_manager_angle->window_create(window_id_counter, nullptr, (__bridge void *)layer, p_rect.size.width, p_rect.size.height);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create an OpenGL context.");
if (err != OK) {
gl_failed = true;
}
window_set_vsync_mode(p_vsync_mode, window_id_counter);
}
if (gl_failed) {
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver) {
accessibility_driver->window_destroy(id);
}
#endif
windows.erase(id);
ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Can't create an OpenGL context.");
}
window_set_vsync_mode(p_vsync_mode, id);
#endif
[wd.window_view updateLayerDelegate];
@ -184,10 +225,8 @@ DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mod
offset.y = (nsrect.origin.y + nsrect.size.height);
offset.y -= (windowRect.origin.y + windowRect.size.height);
[wd.window_object setFrameTopLeftPoint:NSMakePoint(wpos.x - offset.x, wpos.y - offset.y)];
id = window_id_counter++;
windows[id] = wd;
}
window_id_counter++;
WindowData &wd = windows[id];
window_set_mode(p_mode, id);
@ -762,6 +801,8 @@ bool DisplayServerMacOS::get_is_resizing() const {
}
void DisplayServerMacOS::window_destroy(WindowID p_window) {
ERR_FAIL_COND(!windows.has(p_window));
#if defined(GLES3_ENABLED)
if (gl_manager_legacy) {
gl_manager_legacy->window_destroy(p_window);
@ -775,6 +816,11 @@ void DisplayServerMacOS::window_destroy(WindowID p_window) {
if (rendering_context) {
rendering_context->window_destroy(p_window);
}
#endif
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver) {
accessibility_driver->window_destroy(p_window);
}
#endif
windows.erase(p_window);
@ -835,6 +881,11 @@ bool DisplayServerMacOS::has_feature(Feature p_feature) const {
case FEATURE_SCREEN_EXCLUDE_FROM_CAPTURE:
case FEATURE_EMOJI_AND_SYMBOL_PICKER:
return true;
#ifdef ACCESSKIT_ENABLED
case FEATURE_ACCESSIBILITY_SCREEN_READER: {
return (accessibility_driver != nullptr);
} break;
#endif
default: {
}
}
@ -2999,6 +3050,22 @@ DisplayServer::VSyncMode DisplayServerMacOS::window_get_vsync_mode(WindowID p_wi
return DisplayServer::VSYNC_ENABLED;
}
int DisplayServerMacOS::accessibility_should_increase_contrast() const {
return [(GodotApplicationDelegate *)[[NSApplication sharedApplication] delegate] getHighContrast];
}
int DisplayServerMacOS::accessibility_should_reduce_animation() const {
return [(GodotApplicationDelegate *)[[NSApplication sharedApplication] delegate] getReduceMotion];
}
int DisplayServerMacOS::accessibility_should_reduce_transparency() const {
return [(GodotApplicationDelegate *)[[NSApplication sharedApplication] delegate] getReduceTransparency];
}
int DisplayServerMacOS::accessibility_screen_reader_active() const {
return [(GodotApplicationDelegate *)[[NSApplication sharedApplication] delegate] getVoiceOver];
}
Point2i DisplayServerMacOS::ime_get_selection() const {
return im_selection;
}
@ -3592,6 +3659,7 @@ Vector<String> DisplayServerMacOS::get_rendering_drivers_func() {
drivers.push_back("opengl3");
drivers.push_back("opengl3_angle");
#endif
drivers.push_back("dummy");
return drivers;
}
@ -3783,6 +3851,16 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
native_menu = memnew(NativeMenuMacOS);
#ifdef ACCESSKIT_ENABLED
if (accessibility_get_mode() != DisplayServer::AccessibilityMode::ACCESSIBILITY_DISABLED) {
accessibility_driver = memnew(AccessibilityDriverAccessKit);
if (accessibility_driver->init() != OK) {
memdelete(accessibility_driver);
accessibility_driver = nullptr;
}
}
#endif
NSMenuItem *menu_item;
NSString *title;
@ -3974,6 +4052,10 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
}
force_process_and_drop_events();
if (rendering_driver == "dummy") {
RasterizerDummy::make_current();
}
#if defined(GLES3_ENABLED)
if (rendering_driver == "opengl3") {
RasterizerGLES3::make_current(true);
@ -4042,7 +4124,11 @@ DisplayServerMacOS::~DisplayServerMacOS() {
rendering_context = nullptr;
}
#endif
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver) {
memdelete(accessibility_driver);
}
#endif
CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), nullptr, kTISNotifySelectedKeyboardInputSourceChanged, nullptr);
CGDisplayRemoveReconfigurationCallback(_displays_arrangement_changed, nullptr);

View File

@ -35,9 +35,20 @@
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
@interface GodotApplicationDelegate : NSObject <NSUserInterfaceItemSearching, NSApplicationDelegate>
- (void)activate;
@interface GodotApplicationDelegate : NSObject <NSUserInterfaceItemSearching, NSApplicationDelegate> {
bool high_contrast;
bool reduce_motion;
bool reduce_transparency;
bool voice_over;
}
- (void)forceUnbundledWindowActivationHackStep1;
- (void)forceUnbundledWindowActivationHackStep2;
- (void)forceUnbundledWindowActivationHackStep3;
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
- (void)accessibilityDisplayOptionsChange:(NSNotification *)notification;
- (bool)getHighContrast;
- (bool)getReduceMotion;
- (bool)getReduceTransparency;
- (bool)getVoiceOver;
@end

View File

@ -143,14 +143,55 @@
[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(system_theme_changed:) name:@"AppleColorPreferencesChangedNotification" object:nil];
}
static const char *godot_ac_ctx = "gd_accessibility_observer_ctx";
- (id)init {
self = [super init];
[[NSWorkspace sharedWorkspace] addObserver:self forKeyPath:@"voiceOverEnabled" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:(void *)godot_ac_ctx];
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(accessibilityDisplayOptionsChange:) name:NSWorkspaceAccessibilityDisplayOptionsDidChangeNotification object:nil];
high_contrast = [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldIncreaseContrast];
reduce_motion = [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldReduceMotion];
reduce_transparency = [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldReduceTransparency];
voice_over = [[NSWorkspace sharedWorkspace] isVoiceOverEnabled];
return self;
}
- (void)dealloc {
[[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:@"AppleInterfaceThemeChangedNotification" object:nil];
[[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:@"AppleColorPreferencesChangedNotification" object:nil];
[[NSWorkspace sharedWorkspace] removeObserver:self forKeyPath:@"voiceOverEnabled" context:(void *)godot_ac_ctx];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context == (void *)godot_ac_ctx) {
voice_over = [[NSWorkspace sharedWorkspace] isVoiceOverEnabled];
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (void)accessibilityDisplayOptionsChange:(NSNotification *)notification {
high_contrast = [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldIncreaseContrast];
reduce_motion = [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldReduceMotion];
reduce_transparency = [[NSWorkspace sharedWorkspace] accessibilityDisplayShouldReduceTransparency];
}
- (bool)getHighContrast {
return high_contrast;
}
- (bool)getReduceMotion {
return reduce_motion;
}
- (bool)getReduceTransparency {
return reduce_transparency;
}
- (bool)getVoiceOver {
return voice_over;
}
- (void)application:(NSApplication *)application openURLs:(NSArray<NSURL *> *)urls {

View File

@ -324,6 +324,9 @@
wd.focused = true;
ds->set_last_focused_window(window_id);
#ifdef ACCESSKIT_ENABLED
ds->accessibility_set_window_focused(window_id, true);
#endif
ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_IN);
}
@ -341,6 +344,9 @@
wd.focused = false;
ds->release_pressed_events();
#ifdef ACCESSKIT_ENABLED
ds->accessibility_set_window_focused(window_id, false);
#endif
ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_OUT);
}
@ -354,6 +360,9 @@
wd.focused = false;
ds->release_pressed_events();
#ifdef ACCESSKIT_ENABLED
ds->accessibility_set_window_focused(window_id, false);
#endif
ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_OUT);
}
@ -368,6 +377,9 @@
if ([wd.window_object isKeyWindow]) {
wd.focused = true;
ds->set_last_focused_window(window_id);
#ifdef ACCESSKIT_ENABLED
ds->accessibility_set_window_focused(window_id, true);
#endif
ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_IN);
}
}

View File

@ -60,6 +60,12 @@ env.Depends(res_obj, "#core/version_generated.gen.h")
env.add_source_files(sources, common_win)
sources += res_obj
if env["accesskit"] and not env.msvc:
def_file = "uiautomationcore." + env["arch"] + ".def"
def_target = "libuiautomationcore." + env["arch"] + ".a"
def_obj = env.DEF(def_target, def_file)
sources += def_obj
prog = env.add_program("#bin/godot", sources, PROGSUFFIX=env["PROGSUFFIX"])
arrange_program_clean(prog)

View File

@ -5,7 +5,7 @@ import sys
from typing import TYPE_CHECKING
import methods
from methods import print_error, print_warning
from methods import print_error, print_info, print_warning
from platform_methods import detect_arch, validate_arch
if TYPE_CHECKING:
@ -245,6 +245,44 @@ def get_flags():
}
def build_def_file(target, source, env: "SConsEnvironment"):
arch_aliases = {
"x86_32": "i386",
"x86_64": "i386:x86-64",
"arm32": "arm",
"arm64": "arm64",
}
cmdbase = "dlltool -m " + arch_aliases[env["arch"]]
if env["arch"] != "x86_32":
cmdbase += " --no-leading-underscore"
mingw_bin_prefix = get_mingw_bin_prefix(env["mingw_prefix"], env["arch"])
for x in range(len(source)):
ok = True
# Try prefixed executable (MinGW on Linux).
cmd = mingw_bin_prefix + cmdbase + " -d " + str(source[x]) + " -l " + str(target[x])
try:
out = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE).communicate()
if len(out[1]):
ok = False
except Exception:
ok = False
# Try generic executable (MSYS2).
if not ok:
cmd = cmdbase + " -d " + str(source[x]) + " -l " + str(target[x])
try:
out = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE).communicate()
if len(out[1]):
return -1
except Exception:
return -1
return 0
def configure_msvc(env: "SConsEnvironment"):
"""Configure env to work with MSVC"""
@ -365,6 +403,11 @@ def configure_msvc(env: "SConsEnvironment"):
validate_win_version(env)
if env["accesskit"]:
if int(env["target_win_version"], 16) < 0x0602:
print_info("AcceeKit enabled, targeted Windows version changed to Windows 8 (0x602).")
env["target_win_version"] = "0x0602" # Accessibility API require Windows 8+
env.AppendUnique(
CPPDEFINES=[
"WINDOWS_ENABLED",
@ -421,6 +464,29 @@ def configure_msvc(env: "SConsEnvironment"):
if env.debug_features:
LIBS += ["psapi", "dbghelp"]
if env["accesskit"]:
if env["accesskit_sdk_path"] != "":
env.Prepend(CPPPATH=[env["accesskit_sdk_path"] + "/include"])
if env["arch"] == "arm64":
env.Append(LIBPATH=[env["accesskit_sdk_path"] + "/lib/windows/arm64/msvc/static"])
elif env["arch"] == "x86_64":
env.Append(LIBPATH=[env["accesskit_sdk_path"] + "/lib/windows/x86_64/msvc/static"])
elif env["arch"] == "x86_32":
env.Append(LIBPATH=[env["accesskit_sdk_path"] + "/lib/windows/x86/msvc/static"])
LIBS += [
"accesskit",
"uiautomationcore",
"runtimeobject",
"propsys",
"oleaut32",
"user32",
"userenv",
"ntdll",
]
else:
env.Append(CPPDEFINES=["ACCESSKIT_DYNAMIC"])
env.Append(CPPDEFINES=["ACCESSKIT_ENABLED"])
if env["vulkan"]:
env.AppendUnique(CPPDEFINES=["VULKAN_ENABLED", "RD_ENABLED"])
if not env["use_volk"]:
@ -703,6 +769,11 @@ def configure_mingw(env: "SConsEnvironment"):
validate_win_version(env)
if env["accesskit"]:
if int(env["target_win_version"], 16) < 0x0602:
print_info("AcceeKit enabled, targeted Windows version changed to Windows 8 (0x602).")
env["target_win_version"] = "0x0602" # Accessibility API require Windows 8+
if not env["use_llvm"]:
env.Append(CCFLAGS=["-mwindows"])
@ -767,6 +838,38 @@ def configure_mingw(env: "SConsEnvironment"):
]
)
if env["accesskit"]:
if env["accesskit_sdk_path"] != "":
env.Prepend(CPPPATH=[env["accesskit_sdk_path"] + "/include"])
if env["use_llvm"]:
if env["arch"] == "arm64":
env.Append(LIBPATH=[env["accesskit_sdk_path"] + "/lib/windows/arm64/mingw-llvm/static/"])
elif env["arch"] == "x86_64":
env.Append(LIBPATH=[env["accesskit_sdk_path"] + "/lib/windows/x86_64/mingw-llvm/static/"])
elif env["arch"] == "x86_32":
env.Append(LIBPATH=[env["accesskit_sdk_path"] + "/lib/windows/x86/mingw-llvm/static/"])
else:
if env["arch"] == "x86_64":
env.Append(LIBPATH=[env["accesskit_sdk_path"] + "/lib/windows/x86_64/mingw/static/"])
elif env["arch"] == "x86_32":
env.Append(LIBPATH=[env["accesskit_sdk_path"] + "/lib/windows/x86/mingw/static/"])
env.Append(
LIBS=[
"accesskit",
"uiautomationcore." + env["arch"],
"runtimeobject",
"propsys",
"oleaut32",
"user32",
"userenv",
"ntdll",
]
)
else:
env.Append(CPPDEFINES=["ACCESSKIT_DYNAMIC"])
env.Append(LIBPATH=["#platform/windows"])
env.Append(CPPDEFINES=["ACCESSKIT_ENABLED"])
if env.debug_features:
env.Append(LIBS=["psapi", "dbghelp"])
@ -812,6 +915,9 @@ def configure_mingw(env: "SConsEnvironment"):
env.Append(CPPDEFINES=["MINGW_ENABLED", ("MINGW_HAS_SECURE_API", 1)])
# dlltool
env.Append(BUILDERS={"DEF": env.Builder(action=build_def_file, suffix=".a", src_suffix=".def")})
def configure(env: "SConsEnvironment"):
# Validate arch.

View File

@ -43,6 +43,8 @@
#include "main/main.h"
#include "scene/resources/texture.h"
#include "servers/rendering/dummy/rasterizer_dummy.h"
#if defined(VULKAN_ENABLED)
#include "rendering_context_driver_vulkan_windows.h"
#endif
@ -53,6 +55,10 @@
#include "drivers/gles3/rasterizer_gles3.h"
#endif
#if defined(ACCESSKIT_ENABLED)
#include "drivers/accesskit/accessibility_driver_accesskit.h"
#endif
#include <avrt.h>
#include <dwmapi.h>
#include <propkey.h>
@ -142,6 +148,11 @@ bool DisplayServerWindows::has_feature(Feature p_feature) const {
return true;
case FEATURE_EMOJI_AND_SYMBOL_PICKER:
return (os_ver.dwBuildNumber >= 17134); // Windows 10 Redstone 4 (1803)+ only.
#ifdef ACCESSKIT_ENABLED
case FEATURE_ACCESSIBILITY_SCREEN_READER: {
return (accessibility_driver != nullptr);
} break;
#endif
default:
return false;
}
@ -2735,6 +2746,46 @@ bool DisplayServerWindows::can_any_window_draw() const {
return false;
}
int DisplayServerWindows::accessibility_should_increase_contrast() const {
HIGHCONTRASTA hc;
hc.cbSize = sizeof(HIGHCONTRAST);
if (!SystemParametersInfoA(SPI_GETHIGHCONTRAST, sizeof(HIGHCONTRAST), &hc, 0)) {
return -1;
}
return (hc.dwFlags & HCF_HIGHCONTRASTON);
}
int DisplayServerWindows::accessibility_should_reduce_animation() const {
bool anim_enabled = false;
if (!SystemParametersInfoA(SPI_GETCLIENTAREAANIMATION, 0, &anim_enabled, 0)) {
return -1;
}
return (!anim_enabled);
}
int DisplayServerWindows::accessibility_should_reduce_transparency() const {
bool tr_enabled = false;
if (!SystemParametersInfoA(SPI_GETDISABLEOVERLAPPEDCONTENT, 0, &tr_enabled, 0)) {
return -1;
}
return tr_enabled;
}
int DisplayServerWindows::accessibility_screen_reader_active() const {
bool sr_enabled = false;
if (SystemParametersInfoA(SPI_GETSCREENREADER, 0, &sr_enabled, 0) && sr_enabled) {
return true;
}
static const WCHAR *narrator_mutex_name = L"NarratorRunning";
HANDLE narrator_mutex = OpenMutexW(MUTEX_ALL_ACCESS, false, narrator_mutex_name);
if (narrator_mutex) {
CloseHandle(narrator_mutex);
return true;
}
return false;
}
Vector2i DisplayServerWindows::ime_get_selection() const {
_THREAD_SAFE_METHOD_
@ -4522,6 +4573,16 @@ LRESULT DisplayServerWindows::_handle_early_window_message(HWND hWnd, UINT uMsg,
// Fix this up so we can recognize the remaining messages.
pWindowData->hWnd = hWnd;
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver && !accessibility_driver->window_create(pWindowData->id, (void *)hWnd)) {
if (OS::get_singleton()->is_stdout_verbose()) {
ERR_PRINT("Can't create an accessibility adapter for window, accessibility support disabled!");
}
memdelete(accessibility_driver);
accessibility_driver = nullptr;
}
#endif
} break;
default: {
// Additional messages during window creation should happen after we fixed
@ -4572,6 +4633,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
// Process window messages.
switch (uMsg) {
case WM_GETOBJECT: {
get_object_recieved = true;
} break;
case WM_MENUCOMMAND: {
native_menu->_menu_activate(HMENU(lParam), (int)wParam);
} break;
@ -5870,6 +5934,11 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
joypad->probe_joypads();
} break;
case WM_DESTROY: {
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver) {
accessibility_driver->window_destroy(window_id);
}
#endif
Input::get_singleton()->flush_buffered_events();
if (window_mouseover_id == window_id) {
window_mouseover_id = INVALID_WINDOW_ID;
@ -5923,6 +5992,11 @@ void DisplayServerWindows::_process_activate_event(WindowID p_window_id) {
SetFocus(wd.hWnd);
}
wd.window_focused = true;
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver) {
accessibility_driver->accessibility_set_window_focused(p_window_id, true);
}
#endif
_send_window_event(wd, WINDOW_EVENT_FOCUS_IN);
} else { // WM_INACTIVE.
Input::get_singleton()->release_pressed_events();
@ -5936,6 +6010,11 @@ void DisplayServerWindows::_process_activate_event(WindowID p_window_id) {
ReleaseCapture();
}
wd.window_focused = false;
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver) {
accessibility_driver->accessibility_set_window_focused(p_window_id, false);
}
#endif
_send_window_event(wd, WINDOW_EVENT_FOCUS_OUT);
}
@ -6223,6 +6302,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
WindowData &wd = windows[id];
wd.id = id;
wd.hWnd = CreateWindowExW(
dwExStyle,
L"Engine", L"",
@ -6649,6 +6729,19 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
}
native_menu = memnew(NativeMenuWindows);
#ifdef ACCESSKIT_ENABLED
if (accessibility_get_mode() != DisplayServer::AccessibilityMode::ACCESSIBILITY_DISABLED) {
accessibility_driver = memnew(AccessibilityDriverAccessKit);
if (accessibility_driver->init() != OK) {
if (OS::get_singleton()->is_stdout_verbose()) {
ERR_PRINT("Can't create an accessibility driver, accessibility support disabled!");
}
memdelete(accessibility_driver);
accessibility_driver = nullptr;
}
}
#endif
// Enforce default keep screen on value.
screen_set_keep_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on"));
@ -6829,6 +6922,11 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
_register_raw_input_devices(INVALID_WINDOW_ID);
// Init context and rendering device.
if (rendering_driver == "dummy") {
RasterizerDummy::make_current();
}
#if defined(RD_ENABLED)
[[maybe_unused]] bool fallback_to_vulkan = GLOBAL_GET("rendering/rendering_device/fallback_to_vulkan");
[[maybe_unused]] bool fallback_to_d3d12 = GLOBAL_GET("rendering/rendering_device/fallback_to_d3d12");
@ -6901,7 +6999,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
}
}
#endif
// Init context and rendering device
#if defined(GLES3_ENABLED)
bool fallback = GLOBAL_GET("rendering/gl_compatibility/fallback_to_angle");
@ -7076,6 +7174,24 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
windows[MAIN_WINDOW_ID].initialized = true;
if (accessibility_screen_reader_active()) {
_THREAD_SAFE_LOCK_
uint64_t time_wait = OS::get_singleton()->get_ticks_msec();
while (true) {
MSG msg = {};
while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
uint64_t delta = OS::get_singleton()->get_ticks_msec() - time_wait;
if (delta > 500 || get_object_recieved) {
break;
}
}
_THREAD_SAFE_UNLOCK_
}
#if defined(RD_ENABLED)
if (rendering_context) {
rendering_device = memnew(RenderingDevice);
@ -7133,6 +7249,7 @@ Vector<String> DisplayServerWindows::get_rendering_drivers_func() {
drivers.push_back("opengl3");
drivers.push_back("opengl3_angle");
#endif
drivers.push_back("dummy");
return drivers;
}
@ -7284,6 +7401,11 @@ DisplayServerWindows::~DisplayServerWindows() {
memdelete(gl_manager_native);
gl_manager_native = nullptr;
}
#endif
#ifdef ACCESSKIT_ENABLED
if (accessibility_driver) {
memdelete(accessibility_driver);
}
#endif
if (tts) {
memdelete(tts);

View File

@ -459,6 +459,7 @@ class DisplayServerWindows : public DisplayServer {
String rendering_driver;
bool app_focused = false;
bool keep_screen_on = false;
bool get_object_recieved = false;
HANDLE power_request;
TTS_Windows *tts = nullptr;
@ -466,6 +467,7 @@ class DisplayServerWindows : public DisplayServer {
struct WindowData {
HWND hWnd;
WindowID id;
Vector<Vector2> mpath;
@ -823,6 +825,11 @@ public:
virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID) override;
virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID) override;
virtual int accessibility_should_increase_contrast() const override;
virtual int accessibility_should_reduce_animation() const override;
virtual int accessibility_should_reduce_transparency() const override;
virtual int accessibility_screen_reader_active() const override;
virtual Point2i ime_get_selection() const override;
virtual String ime_get_text() const override;

View File

@ -244,6 +244,7 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset>
path = tmp_dir_path.path_join(p_path.get_file().get_basename() + ".exe");
}
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
int export_angle = p_preset->get("application/export_angle");
bool include_angle_libs = false;
if (export_angle == 0) {
@ -252,7 +253,6 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset>
include_angle_libs = true;
}
if (include_angle_libs) {
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (da->file_exists(template_path.get_base_dir().path_join("libEGL." + arch + ".dll"))) {
da->copy(template_path.get_base_dir().path_join("libEGL." + arch + ".dll"), path.get_base_dir().path_join("libEGL.dll"), get_chmod_flags());
}
@ -260,6 +260,9 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset>
da->copy(template_path.get_base_dir().path_join("libGLESv2." + arch + ".dll"), path.get_base_dir().path_join("libGLESv2.dll"), get_chmod_flags());
}
}
if (da->file_exists(template_path.get_base_dir().path_join("accesskit." + arch + ".dll"))) {
da->copy(template_path.get_base_dir().path_join("accesskit." + arch + ".dll"), path.get_base_dir().path_join("accesskit." + arch + ".dll"), get_chmod_flags());
}
int export_d3d12 = p_preset->get("application/export_d3d12");
bool agility_sdk_multiarch = p_preset->get("application/d3d12_agility_sdk_multiarch");
@ -270,7 +273,6 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset>
include_d3d12_extra_libs = true;
}
if (include_d3d12_extra_libs) {
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (da->file_exists(template_path.get_base_dir().path_join("D3D12Core." + arch + ".dll"))) {
if (agility_sdk_multiarch) {
da->make_dir_recursive(path.get_base_dir().path_join(arch));

View File

@ -0,0 +1,115 @@
;
; Definition file of UIAutomationCore.DLL
; Automatic generated by gendef
; written by Kai Tietz 2008
;
LIBRARY "UIAutomationCore.DLL"
EXPORTS
DllGetActivationFactory
DllCanUnloadNow
DllGetClassObject
DockPattern_SetDockPosition
ExpandCollapsePattern_Collapse
ExpandCollapsePattern_Expand
GridPattern_GetItem
IgnoreLeaksInCurrentlyTrackedMemory
InitializeChannelBasedConnectionForProviderProxy
InvokePattern_Invoke
IsIgnoringLeaks
ItemContainerPattern_FindItemByProperty
LegacyIAccessiblePattern_DoDefaultAction
LegacyIAccessiblePattern_GetIAccessible
LegacyIAccessiblePattern_Select
LegacyIAccessiblePattern_SetValue
MultipleViewPattern_GetViewName
MultipleViewPattern_SetCurrentView
PostTestCheckForLeaks
RangeValuePattern_SetValue
ScrollItemPattern_ScrollIntoView
ScrollPattern_Scroll
ScrollPattern_SetScrollPercent
SelectionItemPattern_AddToSelection
SelectionItemPattern_RemoveFromSelection
SelectionItemPattern_Select
StartIgnoringLeaks
StopIgnoringLeaks
SynchronizedInputPattern_Cancel
SynchronizedInputPattern_StartListening
TextPattern_GetSelection
TextPattern_GetVisibleRanges
TextPattern_RangeFromChild
TextPattern_RangeFromPoint
TextPattern_get_DocumentRange
TextPattern_get_SupportedTextSelection
TextRange_AddToSelection
TextRange_Clone
TextRange_Compare
TextRange_CompareEndpoints
TextRange_ExpandToEnclosingUnit
TextRange_FindAttribute
TextRange_FindText
TextRange_GetAttributeValue
TextRange_GetBoundingRectangles
TextRange_GetChildren
TextRange_GetEnclosingElement
TextRange_GetText
TextRange_Move
TextRange_MoveEndpointByRange
TextRange_MoveEndpointByUnit
TextRange_RemoveFromSelection
TextRange_ScrollIntoView
TextRange_Select
TogglePattern_Toggle
TransformPattern_Move
TransformPattern_Resize
TransformPattern_Rotate
UiaAddEvent
UiaClientsAreListening
UiaDisconnectAllProviders
UiaDisconnectProvider
UiaEventAddWindow
UiaEventRemoveWindow
UiaFind
UiaGetErrorDescription
UiaGetPatternProvider
UiaGetPropertyValue
UiaGetReservedMixedAttributeValue
UiaGetReservedNotSupportedValue
UiaGetRootNode
UiaGetRuntimeId
UiaGetUpdatedCache
UiaHPatternObjectFromVariant
UiaHTextRangeFromVariant
UiaHUiaNodeFromVariant
UiaHasServerSideProvider
UiaHostProviderFromHwnd
UiaIAccessibleFromProvider
UiaLookupId
UiaNavigate
UiaNodeFromFocus
UiaNodeFromHandle
UiaNodeFromPoint
UiaNodeFromProvider
UiaNodeRelease
UiaPatternRelease
UiaProviderForNonClient
UiaProviderFromIAccessible
UiaRaiseActiveTextPositionChangedEvent
UiaRaiseAsyncContentLoadedEvent
UiaRaiseAutomationEvent
UiaRaiseAutomationPropertyChangedEvent
UiaRaiseChangesEvent
UiaRaiseNotificationEvent
UiaRaiseStructureChangedEvent
UiaRaiseTextEditTextChangedEvent
UiaRegisterProviderCallback
UiaRemoveEvent
UiaReturnRawElementProvider
UiaSetFocus
UiaTextRangeRelease
UpdateErrorLoggingCallback
ValuePattern_SetValue
VirtualizedItemPattern_Realize
WindowPattern_Close
WindowPattern_SetWindowVisualState
WindowPattern_WaitForInputIdle

View File

@ -0,0 +1,115 @@
;
; Definition file of UIAutomationCore.DLL
; Automatic generated by gendef
; written by Kai Tietz 2008
;
LIBRARY "UIAutomationCore.DLL"
EXPORTS
DllGetActivationFactory
DllCanUnloadNow
DllGetClassObject
DockPattern_SetDockPosition
ExpandCollapsePattern_Collapse
ExpandCollapsePattern_Expand
GridPattern_GetItem
IgnoreLeaksInCurrentlyTrackedMemory
InitializeChannelBasedConnectionForProviderProxy
InvokePattern_Invoke
IsIgnoringLeaks
ItemContainerPattern_FindItemByProperty
LegacyIAccessiblePattern_DoDefaultAction
LegacyIAccessiblePattern_GetIAccessible
LegacyIAccessiblePattern_Select
LegacyIAccessiblePattern_SetValue
MultipleViewPattern_GetViewName
MultipleViewPattern_SetCurrentView
PostTestCheckForLeaks
RangeValuePattern_SetValue
ScrollItemPattern_ScrollIntoView
ScrollPattern_Scroll
ScrollPattern_SetScrollPercent
SelectionItemPattern_AddToSelection
SelectionItemPattern_RemoveFromSelection
SelectionItemPattern_Select
StartIgnoringLeaks
StopIgnoringLeaks
SynchronizedInputPattern_Cancel
SynchronizedInputPattern_StartListening
TextPattern_GetSelection
TextPattern_GetVisibleRanges
TextPattern_RangeFromChild
TextPattern_RangeFromPoint
TextPattern_get_DocumentRange
TextPattern_get_SupportedTextSelection
TextRange_AddToSelection
TextRange_Clone
TextRange_Compare
TextRange_CompareEndpoints
TextRange_ExpandToEnclosingUnit
TextRange_FindAttribute
TextRange_FindText
TextRange_GetAttributeValue
TextRange_GetBoundingRectangles
TextRange_GetChildren
TextRange_GetEnclosingElement
TextRange_GetText
TextRange_Move
TextRange_MoveEndpointByRange
TextRange_MoveEndpointByUnit
TextRange_RemoveFromSelection
TextRange_ScrollIntoView
TextRange_Select
TogglePattern_Toggle
TransformPattern_Move
TransformPattern_Resize
TransformPattern_Rotate
UiaAddEvent
UiaClientsAreListening
UiaDisconnectAllProviders
UiaDisconnectProvider
UiaEventAddWindow
UiaEventRemoveWindow
UiaFind
UiaGetErrorDescription
UiaGetPatternProvider
UiaGetPropertyValue
UiaGetReservedMixedAttributeValue
UiaGetReservedNotSupportedValue
UiaGetRootNode
UiaGetRuntimeId
UiaGetUpdatedCache
UiaHPatternObjectFromVariant
UiaHTextRangeFromVariant
UiaHUiaNodeFromVariant
UiaHasServerSideProvider
UiaHostProviderFromHwnd
UiaIAccessibleFromProvider
UiaLookupId
UiaNavigate
UiaNodeFromFocus
UiaNodeFromHandle
UiaNodeFromPoint
UiaNodeFromProvider
UiaNodeRelease
UiaPatternRelease
UiaProviderForNonClient
UiaProviderFromIAccessible
UiaRaiseActiveTextPositionChangedEvent
UiaRaiseAsyncContentLoadedEvent
UiaRaiseAutomationEvent
UiaRaiseAutomationPropertyChangedEvent
UiaRaiseChangesEvent
UiaRaiseNotificationEvent
UiaRaiseStructureChangedEvent
UiaRaiseTextEditTextChangedEvent
UiaRegisterProviderCallback
UiaRemoveEvent
UiaReturnRawElementProvider
UiaSetFocus
UiaTextRangeRelease
UpdateErrorLoggingCallback
ValuePattern_SetValue
VirtualizedItemPattern_Realize
WindowPattern_Close
WindowPattern_SetWindowVisualState
WindowPattern_WaitForInputIdle

View File

@ -0,0 +1,115 @@
;
; Definition file of UIAutomationCore.DLL
; Automatic generated by gendef
; written by Kai Tietz 2008
;
LIBRARY "UIAutomationCore.DLL"
EXPORTS
DllGetActivationFactory@8
DllCanUnloadNow
DllGetClassObject@12
DockPattern_SetDockPosition@8
ExpandCollapsePattern_Collapse@4
ExpandCollapsePattern_Expand@4
GridPattern_GetItem@16
IgnoreLeaksInCurrentlyTrackedMemory
InitializeChannelBasedConnectionForProviderProxy@12
InvokePattern_Invoke@4
IsIgnoringLeaks
ItemContainerPattern_FindItemByProperty@32
LegacyIAccessiblePattern_DoDefaultAction@4
LegacyIAccessiblePattern_GetIAccessible@8
LegacyIAccessiblePattern_Select@8
LegacyIAccessiblePattern_SetValue@8
MultipleViewPattern_GetViewName@12
MultipleViewPattern_SetCurrentView@8
PostTestCheckForLeaks@8
RangeValuePattern_SetValue@12
ScrollItemPattern_ScrollIntoView@4
ScrollPattern_Scroll@12
ScrollPattern_SetScrollPercent@20
SelectionItemPattern_AddToSelection@4
SelectionItemPattern_RemoveFromSelection@4
SelectionItemPattern_Select@4
StartIgnoringLeaks@4
StopIgnoringLeaks
SynchronizedInputPattern_Cancel@4
SynchronizedInputPattern_StartListening@8
TextPattern_GetSelection@8
TextPattern_GetVisibleRanges@8
TextPattern_RangeFromChild@12
TextPattern_RangeFromPoint@24
TextPattern_get_DocumentRange@8
TextPattern_get_SupportedTextSelection@8
TextRange_AddToSelection@4
TextRange_Clone@8
TextRange_Compare@12
TextRange_CompareEndpoints@20
TextRange_ExpandToEnclosingUnit@8
TextRange_FindAttribute@32
TextRange_FindText@20
TextRange_GetAttributeValue@12
TextRange_GetBoundingRectangles@8
TextRange_GetChildren@8
TextRange_GetEnclosingElement@8
TextRange_GetText@12
TextRange_Move@16
TextRange_MoveEndpointByRange@16
TextRange_MoveEndpointByUnit@20
TextRange_RemoveFromSelection@4
TextRange_ScrollIntoView@8
TextRange_Select@4
TogglePattern_Toggle@4
TransformPattern_Move@20
TransformPattern_Resize@20
TransformPattern_Rotate@12
UiaAddEvent@32
UiaClientsAreListening
UiaDisconnectAllProviders
UiaDisconnectProvider@4
UiaEventAddWindow@8
UiaEventRemoveWindow@8
UiaFind@24
UiaGetErrorDescription@4
UiaGetPatternProvider@12
UiaGetPropertyValue@12
UiaGetReservedMixedAttributeValue@4
UiaGetReservedNotSupportedValue@4
UiaGetRootNode@4
UiaGetRuntimeId@8
UiaGetUpdatedCache@24
UiaHPatternObjectFromVariant@8
UiaHTextRangeFromVariant@8
UiaHUiaNodeFromVariant@8
UiaHasServerSideProvider@4
UiaHostProviderFromHwnd@8
UiaIAccessibleFromProvider@16
UiaLookupId@8
UiaNavigate@24
UiaNodeFromFocus@12
UiaNodeFromHandle@8
UiaNodeFromPoint@28
UiaNodeFromProvider@8
UiaNodeRelease@4
UiaPatternRelease@4
UiaProviderForNonClient@16
UiaProviderFromIAccessible@16
UiaRaiseActiveTextPositionChangedEvent@8
UiaRaiseAsyncContentLoadedEvent@16
UiaRaiseAutomationEvent@8
UiaRaiseAutomationPropertyChangedEvent@40
UiaRaiseChangesEvent@12
UiaRaiseNotificationEvent@20
UiaRaiseStructureChangedEvent@16
UiaRaiseTextEditTextChangedEvent@12
UiaRegisterProviderCallback@4
UiaRemoveEvent@4
UiaReturnRawElementProvider@16
UiaSetFocus@4
UiaTextRangeRelease@4
UpdateErrorLoggingCallback@4
ValuePattern_SetValue@8
VirtualizedItemPattern_Realize@4
WindowPattern_Close@4
WindowPattern_SetWindowVisualState@8
WindowPattern_WaitForInputIdle@12

View File

@ -0,0 +1,115 @@
;
; Definition file of UIAutomationCore.DLL
; Automatic generated by gendef
; written by Kai Tietz 2008
;
LIBRARY "UIAutomationCore.DLL"
EXPORTS
DllGetActivationFactory
DllCanUnloadNow
DllGetClassObject
DockPattern_SetDockPosition
ExpandCollapsePattern_Collapse
ExpandCollapsePattern_Expand
GridPattern_GetItem
IgnoreLeaksInCurrentlyTrackedMemory
InitializeChannelBasedConnectionForProviderProxy
InvokePattern_Invoke
IsIgnoringLeaks
ItemContainerPattern_FindItemByProperty
LegacyIAccessiblePattern_DoDefaultAction
LegacyIAccessiblePattern_GetIAccessible
LegacyIAccessiblePattern_Select
LegacyIAccessiblePattern_SetValue
MultipleViewPattern_GetViewName
MultipleViewPattern_SetCurrentView
PostTestCheckForLeaks
RangeValuePattern_SetValue
ScrollItemPattern_ScrollIntoView
ScrollPattern_Scroll
ScrollPattern_SetScrollPercent
SelectionItemPattern_AddToSelection
SelectionItemPattern_RemoveFromSelection
SelectionItemPattern_Select
StartIgnoringLeaks
StopIgnoringLeaks
SynchronizedInputPattern_Cancel
SynchronizedInputPattern_StartListening
TextPattern_GetSelection
TextPattern_GetVisibleRanges
TextPattern_RangeFromChild
TextPattern_RangeFromPoint
TextPattern_get_DocumentRange
TextPattern_get_SupportedTextSelection
TextRange_AddToSelection
TextRange_Clone
TextRange_Compare
TextRange_CompareEndpoints
TextRange_ExpandToEnclosingUnit
TextRange_FindAttribute
TextRange_FindText
TextRange_GetAttributeValue
TextRange_GetBoundingRectangles
TextRange_GetChildren
TextRange_GetEnclosingElement
TextRange_GetText
TextRange_Move
TextRange_MoveEndpointByRange
TextRange_MoveEndpointByUnit
TextRange_RemoveFromSelection
TextRange_ScrollIntoView
TextRange_Select
TogglePattern_Toggle
TransformPattern_Move
TransformPattern_Resize
TransformPattern_Rotate
UiaAddEvent
UiaClientsAreListening
UiaDisconnectAllProviders
UiaDisconnectProvider
UiaEventAddWindow
UiaEventRemoveWindow
UiaFind
UiaGetErrorDescription
UiaGetPatternProvider
UiaGetPropertyValue
UiaGetReservedMixedAttributeValue
UiaGetReservedNotSupportedValue
UiaGetRootNode
UiaGetRuntimeId
UiaGetUpdatedCache
UiaHPatternObjectFromVariant
UiaHTextRangeFromVariant
UiaHUiaNodeFromVariant
UiaHasServerSideProvider
UiaHostProviderFromHwnd
UiaIAccessibleFromProvider
UiaLookupId
UiaNavigate
UiaNodeFromFocus
UiaNodeFromHandle
UiaNodeFromPoint
UiaNodeFromProvider
UiaNodeRelease
UiaPatternRelease
UiaProviderForNonClient
UiaProviderFromIAccessible
UiaRaiseActiveTextPositionChangedEvent
UiaRaiseAsyncContentLoadedEvent
UiaRaiseAutomationEvent
UiaRaiseAutomationPropertyChangedEvent
UiaRaiseChangesEvent
UiaRaiseNotificationEvent
UiaRaiseStructureChangedEvent
UiaRaiseTextEditTextChangedEvent
UiaRegisterProviderCallback
UiaRemoveEvent
UiaReturnRawElementProvider
UiaSetFocus
UiaTextRangeRelease
UpdateErrorLoggingCallback
ValuePattern_SetValue
VirtualizedItemPattern_Realize
WindowPattern_Close
WindowPattern_SetWindowVisualState
WindowPattern_WaitForInputIdle

12
thirdparty/README.md vendored
View File

@ -5,6 +5,18 @@ respective folder names. Use two empty lines to separate categories for
readability.
## accesskit
- Upstream: https://github.com/AccessKit/accesskit-c
- Version: 0.15.1 (0d1da94a33708041b07c61eb702c67cfa3a5f95b, 2025)
- License: MIT
Files extracted from upstream source:
- `accesskit.h`
- `LICENSE-MIT`
## amd-fsr
- Upstream: https://github.com/GPUOpen-Effects/FidelityFX-FSR

23
thirdparty/accesskit/LICENSE-MIT vendored Normal file
View File

@ -0,0 +1,23 @@
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

2352
thirdparty/accesskit/include/accesskit.h vendored Normal file

File diff suppressed because it is too large Load Diff