diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-08-13 09:15:57 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-08-13 09:15:57 +0300 |
| commit | 883763c17224c69094340d3abc2f9e4cb656966a (patch) | |
| tree | c00a17f5b1283ff78cc8e8a9bc3e819c9c4a3049 | |
| parent | 9063a5dbdc0d4470dc1e13ce5749838e32af6a44 (diff) | |
| download | niri-883763c17224c69094340d3abc2f9e4cb656966a.tar.gz niri-883763c17224c69094340d3abc2f9e4cb656966a.tar.bz2 niri-883763c17224c69094340d3abc2f9e4cb656966a.zip | |
Implement stub mutter-x11-interop
Allows xdp-gnome dialogs to work with X11 clients.
Fixes https://github.com/YaLTeR/niri/issues/594
| -rw-r--r-- | Cargo.lock | 2 | ||||
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | resources/mutter-x11-interop.xml | 18 | ||||
| -rw-r--r-- | src/handlers/mod.rs | 8 | ||||
| -rw-r--r-- | src/niri.rs | 5 | ||||
| -rw-r--r-- | src/protocols/mod.rs | 3 | ||||
| -rw-r--r-- | src/protocols/mutter_x11_interop.rs | 93 | ||||
| -rw-r--r-- | src/protocols/raw.rs | 25 |
8 files changed, 154 insertions, 2 deletions
@@ -2260,6 +2260,8 @@ dependencies = [ "tracing-subscriber", "tracy-client", "url", + "wayland-backend", + "wayland-scanner", "xcursor", "xshell", "zbus", @@ -78,6 +78,8 @@ tracing-subscriber.workspace = true tracing.workspace = true tracy-client.workspace = true url = { version = "2.5.2", optional = true } +wayland-backend = "0.3.6" +wayland-scanner = "0.31.4" xcursor = "0.3.6" zbus = { version = "~3.15.2", optional = true } diff --git a/resources/mutter-x11-interop.xml b/resources/mutter-x11-interop.xml new file mode 100644 index 00000000..ae5bccda --- /dev/null +++ b/resources/mutter-x11-interop.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<protocol name="mutter_x11_interop"> + <description summary="X11 interoperability helper"> + This protocol is intended to be used by the portal backend to map Wayland + dialogs as modal dialogs on top of X11 windows. + </description> + + <interface name="mutter_x11_interop" version="1"> + <description summary="X11 interoperability helper"/> + + <request name="destroy" type="destructor"/> + + <request name="set_x11_parent"> + <arg name="surface" type="object" interface="wl_surface"/> + <arg name="xwindow" type="uint"/> + </request> + </interface> +</protocol> diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index b5c4392d..3e0bb18f 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -69,12 +69,13 @@ use crate::protocols::foreign_toplevel::{ self, ForeignToplevelHandler, ForeignToplevelManagerState, }; use crate::protocols::gamma_control::{GammaControlHandler, GammaControlManagerState}; +use crate::protocols::mutter_x11_interop::MutterX11InteropHandler; use crate::protocols::output_management::{OutputManagementHandler, OutputManagementManagerState}; use crate::protocols::screencopy::{Screencopy, ScreencopyHandler, ScreencopyManagerState}; use crate::utils::{output_size, send_scale_transform}; use crate::{ - delegate_foreign_toplevel, delegate_gamma_control, delegate_output_management, - delegate_screencopy, + delegate_foreign_toplevel, delegate_gamma_control, delegate_mutter_x11_interop, + delegate_output_management, delegate_screencopy, }; impl SeatHandler for State { @@ -580,3 +581,6 @@ impl OutputManagementHandler for State { } } delegate_output_management!(State); + +impl MutterX11InteropHandler for State {} +delegate_mutter_x11_interop!(State); diff --git a/src/niri.rs b/src/niri.rs index 024df37e..9aec5ed1 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -118,6 +118,7 @@ use crate::ipc::server::IpcServer; use crate::layout::{Layout, LayoutElement as _, MonitorRenderElement}; use crate::protocols::foreign_toplevel::{self, ForeignToplevelManagerState}; use crate::protocols::gamma_control::GammaControlManagerState; +use crate::protocols::mutter_x11_interop::MutterX11InteropManagerState; use crate::protocols::output_management::OutputManagementManagerState; use crate::protocols::screencopy::{Screencopy, ScreencopyBuffer, ScreencopyManagerState}; use crate::pw_utils::{Cast, PipeWire}; @@ -233,6 +234,7 @@ pub struct Niri { pub security_context_state: SecurityContextState, pub gamma_control_manager_state: GammaControlManagerState, pub activation_state: XdgActivationState, + pub mutter_x11_interop_state: MutterX11InteropManagerState, pub seat: Seat<State>, /// Scancodes of the keys to suppress. @@ -1602,6 +1604,8 @@ impl Niri { is_tty && !client.get_data::<ClientState>().unwrap().restricted }); let activation_state = XdgActivationState::new::<State>(&display_handle); + let mutter_x11_interop_state = + MutterX11InteropManagerState::new::<State, _>(&display_handle, move |_| true); let mut seat: Seat<State> = seat_state.new_wl_seat(&display_handle, backend.seat_name()); seat.add_keyboard( @@ -1764,6 +1768,7 @@ impl Niri { security_context_state, gamma_control_manager_state, activation_state, + mutter_x11_interop_state, seat, keyboard_focus: KeyboardFocus::Layout { surface: None }, diff --git a/src/protocols/mod.rs b/src/protocols/mod.rs index a58b48bf..3328fb7c 100644 --- a/src/protocols/mod.rs +++ b/src/protocols/mod.rs @@ -1,4 +1,7 @@ pub mod foreign_toplevel; pub mod gamma_control; +pub mod mutter_x11_interop; pub mod output_management; pub mod screencopy; + +pub mod raw; diff --git a/src/protocols/mutter_x11_interop.rs b/src/protocols/mutter_x11_interop.rs new file mode 100644 index 00000000..cce41f15 --- /dev/null +++ b/src/protocols/mutter_x11_interop.rs @@ -0,0 +1,93 @@ +use mutter_x11_interop::MutterX11Interop; +use smithay::reexports::wayland_server::{ + Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, +}; + +use super::raw::mutter_x11_interop::v1::server::mutter_x11_interop; + +const VERSION: u32 = 1; + +pub struct MutterX11InteropManagerState {} + +pub struct MutterX11InteropManagerGlobalData { + filter: Box<dyn for<'c> Fn(&'c Client) -> bool + Send + Sync>, +} + +pub trait MutterX11InteropHandler {} + +impl MutterX11InteropManagerState { + pub fn new<D, F>(display: &DisplayHandle, filter: F) -> Self + where + D: GlobalDispatch<MutterX11Interop, MutterX11InteropManagerGlobalData>, + D: Dispatch<MutterX11Interop, ()>, + D: MutterX11InteropHandler, + D: 'static, + F: for<'c> Fn(&'c Client) -> bool + Send + Sync + 'static, + { + let global_data = MutterX11InteropManagerGlobalData { + filter: Box::new(filter), + }; + display.create_global::<D, MutterX11Interop, _>(VERSION, global_data); + + Self {} + } +} + +impl<D> GlobalDispatch<MutterX11Interop, MutterX11InteropManagerGlobalData, D> + for MutterX11InteropManagerState +where + D: GlobalDispatch<MutterX11Interop, MutterX11InteropManagerGlobalData>, + D: Dispatch<MutterX11Interop, ()>, + D: MutterX11InteropHandler, + D: 'static, +{ + fn bind( + _state: &mut D, + _handle: &DisplayHandle, + _client: &Client, + manager: New<MutterX11Interop>, + _manager_state: &MutterX11InteropManagerGlobalData, + data_init: &mut DataInit<'_, D>, + ) { + data_init.init(manager, ()); + } + + fn can_view(client: Client, global_data: &MutterX11InteropManagerGlobalData) -> bool { + (global_data.filter)(&client) + } +} + +impl<D> Dispatch<MutterX11Interop, (), D> for MutterX11InteropManagerState +where + D: Dispatch<MutterX11Interop, ()>, + D: MutterX11InteropHandler, + D: 'static, +{ + fn request( + _state: &mut D, + _client: &Client, + _resource: &MutterX11Interop, + request: <MutterX11Interop as Resource>::Request, + _data: &(), + _dhandle: &DisplayHandle, + _data_init: &mut DataInit<'_, D>, + ) { + match request { + mutter_x11_interop::Request::Destroy => (), + mutter_x11_interop::Request::SetX11Parent { .. } => (), + } + } +} + +#[macro_export] +macro_rules! delegate_mutter_x11_interop { + ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { + smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + $crate::protocols::raw::mutter_x11_interop::v1::server::mutter_x11_interop::MutterX11Interop: $crate::protocols::mutter_x11_interop::MutterX11InteropManagerGlobalData + ] => $crate::protocols::mutter_x11_interop::MutterX11InteropManagerState); + + smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ + $crate::protocols::raw::mutter_x11_interop::v1::server::mutter_x11_interop::MutterX11Interop: () + ] => $crate::protocols::mutter_x11_interop::MutterX11InteropManagerState); + }; +} diff --git a/src/protocols/raw.rs b/src/protocols/raw.rs new file mode 100644 index 00000000..fac1e4df --- /dev/null +++ b/src/protocols/raw.rs @@ -0,0 +1,25 @@ +pub mod mutter_x11_interop { + pub mod v1 { + pub use self::generated::server; + + mod generated { + pub mod server { + #![allow(dead_code, non_camel_case_types, unused_unsafe, unused_variables)] + #![allow(non_upper_case_globals, non_snake_case, unused_imports)] + #![allow(missing_docs, clippy::all)] + + use smithay::reexports::wayland_server; + use wayland_server::protocol::*; + + pub mod __interfaces { + use smithay::reexports::wayland_server; + use wayland_server::protocol::__interfaces::*; + wayland_scanner::generate_interfaces!("resources/mutter-x11-interop.xml"); + } + use self::__interfaces::*; + + wayland_scanner::generate_server_code!("resources/mutter-x11-interop.xml"); + } + } + } +} |
