From eeb1b7547fc469a63421727e9689a6053978545c Mon Sep 17 00:00:00 2001 From: Lauro Moura Date: Thu, 22 Aug 2024 11:25:06 -0300 Subject: [PATCH] [WPE] Consider actual available size instead of whole screen size for screen.availHeight and screen.availWidth https://bugs.webkit.org/show_bug.cgi?id=278511 Reviewed by NOBODY (OOPS!). Add new wpe_monitor_get_available_width/height API to report the available screen size. This is used to feed JS's screen.availWidth/availHeight[1]. If not possible to detect the available dimensions, fallback to the previous behavior of using the whole screen size, as it's also one of the accepted values in the spec: > The Web-exposed available screen area is one of the following: > The available area of the rendering surface of the output device, in CSS pixels. > The area of the output device, in CSS pixels. https://drafts.csswg.org/cssom-view/#dom-screen-availw In Wayland, use the `xdg_toplevel::configure_bounds` event to get the information from the compositor. Given Wayland design decisions, we can't get the actual screen position of the client, so we default to (0,0). This is not a problem regarding the `availWidth/availHeight`, which is the information settled currently in the CSS spec. For the record, this position limitation might become an issue when Window Management's `availLeft/availTop`[2] eventually become an accepted standard. This limitation is described in the Window Management github, in [3]. [1] https://developer.mozilla.org/en-US/docs/Web/API/Screen/availHeight [2] https://w3c.github.io/window-management/#ref-for-dom-screendetailed-availleft [3] https://github.com/w3c/window-management/issues/68 * Source/WebKit/UIProcess/wpe/ScreenManagerWPE.cpp: (WebKit::ScreenManager::collectScreenProperties const): * Source/WebKit/WPEPlatform/wpe/WPEMonitor.cpp: (wpeMonitorGetProperty): (wpe_monitor_class_init): (wpe_monitor_get_available_width): (wpe_monitor_get_available_height): (wpe_monitor_set_available_size): * Source/WebKit/WPEPlatform/wpe/WPEMonitor.h: * Source/WebKit/WPEPlatform/wpe/wayland/WPEDisplayWayland.cpp: * Source/WebKit/WPEPlatform/wpe/wayland/WPEToplevelWayland.cpp: (wpeToplevelWaylandConstructed): --- .../WebKit/UIProcess/wpe/ScreenManagerWPE.cpp | 4 +- Source/WebKit/WPEPlatform/wpe/WPEMonitor.cpp | 100 ++++++++++++++++++ Source/WebKit/WPEPlatform/wpe/WPEMonitor.h | 5 + .../wpe/wayland/WPEDisplayWayland.cpp | 2 +- .../wpe/wayland/WPEToplevelWayland.cpp | 9 +- 5 files changed, 115 insertions(+), 5 deletions(-) diff --git a/Source/WebKit/UIProcess/wpe/ScreenManagerWPE.cpp b/Source/WebKit/UIProcess/wpe/ScreenManagerWPE.cpp index efb0637ee873c..202eea3af0984 100644 --- a/Source/WebKit/UIProcess/wpe/ScreenManagerWPE.cpp +++ b/Source/WebKit/UIProcess/wpe/ScreenManagerWPE.cpp @@ -81,7 +81,9 @@ ScreenProperties ScreenManager::collectScreenProperties() const ScreenData data; data.screenRect = FloatRect(wpe_monitor_get_x(monitor), wpe_monitor_get_y(monitor), width, height); - data.screenAvailableRect = data.screenRect; + // TODO: add some API to get the available position to support screen.availTop/Left if it become a standard in the future + // For now we're settling to 0,0 as Wayland doesn't provide this information to clients + data.screenAvailableRect = FloatRect(0, 0, wpe_monitor_get_available_width(monitor), wpe_monitor_get_available_height(monitor)); data.screenDepth = 24; data.screenDepthPerComponent = 8; data.screenSize = { wpe_monitor_get_physical_width(monitor), wpe_monitor_get_physical_height(monitor) }; diff --git a/Source/WebKit/WPEPlatform/wpe/WPEMonitor.cpp b/Source/WebKit/WPEPlatform/wpe/WPEMonitor.cpp index 798b139fffff0..4afe2c05d515f 100644 --- a/Source/WebKit/WPEPlatform/wpe/WPEMonitor.cpp +++ b/Source/WebKit/WPEPlatform/wpe/WPEMonitor.cpp @@ -38,6 +38,8 @@ struct _WPEMonitorPrivate { int y { -1 }; int width { -1 }; int height { -1 }; + int availableWidth { -1 }; + int availableHeight { -1 }; int physicalWidth { -1 }; int physicalHeight { -1 }; gdouble scale { 1 }; @@ -54,6 +56,8 @@ enum { PROP_Y, PROP_WIDTH, PROP_HEIGHT, + PROP_AVAILABLE_WIDTH, + PROP_AVAILABLE_HEIGHT, PROP_PHYSICAL_WIDTH, PROP_PHYSICAL_HEIGHT, PROP_SCALE, @@ -84,6 +88,12 @@ static void wpeMonitorSetProperty(GObject* object, guint propId, const GValue* v case PROP_HEIGHT: wpe_monitor_set_size(monitor, -1, g_value_get_int(value)); break; + case PROP_AVAILABLE_WIDTH: + wpe_monitor_set_available_size(monitor, g_value_get_int(value), -1); + break; + case PROP_AVAILABLE_HEIGHT: + wpe_monitor_set_available_size(monitor, -1, g_value_get_int(value)); + break; case PROP_PHYSICAL_WIDTH: wpe_monitor_set_physical_size(monitor, g_value_get_int(value), -1); break; @@ -121,6 +131,12 @@ static void wpeMonitorGetProperty(GObject* object, guint propId, GValue* value, case PROP_HEIGHT: g_value_set_int(value, wpe_monitor_get_height(monitor)); break; + case PROP_AVAILABLE_WIDTH: + g_value_set_int(value, wpe_monitor_get_available_width(monitor)); + break; + case PROP_AVAILABLE_HEIGHT: + g_value_set_int(value, wpe_monitor_get_available_height(monitor)); + break; case PROP_PHYSICAL_WIDTH: g_value_set_int(value, wpe_monitor_get_physical_width(monitor)); break; @@ -204,6 +220,32 @@ static void wpe_monitor_class_init(WPEMonitorClass* monitorClass) -1, G_MAXINT, -1, WEBKIT_PARAM_READWRITE); + /** + * WPEMonitor:available-width: + * + * The available width of the monitor in logical coordinates. This is the + * width of the monitor excluding any reserved areas like docks or panels. + */ + sObjProperties[PROP_AVAILABLE_WIDTH] = + g_param_spec_int( + "available-width", + nullptr, nullptr, + -1, G_MAXINT, -1, + WEBKIT_PARAM_READWRITE); + + /** + * WPEMonitor:available-height: + * + * The available height of the monitor in logical coordinates. This is the + * height of the monitor excluding any reserved areas like docks or panels. + */ + sObjProperties[PROP_AVAILABLE_HEIGHT] = + g_param_spec_int( + "available-height", + nullptr, nullptr, + -1, G_MAXINT, -1, + WEBKIT_PARAM_READWRITE); + /** * WPEMonitor:physical-width: * @@ -398,6 +440,64 @@ void wpe_monitor_set_size(WPEMonitor* monitor, int width, int height) } } +/** + * wpe_monitor_get_available_width: + * @monitor: a #WPEMonitor + * + * Get the available width of @monitor in logical coordinates. This is the + * width of the monitor excluding any reserved areas like docks or panels. + * + * Returns: the available width of @monitor, or the full monitor width if available width could not be determined. + */ +int wpe_monitor_get_available_width(WPEMonitor* monitor) +{ + g_return_val_if_fail(WPE_IS_MONITOR(monitor), -1); + + return monitor->priv->availableWidth != -1 ? monitor->priv->availableWidth : monitor->priv->width; +} + +/** + * wpe_monitor_get_available_height: + * @monitor: a #WPEMonitor + * + * Get the available height of @monitor in logical coordinates. This is the + * height of the monitor excluding any reserved areas like docks or panels. + * + * Returns: the available height of @monitor, or the full monitor height if available height could not be determined. + */ +int wpe_monitor_get_available_height(WPEMonitor* monitor) +{ + g_return_val_if_fail(WPE_IS_MONITOR(monitor), -1); + + return monitor->priv->availableHeight != -1 ? monitor->priv->availableHeight : monitor->priv->height; +} + +/** + * wpe_monitor_set_available_size: + * @monitor: a #WPEMonitor + * @width: the available width, or -1 + * @height: the available height, o -1 + * + * Set the available size of @monitor in logical coordinates. This is the + * size of the monitor excluding any reserved areas like docks or panels. + */ +void wpe_monitor_set_available_size(WPEMonitor* monitor, int width, int height) +{ + g_return_if_fail(WPE_IS_MONITOR(monitor)); + g_return_if_fail(width == -1 || width >= 0); + g_return_if_fail(height == -1 || height >= 0); + + if (width != -1 && width != monitor->priv->availableWidth) { + monitor->priv->availableWidth = width; + g_object_notify_by_pspec(G_OBJECT(monitor), sObjProperties[PROP_AVAILABLE_WIDTH]); + } + + if (height != -1 && height != monitor->priv->availableHeight) { + monitor->priv->availableHeight = height; + g_object_notify_by_pspec(G_OBJECT(monitor), sObjProperties[PROP_AVAILABLE_HEIGHT]); + } +} + /** * wpe_monitor_get_physical_width: * @monitor: a #WPEMonitor diff --git a/Source/WebKit/WPEPlatform/wpe/WPEMonitor.h b/Source/WebKit/WPEPlatform/wpe/WPEMonitor.h index 2de297b521496..6d2fa1348243c 100644 --- a/Source/WebKit/WPEPlatform/wpe/WPEMonitor.h +++ b/Source/WebKit/WPEPlatform/wpe/WPEMonitor.h @@ -59,6 +59,11 @@ WPE_API int wpe_monitor_get_height (WPEMonitor *monitor); WPE_API void wpe_monitor_set_size (WPEMonitor *monitor, int width, int height); +WPE_API int wpe_monitor_get_available_width (WPEMonitor *monitor); +WPE_API int wpe_monitor_get_available_height(WPEMonitor *monitor); +WPE_API void wpe_monitor_set_available_size (WPEMonitor *monitor, + int width, + int height); WPE_API int wpe_monitor_get_physical_width (WPEMonitor *monitor); WPE_API int wpe_monitor_get_physical_height (WPEMonitor *monitor); WPE_API void wpe_monitor_set_physical_size (WPEMonitor *monitor, diff --git a/Source/WebKit/WPEPlatform/wpe/wayland/WPEDisplayWayland.cpp b/Source/WebKit/WPEPlatform/wpe/wayland/WPEDisplayWayland.cpp index dd140328c4ddb..d60d227ddff75 100644 --- a/Source/WebKit/WPEPlatform/wpe/wayland/WPEDisplayWayland.cpp +++ b/Source/WebKit/WPEPlatform/wpe/wayland/WPEDisplayWayland.cpp @@ -216,7 +216,7 @@ const struct wl_registry_listener registryListener = { if (!std::strcmp(interface, "wl_compositor")) priv->wlCompositor = static_cast(wl_registry_bind(registry, name, &wl_compositor_interface, std::min(version, 5))); else if (!std::strcmp(interface, "xdg_wm_base")) - priv->xdgWMBase = static_cast(wl_registry_bind(registry, name, &xdg_wm_base_interface, 1)); + priv->xdgWMBase = static_cast(wl_registry_bind(registry, name, &xdg_wm_base_interface, std::min(version, 4))); // FIXME: support zxdg_shell_v6? else if (!std::strcmp(interface, "wl_seat")) priv->wlSeat = makeUnique(static_cast(wl_registry_bind(registry, name, &wl_seat_interface, std::min(version, 8)))); diff --git a/Source/WebKit/WPEPlatform/wpe/wayland/WPEToplevelWayland.cpp b/Source/WebKit/WPEPlatform/wpe/wayland/WPEToplevelWayland.cpp index f8174725117be..f4b468642cabe 100644 --- a/Source/WebKit/WPEPlatform/wpe/wayland/WPEToplevelWayland.cpp +++ b/Source/WebKit/WPEPlatform/wpe/wayland/WPEToplevelWayland.cpp @@ -349,8 +349,11 @@ const struct xdg_toplevel_listener xdgToplevelListener = { }, #ifdef XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION // configure_bounds - [](void*, struct xdg_toplevel*, int32_t, int32_t) + [](void* data, struct xdg_toplevel*, int32_t width, int32_t height) { + auto* priv = WPE_TOPLEVEL_WAYLAND(data)->priv; + if (priv->currentMonitor) + wpe_monitor_set_available_size(priv->currentMonitor.get(), width, height); }, #endif #ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION @@ -567,8 +570,6 @@ static void wpeToplevelWaylandConstructed(GObject *object) zwp_linux_dmabuf_feedback_v1_add_listener(priv->dmabufFeedback, &linuxDMABufFeedbackListener, object); } - wl_display_roundtrip(wpe_display_wayland_get_wl_display(display)); - // Set the first monitor as the default one until enter monitor is emitted. if (wpe_display_get_n_monitors(WPE_DISPLAY(display))) { priv->currentMonitor = wpe_display_get_monitor(WPE_DISPLAY(display), 0); @@ -578,6 +579,8 @@ static void wpeToplevelWaylandConstructed(GObject *object) wpe_toplevel_scale_changed(toplevel, scale); } + wl_display_roundtrip(wpe_display_wayland_get_wl_display(display)); + if (auto* explicitSync = wpeDisplayWaylandGetLinuxExplicitSync(display)) priv->surfaceSync = zwp_linux_explicit_synchronization_v1_get_synchronization(explicitSync, priv->wlSurface); }