xwayland: Delay selection notify until focused

This commit is contained in:
Victoria Brekenfeld 2025-05-28 16:16:56 +02:00 committed by Victoria Brekenfeld
parent b5e60fcde5
commit 087ebaa2c7
2 changed files with 63 additions and 9 deletions

View file

@ -18,19 +18,42 @@ impl SelectionHandler for State {
source: Option<SelectionSource>,
_seat: Seat<State>,
) {
if let Some(xwm) = self
let Some(xwm_id) = self
.common
.xwayland_state
.as_mut()
.and_then(|xstate| xstate.xwm.as_mut())
{
if let Some(source) = &source {
.as_ref()
.and_then(|xstate| xstate.xwm.as_ref())
.map(|xwm| xwm.id())
else {
return;
};
let x_has_focus = self.common.has_x_keyboard_focus(xwm_id);
let xstate = self.common.xwayland_state.as_mut().unwrap();
let xwm = xstate.xwm.as_mut().unwrap();
if let Some(source) = &source {
if x_has_focus {
if let Err(err) = xwm.new_selection(target, Some(source.mime_types())) {
warn!(?err, "Failed to set Xwayland clipboard selection.");
}
} else if let Err(err) = xwm.new_selection(target, None) {
} else {
match target {
SelectionTarget::Clipboard => {
xstate.clipboard_selection_dirty = Some(source.mime_types())
}
SelectionTarget::Primary => {
xstate.primary_selection_dirty = Some(source.mime_types())
}
};
}
} else {
if let Err(err) = xwm.new_selection(target, None) {
warn!(?err, "Failed to clear Xwayland selection.");
}
xstate.clipboard_selection_dirty = None;
xstate.primary_selection_dirty = None;
}
}

View file

@ -64,6 +64,8 @@ pub struct XWaylandState {
pub pressed_keys: Vec<Keycode>,
pub pressed_buttons: Vec<u32>,
pub last_modifier_state: Option<ModifiersState>,
pub clipboard_selection_dirty: Option<Vec<String>>,
pub primary_selection_dirty: Option<Vec<String>>,
}
impl State {
@ -108,6 +110,8 @@ impl State {
pressed_keys: Vec::new(),
pressed_buttons: Vec::new(),
last_modifier_state: None,
clipboard_selection_dirty: None,
primary_selection_dirty: None,
});
let wm = match X11Wm::start_wm(
@ -244,7 +248,7 @@ impl XWaylandState {
}
impl Common {
fn has_x_keyboard_focus(&self, xwmid: XwmId) -> bool {
pub fn has_x_keyboard_focus(&self, xwmid: XwmId) -> bool {
let keyboard = self
.shell
.read()
@ -290,10 +294,37 @@ impl Common {
if target
.as_ref()
.is_some_and(|target| matches!(target, KeyboardFocusTarget::LockSurface(_)))
|| (!self.has_x_keyboard_focus(xwm_id)
&& target.as_ref().is_some_and(|target| target.is_xwm(xwm_id)))
{
self.xwayland_reset_eavesdropping(serial);
return;
}
if !self.has_x_keyboard_focus(xwm_id)
&& target.as_ref().is_some_and(|target| target.is_xwm(xwm_id))
{
self.xwayland_reset_eavesdropping(serial);
let xstate = self.xwayland_state.as_mut().unwrap();
if let Some(mime_types) = xstate.clipboard_selection_dirty.take() {
if let Err(err) = xstate
.xwm
.as_mut()
.unwrap()
.new_selection(SelectionTarget::Clipboard, Some(mime_types))
{
warn!(?err, "Failed to set Xwayland clipboard selection.");
}
}
if let Some(mime_types) = xstate.primary_selection_dirty.take() {
if let Err(err) = xstate
.xwm
.as_mut()
.unwrap()
.new_selection(SelectionTarget::Primary, Some(mime_types))
{
warn!(?err, "Failed to set Xwayland clipboard selection.");
}
}
}
}
}