From 9c165ab56c281d369129f23f4491bb2c54c0bd8c Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Sun, 20 Jul 2025 11:18:32 +0200 Subject: [PATCH] config: allow disabling the primary selection --- jay-config/src/_private/client.rs | 4 ++++ jay-config/src/_private/ipc.rs | 3 +++ jay-config/src/lib.rs | 10 ++++++++++ src/compositor.rs | 1 + src/config/handler.rs | 7 +++++++ src/ifs/ipc/zwp_primary_selection_device_manager_v1.rs | 5 +++++ src/state.rs | 1 + toml-config/src/config.rs | 1 + toml-config/src/config/parsers/config.rs | 3 +++ toml-config/src/lib.rs | 7 +++++-- toml-spec/spec/spec.generated.json | 4 ++++ toml-spec/spec/spec.generated.md | 10 ++++++++++ toml-spec/spec/spec.yaml | 9 +++++++++ 13 files changed, 63 insertions(+), 2 deletions(-) diff --git a/jay-config/src/_private/client.rs b/jay-config/src/_private/client.rs index b9200780..8bcbf815 100644 --- a/jay-config/src/_private/client.rs +++ b/jay-config/src/_private/client.rs @@ -983,6 +983,10 @@ impl ConfigClient { show } + pub fn set_middle_click_paste_enabled(&self, enabled: bool) { + self.send(&ClientMessage::SetMiddleClickPasteEnabled { enabled }); + } + pub fn set_show_float_pin_icon(&self, show: bool) { self.send(&ClientMessage::SetShowFloatPinIcon { show }); } diff --git a/jay-config/src/_private/ipc.rs b/jay-config/src/_private/ipc.rs index 6d370b4b..71a12816 100644 --- a/jay-config/src/_private/ipc.rs +++ b/jay-config/src/_private/ipc.rs @@ -744,6 +744,9 @@ pub enum ClientMessage<'a> { SeatFocusTiles { seat: Seat, }, + SetMiddleClickPasteEnabled { + enabled: bool, + }, } #[derive(Serialize, Deserialize, Debug)] diff --git a/jay-config/src/lib.rs b/jay-config/src/lib.rs index 15926459..e7e9a586 100644 --- a/jay-config/src/lib.rs +++ b/jay-config/src/lib.rs @@ -343,3 +343,13 @@ pub fn toggle_show_bar() { pub fn on_unload(f: impl FnOnce() + 'static) { get!().on_unload(f); } + +/// Enables or disables middle-click pasting. +/// +/// This has no effect on applications that are already running. +/// +/// The default is `true`. +#[doc(alias("primary-selection", "primary_selection"))] +pub fn set_middle_click_paste_enabled(enabled: bool) { + get!().set_middle_click_paste_enabled(enabled); +} diff --git a/src/compositor.rs b/src/compositor.rs index 992bb189..392ee32d 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -352,6 +352,7 @@ fn start_compositor2( head_managers: Default::default(), head_managers_async: Default::default(), show_bar: Cell::new(true), + enable_primary_selection: Cell::new(true), }); state.tracker.register(ClientId::from_raw(0)); create_dummy_output(&state); diff --git a/src/config/handler.rs b/src/config/handler.rs index 995880ae..e9c86240 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -2204,6 +2204,10 @@ impl ConfigProxyHandler { Ok(()) } + fn handle_set_middle_click_paste_enabled(&self, enabled: bool) { + self.state.enable_primary_selection.set(enabled); + } + fn spaces_change(&self) { struct V; impl NodeVisitorBase for V { @@ -3064,6 +3068,9 @@ impl ConfigProxyHandler { ClientMessage::SeatFocusTiles { seat } => { self.handle_seat_focus_tiles(seat).wrn("seat_focus_tiles")? } + ClientMessage::SetMiddleClickPasteEnabled { enabled } => { + self.handle_set_middle_click_paste_enabled(enabled) + } } Ok(()) } diff --git a/src/ifs/ipc/zwp_primary_selection_device_manager_v1.rs b/src/ifs/ipc/zwp_primary_selection_device_manager_v1.rs index 9cee07d9..9bace1c4 100644 --- a/src/ifs/ipc/zwp_primary_selection_device_manager_v1.rs +++ b/src/ifs/ipc/zwp_primary_selection_device_manager_v1.rs @@ -8,6 +8,7 @@ use { }, leaks::Tracker, object::{Object, Version}, + state::State, wire::{ZwpPrimarySelectionDeviceManagerV1Id, zwp_primary_selection_device_manager_v1::*}, }, std::rc::Rc, @@ -96,6 +97,10 @@ impl Global for ZwpPrimarySelectionDeviceManagerV1Global { fn version(&self) -> u32 { 1 } + + fn exposed(&self, state: &State) -> bool { + state.enable_primary_selection.get() + } } simple_add_global!(ZwpPrimarySelectionDeviceManagerV1Global); diff --git a/src/state.rs b/src/state.rs index 28fa3f35..60c40c1c 100644 --- a/src/state.rs +++ b/src/state.rs @@ -272,6 +272,7 @@ pub struct State { CopyHashMap<(ClientId, JayHeadManagerSessionV1Id), Rc>, pub head_managers_async: AsyncQueue, pub show_bar: Cell, + pub enable_primary_selection: Cell, } // impl Drop for State { diff --git a/toml-config/src/config.rs b/toml-config/src/config.rs index 75b17815..a23d2d58 100644 --- a/toml-config/src/config.rs +++ b/toml-config/src/config.rs @@ -494,6 +494,7 @@ pub struct Config { pub use_hardware_cursor: Option, pub show_bar: Option, pub focus_history: Option, + pub middle_click_paste: Option, } #[derive(Debug, Error)] diff --git a/toml-config/src/config/parsers/config.rs b/toml-config/src/config/parsers/config.rs index 41bd364b..31b3448d 100644 --- a/toml-config/src/config/parsers/config.rs +++ b/toml-config/src/config/parsers/config.rs @@ -136,6 +136,7 @@ impl Parser for ConfigParser<'_> { show_bar, focus_history_val, ), + (middle_click_paste,), ) = ext.extract(( ( opt(val("keymap")), @@ -185,6 +186,7 @@ impl Parser for ConfigParser<'_> { recover(opt(bol("show-bar"))), opt(val("focus-history")), ), + (recover(opt(bol("middle-click-paste"))),), ))?; let mut keymap = None; if let Some(value) = keymap_val { @@ -513,6 +515,7 @@ impl Parser for ConfigParser<'_> { use_hardware_cursor: use_hardware_cursor.despan(), show_bar: show_bar.despan(), focus_history, + middle_click_paste: middle_click_paste.despan(), }) } } diff --git a/toml-config/src/lib.rs b/toml-config/src/lib.rs index 7caac63c..64c0daec 100644 --- a/toml-config/src/lib.rs +++ b/toml-config/src/lib.rs @@ -35,8 +35,8 @@ use { logging::set_log_level, on_devices_enumerated, on_idle, on_unload, quit, reload, set_color_management_enabled, set_default_workspace_capture, set_explicit_sync_enabled, set_float_above_fullscreen, - set_idle, set_idle_grace_period, set_show_bar, set_show_float_pin_icon, - set_ui_drag_enabled, set_ui_drag_threshold, + set_idle, set_idle_grace_period, set_middle_click_paste_enabled, set_show_bar, + set_show_float_pin_icon, set_ui_drag_enabled, set_ui_drag_threshold, status::{set_i3bar_separator, set_status, set_status_command, unset_status_command}, switch_to_vt, theme::{reset_colors, reset_font, reset_sizes, set_font}, @@ -1272,6 +1272,9 @@ fn load_config(initial_load: bool, persistent: &Rc) { persistent.seat.focus_history_set_same_workspace(v); } } + if let Some(v) = config.middle_click_paste { + set_middle_click_paste_enabled(v); + } } fn create_command(exec: &Exec) -> Command { diff --git a/toml-spec/spec/spec.generated.json b/toml-spec/spec/spec.generated.json index 90a3d3e3..798f4eb2 100644 --- a/toml-spec/spec/spec.generated.json +++ b/toml-spec/spec/spec.generated.json @@ -891,6 +891,10 @@ "focus-history": { "description": "Configures the focus-history settings.\n\n- Example:\n\n ```toml\n [focus-history]\n only-visible: true\n same-workspace: true\n ```\n", "$ref": "#/$defs/FocusHistory" + }, + "middle-click-paste": { + "type": "boolean", + "description": "Configures whether middle-click pasting is enabled.\n\nChanging this has no effect on running applications.\n\nThe default is `true`.\n" } }, "required": [] diff --git a/toml-spec/spec/spec.generated.md b/toml-spec/spec/spec.generated.md index 1abda90a..f0acdda6 100644 --- a/toml-spec/spec/spec.generated.md +++ b/toml-spec/spec/spec.generated.md @@ -1816,6 +1816,16 @@ The table has the following fields: The value of this field should be a [FocusHistory](#types-FocusHistory). +- `middle-click-paste` (optional): + + Configures whether middle-click pasting is enabled. + + Changing this has no effect on running applications. + + The default is `true`. + + The value of this field should be a boolean. + ### `Connector` diff --git a/toml-spec/spec/spec.yaml b/toml-spec/spec/spec.yaml index ba6c5f69..581084b4 100644 --- a/toml-spec/spec/spec.yaml +++ b/toml-spec/spec/spec.yaml @@ -2650,6 +2650,15 @@ Config: only-visible: true same-workspace: true ``` + middle-click-paste: + kind: boolean + required: false + description: | + Configures whether middle-click pasting is enabled. + + Changing this has no effect on running applications. + + The default is `true`. Idle: