Skip to content

Add GlobalFactory::can_view to filter globals on a per-client basis#4859

Open
mattkae wants to merge 2 commits intomainfrom
wayland-rs-global-filter
Open

Add GlobalFactory::can_view to filter globals on a per-client basis#4859
mattkae wants to merge 2 commits intomainfrom
wayland-rs-global-filter

Conversation

@mattkae
Copy link
Copy Markdown
Contributor

@mattkae mattkae commented Apr 16, 2026

What's new?

  • Implement a wl_display_set_global_filter equivalent on the GlobalFactory class

Checklist

  • Tests added and pass
  • Adequate documentation added
  • (optional) Added Screenshots or videos

@mattkae mattkae marked this pull request as ready for review April 20, 2026 13:42
@mattkae mattkae requested a review from a team as a code owner April 20, 2026 13:42
Base automatically changed from wayland-rs-wayland-client to main April 21, 2026 08:25
Copilot AI review requested due to automatic review settings April 21, 2026 12:15
@mattkae mattkae force-pushed the wayland-rs-global-filter branch from 5862a79 to 9df6ce8 Compare April 21, 2026 12:15
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the Wayland Rust/C++ bridging layer to support per-client filtering of advertised Wayland globals by adding a GlobalFactory::can_view() hook that is wired into generated GlobalDispatch implementations (similar in spirit to wl_display_set_global_filter).

Changes:

  • Generate GlobalDispatch::can_view() implementations that delegate global visibility decisions to ffi::GlobalFactory::can_view().
  • Extend the C++ header generator to emit a GlobalFactory::can_view() virtual method and forward-declare WaylandClientId.
  • Add CppType::Bool support to the generator so C++ bool return/arg types can be emitted and bound to Rust.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/server/frontend_wayland/wayland_rs/build_script/main.rs Generates can_view() in Rust dispatch and adds a corresponding virtual method to the generated GlobalFactory C++ interface.
src/server/frontend_wayland/wayland_rs/build_script/cpp_builder.rs Adds generator support for C++/Rust bool types needed by GlobalFactory::can_view().

fn can_view(client: Client, global_data: &Arc<Mutex<cxx::UniquePtr<ffi::GlobalFactory>>>) -> bool {
let interface_name = #interface_name_str.to_string();
let client_id = Box::new(WaylandClientId::new(client.id()));
let mut guard = global_data.lock().unwrap();
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GlobalDispatch::can_view() unconditionally calls pin_mut() on the UniquePtr<ffi::GlobalFactory>. Since WaylandServer::run() accepts a possibly-null UniquePtr<GlobalFactory> (e.g. the example passes nullptr), this can panic at runtime when can_view is invoked. Consider explicitly handling the null case (e.g. treat a null factory as "no filtering" and return true, or skip registering filtered globals when factory is null) before calling into C++.

Suggested change
let mut guard = global_data.lock().unwrap();
let mut guard = global_data.lock().unwrap();
if guard.is_null() {
return false;
}

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nah. You can't have a null GlobalFactory.

}

fn can_view(client: Client, global_data: &Arc<Mutex<cxx::UniquePtr<ffi::GlobalFactory>>>) -> bool {
let interface_name = #interface_name_str.to_string();
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can_view() allocates a new String on every call (#interface_name_str.to_string()). Global visibility checks can happen frequently (per client and per global), so this adds avoidable allocation/UTF-8 copying. Consider generating a 'static interface-name constant and/or changing the FFI to accept a borrowed string (e.g. &str/rust::Str) so the check can run without heap allocation.

Suggested change
let interface_name = #interface_name_str.to_string();
let interface_name = #interface_name_str;

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's not unreasonable. This could totally be rust::Str on the C++ side, rather than rust::String.

Comment on lines +667 to +675
let mut can_view_method =
CppMethod::new("can_view", Some(CppType::Bool), true, false, true, true);
can_view_method.add_arg(CppArg::new(CppType::String, "interface_name", false));
can_view_method.add_arg(CppArg::new(
CppType::Box("WaylandClientId".to_string()),
"client_id",
false,
));
class.add_method(can_view_method);
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The generated GlobalFactory::can_view() signature takes ownership of client_id as a rust::Box<WaylandClientId>, which forces a heap allocation in Rust for every visibility check and transfers ownership across the FFI boundary. If can_view is expected to be called often, consider switching the API to take a lightweight identifier (e.g. ClientId/u32) or a borrowed reference so the check can be performed without per-call allocation/ownership transfer.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wereas this one would be annoying to pass as a reference, I think?

@mattkae mattkae requested a review from RAOF April 21, 2026 12:22
}

fn can_view(client: Client, global_data: &Arc<Mutex<cxx::UniquePtr<ffi::GlobalFactory>>>) -> bool {
let interface_name = #interface_name_str.to_string();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's not unreasonable. This could totally be rust::Str on the C++ side, rather than rust::String.

Comment on lines +667 to +675
let mut can_view_method =
CppMethod::new("can_view", Some(CppType::Bool), true, false, true, true);
can_view_method.add_arg(CppArg::new(CppType::String, "interface_name", false));
can_view_method.add_arg(CppArg::new(
CppType::Box("WaylandClientId".to_string()),
"client_id",
false,
));
class.add_method(can_view_method);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wereas this one would be annoying to pass as a reference, I think?

fn can_view(client: Client, global_data: &Arc<Mutex<cxx::UniquePtr<ffi::GlobalFactory>>>) -> bool {
let interface_name = #interface_name_str.to_string();
let client_id = Box::new(WaylandClientId::new(client.id()));
let mut guard = global_data.lock().unwrap();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nah. You can't have a null GlobalFactory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants