feat: updated engine version to 4.4-rc1
This commit is contained in:
parent
ee00efde1f
commit
21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
@ -10,16 +11,16 @@ if env["use_sowrap"]:
|
|||
|
||||
WAYLAND_BUILDERS_SOWRAP = {
|
||||
"WAYLAND_API_HEADER": Builder(
|
||||
action=Action(
|
||||
r"wayland-scanner -c client-header < ${SOURCE} | sed 's:wayland-client-core\.h:../dynwrappers/wayland-client-core-so_wrap\.h:' > ${TARGET}",
|
||||
'Generating Wayland client header: "${TARGET}"',
|
||||
action=env.Run(
|
||||
r"wayland-scanner -c client-header < ${SOURCE} | "
|
||||
r"sed 's:wayland-client-core\.h:../dynwrappers/wayland-client-core-so_wrap\.h:' > ${TARGET}",
|
||||
),
|
||||
single_source=True,
|
||||
),
|
||||
"WAYLAND_API_CODE": Builder(
|
||||
action=Action(
|
||||
r"wayland-scanner -c private-code < ${SOURCE} | sed 's:wayland-util\.h:../dynwrappers/wayland-client-core-so_wrap\.h:' > ${TARGET}",
|
||||
'Generating Wayland protocol marshaling code: "${TARGET}"',
|
||||
action=env.Run(
|
||||
r"wayland-scanner -c private-code < ${SOURCE} | "
|
||||
r"sed 's:wayland-util\.h:../dynwrappers/wayland-client-core-so_wrap\.h:' > ${TARGET}",
|
||||
),
|
||||
single_source=True,
|
||||
),
|
||||
|
|
@ -28,155 +29,140 @@ if env["use_sowrap"]:
|
|||
else:
|
||||
WAYLAND_BUILDERS = {
|
||||
"WAYLAND_API_HEADER": Builder(
|
||||
action=Action(
|
||||
r"wayland-scanner -c client-header < ${SOURCE} > ${TARGET}",
|
||||
'Generating Wayland client header: "${TARGET}"',
|
||||
),
|
||||
action=env.Run(r"wayland-scanner -c client-header < ${SOURCE} > ${TARGET}"),
|
||||
single_source=True,
|
||||
),
|
||||
"WAYLAND_API_CODE": Builder(
|
||||
action=Action(
|
||||
r"wayland-scanner -c private-code < ${SOURCE} > ${TARGET}",
|
||||
'Generating Wayland protocol marshaling code: "${TARGET}"',
|
||||
),
|
||||
action=env.Run(r"wayland-scanner -c private-code < ${SOURCE} > ${TARGET}"),
|
||||
single_source=True,
|
||||
),
|
||||
}
|
||||
env.Append(BUILDERS=WAYLAND_BUILDERS)
|
||||
|
||||
env.WAYLAND_API_HEADER(target="protocol/wayland.gen.h", source="#thirdparty/wayland/protocol/wayland.xml")
|
||||
env.WAYLAND_API_CODE(target="protocol/wayland.gen.c", source="#thirdparty/wayland/protocol/wayland.xml")
|
||||
|
||||
env.WAYLAND_API_HEADER(
|
||||
target="protocol/viewporter.gen.h", source="#thirdparty/wayland-protocols/stable/viewporter/viewporter.xml"
|
||||
)
|
||||
env.WAYLAND_API_CODE(
|
||||
target="protocol/viewporter.gen.c", source="#thirdparty/wayland-protocols/stable/viewporter/viewporter.xml"
|
||||
env.NoCache(
|
||||
env.WAYLAND_API_HEADER("protocol/wayland.gen.h", "#thirdparty/wayland/protocol/wayland.xml"),
|
||||
env.WAYLAND_API_CODE("protocol/wayland.gen.c", "#thirdparty/wayland/protocol/wayland.xml"),
|
||||
env.WAYLAND_API_HEADER(
|
||||
"protocol/viewporter.gen.h", "#thirdparty/wayland-protocols/stable/viewporter/viewporter.xml"
|
||||
),
|
||||
env.WAYLAND_API_CODE("protocol/viewporter.gen.c", "#thirdparty/wayland-protocols/stable/viewporter/viewporter.xml"),
|
||||
env.WAYLAND_API_HEADER(
|
||||
"protocol/fractional_scale.gen.h",
|
||||
"#thirdparty/wayland-protocols/staging/fractional-scale/fractional-scale-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_CODE(
|
||||
"protocol/fractional_scale.gen.c",
|
||||
"#thirdparty/wayland-protocols/staging/fractional-scale/fractional-scale-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_HEADER("protocol/xdg_shell.gen.h", "#thirdparty/wayland-protocols/stable/xdg-shell/xdg-shell.xml"),
|
||||
env.WAYLAND_API_CODE("protocol/xdg_shell.gen.c", "#thirdparty/wayland-protocols/stable/xdg-shell/xdg-shell.xml"),
|
||||
env.WAYLAND_API_HEADER(
|
||||
"protocol/xdg_decoration.gen.h",
|
||||
"#thirdparty/wayland-protocols/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_CODE(
|
||||
"protocol/xdg_decoration.gen.c",
|
||||
"#thirdparty/wayland-protocols/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_HEADER(
|
||||
"protocol/xdg_activation.gen.h",
|
||||
"#thirdparty/wayland-protocols/staging/xdg-activation/xdg-activation-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_CODE(
|
||||
"protocol/xdg_activation.gen.c",
|
||||
"#thirdparty/wayland-protocols/staging/xdg-activation/xdg-activation-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_HEADER(
|
||||
"protocol/relative_pointer.gen.h",
|
||||
"#thirdparty/wayland-protocols/unstable/relative-pointer/relative-pointer-unstable-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_CODE(
|
||||
"protocol/relative_pointer.gen.c",
|
||||
"#thirdparty/wayland-protocols/unstable/relative-pointer/relative-pointer-unstable-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_HEADER(
|
||||
"protocol/pointer_constraints.gen.h",
|
||||
"#thirdparty/wayland-protocols/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_CODE(
|
||||
"protocol/pointer_constraints.gen.c",
|
||||
"#thirdparty/wayland-protocols/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_HEADER(
|
||||
"protocol/pointer_gestures.gen.h",
|
||||
"#thirdparty/wayland-protocols/unstable/pointer-gestures/pointer-gestures-unstable-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_CODE(
|
||||
"protocol/pointer_gestures.gen.c",
|
||||
"#thirdparty/wayland-protocols/unstable/pointer-gestures/pointer-gestures-unstable-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_HEADER(
|
||||
"protocol/primary_selection.gen.h",
|
||||
"#thirdparty/wayland-protocols/unstable/primary-selection/primary-selection-unstable-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_CODE(
|
||||
"protocol/primary_selection.gen.c",
|
||||
"#thirdparty/wayland-protocols/unstable/primary-selection/primary-selection-unstable-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_HEADER(
|
||||
"protocol/idle_inhibit.gen.h",
|
||||
"#thirdparty/wayland-protocols/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_CODE(
|
||||
"protocol/idle_inhibit.gen.c",
|
||||
"#thirdparty/wayland-protocols/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_HEADER(
|
||||
"protocol/tablet.gen.h",
|
||||
"#thirdparty/wayland-protocols/unstable/tablet/tablet-unstable-v2.xml",
|
||||
),
|
||||
env.WAYLAND_API_CODE(
|
||||
"protocol/tablet.gen.c",
|
||||
"#thirdparty/wayland-protocols/unstable/tablet/tablet-unstable-v2.xml",
|
||||
),
|
||||
env.WAYLAND_API_HEADER(
|
||||
"protocol/text_input.gen.h",
|
||||
"#thirdparty/wayland-protocols/unstable/text-input/text-input-unstable-v3.xml",
|
||||
),
|
||||
env.WAYLAND_API_CODE(
|
||||
"protocol/text_input.gen.c",
|
||||
"#thirdparty/wayland-protocols/unstable/text-input/text-input-unstable-v3.xml",
|
||||
),
|
||||
env.WAYLAND_API_HEADER(
|
||||
"protocol/xdg_foreign_v1.gen.h",
|
||||
"#thirdparty/wayland-protocols/unstable/xdg-foreign/xdg-foreign-unstable-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_CODE(
|
||||
"protocol/xdg_foreign_v1.gen.c",
|
||||
"#thirdparty/wayland-protocols/unstable/xdg-foreign/xdg-foreign-unstable-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_HEADER(
|
||||
"protocol/xdg_foreign_v2.gen.h",
|
||||
"#thirdparty/wayland-protocols/unstable/xdg-foreign/xdg-foreign-unstable-v2.xml",
|
||||
),
|
||||
env.WAYLAND_API_CODE(
|
||||
"protocol/xdg_foreign_v2.gen.c",
|
||||
"#thirdparty/wayland-protocols/unstable/xdg-foreign/xdg-foreign-unstable-v2.xml",
|
||||
),
|
||||
env.WAYLAND_API_HEADER(
|
||||
"protocol/xdg_system_bell.gen.h",
|
||||
"#thirdparty/wayland-protocols/staging/xdg-system-bell/xdg-system-bell-v1.xml",
|
||||
),
|
||||
env.WAYLAND_API_CODE(
|
||||
"protocol/xdg_system_bell.gen.c",
|
||||
"#thirdparty/wayland-protocols/staging/xdg-system-bell/xdg-system-bell-v1.xml",
|
||||
),
|
||||
)
|
||||
|
||||
env.WAYLAND_API_HEADER(
|
||||
target="protocol/fractional_scale.gen.h",
|
||||
source="#thirdparty/wayland-protocols/staging/fractional-scale/fractional-scale-v1.xml",
|
||||
)
|
||||
env.WAYLAND_API_CODE(
|
||||
target="protocol/fractional_scale.gen.c",
|
||||
source="#thirdparty/wayland-protocols/staging/fractional-scale/fractional-scale-v1.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_HEADER(
|
||||
target="protocol/xdg_shell.gen.h", source="#thirdparty/wayland-protocols/stable/xdg-shell/xdg-shell.xml"
|
||||
)
|
||||
|
||||
env.WAYLAND_API_CODE(
|
||||
target="protocol/xdg_shell.gen.c", source="#thirdparty/wayland-protocols/stable/xdg-shell/xdg-shell.xml"
|
||||
)
|
||||
|
||||
env.WAYLAND_API_HEADER(
|
||||
target="protocol/xdg_decoration.gen.h",
|
||||
source="#thirdparty/wayland-protocols/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_CODE(
|
||||
target="protocol/xdg_decoration.gen.c",
|
||||
source="#thirdparty/wayland-protocols/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_HEADER(
|
||||
target="protocol/xdg_activation.gen.h",
|
||||
source="#thirdparty/wayland-protocols/staging/xdg-activation/xdg-activation-v1.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_CODE(
|
||||
target="protocol/xdg_activation.gen.c",
|
||||
source="#thirdparty/wayland-protocols/staging/xdg-activation/xdg-activation-v1.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_HEADER(
|
||||
target="protocol/relative_pointer.gen.h",
|
||||
source="#thirdparty/wayland-protocols/unstable/relative-pointer/relative-pointer-unstable-v1.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_CODE(
|
||||
target="protocol/relative_pointer.gen.c",
|
||||
source="#thirdparty/wayland-protocols/unstable/relative-pointer/relative-pointer-unstable-v1.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_HEADER(
|
||||
target="protocol/pointer_constraints.gen.h",
|
||||
source="#thirdparty/wayland-protocols/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_CODE(
|
||||
target="protocol/pointer_constraints.gen.c",
|
||||
source="#thirdparty/wayland-protocols/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_HEADER(
|
||||
target="protocol/pointer_gestures.gen.h",
|
||||
source="#thirdparty/wayland-protocols/unstable/pointer-gestures/pointer-gestures-unstable-v1.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_CODE(
|
||||
target="protocol/pointer_gestures.gen.c",
|
||||
source="#thirdparty/wayland-protocols/unstable/pointer-gestures/pointer-gestures-unstable-v1.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_HEADER(
|
||||
target="protocol/primary_selection.gen.h",
|
||||
source="#thirdparty/wayland-protocols/unstable/primary-selection/primary-selection-unstable-v1.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_CODE(
|
||||
target="protocol/primary_selection.gen.c",
|
||||
source="#thirdparty/wayland-protocols/unstable/primary-selection/primary-selection-unstable-v1.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_HEADER(
|
||||
target="protocol/idle_inhibit.gen.h",
|
||||
source="#thirdparty/wayland-protocols/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_CODE(
|
||||
target="protocol/idle_inhibit.gen.c",
|
||||
source="#thirdparty/wayland-protocols/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_HEADER(
|
||||
target="protocol/tablet.gen.h",
|
||||
source="#thirdparty/wayland-protocols/unstable/tablet/tablet-unstable-v2.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_CODE(
|
||||
target="protocol/tablet.gen.c",
|
||||
source="#thirdparty/wayland-protocols/unstable/tablet/tablet-unstable-v2.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_HEADER(
|
||||
target="protocol/text_input.gen.h",
|
||||
source="#thirdparty/wayland-protocols/unstable/text-input/text-input-unstable-v3.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_CODE(
|
||||
target="protocol/text_input.gen.c",
|
||||
source="#thirdparty/wayland-protocols/unstable/text-input/text-input-unstable-v3.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_HEADER(
|
||||
target="protocol/xdg_foreign.gen.h",
|
||||
source="#thirdparty/wayland-protocols/unstable/xdg-foreign/xdg-foreign-unstable-v1.xml",
|
||||
)
|
||||
|
||||
env.WAYLAND_API_CODE(
|
||||
target="protocol/xdg_foreign.gen.c",
|
||||
source="#thirdparty/wayland-protocols/unstable/xdg-foreign/xdg-foreign-unstable-v1.xml",
|
||||
)
|
||||
|
||||
source_files = [
|
||||
"protocol/wayland.gen.c",
|
||||
"protocol/viewporter.gen.c",
|
||||
"protocol/fractional_scale.gen.c",
|
||||
"protocol/xdg_shell.gen.c",
|
||||
"protocol/xdg_foreign.gen.c",
|
||||
"protocol/xdg_system_bell.gen.c",
|
||||
"protocol/xdg_foreign_v1.gen.c",
|
||||
"protocol/xdg_foreign_v2.gen.c",
|
||||
"protocol/xdg_decoration.gen.c",
|
||||
"protocol/xdg_activation.gen.c",
|
||||
"protocol/relative_pointer.gen.c",
|
||||
|
|
|
|||
|
|
@ -209,6 +209,7 @@ bool DisplayServerWayland::has_feature(Feature p_feature) const {
|
|||
case FEATURE_SWAP_BUFFERS:
|
||||
case FEATURE_KEEP_SCREEN_ON:
|
||||
case FEATURE_IME:
|
||||
case FEATURE_WINDOW_DRAG:
|
||||
case FEATURE_CLIPBOARD_PRIMARY: {
|
||||
return true;
|
||||
} break;
|
||||
|
|
@ -216,8 +217,10 @@ bool DisplayServerWayland::has_feature(Feature p_feature) const {
|
|||
//case FEATURE_NATIVE_DIALOG:
|
||||
//case FEATURE_NATIVE_DIALOG_INPUT:
|
||||
#ifdef DBUS_ENABLED
|
||||
case FEATURE_NATIVE_DIALOG_FILE: {
|
||||
return true;
|
||||
case FEATURE_NATIVE_DIALOG_FILE:
|
||||
case FEATURE_NATIVE_DIALOG_FILE_EXTRA:
|
||||
case FEATURE_NATIVE_DIALOG_FILE_MIME: {
|
||||
return (portal_desktop && portal_desktop->is_supported() && portal_desktop->is_file_chooser_supported());
|
||||
} break;
|
||||
#endif
|
||||
|
||||
|
|
@ -279,10 +282,13 @@ void DisplayServerWayland::tts_stop() {
|
|||
#ifdef DBUS_ENABLED
|
||||
|
||||
bool DisplayServerWayland::is_dark_mode_supported() const {
|
||||
return portal_desktop->is_supported();
|
||||
return portal_desktop && portal_desktop->is_supported() && portal_desktop->is_settings_supported();
|
||||
}
|
||||
|
||||
bool DisplayServerWayland::is_dark_mode() const {
|
||||
if (!is_dark_mode_supported()) {
|
||||
return false;
|
||||
}
|
||||
switch (portal_desktop->get_appearance_color_scheme()) {
|
||||
case 1:
|
||||
// Prefers dark theme.
|
||||
|
|
@ -318,28 +324,28 @@ Error DisplayServerWayland::file_dialog_with_options_show(const String &p_title,
|
|||
|
||||
#endif
|
||||
|
||||
void DisplayServerWayland::mouse_set_mode(MouseMode p_mode) {
|
||||
if (p_mode == mouse_mode) {
|
||||
void DisplayServerWayland::beep() const {
|
||||
wayland_thread.beep();
|
||||
}
|
||||
|
||||
void DisplayServerWayland::_mouse_update_mode() {
|
||||
MouseMode wanted_mouse_mode = mouse_mode_override_enabled
|
||||
? mouse_mode_override
|
||||
: mouse_mode_base;
|
||||
|
||||
if (wanted_mouse_mode == mouse_mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutexLock mutex_lock(wayland_thread.mutex);
|
||||
|
||||
bool show_cursor = (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED);
|
||||
bool show_cursor = (wanted_mouse_mode == MOUSE_MODE_VISIBLE || wanted_mouse_mode == MOUSE_MODE_CONFINED);
|
||||
|
||||
if (show_cursor) {
|
||||
if (custom_cursors.has(cursor_shape)) {
|
||||
wayland_thread.cursor_set_custom_shape(cursor_shape);
|
||||
} else {
|
||||
wayland_thread.cursor_set_shape(cursor_shape);
|
||||
}
|
||||
} else {
|
||||
wayland_thread.cursor_hide();
|
||||
}
|
||||
wayland_thread.cursor_set_visible(show_cursor);
|
||||
|
||||
WaylandThread::PointerConstraint constraint = WaylandThread::PointerConstraint::NONE;
|
||||
|
||||
switch (p_mode) {
|
||||
switch (wanted_mouse_mode) {
|
||||
case DisplayServer::MOUSE_MODE_CAPTURED: {
|
||||
constraint = WaylandThread::PointerConstraint::LOCKED;
|
||||
} break;
|
||||
|
|
@ -355,13 +361,47 @@ void DisplayServerWayland::mouse_set_mode(MouseMode p_mode) {
|
|||
|
||||
wayland_thread.pointer_set_constraint(constraint);
|
||||
|
||||
mouse_mode = p_mode;
|
||||
mouse_mode = wanted_mouse_mode;
|
||||
}
|
||||
|
||||
void DisplayServerWayland::mouse_set_mode(MouseMode p_mode) {
|
||||
ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX);
|
||||
if (p_mode == mouse_mode_base) {
|
||||
return;
|
||||
}
|
||||
mouse_mode_base = p_mode;
|
||||
_mouse_update_mode();
|
||||
}
|
||||
|
||||
DisplayServerWayland::MouseMode DisplayServerWayland::mouse_get_mode() const {
|
||||
return mouse_mode;
|
||||
}
|
||||
|
||||
void DisplayServerWayland::mouse_set_mode_override(MouseMode p_mode) {
|
||||
ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX);
|
||||
if (p_mode == mouse_mode_override) {
|
||||
return;
|
||||
}
|
||||
mouse_mode_override = p_mode;
|
||||
_mouse_update_mode();
|
||||
}
|
||||
|
||||
DisplayServerWayland::MouseMode DisplayServerWayland::mouse_get_mode_override() const {
|
||||
return mouse_mode_override;
|
||||
}
|
||||
|
||||
void DisplayServerWayland::mouse_set_mode_override_enabled(bool p_override_enabled) {
|
||||
if (p_override_enabled == mouse_mode_override_enabled) {
|
||||
return;
|
||||
}
|
||||
mouse_mode_override_enabled = p_override_enabled;
|
||||
_mouse_update_mode();
|
||||
}
|
||||
|
||||
bool DisplayServerWayland::mouse_is_mode_override_enabled() const {
|
||||
return mouse_mode_override_enabled;
|
||||
}
|
||||
|
||||
// NOTE: This is hacked together (and not guaranteed to work in the first place)
|
||||
// as for some reason the there's no proper way to ask the compositor to warp
|
||||
// the pointer, although, at the time of writing, there's a proposal for a
|
||||
|
|
@ -480,7 +520,7 @@ String DisplayServerWayland::clipboard_get_primary() const {
|
|||
for (String mime : text_mimes) {
|
||||
if (wayland_thread.primary_has_mime(mime)) {
|
||||
print_verbose(vformat("Selecting media type \"%s\" from offered types.", mime));
|
||||
wayland_thread.primary_get_mime(mime);
|
||||
data = wayland_thread.primary_get_mime(mime);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -635,6 +675,18 @@ int64_t DisplayServerWayland::window_get_native_handle(HandleType p_handle_type,
|
|||
}
|
||||
return 0;
|
||||
} break;
|
||||
case EGL_DISPLAY: {
|
||||
if (egl_manager) {
|
||||
return (int64_t)egl_manager->get_display(p_window);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case EGL_CONFIG: {
|
||||
if (egl_manager) {
|
||||
return (int64_t)egl_manager->get_config(p_window);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif // GLES3_ENABLED
|
||||
|
||||
default: {
|
||||
|
|
@ -896,11 +948,11 @@ bool DisplayServerWayland::window_is_focused(WindowID p_window_id) const {
|
|||
}
|
||||
|
||||
bool DisplayServerWayland::window_can_draw(DisplayServer::WindowID p_window_id) const {
|
||||
return !suspended;
|
||||
return suspend_state == SuspendState::NONE;
|
||||
}
|
||||
|
||||
bool DisplayServerWayland::can_any_window_draw() const {
|
||||
return !suspended;
|
||||
return suspend_state == SuspendState::NONE;
|
||||
}
|
||||
|
||||
void DisplayServerWayland::window_set_ime_active(const bool p_active, DisplayServer::WindowID p_window_id) {
|
||||
|
|
@ -977,6 +1029,19 @@ DisplayServer::VSyncMode DisplayServerWayland::window_get_vsync_mode(DisplayServ
|
|||
return DisplayServer::VSYNC_ENABLED;
|
||||
}
|
||||
|
||||
void DisplayServerWayland::window_start_drag(WindowID p_window) {
|
||||
MutexLock mutex_lock(wayland_thread.mutex);
|
||||
|
||||
wayland_thread.window_start_drag(p_window);
|
||||
}
|
||||
|
||||
void DisplayServerWayland::window_start_resize(WindowResizeEdge p_edge, WindowID p_window) {
|
||||
MutexLock mutex_lock(wayland_thread.mutex);
|
||||
|
||||
ERR_FAIL_INDEX(int(p_edge), WINDOW_EDGE_MAX);
|
||||
wayland_thread.window_start_resize(p_edge, p_window);
|
||||
}
|
||||
|
||||
void DisplayServerWayland::cursor_set_shape(CursorShape p_shape) {
|
||||
ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
|
||||
|
||||
|
|
@ -993,11 +1058,7 @@ void DisplayServerWayland::cursor_set_shape(CursorShape p_shape) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (custom_cursors.has(p_shape)) {
|
||||
wayland_thread.cursor_set_custom_shape(p_shape);
|
||||
} else {
|
||||
wayland_thread.cursor_set_shape(p_shape);
|
||||
}
|
||||
wayland_thread.cursor_set_shape(p_shape);
|
||||
}
|
||||
|
||||
DisplayServerWayland::CursorShape DisplayServerWayland::cursor_get_shape() const {
|
||||
|
|
@ -1009,18 +1070,13 @@ DisplayServerWayland::CursorShape DisplayServerWayland::cursor_get_shape() const
|
|||
void DisplayServerWayland::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
|
||||
MutexLock mutex_lock(wayland_thread.mutex);
|
||||
|
||||
bool visible = (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED);
|
||||
|
||||
if (p_cursor.is_valid()) {
|
||||
HashMap<CursorShape, CustomCursor>::Iterator cursor_c = custom_cursors.find(p_shape);
|
||||
|
||||
if (cursor_c) {
|
||||
if (cursor_c->value.rid == p_cursor->get_rid() && cursor_c->value.hotspot == p_hotspot) {
|
||||
if (cursor_c->value.resource == p_cursor && cursor_c->value.hotspot == p_hotspot) {
|
||||
// We have a cached cursor. Nice.
|
||||
if (visible) {
|
||||
wayland_thread.cursor_set_custom_shape(p_shape);
|
||||
}
|
||||
|
||||
wayland_thread.cursor_set_shape(p_shape);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1034,25 +1090,23 @@ void DisplayServerWayland::cursor_set_custom_image(const Ref<Resource> &p_cursor
|
|||
|
||||
CustomCursor &cursor = custom_cursors[p_shape];
|
||||
|
||||
cursor.rid = p_cursor->get_rid();
|
||||
cursor.resource = p_cursor;
|
||||
cursor.hotspot = p_hotspot;
|
||||
|
||||
wayland_thread.cursor_shape_set_custom_image(p_shape, image, p_hotspot);
|
||||
|
||||
if (visible) {
|
||||
wayland_thread.cursor_set_custom_shape(p_shape);
|
||||
}
|
||||
wayland_thread.cursor_set_shape(p_shape);
|
||||
} else {
|
||||
// Clear cache and reset to default system cursor.
|
||||
if (cursor_shape == p_shape && visible) {
|
||||
wayland_thread.cursor_shape_clear_custom_image(p_shape);
|
||||
|
||||
if (cursor_shape == p_shape) {
|
||||
wayland_thread.cursor_set_shape(p_shape);
|
||||
}
|
||||
|
||||
if (custom_cursors.has(p_shape)) {
|
||||
custom_cursors.erase(p_shape);
|
||||
}
|
||||
|
||||
wayland_thread.cursor_shape_clear_custom_image(p_shape);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1120,16 +1174,21 @@ void DisplayServerWayland::try_suspend() {
|
|||
if (emulate_vsync) {
|
||||
bool frame = wayland_thread.wait_frame_suspend_ms(1000);
|
||||
if (!frame) {
|
||||
suspended = true;
|
||||
}
|
||||
} else {
|
||||
if (wayland_thread.is_suspended()) {
|
||||
suspended = true;
|
||||
suspend_state = SuspendState::TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
if (suspended) {
|
||||
DEBUG_LOG_WAYLAND("Window suspended.");
|
||||
// If we suspended by capability, we'll know with this check. We must do this
|
||||
// after `wait_frame_suspend_ms` as it progressively dispatches the event queue
|
||||
// during the "timeout".
|
||||
if (wayland_thread.is_suspended()) {
|
||||
suspend_state = SuspendState::CAPABILITY;
|
||||
}
|
||||
|
||||
if (suspend_state == SuspendState::TIMEOUT) {
|
||||
DEBUG_LOG_WAYLAND("Suspending. Reason: timeout.");
|
||||
} else if (suspend_state == SuspendState::CAPABILITY) {
|
||||
DEBUG_LOG_WAYLAND("Suspending. Reason: capability.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1156,6 +1215,7 @@ void DisplayServerWayland::process_events() {
|
|||
if (OS::get_singleton()->get_main_loop()) {
|
||||
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT);
|
||||
}
|
||||
Input::get_singleton()->release_pressed_events();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1205,16 +1265,18 @@ void DisplayServerWayland::process_events() {
|
|||
|
||||
Ref<WaylandThread::IMEUpdateEventMessage> ime_update_msg = msg;
|
||||
if (ime_update_msg.is_valid()) {
|
||||
ime_text = ime_update_msg->text;
|
||||
ime_selection = ime_update_msg->selection;
|
||||
if (ime_text != ime_update_msg->text || ime_selection != ime_update_msg->selection) {
|
||||
ime_text = ime_update_msg->text;
|
||||
ime_selection = ime_update_msg->selection;
|
||||
|
||||
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_IME_UPDATE);
|
||||
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_IME_UPDATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wayland_thread.keyboard_echo_keys();
|
||||
|
||||
if (!suspended) {
|
||||
if (suspend_state == SuspendState::NONE) {
|
||||
// Due to the way legacy suspension works, we have to treat low processor
|
||||
// usage mode very differently than the regular one.
|
||||
if (OS::get_singleton()->is_in_low_processor_usage_mode()) {
|
||||
|
|
@ -1238,9 +1300,27 @@ void DisplayServerWayland::process_events() {
|
|||
} else {
|
||||
try_suspend();
|
||||
}
|
||||
} else if (!wayland_thread.is_suspended() || wayland_thread.get_reset_frame()) {
|
||||
// At last, a sign of life! We're no longer suspended.
|
||||
suspended = false;
|
||||
} else {
|
||||
if (suspend_state == SuspendState::CAPABILITY) {
|
||||
// If we suspended by capability we can assume that it will be reset when
|
||||
// the compositor wants us to repaint.
|
||||
if (!wayland_thread.is_suspended()) {
|
||||
suspend_state = SuspendState::NONE;
|
||||
DEBUG_LOG_WAYLAND("Unsuspending from capability.");
|
||||
}
|
||||
} else if (suspend_state == SuspendState::TIMEOUT) {
|
||||
// Certain compositors might not report the "suspended" wm_capability flag.
|
||||
// Because of this we'll wake up at the next frame event, indicating the
|
||||
// desire for the compositor to let us repaint.
|
||||
if (wayland_thread.get_reset_frame()) {
|
||||
suspend_state = SuspendState::NONE;
|
||||
DEBUG_LOG_WAYLAND("Unsuspending from timeout.");
|
||||
}
|
||||
}
|
||||
|
||||
// Since we're not rendering, nothing is committing the windows'
|
||||
// surfaces. We have to do it ourselves.
|
||||
wayland_thread.commit_surfaces();
|
||||
}
|
||||
|
||||
#ifdef DBUS_ENABLED
|
||||
|
|
@ -1305,8 +1385,8 @@ Vector<String> DisplayServerWayland::get_rendering_drivers_func() {
|
|||
return drivers;
|
||||
}
|
||||
|
||||
DisplayServer *DisplayServerWayland::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) {
|
||||
DisplayServer *ds = memnew(DisplayServerWayland(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, p_context, r_error));
|
||||
DisplayServer *DisplayServerWayland::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, int64_t p_parent_window, Error &r_error) {
|
||||
DisplayServer *ds = memnew(DisplayServerWayland(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, p_context, p_parent_window, r_error));
|
||||
if (r_error != OK) {
|
||||
ERR_PRINT("Can't create the Wayland display server.");
|
||||
memdelete(ds);
|
||||
|
|
@ -1316,7 +1396,7 @@ DisplayServer *DisplayServerWayland::create_func(const String &p_rendering_drive
|
|||
return ds;
|
||||
}
|
||||
|
||||
DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Context p_context, Error &r_error) {
|
||||
DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Context p_context, int64_t p_parent_window, Error &r_error) {
|
||||
#ifdef GLES3_ENABLED
|
||||
#ifdef SOWRAP_ENABLED
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
|
@ -1349,23 +1429,50 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
|
|||
|
||||
rendering_driver = p_rendering_driver;
|
||||
|
||||
bool driver_found = false;
|
||||
String executable_name = OS::get_singleton()->get_executable_path().get_file();
|
||||
|
||||
#ifdef RD_ENABLED
|
||||
#ifdef VULKAN_ENABLED
|
||||
if (rendering_driver == "vulkan") {
|
||||
rendering_context = memnew(RenderingContextDriverVulkanWayland);
|
||||
}
|
||||
#endif
|
||||
#endif // VULKAN_ENABLED
|
||||
|
||||
if (rendering_context) {
|
||||
if (rendering_context->initialize() != OK) {
|
||||
ERR_PRINT(vformat("Could not initialize %s", rendering_driver));
|
||||
memdelete(rendering_context);
|
||||
rendering_context = nullptr;
|
||||
r_error = ERR_CANT_CREATE;
|
||||
return;
|
||||
#if defined(GLES3_ENABLED)
|
||||
bool fallback_to_opengl3 = GLOBAL_GET("rendering/rendering_device/fallback_to_opengl3");
|
||||
if (fallback_to_opengl3 && rendering_driver != "opengl3") {
|
||||
WARN_PRINT("Your video card drivers seem not to support the required Vulkan version, switching to OpenGL 3.");
|
||||
rendering_driver = "opengl3";
|
||||
OS::get_singleton()->set_current_rendering_method("gl_compatibility");
|
||||
OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
|
||||
} else
|
||||
#endif // GLES3_ENABLED
|
||||
{
|
||||
r_error = ERR_CANT_CREATE;
|
||||
|
||||
if (p_rendering_driver == "vulkan") {
|
||||
OS::get_singleton()->alert(
|
||||
vformat("Your video card drivers seem not to support the required Vulkan version.\n\n"
|
||||
"If possible, consider updating your video card drivers or using the OpenGL 3 driver.\n\n"
|
||||
"You can enable the OpenGL 3 driver by starting the engine from the\n"
|
||||
"command line with the command:\n\n \"%s\" --rendering-driver opengl3\n\n"
|
||||
"If you recently updated your video card drivers, try rebooting.",
|
||||
executable_name),
|
||||
"Unable to initialize Vulkan video driver");
|
||||
}
|
||||
|
||||
ERR_FAIL_MSG(vformat("Could not initialize %s", rendering_driver));
|
||||
}
|
||||
}
|
||||
|
||||
driver_found = true;
|
||||
}
|
||||
#endif
|
||||
#endif // RD_ENABLED
|
||||
|
||||
#ifdef GLES3_ENABLED
|
||||
if (rendering_driver == "opengl3" || rendering_driver == "opengl3_es") {
|
||||
|
|
@ -1429,30 +1536,58 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
|
|||
if (fallback) {
|
||||
WARN_PRINT("Your video card drivers seem not to support the required OpenGL version, switching to OpenGLES.");
|
||||
rendering_driver = "opengl3_es";
|
||||
OS::get_singleton()->set_current_rendering_driver_name(rendering_driver);
|
||||
} else {
|
||||
r_error = ERR_UNAVAILABLE;
|
||||
|
||||
OS::get_singleton()->alert(
|
||||
vformat("Your video card drivers seem not to support the required OpenGL 3.3 version.\n\n"
|
||||
"If possible, consider updating your video card drivers or using the Vulkan driver.\n\n"
|
||||
"You can enable the Vulkan driver by starting the engine from the\n"
|
||||
"command line with the command:\n\n \"%s\" --rendering-driver vulkan\n\n"
|
||||
"If you recently updated your video card drivers, try rebooting.",
|
||||
executable_name),
|
||||
"Unable to initialize OpenGL video driver");
|
||||
|
||||
ERR_FAIL_MSG("Could not initialize OpenGL.");
|
||||
}
|
||||
} else {
|
||||
RasterizerGLES3::make_current(true);
|
||||
driver_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (rendering_driver == "opengl3_es") {
|
||||
egl_manager = memnew(EGLManagerWaylandGLES);
|
||||
|
||||
if (egl_manager->initialize(wayland_thread.get_wl_display()) != OK) {
|
||||
if (egl_manager->initialize(wayland_thread.get_wl_display()) != OK || egl_manager->open_display(wayland_thread.get_wl_display()) != OK) {
|
||||
memdelete(egl_manager);
|
||||
egl_manager = nullptr;
|
||||
r_error = ERR_CANT_CREATE;
|
||||
ERR_FAIL_MSG("Could not initialize GLES3.");
|
||||
|
||||
OS::get_singleton()->alert(
|
||||
vformat("Your video card drivers seem not to support the required OpenGL ES 3.0 version.\n\n"
|
||||
"If possible, consider updating your video card drivers or using the Vulkan driver.\n\n"
|
||||
"You can enable the Vulkan driver by starting the engine from the\n"
|
||||
"command line with the command:\n\n \"%s\" --rendering-driver vulkan\n\n"
|
||||
"If you recently updated your video card drivers, try rebooting.",
|
||||
executable_name),
|
||||
"Unable to initialize OpenGL ES video driver");
|
||||
|
||||
ERR_FAIL_MSG("Could not initialize OpenGL ES.");
|
||||
}
|
||||
|
||||
RasterizerGLES3::make_current(false);
|
||||
driver_found = true;
|
||||
}
|
||||
}
|
||||
#endif // GLES3_ENABLED
|
||||
|
||||
if (!driver_found) {
|
||||
r_error = ERR_UNAVAILABLE;
|
||||
ERR_FAIL_MSG("Video driver not found.");
|
||||
}
|
||||
|
||||
cursor_set_shape(CURSOR_BUSY);
|
||||
|
||||
WindowData &wd = main_window;
|
||||
|
|
@ -1481,12 +1616,12 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
|
|||
|
||||
RendererCompositorRD::make_current();
|
||||
}
|
||||
#endif
|
||||
#endif // RD_ENABLED
|
||||
|
||||
#ifdef DBUS_ENABLED
|
||||
portal_desktop = memnew(FreeDesktopPortalDesktop);
|
||||
screensaver = memnew(FreeDesktopScreenSaver);
|
||||
#endif
|
||||
#endif // DBUS_ENABLED
|
||||
|
||||
screen_set_keep_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on"));
|
||||
|
||||
|
|
|
|||
|
|
@ -101,12 +101,22 @@ class DisplayServerWayland : public DisplayServer {
|
|||
};
|
||||
|
||||
struct CustomCursor {
|
||||
RID rid;
|
||||
Ref<Resource> resource;
|
||||
Point2i hotspot;
|
||||
};
|
||||
|
||||
enum class SuspendState {
|
||||
NONE, // Unsuspended.
|
||||
TIMEOUT, // Legacy fallback.
|
||||
CAPABILITY, // New "suspended" wm_capability flag.
|
||||
};
|
||||
|
||||
CursorShape cursor_shape = CURSOR_ARROW;
|
||||
DisplayServer::MouseMode mouse_mode = DisplayServer::MOUSE_MODE_VISIBLE;
|
||||
DisplayServer::MouseMode mouse_mode_base = MOUSE_MODE_VISIBLE;
|
||||
DisplayServer::MouseMode mouse_mode_override = MOUSE_MODE_VISIBLE;
|
||||
bool mouse_mode_override_enabled = false;
|
||||
void _mouse_update_mode();
|
||||
|
||||
HashMap<CursorShape, CustomCursor> custom_cursors;
|
||||
|
||||
|
|
@ -118,7 +128,7 @@ class DisplayServerWayland : public DisplayServer {
|
|||
String ime_text;
|
||||
Vector2i ime_selection;
|
||||
|
||||
bool suspended = false;
|
||||
SuspendState suspend_state = SuspendState::NONE;
|
||||
bool emulate_vsync = false;
|
||||
|
||||
String rendering_driver;
|
||||
|
|
@ -181,8 +191,14 @@ public:
|
|||
virtual 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) override;
|
||||
#endif
|
||||
|
||||
virtual void beep() const override;
|
||||
|
||||
virtual void mouse_set_mode(MouseMode p_mode) override;
|
||||
virtual MouseMode mouse_get_mode() const override;
|
||||
virtual void mouse_set_mode_override(MouseMode p_mode) override;
|
||||
virtual MouseMode mouse_get_mode_override() const override;
|
||||
virtual void mouse_set_mode_override_enabled(bool p_override_enabled) override;
|
||||
virtual bool mouse_is_mode_override_enabled() const override;
|
||||
|
||||
virtual void warp_mouse(const Point2i &p_to) override;
|
||||
virtual Point2i mouse_get_position() const override;
|
||||
|
|
@ -270,6 +286,9 @@ public:
|
|||
virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window_id = MAIN_WINDOW_ID) override;
|
||||
virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_window_id) const override;
|
||||
|
||||
virtual void window_start_drag(WindowID p_window = MAIN_WINDOW_ID) override;
|
||||
virtual void window_start_resize(WindowResizeEdge p_edge, WindowID p_window) override;
|
||||
|
||||
virtual void cursor_set_shape(CursorShape p_shape) override;
|
||||
virtual CursorShape cursor_get_shape() const override;
|
||||
virtual void cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) override;
|
||||
|
|
@ -290,12 +309,12 @@ public:
|
|||
|
||||
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 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, int64_t p_parent_window, Error &r_error);
|
||||
static Vector<String> get_rendering_drivers_func();
|
||||
|
||||
static void register_wayland_driver();
|
||||
|
||||
DisplayServerWayland(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Context p_context, Error &r_error);
|
||||
DisplayServerWayland(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Context p_context, int64_t p_parent_window, Error &r_error);
|
||||
~DisplayServerWayland();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// This file is generated. Do not edit!
|
||||
// see https://github.com/hpvb/dynload-wrapper for details
|
||||
// generated by ./generate-wrapper.py 0.3 on 2022-12-12 10:55:19
|
||||
// flags: ./generate-wrapper.py --include /usr/include/libdecor-0/libdecor.h --sys-include <libdecor-0/libdecor.h> --soname libdecor-0.so.0 --init-name libdecor --output-header libdecor-so_wrap.h --output-implementation libdecor-so_wrap.c --omit-prefix wl_
|
||||
// flags: ./generate-wrapper.py --include /usr/include/libdecor-0/libdecor.h --sys-include <libdecor.h> --soname libdecor-0.so.0 --init-name libdecor --output-header libdecor-so_wrap.h --output-implementation libdecor-so_wrap.c --omit-prefix wl_
|
||||
//
|
||||
// EDIT: This has been handpatched to properly report the pointer type of the window_state argument of libdecor_configuration_get_window_state.
|
||||
#include <stdint.h>
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
#define libdecor_state_free libdecor_state_free_dylibloader_orig_libdecor
|
||||
#define libdecor_configuration_get_content_size libdecor_configuration_get_content_size_dylibloader_orig_libdecor
|
||||
#define libdecor_configuration_get_window_state libdecor_configuration_get_window_state_dylibloader_orig_libdecor
|
||||
#include <libdecor-0/libdecor.h>
|
||||
#include <libdecor.h>
|
||||
#undef libdecor_unref
|
||||
#undef libdecor_new
|
||||
#undef libdecor_get_fd
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
// This file is generated. Do not edit!
|
||||
// see https://github.com/hpvb/dynload-wrapper for details
|
||||
// generated by ./generate-wrapper.py 0.3 on 2022-12-12 10:55:19
|
||||
// flags: ./generate-wrapper.py --include /usr/include/libdecor-0/libdecor.h --sys-include <libdecor-0/libdecor.h> --soname libdecor-0.so.0 --init-name libdecor --output-header libdecor-so_wrap.h --output-implementation libdecor-so_wrap.c --omit-prefix wl_
|
||||
// flags: ./generate-wrapper.py --include /usr/include/libdecor-0/libdecor.h --sys-include <libdecor.h> --soname libdecor-0.so.0 --init-name libdecor --output-header libdecor-so_wrap.h --output-implementation libdecor-so_wrap.c --omit-prefix wl_
|
||||
//
|
||||
// EDIT: This has been handpatched to properly report the pointer type of the window_state argument of libdecor_configuration_get_window_state.
|
||||
#include <stdint.h>
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
#define libdecor_state_free libdecor_state_free_dylibloader_orig_libdecor
|
||||
#define libdecor_configuration_get_content_size libdecor_configuration_get_content_size_dylibloader_orig_libdecor
|
||||
#define libdecor_configuration_get_window_state libdecor_configuration_get_window_state_dylibloader_orig_libdecor
|
||||
#include <libdecor-0/libdecor.h>
|
||||
#include <libdecor.h>
|
||||
#undef libdecor_unref
|
||||
#undef libdecor_new
|
||||
#undef libdecor_get_fd
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class KeyMappingXKB {
|
|||
static inline HashMap<Key, unsigned int, HashMapHasherKeys> scancode_map_inv;
|
||||
static inline HashMap<unsigned int, KeyLocation, HashMapHasherKeys> location_map;
|
||||
|
||||
KeyMappingXKB(){};
|
||||
KeyMappingXKB() {}
|
||||
|
||||
public:
|
||||
static void initialize();
|
||||
|
|
|
|||
|
|
@ -32,11 +32,7 @@
|
|||
|
||||
#include "rendering_context_driver_vulkan_wayland.h"
|
||||
|
||||
#ifdef USE_VOLK
|
||||
#include <volk.h>
|
||||
#else
|
||||
#include <vulkan/vulkan.h>
|
||||
#endif
|
||||
#include "drivers/vulkan/godot_vulkan.h"
|
||||
|
||||
const char *RenderingContextDriverVulkanWayland::_get_platform_surface_extension() const {
|
||||
return VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME;
|
||||
|
|
@ -51,7 +47,7 @@ RenderingContextDriver::SurfaceID RenderingContextDriverVulkanWayland::surface_c
|
|||
create_info.surface = wpd->surface;
|
||||
|
||||
VkSurfaceKHR vk_surface = VK_NULL_HANDLE;
|
||||
VkResult err = vkCreateWaylandSurfaceKHR(instance_get(), &create_info, nullptr, &vk_surface);
|
||||
VkResult err = vkCreateWaylandSurfaceKHR(instance_get(), &create_info, get_allocation_callbacks(VK_OBJECT_TYPE_SURFACE_KHR), &vk_surface);
|
||||
ERR_FAIL_COND_V(err != VK_SUCCESS, SurfaceID());
|
||||
|
||||
Surface *surface = memnew(Surface);
|
||||
|
|
|
|||
|
|
@ -32,8 +32,12 @@
|
|||
|
||||
#ifdef WAYLAND_ENABLED
|
||||
|
||||
// FIXME: Does this cause issues with *BSDs?
|
||||
#ifdef __FreeBSD__
|
||||
#include <dev/evdev/input-event-codes.h>
|
||||
#else
|
||||
// Assume Linux.
|
||||
#include <linux/input-event-codes.h>
|
||||
#endif
|
||||
|
||||
// For the actual polling thread.
|
||||
#include <poll.h>
|
||||
|
|
@ -169,12 +173,13 @@ Vector<uint8_t> WaylandThread::_wp_primary_selection_offer_read(struct wl_displa
|
|||
|
||||
int fds[2];
|
||||
if (pipe(fds) == 0) {
|
||||
// This function expects to return a string, so we can only ask for a MIME of
|
||||
// "text/plain"
|
||||
zwp_primary_selection_offer_v1_receive(p_offer, p_mime, fds[1]);
|
||||
|
||||
// Wait for the compositor to know about the pipe.
|
||||
wl_display_roundtrip(p_display);
|
||||
// NOTE: It's important to just flush and not roundtrip here as we would risk
|
||||
// running some cleanup event, like for example `wl_data_device::leave`. We're
|
||||
// going to wait for the message anyways as the read will probably block if
|
||||
// the compositor doesn't read from the other end of the pipe.
|
||||
wl_display_flush(p_display);
|
||||
|
||||
// Close the write end of the pipe, which we don't need and would otherwise
|
||||
// just stall our next `read`s.
|
||||
|
|
@ -186,15 +191,34 @@ Vector<uint8_t> WaylandThread::_wp_primary_selection_offer_read(struct wl_displa
|
|||
return Vector<uint8_t>();
|
||||
}
|
||||
|
||||
// Sets up an `InputEventKey` and returns whether it has any meaningful value.
|
||||
bool WaylandThread::_seat_state_configure_key_event(SeatState &p_ss, Ref<InputEventKey> p_event, xkb_keycode_t p_keycode, bool p_pressed) {
|
||||
// TODO: Handle keys that release multiple symbols?
|
||||
Key keycode = KeyMappingXKB::get_keycode(xkb_state_key_get_one_sym(p_ss.xkb_state, p_keycode));
|
||||
Ref<InputEventKey> WaylandThread::_seat_state_get_key_event(SeatState *p_ss, xkb_keycode_t p_keycode, bool p_pressed) {
|
||||
Ref<InputEventKey> event;
|
||||
|
||||
ERR_FAIL_NULL_V(p_ss, event);
|
||||
|
||||
Key shifted_key = KeyMappingXKB::get_keycode(xkb_state_key_get_one_sym(p_ss->xkb_state, p_keycode));
|
||||
|
||||
Key plain_key = Key::NONE;
|
||||
// NOTE: xkbcommon's API really encourages to apply the modifier state but we
|
||||
// only want a "plain" symbol so that we can convert it into a godot keycode.
|
||||
const xkb_keysym_t *syms = nullptr;
|
||||
int num_sys = xkb_keymap_key_get_syms_by_level(p_ss->xkb_keymap, p_keycode, p_ss->current_layout_index, 0, &syms);
|
||||
if (num_sys > 0 && syms) {
|
||||
plain_key = KeyMappingXKB::get_keycode(syms[0]);
|
||||
}
|
||||
|
||||
Key physical_keycode = KeyMappingXKB::get_scancode(p_keycode);
|
||||
KeyLocation key_location = KeyMappingXKB::get_location(p_keycode);
|
||||
uint32_t unicode = xkb_state_key_get_utf32(p_ss->xkb_state, p_keycode);
|
||||
|
||||
if (physical_keycode == Key::NONE) {
|
||||
return false;
|
||||
Key keycode = Key::NONE;
|
||||
|
||||
if ((shifted_key & Key::SPECIAL) != Key::NONE || (plain_key & Key::SPECIAL) != Key::NONE) {
|
||||
keycode = shifted_key;
|
||||
}
|
||||
|
||||
if (keycode == Key::NONE) {
|
||||
keycode = plain_key;
|
||||
}
|
||||
|
||||
if (keycode == Key::NONE) {
|
||||
|
|
@ -205,40 +229,71 @@ bool WaylandThread::_seat_state_configure_key_event(SeatState &p_ss, Ref<InputEv
|
|||
keycode -= 'a' - 'A';
|
||||
}
|
||||
|
||||
p_event->set_window_id(DisplayServer::MAIN_WINDOW_ID);
|
||||
if (physical_keycode == Key::NONE && keycode == Key::NONE && unicode == 0) {
|
||||
return event;
|
||||
}
|
||||
|
||||
event.instantiate();
|
||||
|
||||
event->set_window_id(DisplayServer::MAIN_WINDOW_ID);
|
||||
|
||||
// Set all pressed modifiers.
|
||||
p_event->set_shift_pressed(p_ss.shift_pressed);
|
||||
p_event->set_ctrl_pressed(p_ss.ctrl_pressed);
|
||||
p_event->set_alt_pressed(p_ss.alt_pressed);
|
||||
p_event->set_meta_pressed(p_ss.meta_pressed);
|
||||
event->set_shift_pressed(p_ss->shift_pressed);
|
||||
event->set_ctrl_pressed(p_ss->ctrl_pressed);
|
||||
event->set_alt_pressed(p_ss->alt_pressed);
|
||||
event->set_meta_pressed(p_ss->meta_pressed);
|
||||
|
||||
p_event->set_pressed(p_pressed);
|
||||
p_event->set_keycode(keycode);
|
||||
p_event->set_physical_keycode(physical_keycode);
|
||||
p_event->set_location(key_location);
|
||||
|
||||
uint32_t unicode = xkb_state_key_get_utf32(p_ss.xkb_state, p_keycode);
|
||||
event->set_pressed(p_pressed);
|
||||
event->set_keycode(keycode);
|
||||
event->set_physical_keycode(physical_keycode);
|
||||
event->set_location(key_location);
|
||||
|
||||
if (unicode != 0) {
|
||||
p_event->set_key_label(fix_key_label(unicode, keycode));
|
||||
event->set_key_label(fix_key_label(unicode, keycode));
|
||||
} else {
|
||||
p_event->set_key_label(keycode);
|
||||
event->set_key_label(keycode);
|
||||
}
|
||||
|
||||
if (p_pressed) {
|
||||
p_event->set_unicode(fix_unicode(unicode));
|
||||
event->set_unicode(fix_unicode(unicode));
|
||||
}
|
||||
|
||||
// Taken from DisplayServerX11.
|
||||
if (p_event->get_keycode() == Key::BACKTAB) {
|
||||
if (event->get_keycode() == Key::BACKTAB) {
|
||||
// Make it consistent across platforms.
|
||||
p_event->set_keycode(Key::TAB);
|
||||
p_event->set_physical_keycode(Key::TAB);
|
||||
p_event->set_shift_pressed(true);
|
||||
event->set_keycode(Key::TAB);
|
||||
event->set_physical_keycode(Key::TAB);
|
||||
event->set_shift_pressed(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
return event;
|
||||
}
|
||||
|
||||
// NOTE: Due to the nature of the way keys are encoded, there's an ambiguity
|
||||
// regarding "special" keys. In other words: there's no reliable way of
|
||||
// switching between a special key and a character key if not marking a
|
||||
// different Godot keycode, even if we're actually using the same XKB raw
|
||||
// keycode. This means that, during this switch, the old key will get "stuck",
|
||||
// as it will never receive a release event. This method returns the necessary
|
||||
// event to fix this if needed.
|
||||
Ref<InputEventKey> WaylandThread::_seat_state_get_unstuck_key_event(SeatState *p_ss, xkb_keycode_t p_keycode, bool p_pressed, Key p_key) {
|
||||
Ref<InputEventKey> event;
|
||||
|
||||
if (p_pressed) {
|
||||
Key *old_key = p_ss->pressed_keycodes.getptr(p_keycode);
|
||||
if (old_key != nullptr && *old_key != p_key) {
|
||||
print_verbose(vformat("%s and %s have same keycode. Generating release event for %s", keycode_get_string(*old_key), keycode_get_string(p_key), keycode_get_string(*old_key)));
|
||||
event = _seat_state_get_key_event(p_ss, p_keycode, false);
|
||||
if (event.is_valid()) {
|
||||
event->set_keycode(*old_key);
|
||||
}
|
||||
}
|
||||
p_ss->pressed_keycodes[p_keycode] = p_key;
|
||||
} else {
|
||||
p_ss->pressed_keycodes.erase(p_keycode);
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
void WaylandThread::_set_current_seat(struct wl_seat *p_seat) {
|
||||
|
|
@ -264,8 +319,6 @@ bool WaylandThread::_load_cursor_theme(int p_cursor_size) {
|
|||
if (wl_cursor_theme) {
|
||||
wl_cursor_theme_destroy(wl_cursor_theme);
|
||||
wl_cursor_theme = nullptr;
|
||||
|
||||
current_wl_cursor = nullptr;
|
||||
}
|
||||
|
||||
if (cursor_theme_name.is_empty()) {
|
||||
|
|
@ -356,7 +409,12 @@ void WaylandThread::_update_scale(int p_scale) {
|
|||
int cursor_size = unscaled_cursor_size * p_scale;
|
||||
|
||||
if (_load_cursor_theme(cursor_size)) {
|
||||
cursor_set_shape(last_cursor_shape);
|
||||
for (struct wl_seat *wl_seat : registry.wl_seats) {
|
||||
SeatState *ss = wl_seat_get_seat_state(wl_seat);
|
||||
ERR_FAIL_NULL(ss);
|
||||
|
||||
seat_state_update_cursor(ss);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -370,9 +428,16 @@ void WaylandThread::_wl_registry_on_global(void *data, struct wl_registry *wl_re
|
|||
return;
|
||||
}
|
||||
|
||||
// NOTE: Deprecated.
|
||||
if (strcmp(interface, zxdg_exporter_v1_interface.name) == 0) {
|
||||
registry->xdg_exporter = (struct zxdg_exporter_v1 *)wl_registry_bind(wl_registry, name, &zxdg_exporter_v1_interface, 1);
|
||||
registry->xdg_exporter_name = name;
|
||||
registry->xdg_exporter_v1 = (struct zxdg_exporter_v1 *)wl_registry_bind(wl_registry, name, &zxdg_exporter_v1_interface, 1);
|
||||
registry->xdg_exporter_v1_name = name;
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(interface, zxdg_exporter_v2_interface.name) == 0) {
|
||||
registry->xdg_exporter_v2 = (struct zxdg_exporter_v2 *)wl_registry_bind(wl_registry, name, &zxdg_exporter_v2_interface, 1);
|
||||
registry->xdg_exporter_v2_name = name;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -493,6 +558,12 @@ void WaylandThread::_wl_registry_on_global(void *data, struct wl_registry *wl_re
|
|||
return;
|
||||
}
|
||||
|
||||
if (strcmp(interface, xdg_system_bell_v1_interface.name) == 0) {
|
||||
registry->xdg_system_bell = (struct xdg_system_bell_v1 *)wl_registry_bind(wl_registry, name, &xdg_system_bell_v1_interface, 1);
|
||||
registry->xdg_system_bell_name = name;
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(interface, xdg_activation_v1_interface.name) == 0) {
|
||||
registry->xdg_activation = (struct xdg_activation_v1 *)wl_registry_bind(wl_registry, name, &xdg_activation_v1_interface, 1);
|
||||
registry->xdg_activation_name = name;
|
||||
|
|
@ -586,13 +657,25 @@ void WaylandThread::_wl_registry_on_global_remove(void *data, struct wl_registry
|
|||
return;
|
||||
}
|
||||
|
||||
if (name == registry->xdg_exporter_name) {
|
||||
if (registry->xdg_exporter) {
|
||||
zxdg_exporter_v1_destroy(registry->xdg_exporter);
|
||||
registry->xdg_exporter = nullptr;
|
||||
// NOTE: Deprecated.
|
||||
if (name == registry->xdg_exporter_v1_name) {
|
||||
if (registry->xdg_exporter_v1) {
|
||||
zxdg_exporter_v1_destroy(registry->xdg_exporter_v1);
|
||||
registry->xdg_exporter_v1 = nullptr;
|
||||
}
|
||||
|
||||
registry->xdg_exporter_name = 0;
|
||||
registry->xdg_exporter_v1_name = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (name == registry->xdg_exporter_v2_name) {
|
||||
if (registry->xdg_exporter_v2) {
|
||||
zxdg_exporter_v2_destroy(registry->xdg_exporter_v2);
|
||||
registry->xdg_exporter_v2 = nullptr;
|
||||
}
|
||||
|
||||
registry->xdg_exporter_v2_name = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -688,6 +771,17 @@ void WaylandThread::_wl_registry_on_global_remove(void *data, struct wl_registry
|
|||
return;
|
||||
}
|
||||
|
||||
if (name == registry->xdg_system_bell_name) {
|
||||
if (registry->xdg_system_bell) {
|
||||
xdg_system_bell_v1_destroy(registry->xdg_system_bell);
|
||||
registry->xdg_system_bell = nullptr;
|
||||
}
|
||||
|
||||
registry->xdg_system_bell_name = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (name == registry->xdg_activation_name) {
|
||||
if (registry->xdg_activation) {
|
||||
xdg_activation_v1_destroy(registry->xdg_activation);
|
||||
|
|
@ -1162,7 +1256,15 @@ void WaylandThread::_xdg_toplevel_on_wm_capabilities(void *data, struct xdg_topl
|
|||
}
|
||||
}
|
||||
|
||||
void WaylandThread::_xdg_exported_on_exported(void *data, zxdg_exported_v1 *exported, const char *handle) {
|
||||
// NOTE: Deprecated.
|
||||
void WaylandThread::_xdg_exported_v1_on_handle(void *data, zxdg_exported_v1 *exported, const char *handle) {
|
||||
WindowState *ws = (WindowState *)data;
|
||||
ERR_FAIL_NULL(ws);
|
||||
|
||||
ws->exported_handle = vformat("wayland:%s", String::utf8(handle));
|
||||
}
|
||||
|
||||
void WaylandThread::_xdg_exported_v2_on_handle(void *data, zxdg_exported_v2 *exported, const char *handle) {
|
||||
WindowState *ws = (WindowState *)data;
|
||||
ERR_FAIL_NULL(ws);
|
||||
|
||||
|
|
@ -1394,6 +1496,8 @@ void WaylandThread::_wl_pointer_on_leave(void *data, struct wl_pointer *wl_point
|
|||
|
||||
ss->pointed_surface = nullptr;
|
||||
|
||||
ss->pointer_data_buffer.pressed_button_mask.clear();
|
||||
|
||||
Ref<WindowEventMessage> msg;
|
||||
msg.instantiate();
|
||||
msg->event = DisplayServer::WINDOW_EVENT_MOUSE_EXIT;
|
||||
|
|
@ -1416,10 +1520,10 @@ void WaylandThread::_wl_pointer_on_motion(void *data, struct wl_pointer *wl_poin
|
|||
PointerData &pd = ss->pointer_data_buffer;
|
||||
|
||||
// TODO: Scale only when sending the Wayland message.
|
||||
pd.position.x = wl_fixed_to_int(surface_x);
|
||||
pd.position.y = wl_fixed_to_int(surface_y);
|
||||
pd.position.x = wl_fixed_to_double(surface_x);
|
||||
pd.position.y = wl_fixed_to_double(surface_y);
|
||||
|
||||
pd.position = scale_vector2i(pd.position, window_state_get_scale_factor(ws));
|
||||
pd.position *= window_state_get_scale_factor(ws);
|
||||
|
||||
pd.motion_time = time;
|
||||
}
|
||||
|
|
@ -1532,7 +1636,7 @@ void WaylandThread::_wl_pointer_on_frame(void *data, struct wl_pointer *wl_point
|
|||
mm->set_position(pd.position);
|
||||
mm->set_global_position(pd.position);
|
||||
|
||||
Vector2i pos_delta = pd.position - old_pd.position;
|
||||
Vector2 pos_delta = pd.position - old_pd.position;
|
||||
|
||||
if (old_pd.relative_motion_time != pd.relative_motion_time) {
|
||||
uint32_t time_delta = pd.relative_motion_time - old_pd.relative_motion_time;
|
||||
|
|
@ -1649,7 +1753,7 @@ void WaylandThread::_wl_pointer_on_frame(void *data, struct wl_pointer *wl_point
|
|||
|
||||
// We have to set the last position pressed here as we can't take for
|
||||
// granted what the individual events might have seen due to them not having
|
||||
// a garaunteed order.
|
||||
// a guaranteed order.
|
||||
if (mb->is_pressed()) {
|
||||
pd.last_pressed_position = pd.position;
|
||||
}
|
||||
|
|
@ -1741,7 +1845,7 @@ void WaylandThread::_wl_pointer_on_axis_discrete(void *data, struct wl_pointer *
|
|||
pd.discrete_scroll_vector_120.y = discrete * 120;
|
||||
}
|
||||
|
||||
if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
|
||||
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
|
||||
pd.discrete_scroll_vector_120.x = discrete * 120;
|
||||
}
|
||||
}
|
||||
|
|
@ -1762,7 +1866,7 @@ void WaylandThread::_wl_pointer_on_axis_value120(void *data, struct wl_pointer *
|
|||
pd.discrete_scroll_vector_120.y += value120;
|
||||
}
|
||||
|
||||
if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
|
||||
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
|
||||
pd.discrete_scroll_vector_120.x += value120;
|
||||
}
|
||||
}
|
||||
|
|
@ -1848,13 +1952,19 @@ void WaylandThread::_wl_keyboard_on_key(void *data, struct wl_keyboard *wl_keybo
|
|||
ss->repeating_keycode = XKB_KEYCODE_INVALID;
|
||||
}
|
||||
|
||||
Ref<InputEventKey> k;
|
||||
k.instantiate();
|
||||
|
||||
if (!_seat_state_configure_key_event(*ss, k, xkb_keycode, pressed)) {
|
||||
Ref<InputEventKey> k = _seat_state_get_key_event(ss, xkb_keycode, pressed);
|
||||
if (k.is_null()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<InputEventKey> uk = _seat_state_get_unstuck_key_event(ss, xkb_keycode, pressed, k->get_keycode());
|
||||
if (uk.is_valid()) {
|
||||
Ref<InputEventMessage> u_msg;
|
||||
u_msg.instantiate();
|
||||
u_msg->event = uk;
|
||||
wayland_thread->push_message(u_msg);
|
||||
}
|
||||
|
||||
Ref<InputEventMessage> msg;
|
||||
msg.instantiate();
|
||||
msg->event = k;
|
||||
|
|
@ -2388,9 +2498,9 @@ void WaylandThread::_wp_tablet_tool_on_motion(void *data, struct zwp_tablet_tool
|
|||
|
||||
double scale_factor = window_state_get_scale_factor(ws);
|
||||
|
||||
td.position.x = wl_fixed_to_int(x);
|
||||
td.position.y = wl_fixed_to_int(y);
|
||||
td.position = scale_vector2i(td.position, scale_factor);
|
||||
td.position.x = wl_fixed_to_double(x);
|
||||
td.position.y = wl_fixed_to_double(y);
|
||||
td.position *= scale_factor;
|
||||
|
||||
td.motion_time = OS::get_singleton()->get_ticks_msec();
|
||||
}
|
||||
|
|
@ -2520,7 +2630,7 @@ void WaylandThread::_wp_tablet_tool_on_frame(void *data, struct zwp_tablet_tool_
|
|||
mm->set_relative(td.position - old_td.position);
|
||||
mm->set_relative_screen_position(mm->get_relative());
|
||||
|
||||
Vector2i pos_delta = td.position - old_td.position;
|
||||
Vector2 pos_delta = td.position - old_td.position;
|
||||
uint32_t time_delta = td.motion_time - old_td.motion_time;
|
||||
mm->set_velocity((Vector2)pos_delta / time_delta);
|
||||
|
||||
|
|
@ -2681,7 +2791,7 @@ void WaylandThread::_wp_text_input_on_done(void *data, struct zwp_text_input_v3
|
|||
msg.instantiate();
|
||||
msg->text = ss->ime_text_commit;
|
||||
ss->wayland_thread->push_message(msg);
|
||||
} else if (!ss->ime_text.is_empty()) {
|
||||
} else {
|
||||
Ref<IMEUpdateEventMessage> msg;
|
||||
msg.instantiate();
|
||||
msg->text = ss->ime_text;
|
||||
|
|
@ -3071,19 +3181,25 @@ void WaylandThread::seat_state_confine_pointer(SeatState *p_ss) {
|
|||
|
||||
void WaylandThread::seat_state_update_cursor(SeatState *p_ss) {
|
||||
ERR_FAIL_NULL(p_ss);
|
||||
|
||||
WaylandThread *thread = p_ss->wayland_thread;
|
||||
ERR_FAIL_NULL(p_ss->wayland_thread);
|
||||
|
||||
if (p_ss->wl_pointer && p_ss->cursor_surface) {
|
||||
// NOTE: Those values are valid by default and will hide the cursor when
|
||||
// unchanged, which happens when both the current custom cursor and the
|
||||
// current wl_cursor are `nullptr`.
|
||||
struct wl_buffer *cursor_buffer = nullptr;
|
||||
uint32_t hotspot_x = 0;
|
||||
uint32_t hotspot_y = 0;
|
||||
int scale = 1;
|
||||
if (!p_ss->wl_pointer || !p_ss->cursor_surface) {
|
||||
return;
|
||||
}
|
||||
|
||||
CustomCursor *custom_cursor = p_ss->wayland_thread->current_custom_cursor;
|
||||
struct wl_cursor *wl_cursor = p_ss->wayland_thread->current_wl_cursor;
|
||||
// NOTE: Those values are valid by default and will hide the cursor when
|
||||
// unchanged.
|
||||
struct wl_buffer *cursor_buffer = nullptr;
|
||||
uint32_t hotspot_x = 0;
|
||||
uint32_t hotspot_y = 0;
|
||||
int scale = 1;
|
||||
|
||||
if (thread->cursor_visible) {
|
||||
DisplayServer::CursorShape shape = thread->cursor_shape;
|
||||
|
||||
struct CustomCursor *custom_cursor = thread->custom_cursors.getptr(shape);
|
||||
|
||||
if (custom_cursor) {
|
||||
cursor_buffer = custom_cursor->wl_buffer;
|
||||
|
|
@ -3093,7 +3209,13 @@ void WaylandThread::seat_state_update_cursor(SeatState *p_ss) {
|
|||
// We can't really reasonably scale custom cursors, so we'll let the
|
||||
// compositor do it for us (badly).
|
||||
scale = 1;
|
||||
} else if (wl_cursor) {
|
||||
} else {
|
||||
struct wl_cursor *wl_cursor = thread->wl_cursors[shape];
|
||||
|
||||
if (!wl_cursor) {
|
||||
return;
|
||||
}
|
||||
|
||||
int frame_idx = 0;
|
||||
|
||||
if (wl_cursor->image_count > 1) {
|
||||
|
|
@ -3109,24 +3231,24 @@ void WaylandThread::seat_state_update_cursor(SeatState *p_ss) {
|
|||
|
||||
struct wl_cursor_image *wl_cursor_image = wl_cursor->images[frame_idx];
|
||||
|
||||
scale = p_ss->wayland_thread->cursor_scale;
|
||||
scale = thread->cursor_scale;
|
||||
|
||||
cursor_buffer = wl_cursor_image_get_buffer(wl_cursor_image);
|
||||
|
||||
// As the surface's buffer is scaled (thus the surface is smaller) and the
|
||||
// hotspot must be expressed in surface-local coordinates, we need to scale
|
||||
// them down accordingly.
|
||||
// it down accordingly.
|
||||
hotspot_x = wl_cursor_image->hotspot_x / scale;
|
||||
hotspot_y = wl_cursor_image->hotspot_y / scale;
|
||||
}
|
||||
|
||||
wl_pointer_set_cursor(p_ss->wl_pointer, p_ss->pointer_enter_serial, p_ss->cursor_surface, hotspot_x, hotspot_y);
|
||||
wl_surface_set_buffer_scale(p_ss->cursor_surface, scale);
|
||||
wl_surface_attach(p_ss->cursor_surface, cursor_buffer, 0, 0);
|
||||
wl_surface_damage_buffer(p_ss->cursor_surface, 0, 0, INT_MAX, INT_MAX);
|
||||
|
||||
wl_surface_commit(p_ss->cursor_surface);
|
||||
}
|
||||
|
||||
wl_pointer_set_cursor(p_ss->wl_pointer, p_ss->pointer_enter_serial, p_ss->cursor_surface, hotspot_x, hotspot_y);
|
||||
wl_surface_set_buffer_scale(p_ss->cursor_surface, scale);
|
||||
wl_surface_attach(p_ss->cursor_surface, cursor_buffer, 0, 0);
|
||||
wl_surface_damage_buffer(p_ss->cursor_surface, 0, 0, INT_MAX, INT_MAX);
|
||||
|
||||
wl_surface_commit(p_ss->cursor_surface);
|
||||
}
|
||||
|
||||
void WaylandThread::seat_state_echo_keys(SeatState *p_ss) {
|
||||
|
|
@ -3152,15 +3274,18 @@ void WaylandThread::seat_state_echo_keys(SeatState *p_ss) {
|
|||
int keys_amount = (ticks_delta / p_ss->repeat_key_delay_msec);
|
||||
|
||||
for (int i = 0; i < keys_amount; i++) {
|
||||
Ref<InputEventKey> k;
|
||||
k.instantiate();
|
||||
|
||||
if (!_seat_state_configure_key_event(*p_ss, k, p_ss->repeating_keycode, true)) {
|
||||
Ref<InputEventKey> k = _seat_state_get_key_event(p_ss, p_ss->repeating_keycode, true);
|
||||
if (k.is_null()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
k->set_echo(true);
|
||||
|
||||
Ref<InputEventKey> uk = _seat_state_get_unstuck_key_event(p_ss, p_ss->repeating_keycode, true, k->get_keycode());
|
||||
if (uk.is_valid()) {
|
||||
Input::get_singleton()->parse_input_event(uk);
|
||||
}
|
||||
|
||||
Input::get_singleton()->parse_input_event(k);
|
||||
}
|
||||
|
||||
|
|
@ -3246,9 +3371,12 @@ void WaylandThread::window_create(DisplayServer::WindowID p_window_id, int p_wid
|
|||
ws.frame_callback = wl_surface_frame(ws.wl_surface);
|
||||
wl_callback_add_listener(ws.frame_callback, &frame_wl_callback_listener, &ws);
|
||||
|
||||
if (registry.xdg_exporter) {
|
||||
ws.xdg_exported = zxdg_exporter_v1_export(registry.xdg_exporter, ws.wl_surface);
|
||||
zxdg_exported_v1_add_listener(ws.xdg_exported, &xdg_exported_listener, &ws);
|
||||
if (registry.xdg_exporter_v2) {
|
||||
ws.xdg_exported_v2 = zxdg_exporter_v2_export_toplevel(registry.xdg_exporter_v2, ws.wl_surface);
|
||||
zxdg_exported_v2_add_listener(ws.xdg_exported_v2, &xdg_exported_v2_listener, &ws);
|
||||
} else if (registry.xdg_exporter_v1) {
|
||||
ws.xdg_exported_v1 = zxdg_exporter_v1_export(registry.xdg_exporter_v1, ws.wl_surface);
|
||||
zxdg_exported_v1_add_listener(ws.xdg_exported_v1, &xdg_exported_v1_listener, &ws);
|
||||
}
|
||||
|
||||
wl_surface_commit(ws.wl_surface);
|
||||
|
|
@ -3264,6 +3392,102 @@ struct wl_surface *WaylandThread::window_get_wl_surface(DisplayServer::WindowID
|
|||
return ws.wl_surface;
|
||||
}
|
||||
|
||||
void WaylandThread::beep() const {
|
||||
if (registry.xdg_system_bell) {
|
||||
xdg_system_bell_v1_ring(registry.xdg_system_bell, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandThread::window_start_drag(DisplayServer::WindowID p_window_id) {
|
||||
// TODO: Use window IDs for multiwindow support.
|
||||
WindowState &ws = main_window;
|
||||
SeatState *ss = wl_seat_get_seat_state(wl_seat_current);
|
||||
|
||||
if (ss && ws.xdg_toplevel) {
|
||||
xdg_toplevel_move(ws.xdg_toplevel, ss->wl_seat, ss->pointer_data.button_serial);
|
||||
}
|
||||
|
||||
#ifdef LIBDECOR_ENABLED
|
||||
if (ws.libdecor_frame) {
|
||||
libdecor_frame_move(ws.libdecor_frame, ss->wl_seat, ss->pointer_data.button_serial);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void WaylandThread::window_start_resize(DisplayServer::WindowResizeEdge p_edge, DisplayServer::WindowID p_window) {
|
||||
// TODO: Use window IDs for multiwindow support.
|
||||
WindowState &ws = main_window;
|
||||
SeatState *ss = wl_seat_get_seat_state(wl_seat_current);
|
||||
|
||||
if (ss && ws.xdg_toplevel) {
|
||||
xdg_toplevel_resize_edge edge = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
|
||||
switch (p_edge) {
|
||||
case DisplayServer::WINDOW_EDGE_TOP_LEFT: {
|
||||
edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EDGE_TOP: {
|
||||
edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EDGE_TOP_RIGHT: {
|
||||
edge = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EDGE_LEFT: {
|
||||
edge = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EDGE_RIGHT: {
|
||||
edge = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EDGE_BOTTOM_LEFT: {
|
||||
edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EDGE_BOTTOM: {
|
||||
edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM;
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EDGE_BOTTOM_RIGHT: {
|
||||
edge = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
xdg_toplevel_resize(ws.xdg_toplevel, ss->wl_seat, ss->pointer_data.button_serial, edge);
|
||||
}
|
||||
|
||||
#ifdef LIBDECOR_ENABLED
|
||||
if (ws.libdecor_frame) {
|
||||
libdecor_resize_edge edge = LIBDECOR_RESIZE_EDGE_NONE;
|
||||
switch (p_edge) {
|
||||
case DisplayServer::WINDOW_EDGE_TOP_LEFT: {
|
||||
edge = LIBDECOR_RESIZE_EDGE_TOP_LEFT;
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EDGE_TOP: {
|
||||
edge = LIBDECOR_RESIZE_EDGE_TOP;
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EDGE_TOP_RIGHT: {
|
||||
edge = LIBDECOR_RESIZE_EDGE_TOP_RIGHT;
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EDGE_LEFT: {
|
||||
edge = LIBDECOR_RESIZE_EDGE_LEFT;
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EDGE_RIGHT: {
|
||||
edge = LIBDECOR_RESIZE_EDGE_RIGHT;
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EDGE_BOTTOM_LEFT: {
|
||||
edge = LIBDECOR_RESIZE_EDGE_BOTTOM_LEFT;
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EDGE_BOTTOM: {
|
||||
edge = LIBDECOR_RESIZE_EDGE_BOTTOM;
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EDGE_BOTTOM_RIGHT: {
|
||||
edge = LIBDECOR_RESIZE_EDGE_BOTTOM_RIGHT;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
libdecor_frame_resize(ws.libdecor_frame, ss->wl_seat, ss->pointer_data.button_serial, edge);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void WaylandThread::window_set_max_size(DisplayServer::WindowID p_window_id, const Size2i &p_size) {
|
||||
// TODO: Use window IDs for multiwindow support.
|
||||
WindowState &ws = main_window;
|
||||
|
|
@ -3328,7 +3552,8 @@ bool WaylandThread::window_can_set_mode(DisplayServer::WindowID p_window_id, Dis
|
|||
return ws.can_maximize;
|
||||
};
|
||||
|
||||
case DisplayServer::WINDOW_MODE_FULLSCREEN: {
|
||||
case DisplayServer::WINDOW_MODE_FULLSCREEN:
|
||||
case DisplayServer::WINDOW_MODE_EXCLUSIVE_FULLSCREEN: {
|
||||
#ifdef LIBDECOR_ENABLED
|
||||
if (ws.libdecor_frame) {
|
||||
return libdecor_frame_has_capability(ws.libdecor_frame, LIBDECOR_ACTION_FULLSCREEN);
|
||||
|
|
@ -3337,13 +3562,6 @@ bool WaylandThread::window_can_set_mode(DisplayServer::WindowID p_window_id, Dis
|
|||
|
||||
return ws.can_fullscreen;
|
||||
};
|
||||
|
||||
case DisplayServer::WINDOW_MODE_EXCLUSIVE_FULLSCREEN: {
|
||||
// I'm not really sure but from what I can find Wayland doesn't really have
|
||||
// the concept of exclusive fullscreen.
|
||||
// TODO: Discuss whether to fallback to regular fullscreen or not.
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -3458,7 +3676,8 @@ void WaylandThread::window_try_set_mode(DisplayServer::WindowID p_window_id, Dis
|
|||
#endif // LIBDECOR_ENABLED
|
||||
} break;
|
||||
|
||||
case DisplayServer::WINDOW_MODE_FULLSCREEN: {
|
||||
case DisplayServer::WINDOW_MODE_FULLSCREEN:
|
||||
case DisplayServer::WINDOW_MODE_EXCLUSIVE_FULLSCREEN: {
|
||||
if (ws.xdg_toplevel) {
|
||||
xdg_toplevel_set_fullscreen(ws.xdg_toplevel, nullptr);
|
||||
}
|
||||
|
|
@ -3767,25 +3986,19 @@ Error WaylandThread::init() {
|
|||
return OK;
|
||||
}
|
||||
|
||||
void WaylandThread::cursor_hide() {
|
||||
current_wl_cursor = nullptr;
|
||||
current_custom_cursor = nullptr;
|
||||
void WaylandThread::cursor_set_visible(bool p_visible) {
|
||||
cursor_visible = p_visible;
|
||||
|
||||
SeatState *ss = wl_seat_get_seat_state(wl_seat_current);
|
||||
ERR_FAIL_NULL(ss);
|
||||
seat_state_update_cursor(ss);
|
||||
for (struct wl_seat *wl_seat : registry.wl_seats) {
|
||||
SeatState *ss = wl_seat_get_seat_state(wl_seat);
|
||||
ERR_FAIL_NULL(ss);
|
||||
|
||||
seat_state_update_cursor(ss);
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandThread::cursor_set_shape(DisplayServer::CursorShape p_cursor_shape) {
|
||||
if (!wl_cursors[p_cursor_shape]) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The point of this method is make the current cursor a "plain" shape and, as
|
||||
// the custom cursor overrides what gets set, we have to clear it too.
|
||||
current_custom_cursor = nullptr;
|
||||
|
||||
current_wl_cursor = wl_cursors[p_cursor_shape];
|
||||
cursor_shape = p_cursor_shape;
|
||||
|
||||
for (struct wl_seat *wl_seat : registry.wl_seats) {
|
||||
SeatState *ss = wl_seat_get_seat_state(wl_seat);
|
||||
|
|
@ -3793,27 +4006,10 @@ void WaylandThread::cursor_set_shape(DisplayServer::CursorShape p_cursor_shape)
|
|||
|
||||
seat_state_update_cursor(ss);
|
||||
}
|
||||
|
||||
last_cursor_shape = p_cursor_shape;
|
||||
}
|
||||
|
||||
void WaylandThread::cursor_set_custom_shape(DisplayServer::CursorShape p_cursor_shape) {
|
||||
ERR_FAIL_COND(!custom_cursors.has(p_cursor_shape));
|
||||
|
||||
current_custom_cursor = &custom_cursors[p_cursor_shape];
|
||||
|
||||
for (struct wl_seat *wl_seat : registry.wl_seats) {
|
||||
SeatState *ss = wl_seat_get_seat_state(wl_seat);
|
||||
ERR_FAIL_NULL(ss);
|
||||
|
||||
seat_state_update_cursor(ss);
|
||||
}
|
||||
|
||||
last_cursor_shape = p_cursor_shape;
|
||||
}
|
||||
|
||||
void WaylandThread::cursor_shape_set_custom_image(DisplayServer::CursorShape p_cursor_shape, Ref<Image> p_image, const Point2i &p_hotspot) {
|
||||
ERR_FAIL_COND(!p_image.is_valid());
|
||||
ERR_FAIL_COND(p_image.is_null());
|
||||
|
||||
Size2i image_size = p_image->get_size();
|
||||
|
||||
|
|
@ -3829,23 +4025,21 @@ void WaylandThread::cursor_shape_set_custom_image(DisplayServer::CursorShape p_c
|
|||
CustomCursor &cursor = custom_cursors[p_cursor_shape];
|
||||
cursor.hotspot = p_hotspot;
|
||||
|
||||
if (cursor.buffer_data) {
|
||||
// Clean up the old buffer data.
|
||||
munmap(cursor.buffer_data, cursor.buffer_data_size);
|
||||
}
|
||||
|
||||
// NOTE: From `wl_keyboard`s of version 7 or later, the spec requires the mmap
|
||||
// operation to be done with MAP_PRIVATE, as "MAP_SHARED may fail". We'll do it
|
||||
// regardless of global version.
|
||||
cursor.buffer_data = (uint32_t *)mmap(nullptr, data_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
|
||||
|
||||
if (cursor.wl_buffer) {
|
||||
// Clean up the old Wayland buffer.
|
||||
wl_buffer_destroy(cursor.wl_buffer);
|
||||
}
|
||||
|
||||
if (cursor.buffer_data) {
|
||||
// Clean up the old buffer data.
|
||||
munmap(cursor.buffer_data, cursor.buffer_data_size);
|
||||
}
|
||||
|
||||
cursor.buffer_data = (uint32_t *)mmap(nullptr, data_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
cursor.buffer_data_size = data_size;
|
||||
|
||||
// Create the Wayland buffer.
|
||||
struct wl_shm_pool *wl_shm_pool = wl_shm_create_pool(registry.wl_shm, fd, image_size.height * data_size);
|
||||
struct wl_shm_pool *wl_shm_pool = wl_shm_create_pool(registry.wl_shm, fd, data_size);
|
||||
// TODO: Make sure that WL_SHM_FORMAT_ARGB8888 format is supported. It
|
||||
// technically isn't garaunteed to be supported, but I think that'd be a
|
||||
// pretty unlikely thing to stumble upon.
|
||||
|
|
@ -3873,8 +4067,6 @@ void WaylandThread::cursor_shape_clear_custom_image(DisplayServer::CursorShape p
|
|||
CustomCursor cursor = custom_cursors[p_cursor_shape];
|
||||
custom_cursors.erase(p_cursor_shape);
|
||||
|
||||
current_custom_cursor = nullptr;
|
||||
|
||||
if (cursor.wl_buffer) {
|
||||
wl_buffer_destroy(cursor.wl_buffer);
|
||||
}
|
||||
|
|
@ -3979,6 +4171,7 @@ void WaylandThread::selection_set_text(const String &p_text) {
|
|||
|
||||
if (registry.wl_data_device_manager == nullptr) {
|
||||
DEBUG_LOG_WAYLAND_THREAD("Couldn't set selection, wl_data_device_manager global not available.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ss == nullptr) {
|
||||
|
|
@ -3997,10 +4190,10 @@ void WaylandThread::selection_set_text(const String &p_text) {
|
|||
wl_data_source_add_listener(ss->wl_data_source_selection, &wl_data_source_listener, ss);
|
||||
wl_data_source_offer(ss->wl_data_source_selection, "text/plain;charset=utf-8");
|
||||
wl_data_source_offer(ss->wl_data_source_selection, "text/plain");
|
||||
}
|
||||
|
||||
// TODO: Implement a good way of getting the latest serial from the user.
|
||||
wl_data_device_set_selection(ss->wl_data_device, ss->wl_data_source_selection, MAX(ss->pointer_data.button_serial, ss->last_key_pressed_serial));
|
||||
// TODO: Implement a good way of getting the latest serial from the user.
|
||||
wl_data_device_set_selection(ss->wl_data_device, ss->wl_data_source_selection, MAX(ss->pointer_data.button_serial, ss->last_key_pressed_serial));
|
||||
}
|
||||
|
||||
// Wait for the message to get to the server before continuing, otherwise the
|
||||
// clipboard update might come with a delay.
|
||||
|
|
@ -4106,6 +4299,11 @@ void WaylandThread::primary_set_text(const String &p_text) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (ss->wp_primary_selection_device == nullptr) {
|
||||
DEBUG_LOG_WAYLAND_THREAD("Couldn't set primary selection, seat doesn't have wp_primary_selection_device.");
|
||||
return;
|
||||
}
|
||||
|
||||
ss->primary_data = p_text.to_utf8_buffer();
|
||||
|
||||
if (ss->wp_primary_selection_source == nullptr) {
|
||||
|
|
@ -4113,10 +4311,10 @@ void WaylandThread::primary_set_text(const String &p_text) {
|
|||
zwp_primary_selection_source_v1_add_listener(ss->wp_primary_selection_source, &wp_primary_selection_source_listener, ss);
|
||||
zwp_primary_selection_source_v1_offer(ss->wp_primary_selection_source, "text/plain;charset=utf-8");
|
||||
zwp_primary_selection_source_v1_offer(ss->wp_primary_selection_source, "text/plain");
|
||||
}
|
||||
|
||||
// TODO: Implement a good way of getting the latest serial from the user.
|
||||
zwp_primary_selection_device_v1_set_selection(ss->wp_primary_selection_device, ss->wp_primary_selection_source, MAX(ss->pointer_data.button_serial, ss->last_key_pressed_serial));
|
||||
// TODO: Implement a good way of getting the latest serial from the user.
|
||||
zwp_primary_selection_device_v1_set_selection(ss->wp_primary_selection_device, ss->wp_primary_selection_source, MAX(ss->pointer_data.button_serial, ss->last_key_pressed_serial));
|
||||
}
|
||||
|
||||
// Wait for the message to get to the server before continuing, otherwise the
|
||||
// clipboard update might come with a delay.
|
||||
|
|
@ -4141,6 +4339,16 @@ bool WaylandThread::get_reset_frame() {
|
|||
// Dispatches events until a frame event is received, a window is reported as
|
||||
// suspended or the timeout expires.
|
||||
bool WaylandThread::wait_frame_suspend_ms(int p_timeout) {
|
||||
// This is a bit of a chicken and egg thing... Looks like the main event loop
|
||||
// has to call its rightfully forever-blocking poll right in between
|
||||
// `wl_display_prepare_read` and `wl_display_read`. This means, that it will
|
||||
// basically be guaranteed to stay stuck in a "prepare read" state, where it
|
||||
// will block any other attempt at reading the display fd, such as ours. The
|
||||
// solution? Let's make sure the mutex is locked (it should) and unblock the
|
||||
// main thread with a roundtrip!
|
||||
MutexLock mutex_lock(mutex);
|
||||
wl_display_roundtrip(wl_display);
|
||||
|
||||
if (main_window.suspended) {
|
||||
// The window is suspended! The compositor is telling us _explicitly_ that we
|
||||
// don't need to draw, without letting us guess through the frame event's
|
||||
|
|
@ -4373,6 +4581,10 @@ void WaylandThread::destroy() {
|
|||
xdg_activation_v1_destroy(registry.xdg_activation);
|
||||
}
|
||||
|
||||
if (registry.xdg_system_bell) {
|
||||
xdg_system_bell_v1_destroy(registry.xdg_system_bell);
|
||||
}
|
||||
|
||||
if (registry.xdg_decoration_manager) {
|
||||
zxdg_decoration_manager_v1_destroy(registry.xdg_decoration_manager);
|
||||
}
|
||||
|
|
@ -4389,10 +4601,14 @@ void WaylandThread::destroy() {
|
|||
xdg_wm_base_destroy(registry.xdg_wm_base);
|
||||
}
|
||||
|
||||
if (registry.xdg_exporter) {
|
||||
zxdg_exporter_v1_destroy(registry.xdg_exporter);
|
||||
// NOTE: Deprecated.
|
||||
if (registry.xdg_exporter_v1) {
|
||||
zxdg_exporter_v1_destroy(registry.xdg_exporter_v1);
|
||||
}
|
||||
|
||||
if (registry.xdg_exporter_v2) {
|
||||
zxdg_exporter_v2_destroy(registry.xdg_exporter_v2);
|
||||
}
|
||||
if (registry.wl_shm) {
|
||||
wl_shm_destroy(registry.wl_shm);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
#include <wayland-client-core.h>
|
||||
#include <wayland-cursor.h>
|
||||
#ifdef GLES3_ENABLED
|
||||
#include <wayland-egl.h>
|
||||
#include <wayland-egl-core.h>
|
||||
#endif
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#endif // SOWRAP_ENABLED
|
||||
|
|
@ -67,14 +67,18 @@
|
|||
#include "wayland/protocol/wayland.gen.h"
|
||||
#include "wayland/protocol/xdg_activation.gen.h"
|
||||
#include "wayland/protocol/xdg_decoration.gen.h"
|
||||
#include "wayland/protocol/xdg_foreign.gen.h"
|
||||
#include "wayland/protocol/xdg_foreign_v2.gen.h"
|
||||
#include "wayland/protocol/xdg_shell.gen.h"
|
||||
#include "wayland/protocol/xdg_system_bell.gen.h"
|
||||
|
||||
// NOTE: Deprecated.
|
||||
#include "wayland/protocol/xdg_foreign_v1.gen.h"
|
||||
|
||||
#ifdef LIBDECOR_ENABLED
|
||||
#ifdef SOWRAP_ENABLED
|
||||
#include "dynwrappers/libdecor-so_wrap.h"
|
||||
#else
|
||||
#include <libdecor-0/libdecor.h>
|
||||
#include <libdecor.h>
|
||||
#endif // SOWRAP_ENABLED
|
||||
#endif // LIBDECOR_ENABLED
|
||||
|
||||
|
|
@ -148,8 +152,12 @@ public:
|
|||
struct xdg_wm_base *xdg_wm_base = nullptr;
|
||||
uint32_t xdg_wm_base_name = 0;
|
||||
|
||||
struct zxdg_exporter_v1 *xdg_exporter = nullptr;
|
||||
uint32_t xdg_exporter_name = 0;
|
||||
// NOTE: Deprecated.
|
||||
struct zxdg_exporter_v1 *xdg_exporter_v1 = nullptr;
|
||||
uint32_t xdg_exporter_v1_name = 0;
|
||||
|
||||
uint32_t xdg_exporter_v2_name = 0;
|
||||
struct zxdg_exporter_v2 *xdg_exporter_v2 = nullptr;
|
||||
|
||||
// wayland-protocols globals.
|
||||
|
||||
|
|
@ -162,6 +170,9 @@ public:
|
|||
struct zxdg_decoration_manager_v1 *xdg_decoration_manager = nullptr;
|
||||
uint32_t xdg_decoration_manager_name = 0;
|
||||
|
||||
struct xdg_system_bell_v1 *xdg_system_bell = nullptr;
|
||||
uint32_t xdg_system_bell_name = 0;
|
||||
|
||||
struct xdg_activation_v1 *xdg_activation = nullptr;
|
||||
uint32_t xdg_activation_name = 0;
|
||||
|
||||
|
|
@ -220,7 +231,11 @@ public:
|
|||
|
||||
struct wp_viewport *wp_viewport = nullptr;
|
||||
struct wp_fractional_scale_v1 *wp_fractional_scale = nullptr;
|
||||
struct zxdg_exported_v1 *xdg_exported = nullptr;
|
||||
|
||||
// NOTE: Deprecated.
|
||||
struct zxdg_exported_v1 *xdg_exported_v1 = nullptr;
|
||||
|
||||
struct zxdg_exported_v2 *xdg_exported_v2 = nullptr;
|
||||
|
||||
String exported_handle;
|
||||
|
||||
|
|
@ -295,7 +310,7 @@ public:
|
|||
};
|
||||
|
||||
struct PointerData {
|
||||
Point2i position;
|
||||
Point2 position;
|
||||
uint32_t motion_time = 0;
|
||||
|
||||
// Relative motion has its own optional event and so needs its own time.
|
||||
|
|
@ -305,7 +320,7 @@ public:
|
|||
BitField<MouseButtonMask> pressed_button_mask;
|
||||
|
||||
MouseButton last_button_pressed = MouseButton::NONE;
|
||||
Point2i last_pressed_position;
|
||||
Point2 last_pressed_position;
|
||||
|
||||
// This is needed to check for a new double click every time.
|
||||
bool double_click_begun = false;
|
||||
|
|
@ -325,14 +340,14 @@ public:
|
|||
};
|
||||
|
||||
struct TabletToolData {
|
||||
Point2i position;
|
||||
Point2 position;
|
||||
Vector2 tilt;
|
||||
uint32_t pressure = 0;
|
||||
|
||||
BitField<MouseButtonMask> pressed_button_mask;
|
||||
|
||||
MouseButton last_button_pressed = MouseButton::NONE;
|
||||
Point2i last_pressed_position;
|
||||
Point2 last_pressed_position;
|
||||
|
||||
bool double_click_begun = false;
|
||||
|
||||
|
|
@ -413,6 +428,8 @@ public:
|
|||
const char *keymap_buffer = nullptr;
|
||||
uint32_t keymap_buffer_size = 0;
|
||||
|
||||
HashMap<xkb_keycode_t, Key> pressed_keycodes;
|
||||
|
||||
xkb_layout_index_t current_layout_index = 0;
|
||||
|
||||
int32_t repeat_key_delay_msec = 0;
|
||||
|
|
@ -469,7 +486,6 @@ public:
|
|||
uint32_t *buffer_data = nullptr;
|
||||
uint32_t buffer_data_size = 0;
|
||||
|
||||
RID rid;
|
||||
Point2i hotspot;
|
||||
};
|
||||
|
||||
|
|
@ -506,10 +522,8 @@ private:
|
|||
|
||||
HashMap<DisplayServer::CursorShape, CustomCursor> custom_cursors;
|
||||
|
||||
struct wl_cursor *current_wl_cursor = nullptr;
|
||||
struct CustomCursor *current_custom_cursor = nullptr;
|
||||
|
||||
DisplayServer::CursorShape last_cursor_shape = DisplayServer::CURSOR_ARROW;
|
||||
DisplayServer::CursorShape cursor_shape = DisplayServer::CURSOR_ARROW;
|
||||
bool cursor_visible = true;
|
||||
|
||||
PointerConstraint pointer_constraint = PointerConstraint::NONE;
|
||||
|
||||
|
|
@ -651,7 +665,10 @@ private:
|
|||
|
||||
static void _xdg_toplevel_decoration_on_configure(void *data, struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration, uint32_t mode);
|
||||
|
||||
static void _xdg_exported_on_exported(void *data, zxdg_exported_v1 *exported, const char *handle);
|
||||
// NOTE: Deprecated.
|
||||
static void _xdg_exported_v1_on_handle(void *data, zxdg_exported_v1 *exported, const char *handle);
|
||||
|
||||
static void _xdg_exported_v2_on_handle(void *data, zxdg_exported_v2 *exported, const char *handle);
|
||||
|
||||
static void _xdg_activation_token_on_done(void *data, struct xdg_activation_token_v1 *xdg_activation_token, const char *token);
|
||||
|
||||
|
|
@ -668,7 +685,7 @@ private:
|
|||
.preferred_buffer_transform = _wl_surface_on_preferred_buffer_transform,
|
||||
};
|
||||
|
||||
static constexpr struct wl_callback_listener frame_wl_callback_listener {
|
||||
static constexpr struct wl_callback_listener frame_wl_callback_listener = {
|
||||
.done = _frame_wl_callback_on_done,
|
||||
};
|
||||
|
||||
|
|
@ -686,7 +703,7 @@ private:
|
|||
.name = _wl_seat_on_name,
|
||||
};
|
||||
|
||||
static constexpr struct wl_callback_listener cursor_frame_callback_listener {
|
||||
static constexpr struct wl_callback_listener cursor_frame_callback_listener = {
|
||||
.done = _cursor_frame_callback_on_done,
|
||||
};
|
||||
|
||||
|
|
@ -819,8 +836,13 @@ private:
|
|||
.done = _wp_text_input_on_done,
|
||||
};
|
||||
|
||||
static constexpr struct zxdg_exported_v1_listener xdg_exported_listener = {
|
||||
.handle = _xdg_exported_on_exported
|
||||
// NOTE: Deprecated.
|
||||
static constexpr struct zxdg_exported_v1_listener xdg_exported_v1_listener = {
|
||||
.handle = _xdg_exported_v1_on_handle,
|
||||
};
|
||||
|
||||
static constexpr struct zxdg_exported_v2_listener xdg_exported_v2_listener = {
|
||||
.handle = _xdg_exported_v2_on_handle,
|
||||
};
|
||||
|
||||
static constexpr struct zxdg_toplevel_decoration_v1_listener xdg_toplevel_decoration_listener = {
|
||||
|
|
@ -883,7 +905,8 @@ private:
|
|||
static Vector<uint8_t> _wp_primary_selection_offer_read(struct wl_display *wl_display, const char *p_mime, struct zwp_primary_selection_offer_v1 *wp_primary_selection_offer);
|
||||
|
||||
static void _seat_state_set_current(WaylandThread::SeatState &p_ss);
|
||||
static bool _seat_state_configure_key_event(WaylandThread::SeatState &p_seat, Ref<InputEventKey> p_event, xkb_keycode_t p_keycode, bool p_pressed);
|
||||
static Ref<InputEventKey> _seat_state_get_key_event(SeatState *p_ss, xkb_keycode_t p_keycode, bool p_pressed);
|
||||
static Ref<InputEventKey> _seat_state_get_unstuck_key_event(SeatState *p_ss, xkb_keycode_t p_keycode, bool p_pressed, Key p_key);
|
||||
|
||||
static void _wayland_state_update_cursor();
|
||||
|
||||
|
|
@ -929,10 +952,14 @@ public:
|
|||
bool has_message();
|
||||
Ref<Message> pop_message();
|
||||
|
||||
void beep() const;
|
||||
|
||||
void window_create(DisplayServer::WindowID p_window_id, int p_width, int p_height);
|
||||
|
||||
struct wl_surface *window_get_wl_surface(DisplayServer::WindowID p_window_id) const;
|
||||
|
||||
void window_start_resize(DisplayServer::WindowResizeEdge p_edge, DisplayServer::WindowID p_window);
|
||||
|
||||
void window_set_max_size(DisplayServer::WindowID p_window_id, const Size2i &p_size);
|
||||
void window_set_min_size(DisplayServer::WindowID p_window_id, const Size2i &p_size);
|
||||
|
||||
|
|
@ -949,6 +976,8 @@ public:
|
|||
// Optional - requires xdg_activation_v1
|
||||
void window_request_attention(DisplayServer::WindowID p_window_id);
|
||||
|
||||
void window_start_drag(DisplayServer::WindowID p_window_id);
|
||||
|
||||
// Optional - require idle_inhibit_unstable_v1
|
||||
void window_set_idle_inhibition(DisplayServer::WindowID p_window_id, bool p_enable);
|
||||
bool window_get_idle_inhibition(DisplayServer::WindowID p_window_id) const;
|
||||
|
|
@ -962,7 +991,7 @@ public:
|
|||
DisplayServer::WindowID pointer_get_pointed_window_id() const;
|
||||
BitField<MouseButtonMask> pointer_get_button_mask() const;
|
||||
|
||||
void cursor_hide();
|
||||
void cursor_set_visible(bool p_visible);
|
||||
void cursor_set_shape(DisplayServer::CursorShape p_cursor_shape);
|
||||
|
||||
void cursor_set_custom_shape(DisplayServer::CursorShape p_cursor_shape);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue