You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-16 14:00:40 +00:00
Wayland: Implement native sub-windows
The backend is now mature enough to not explode with multiple windows but the `DisplayServer` API still cannot meet some guarantees required by the various Wayland protocols we use. To meet those guarantees this patch adds three new elements to the DisplayServer API, with relative handling logic for `Window` and `Popup` nodes: - `WINDOW_EVENT_FORCE_CLOSE`, which tells a window to *forcefully* close itself and ensure a proper cleanup of its references, as Wayland enforces this behavior; - `WINDOW_FLAG_POPUP_WM_HINT`, which explicitly declares a window as a "popup", as Wayland enforces this distinction and heuristics are not reliable enough; - `FEATURE_SELF_FITTING_WINDOWS`, which signals that the compositor can fit windows to the screen automatically and that nodes should not do that themselves. Given the size of this feature, this patch also includes various `WaylandThread` reworks and fixes including: - Improvements to frame wait logic, with fixes to various stalls and a configurable (through a `#define`) timeout amount; - A proper implementation of `window_can_draw`; - Complete overhaul of pointer and tablet handling. Now everything is always accumulated and handled only on each respective `frame` event. This makes their logic simpler and more robust. - Better handling of pointer leaving and pointer enter/exit event sending; - Keyboard focus tracking; - More solid window references using IDs instead of raw pointers as windows can be deleted at any time; - More aggressive messaging to window nodes to enforce rects imposed by the compositor.
This commit is contained in:
@@ -835,6 +835,9 @@ void Window::_event_callback(DisplayServer::WindowEvent p_event) {
|
||||
case DisplayServer::WINDOW_EVENT_TITLEBAR_CHANGE: {
|
||||
emit_signal(SNAME("titlebar_changed"));
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EVENT_FORCE_CLOSE: {
|
||||
hide();
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1859,12 +1862,19 @@ void Window::popup(const Rect2i &p_screen_rect) {
|
||||
// Update window size to calculate the actual window size based on contents minimum size and minimum size.
|
||||
_update_window_size();
|
||||
|
||||
bool should_fit = !DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_SELF_FITTING_WINDOWS);
|
||||
|
||||
if (p_screen_rect != Rect2i()) {
|
||||
set_position(p_screen_rect.position);
|
||||
int screen_id = DisplayServer::get_singleton()->get_screen_from_rect(p_screen_rect);
|
||||
Size2i screen_size = DisplayServer::get_singleton()->screen_get_usable_rect(screen_id).size;
|
||||
Size2i new_size = p_screen_rect.size.min(screen_size);
|
||||
set_size(new_size);
|
||||
|
||||
if (should_fit) {
|
||||
int screen_id = DisplayServer::get_singleton()->get_screen_from_rect(p_screen_rect);
|
||||
Size2i screen_size = DisplayServer::get_singleton()->screen_get_usable_rect(screen_id).size;
|
||||
Size2i new_size = p_screen_rect.size.min(screen_size);
|
||||
set_size(new_size);
|
||||
} else {
|
||||
set_size(p_screen_rect.size);
|
||||
}
|
||||
}
|
||||
|
||||
Rect2i adjust = _popup_adjust_rect();
|
||||
@@ -1892,7 +1902,7 @@ void Window::popup(const Rect2i &p_screen_rect) {
|
||||
int screen_id = DisplayServer::get_singleton()->window_get_current_screen(get_window_id());
|
||||
parent_rect = DisplayServer::get_singleton()->screen_get_usable_rect(screen_id);
|
||||
}
|
||||
if (parent_rect != Rect2i() && !parent_rect.intersects(Rect2i(position, size))) {
|
||||
if (should_fit && parent_rect != Rect2i() && !parent_rect.intersects(Rect2i(position, size))) {
|
||||
ERR_PRINT(vformat("Window %d spawned at invalid position: %s.", get_window_id(), position));
|
||||
set_position((parent_rect.size - size) / 2);
|
||||
}
|
||||
@@ -3095,6 +3105,7 @@ void Window::_bind_methods() {
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "mouse_passthrough"), "set_flag", "get_flag", FLAG_MOUSE_PASSTHROUGH);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "sharp_corners"), "set_flag", "get_flag", FLAG_SHARP_CORNERS);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "exclude_from_capture"), "set_flag", "get_flag", FLAG_EXCLUDE_FROM_CAPTURE);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "popup_wm_hint"), "set_flag", "get_flag", FLAG_POPUP_WM_HINT);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_native"), "set_force_native", "get_force_native");
|
||||
|
||||
ADD_GROUP("Limits", "");
|
||||
@@ -3151,6 +3162,7 @@ void Window::_bind_methods() {
|
||||
BIND_ENUM_CONSTANT(FLAG_MOUSE_PASSTHROUGH);
|
||||
BIND_ENUM_CONSTANT(FLAG_SHARP_CORNERS);
|
||||
BIND_ENUM_CONSTANT(FLAG_EXCLUDE_FROM_CAPTURE);
|
||||
BIND_ENUM_CONSTANT(FLAG_POPUP_WM_HINT);
|
||||
BIND_ENUM_CONSTANT(FLAG_MAX);
|
||||
|
||||
BIND_ENUM_CONSTANT(CONTENT_SCALE_MODE_DISABLED);
|
||||
|
||||
Reference in New Issue
Block a user