Skip to content

Commit

Permalink
Did someone say heuristic + basic 'n' broken popups
Browse files Browse the repository at this point in the history
  • Loading branch information
Riteo committed Sep 27, 2024
1 parent 9d8520d commit aecf0be
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 11 deletions.
38 changes: 27 additions & 11 deletions platform/linuxbsd/wayland/display_server_wayland.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ DisplayServer::WindowID DisplayServerWayland::create_sub_window(WindowMode p_mod
wd.mode = p_mode;
wd.flags = p_flags;
wd.vsync_mode = p_vsync_mode;
wd.rect.size = p_rect.size;
wd.rect = p_rect;
wd.title = "Godot";
wd.parent_id = p_transient_parent;
return id;
Expand All @@ -565,20 +565,26 @@ void DisplayServerWayland::show_window(WindowID p_window_id) {

if (!wd.visible) {
DEBUG_LOG_WAYLAND(vformat("Showing window %d", p_window_id));

// Showing this window will reset its mode with whatever the compositor
// reports. We'll save the mode beforehand so that we can reapply it later.
// TODO: Fix/Port/Move/Whatever to `WaylandThread` APIs.
WindowMode setup_mode = wd.mode;

wayland_thread.window_create(p_window_id, wd.rect.size.width, wd.rect.size.height);
wayland_thread.window_set_min_size(p_window_id, wd.min_size);
wayland_thread.window_set_max_size(p_window_id, wd.max_size);
wayland_thread.window_set_app_id(p_window_id, _get_app_id_from_context(context));
wayland_thread.window_set_borderless(p_window_id, window_get_flag(WINDOW_FLAG_BORDERLESS));

if (wd.parent_id != INVALID_WINDOW_ID) {
wayland_thread.window_set_parent(wd.id, wd.parent_id);
// DEBUG: Temporary heuristic to test popup logic. I'm pretty darn sure that
// we should not rely on it as a "popup flag".
// FIXME
if (!window_get_flag(WINDOW_FLAG_RESIZE_DISABLED, p_window_id)) {
wayland_thread.window_create(p_window_id, wd.rect.size.width, wd.rect.size.height);
wayland_thread.window_set_min_size(p_window_id, wd.min_size);
wayland_thread.window_set_max_size(p_window_id, wd.max_size);
wayland_thread.window_set_app_id(p_window_id, _get_app_id_from_context(context));
wayland_thread.window_set_borderless(p_window_id, window_get_flag(WINDOW_FLAG_BORDERLESS));

if (wd.parent_id != INVALID_WINDOW_ID) {
wayland_thread.window_set_parent(wd.id, wd.parent_id);
}
} else {
DEBUG_LOG_WAYLAND("!!!!! Making popup !!!!!");
wayland_thread.window_create_popup(p_window_id, wd.parent_id, wd.rect);
}

// NOTE: The XDG shell protocol is built in a way that causes the window to
Expand Down Expand Up @@ -611,6 +617,10 @@ void DisplayServerWayland::show_window(WindowID p_window_id) {
rendering_context->window_set_vsync_mode(wd.id, DisplayServer::VSYNC_MAILBOX);
}
}

if (rendering_device) {
rendering_device->screen_create(wd.id);
}
#endif

#ifdef GLES3_ENABLED
Expand Down Expand Up @@ -643,6 +653,10 @@ void DisplayServerWayland::delete_sub_window(WindowID p_window_id) {
ERR_FAIL_COND(!windows.has(p_window_id));

#ifdef VULKAN_ENABLED
if (rendering_device) {
rendering_device->screen_free(p_window_id);
}

if (rendering_context) {
rendering_context->window_destroy(p_window_id);
}
Expand All @@ -657,6 +671,8 @@ void DisplayServerWayland::delete_sub_window(WindowID p_window_id) {
wayland_thread.window_destroy(p_window_id);

windows.erase(p_window_id);

DEBUG_LOG_WAYLAND(vformat("Deleted window %d", p_window_id));
}

int64_t DisplayServerWayland::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const {
Expand Down
54 changes: 54 additions & 0 deletions platform/linuxbsd/wayland/wayland_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3248,6 +3248,7 @@ Ref<WaylandThread::Message> WaylandThread::pop_message() {
}

void WaylandThread::window_create(DisplayServer::WindowID p_window_id, int p_width, int p_height) {
ERR_FAIL_COND(windows.has(p_window_id));
WindowState &ws = windows[p_window_id];

ws.id = p_window_id;
Expand Down Expand Up @@ -3314,6 +3315,55 @@ void WaylandThread::window_create(DisplayServer::WindowID p_window_id, int p_wid
wl_display_roundtrip(wl_display);
}

void WaylandThread::window_create_popup(DisplayServer::WindowID p_window_id, DisplayServer::WindowID p_parent_id, Rect2i p_rect) {
ERR_FAIL_COND(windows.has(p_window_id));
ERR_FAIL_COND(!windows.has(p_parent_id));

WindowState &ws = windows[p_window_id];
WindowState &parent = windows[p_parent_id];

ws.id = p_window_id;
ws.registry = &registry;
ws.wayland_thread = this;

ws.rect = p_rect;

ws.wl_surface = wl_compositor_create_surface(registry.wl_compositor);
wl_proxy_tag_godot((struct wl_proxy *)ws.wl_surface);
wl_surface_add_listener(ws.wl_surface, &wl_surface_listener, &ws);

if (registry.wp_viewporter) {
ws.wp_viewport = wp_viewporter_get_viewport(registry.wp_viewporter, ws.wl_surface);

if (registry.wp_fractional_scale_manager) {
ws.wp_fractional_scale = wp_fractional_scale_manager_v1_get_fractional_scale(registry.wp_fractional_scale_manager, ws.wl_surface);
wp_fractional_scale_v1_add_listener(ws.wp_fractional_scale, &wp_fractional_scale_listener, &ws);
}
}

ws.xdg_surface = xdg_wm_base_get_xdg_surface(registry.xdg_wm_base, ws.wl_surface);
xdg_surface_add_listener(ws.xdg_surface, &xdg_surface_listener, &ws);

struct xdg_positioner *xdg_positioner = xdg_wm_base_create_positioner(registry.xdg_wm_base);
xdg_positioner_set_size(xdg_positioner, ws.rect.size.width, ws.rect.size.height);
xdg_positioner_set_anchor(xdg_positioner, XDG_POSITIONER_ANCHOR_TOP_LEFT);
xdg_positioner_set_gravity(xdg_positioner, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT);
xdg_positioner_set_anchor_rect(xdg_positioner, ws.rect.position.x, ws.rect.position.y, parent.rect.size.width, parent.rect.size.height);

// TODO: handle libdecor
ws.xdg_popup = xdg_surface_get_popup(ws.xdg_surface, parent.xdg_surface, xdg_positioner);

xdg_positioner_destroy(xdg_positioner);

ws.frame_callback = wl_surface_frame(ws.wl_surface);
wl_callback_add_listener(ws.frame_callback, &frame_wl_callback_listener, &ws);

wl_surface_commit(ws.wl_surface);

// Wait for the surface to be configured before continuing.
wl_display_roundtrip(wl_display);
}

void WaylandThread::window_destroy(DisplayServer::WindowID p_window_id) {
ERR_FAIL_COND(!windows.has(p_window_id));
WindowState &ws = windows[p_window_id];
Expand All @@ -3340,6 +3390,10 @@ void WaylandThread::window_destroy(DisplayServer::WindowID p_window_id) {
zxdg_toplevel_decoration_v1_destroy(ws.xdg_toplevel_decoration);
}

if (ws.xdg_popup) {
xdg_popup_destroy(ws.xdg_popup);
}

if (ws.xdg_toplevel) {
xdg_toplevel_destroy(ws.xdg_toplevel);
}
Expand Down
3 changes: 3 additions & 0 deletions platform/linuxbsd/wayland/wayland_thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ class WaylandThread {
struct wp_fractional_scale_v1 *wp_fractional_scale = nullptr;
struct zxdg_exported_v1 *xdg_exported = nullptr;

struct xdg_popup *xdg_popup = nullptr;

String exported_handle;

// Currently applied buffer scale.
Expand Down Expand Up @@ -932,6 +934,7 @@ class WaylandThread {
Ref<Message> pop_message();

void window_create(DisplayServer::WindowID p_window_id, int p_width, int p_height);
void window_create_popup(DisplayServer::WindowID p_window_id, DisplayServer::WindowID p_parent_id, Rect2i p_rect);
void window_destroy(DisplayServer::WindowID p_window_Id);

void window_set_parent(DisplayServer::WindowID p_window_id, DisplayServer::WindowID p_parent_id);
Expand Down

0 comments on commit aecf0be

Please sign in to comment.