From 34e449f96d82373e62370e018295f029f630286a Mon Sep 17 00:00:00 2001 From: Ray Smith Date: Tue, 23 Dec 2025 20:11:56 +0000 Subject: [PATCH 1/2] feat: Move Z-order management to the compositor OS-20183 --- patches/chromium/.patches | 1 + ...z-order-management-to-the-compositor.patch | 245 ++++++++++++++++++ 2 files changed, 246 insertions(+) create mode 100644 patches/chromium/os-20183-move-z-order-management-to-the-compositor.patch diff --git a/patches/chromium/.patches b/patches/chromium/.patches index e8debfb851f45..a1f03436fa0f1 100644 --- a/patches/chromium/.patches +++ b/patches/chromium/.patches @@ -205,3 +205,4 @@ feat_enable_cross-process_memory_pressure_notification_on_all.patch feat_brightsign_keep_compositing_active_for_window-level_zero.patch fix_brightsign_set_root_surface_opacity_when_window_level_opacity_is.patch brightsign_nexus_update_window_visibility_flag_on_opacity_change.patch +os-20183-move-z-order-management-to-the-compositor.patch diff --git a/patches/chromium/os-20183-move-z-order-management-to-the-compositor.patch b/patches/chromium/os-20183-move-z-order-management-to-the-compositor.patch new file mode 100644 index 0000000000000..efb6956b86ddb --- /dev/null +++ b/patches/chromium/os-20183-move-z-order-management-to-the-compositor.patch @@ -0,0 +1,245 @@ +From 71174e7bbd74c21f2a7f00d5949a5dfbba1d94f6 Mon Sep 17 00:00:00 2001 +From: Ray Smith +Date: Tue, 23 Dec 2025 19:46:23 +0000 +Subject: [PATCH] os-20183: move z-order management to the compositor + +Z-order is now managed in the compositor so that HTML and non-HTML +graphics widgets can be interspersed. +--- + third_party/wayland-protocols/BUILD.gn | 2 +- + .../bs-z-order/bs-z-order-unstable-v1.xml | 14 --------- + .../bs-z-order/bs-z-order-unstable-v2.xml | 31 +++++++++++++++++++ + ui/base/ui_base_types.h | 6 ++++ + .../platform/wayland/common/wayland_object.cc | 2 +- + .../platform/wayland/common/wayland_object.h | 4 +-- + .../wayland/host/wayland_connection.cc | 12 +++---- + .../wayland/host/wayland_connection.h | 4 +-- + .../wayland/host/xdg_toplevel_wrapper_impl.cc | 21 +++++++++++-- + 9 files changed, 68 insertions(+), 28 deletions(-) + delete mode 100644 third_party/wayland-protocols/unstable/bs-z-order/bs-z-order-unstable-v1.xml + create mode 100644 third_party/wayland-protocols/unstable/bs-z-order/bs-z-order-unstable-v2.xml + +diff --git a/third_party/wayland-protocols/BUILD.gn b/third_party/wayland-protocols/BUILD.gn +index c59c5a182c..3bbf95ba5b 100644 +--- a/third_party/wayland-protocols/BUILD.gn ++++ b/third_party/wayland-protocols/BUILD.gn +@@ -12,7 +12,7 @@ wayland_protocol("alpha_compositing_protocol") { + } + + wayland_protocol("bs_z_order_protocol") { +- sources = [ "unstable/bs-z-order/bs-z-order-unstable-v1.xml" ] ++ sources = [ "unstable/bs-z-order/bs-z-order-unstable-v2.xml" ] + } + + wayland_protocol("content_type_protocol") { +diff --git a/third_party/wayland-protocols/unstable/bs-z-order/bs-z-order-unstable-v1.xml b/third_party/wayland-protocols/unstable/bs-z-order/bs-z-order-unstable-v1.xml +deleted file mode 100644 +index da7ae7a6e2..0000000000 +--- a/third_party/wayland-protocols/unstable/bs-z-order/bs-z-order-unstable-v1.xml ++++ /dev/null +@@ -1,14 +0,0 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +diff --git a/third_party/wayland-protocols/unstable/bs-z-order/bs-z-order-unstable-v2.xml b/third_party/wayland-protocols/unstable/bs-z-order/bs-z-order-unstable-v2.xml +new file mode 100644 +index 0000000000..f961a47c67 +--- /dev/null ++++ b/third_party/wayland-protocols/unstable/bs-z-order/bs-z-order-unstable-v2.xml +@@ -0,0 +1,31 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/ui/base/ui_base_types.h b/ui/base/ui_base_types.h +index 73d3213322..183adefccc 100644 +--- a/ui/base/ui_base_types.h ++++ b/ui/base/ui_base_types.h +@@ -121,6 +121,12 @@ enum class ZOrderLevel { + // situations where window modality (as in ModalType) cannot or should not be + // used. + kSecuritySurface, ++ ++ // TODO: BrightSign hacks - need to be turned into function calls and plumbed all the way through once they're stable ++ kRaise = 566, ++ kLower = 565, ++ kRoleVirtualKeyboard = 567, ++ kRoleGraphics = 568, + }; + + // TODO(varunjain): Remove MENU_SOURCE_NONE (crbug.com/250964) +diff --git a/ui/ozone/platform/wayland/common/wayland_object.cc b/ui/ozone/platform/wayland/common/wayland_object.cc +index cf291424ff..e2703805cd 100644 +--- a/ui/ozone/platform/wayland/common/wayland_object.cc ++++ b/ui/ozone/platform/wayland/common/wayland_object.cc +@@ -190,7 +190,7 @@ void (*ObjectTraits::deleter)(void*) = &wl_proxy_wrapper_destroy; + // For convenience, keep aphabetical order in this list. + IMPLEMENT_WAYLAND_OBJECT_TRAITS(augmented_surface) + IMPLEMENT_WAYLAND_OBJECT_TRAITS(augmented_sub_surface) +-IMPLEMENT_WAYLAND_OBJECT_TRAITS(bs_z_order_v1) ++IMPLEMENT_WAYLAND_OBJECT_TRAITS(bs_z_order_v2) + IMPLEMENT_WAYLAND_OBJECT_TRAITS(gtk_primary_selection_device) + IMPLEMENT_WAYLAND_OBJECT_TRAITS(gtk_primary_selection_device_manager) + IMPLEMENT_WAYLAND_OBJECT_TRAITS(gtk_primary_selection_offer) +diff --git a/ui/ozone/platform/wayland/common/wayland_object.h b/ui/ozone/platform/wayland/common/wayland_object.h +index 9f2c034da7..fbbd0a8c8a 100644 +--- a/ui/ozone/platform/wayland/common/wayland_object.h ++++ b/ui/ozone/platform/wayland/common/wayland_object.h +@@ -6,7 +6,7 @@ + #define UI_OZONE_PLATFORM_WAYLAND_COMMON_WAYLAND_OBJECT_H_ + + #include +-#include ++#include + + #include "base/check.h" + #include "ui/ozone/platform/wayland/common/wayland.h" +@@ -106,7 +106,7 @@ bool CanBind(const std::string& interface, + // For convenience, keep aphabetical order in this list. + DECLARE_WAYLAND_OBJECT_TRAITS(augmented_surface) + DECLARE_WAYLAND_OBJECT_TRAITS(augmented_sub_surface) +-DECLARE_WAYLAND_OBJECT_TRAITS(bs_z_order_v1) ++DECLARE_WAYLAND_OBJECT_TRAITS(bs_z_order_v2) + DECLARE_WAYLAND_OBJECT_TRAITS(gtk_primary_selection_device) + DECLARE_WAYLAND_OBJECT_TRAITS(gtk_primary_selection_device_manager) + DECLARE_WAYLAND_OBJECT_TRAITS(gtk_primary_selection_offer) +diff --git a/ui/ozone/platform/wayland/host/wayland_connection.cc b/ui/ozone/platform/wayland/host/wayland_connection.cc +index e444e8d810..e0e77580fc 100644 +--- a/ui/ozone/platform/wayland/host/wayland_connection.cc ++++ b/ui/ozone/platform/wayland/host/wayland_connection.cc +@@ -8,7 +8,7 @@ + #include + #include + #include +-#include ++#include + + #include + #include +@@ -552,12 +552,12 @@ void WaylandConnection::HandleGlobal(void* data, + auto factory_it = global_object_factories_.find(interface); + if (factory_it != global_object_factories_.end()) { + (*factory_it->second)(this, registry, name, interface, version); +- } else if (!connection->bs_z_order_v1_ && +- strcmp(interface, "bs_z_order_v1") == 0) { +- connection->bs_z_order_v1_ = wl::Bind( ++ } else if (!connection->bs_z_order_v2_ && ++ strcmp(interface, "bs_z_order_v2") == 0) { ++ connection->bs_z_order_v2_ = wl::Bind( + registry, name, std::min(version, kMaxBsZOrderVersion)); +- if (!connection->bs_z_order_v1_) { +- LOG(ERROR) << "Failed to bind to bs_z_order_v1 global"; ++ if (!connection->bs_z_order_v2_) { ++ LOG(ERROR) << "Failed to bind to bs_z_order_v2 global"; + return; + } + } else if (!compositor_ && strcmp(interface, "wl_compositor") == 0) { +diff --git a/ui/ozone/platform/wayland/host/wayland_connection.h b/ui/ozone/platform/wayland/host/wayland_connection.h +index 2cb8078dba..44aae57cca 100644 +--- a/ui/ozone/platform/wayland/host/wayland_connection.h ++++ b/ui/ozone/platform/wayland/host/wayland_connection.h +@@ -110,7 +110,7 @@ class WaylandConnection { + // error. Called by WaylandEventWatcher. + void SetShutdownCb(base::OnceCallback shutdown_cb); + +- bs_z_order_v1* bs_z_order() const { return bs_z_order_v1_.get(); } ++ bs_z_order_v2* bs_z_order() const { return bs_z_order_v2_.get(); } + + // A correct display must be chosen when creating objects or calling + // roundrips. That is, all the methods that deal with polling, pulling event +@@ -433,7 +433,7 @@ class WaylandConnection { + base::flat_map global_object_factories_; + + uint32_t compositor_version_ = 0; +- wl::Object bs_z_order_v1_; ++ wl::Object bs_z_order_v2_; + wl::Object display_; + wl::Object wrapped_display_; + wl::Object event_queue_; +diff --git a/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc +index dd66fd2e2a..9e48717f37 100644 +--- a/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc ++++ b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc +@@ -6,7 +6,7 @@ + + #include + #include +-#include ++#include + + #include "base/logging.h" + #include "base/notreached.h" +@@ -78,6 +78,8 @@ zaura_toplevel_z_order_level ToZauraToplevelZOrderLevel( + return ZAURA_TOPLEVEL_Z_ORDER_LEVEL_FLOATING_UI_ELEMENT; + case ZOrderLevel::kSecuritySurface: + return ZAURA_TOPLEVEL_Z_ORDER_LEVEL_SECURITY_SURFACE; ++ default: // TODO: BrightSign hack. These ZOrderLevels won't exist. ++ abort(); + } + + NOTREACHED(); +@@ -580,7 +582,22 @@ void XDGToplevelWrapperImpl::SetZOrder(ZOrderLevel z_order) { + } + else if (!aura_toplevel_ && connection_->bs_z_order()) { + // The z-index we get if we are using xdg on a BS device is an absolute value. +- bs_z_order_v1_set_z_index(connection_->bs_z_order(), wayland_window_->root_surface()->surface(), (int)z_order); ++ switch (z_order) { ++ case ZOrderLevel::kRaise: ++ bs_z_order_v2_raise(connection_->bs_z_order(), wayland_window_->root_surface()->surface()); ++ break; ++ case ZOrderLevel::kLower: ++ bs_z_order_v2_lower(connection_->bs_z_order(), wayland_window_->root_surface()->surface()); ++ break; ++ case ZOrderLevel::kRoleVirtualKeyboard: ++ bs_z_order_v2_set_role(connection_->bs_z_order(), wayland_window_->root_surface()->surface(), BS_Z_ORDER_V2_ROLE_VIRTUAL_KEYBOARD); ++ break; ++ case ZOrderLevel::kRoleGraphics: ++ bs_z_order_v2_set_role(connection_->bs_z_order(), wayland_window_->root_surface()->surface(), BS_Z_ORDER_V2_ROLE_GRAPHICS); ++ break; ++ default: ++ abort(); ++ } + } + } + +-- +2.30.2 + From 66dcebba3fe1081602355ec040984929ec409fab Mon Sep 17 00:00:00 2001 From: Ray Smith Date: Mon, 9 Feb 2026 13:15:15 +0000 Subject: [PATCH 2/2] Nexus: Add full z-order support OS-20183 --- patches/chromium/.patches | 2 + ...ow-Add-full-z-order-support-OS-20183.patch | 82 +++++++++++++++++++ ...y-update-window-properties-that-actu.patch | 82 +++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 patches/chromium/nexus_window-Add-full-z-order-support-OS-20183.patch create mode 100644 patches/chromium/nexus_window-Only-update-window-properties-that-actu.patch diff --git a/patches/chromium/.patches b/patches/chromium/.patches index a1f03436fa0f1..3a66fc1eb473d 100644 --- a/patches/chromium/.patches +++ b/patches/chromium/.patches @@ -206,3 +206,5 @@ feat_brightsign_keep_compositing_active_for_window-level_zero.patch fix_brightsign_set_root_surface_opacity_when_window_level_opacity_is.patch brightsign_nexus_update_window_visibility_flag_on_opacity_change.patch os-20183-move-z-order-management-to-the-compositor.patch +nexus_window-Only-update-window-properties-that-actu.patch +nexus_window-Add-full-z-order-support-OS-20183.patch diff --git a/patches/chromium/nexus_window-Add-full-z-order-support-OS-20183.patch b/patches/chromium/nexus_window-Add-full-z-order-support-OS-20183.patch new file mode 100644 index 0000000000000..73640cb7b44e6 --- /dev/null +++ b/patches/chromium/nexus_window-Add-full-z-order-support-OS-20183.patch @@ -0,0 +1,82 @@ +From 5fc948128766ac57706fb26acdd9e370b8a772c4 Mon Sep 17 00:00:00 2001 +From: Ray Smith +Date: Mon, 9 Feb 2026 13:07:52 +0000 +Subject: [PATCH 2/2] nexus_window: Add full z-order support OS-20183 + +HTML and other graphics widget z-ordering is now handled in the +compositor. Plumb through the raise/lower commands to the compositor. + +Since the virtual keyboard is always on top, we just have to set its +special role and the compositor ensures it appears in the right place in +the z-order. +--- + ui/ozone/platform/nexus/nexus_window.cc | 28 +++++++++++++++++++++---- + ui/ozone/platform/nexus/nexus_window.h | 1 + + 2 files changed, 25 insertions(+), 4 deletions(-) + +diff --git a/ui/ozone/platform/nexus/nexus_window.cc b/ui/ozone/platform/nexus/nexus_window.cc +index 654ff513dc..3110546a61 100644 +--- a/ui/ozone/platform/nexus/nexus_window.cc ++++ b/ui/ozone/platform/nexus/nexus_window.cc +@@ -55,9 +55,6 @@ const NEXUS_BlendEquation ShowSourceColor = { + NEXUS_BlendFactor_eZero + }; + +-// Define z-order as constant +-const int kZOrder = 100; +- + namespace ui { + + NexusWindow::NexusWindow(PlatformWindowDelegate* delegate, +@@ -81,7 +78,6 @@ NexusWindow::NexusWindow(PlatformWindowDelegate* delegate, + win_info.y = bounds_.y(); + win_info.width = bounds_.width(); + win_info.height = bounds_.height(); +- win_info.zOrder = kZOrder; + win_info.colorBlend = HideSourceColor; + win_info.alphaBlend = HideSourceAlpha; + native_window_ = NXPL_CreateNativeWindowEXT(&win_info); +@@ -478,4 +474,28 @@ void NexusWindow::SetOpacity(float opacity) { + } + } + ++void NexusWindow::SetZOrderLevel(ZOrderLevel order) { ++ BS_DEBUG( "%s order: %d\n", __PRETTY_FUNCTION__, static_cast(order)); ++ ++ NXPL_NativeWindowInfoEXT win_info; ++ NXPL_GetNativeWindowInfoEXT(native_window_, &win_info); ++ switch (order) { ++ case ZOrderLevel::kRaise: ++ win_info.roleAction = NEXUS_BrightSignSurfaceAction_eRaise; ++ break; ++ case ZOrderLevel::kLower: ++ win_info.roleAction = NEXUS_BrightSignSurfaceAction_eLower; ++ break; ++ case ZOrderLevel::kRoleGraphics: ++ win_info.role = NEXUS_BrightSignSurfaceRole_eGraphics; ++ break; ++ case ZOrderLevel::kRoleVirtualKeyboard: ++ win_info.role = NEXUS_BrightSignSurfaceRole_eVirtualKeyboard; ++ break; ++ default: ++ break; ++ } ++ NXPL_UpdateNativeWindowEXT(native_window_, &win_info); ++} ++ + } // namespace ui +diff --git a/ui/ozone/platform/nexus/nexus_window.h b/ui/ozone/platform/nexus/nexus_window.h +index 9b3a965a8a..3cf0278c09 100644 +--- a/ui/ozone/platform/nexus/nexus_window.h ++++ b/ui/ozone/platform/nexus/nexus_window.h +@@ -79,6 +79,7 @@ class NexusWindow : public PlatformWindow, public PlatformEventDispatcher { + virtual bool IsTranslucentWindowOpacitySupported() const override; + virtual bool ShouldWindowContentsBeTransparent() const override; + virtual void SetOpacity(float opacity) override; ++ virtual void SetZOrderLevel(ZOrderLevel order) override; + + void UpdateBounds(const gfx::Rect& bounds); + void OnMouseEnter(); +-- +2.30.2 + diff --git a/patches/chromium/nexus_window-Only-update-window-properties-that-actu.patch b/patches/chromium/nexus_window-Only-update-window-properties-that-actu.patch new file mode 100644 index 0000000000000..3119628790627 --- /dev/null +++ b/patches/chromium/nexus_window-Only-update-window-properties-that-actu.patch @@ -0,0 +1,82 @@ +From e578fb7405c399d7ac98bb5889a8f0f145c9a092 Mon Sep 17 00:00:00 2001 +From: Ray Smith +Date: Mon, 9 Feb 2026 12:55:09 +0000 +Subject: [PATCH 1/2] nexus_window: Only update window properties that actually + change + +Now that NXPL_GetNativeWindowInfoEXT works properly, we don't need to +re-apply bounds, zorder etc. in unrelated functions. +--- + ui/ozone/platform/nexus/nexus_window.cc | 31 ++++--------------------- + 1 file changed, 4 insertions(+), 27 deletions(-) + +diff --git a/ui/ozone/platform/nexus/nexus_window.cc b/ui/ozone/platform/nexus/nexus_window.cc +index e126a07d15..654ff513dc 100644 +--- a/ui/ozone/platform/nexus/nexus_window.cc ++++ b/ui/ozone/platform/nexus/nexus_window.cc +@@ -110,12 +110,7 @@ void NexusWindow::Show(bool inactive) { + BS_DEBUG( "%s\n", __PRETTY_FUNCTION__); + visible_ = true; + NXPL_NativeWindowInfoEXT win_info; +- NXPL_GetDefaultNativeWindowInfoEXT(&win_info); +- win_info.x = bounds_.x(); +- win_info.y = bounds_.y(); +- win_info.width = bounds_.width(); +- win_info.height = bounds_.height(); +- win_info.zOrder = kZOrder; ++ NXPL_GetNativeWindowInfoEXT(native_window_, &win_info); + + // Apply current opacity when showing + if (opacity_ == 1.0f) { +@@ -153,12 +148,7 @@ void NexusWindow::Hide() { + BS_DEBUG( "%s\n", __PRETTY_FUNCTION__); + visible_ = false; + NXPL_NativeWindowInfoEXT win_info; +- NXPL_GetDefaultNativeWindowInfoEXT(&win_info); +- win_info.x = bounds_.x(); +- win_info.y = bounds_.y(); +- win_info.width = bounds_.width(); +- win_info.height = bounds_.height(); +- win_info.zOrder = kZOrder; ++ NXPL_GetNativeWindowInfoEXT(native_window_, &win_info); + win_info.colorBlend = HideSourceColor; + win_info.alphaBlend = HideSourceAlpha; + NXPL_UpdateNativeWindowEXT(native_window_, &win_info); +@@ -200,19 +190,11 @@ void NexusWindow::SetBoundsInPixels(const gfx::Rect& bounds) { + if (adjusted_bounds != bounds_) + { + NXPL_NativeWindowInfoEXT win_info; +- NXPL_GetDefaultNativeWindowInfoEXT(&win_info); ++ NXPL_GetNativeWindowInfoEXT(native_window_, &win_info); + win_info.x = adjusted_bounds.x(); + win_info.y = adjusted_bounds.y(); + win_info.width = adjusted_bounds.width(); + win_info.height = adjusted_bounds.height(); +- win_info.zOrder = kZOrder; +- if (!visible_ ) { +- win_info.colorBlend = HideSourceColor; +- win_info.alphaBlend = HideSourceAlpha; +- } +- else { +- win_info.colorBlend = ShowSourceColor; +- } + NXPL_UpdateNativeWindowEXT(native_window_, &win_info); + + bounds_ = adjusted_bounds; +@@ -455,12 +437,7 @@ void NexusWindow::SetOpacity(float opacity) { + // Update the window with new opacity settings + if (native_window_) { + NXPL_NativeWindowInfoEXT win_info; +- NXPL_GetDefaultNativeWindowInfoEXT(&win_info); +- win_info.x = bounds_.x(); +- win_info.y = bounds_.y(); +- win_info.width = bounds_.width(); +- win_info.height = bounds_.height(); +- win_info.zOrder = kZOrder; ++ NXPL_GetNativeWindowInfoEXT(native_window_, &win_info); + + if (!visible_ || opacity_ == 0.0f) { + // Hidden or fully transparent +-- +2.30.2 +