diff --git a/src/wayland/handlers/xdg_activation.rs b/src/wayland/handlers/xdg_activation.rs index c740e296..e50c2172 100644 --- a/src/wayland/handlers/xdg_activation.rs +++ b/src/wayland/handlers/xdg_activation.rs @@ -106,132 +106,145 @@ impl XdgActivationHandler for State { let Some(context) = token_data.user_data.get::() else { return; }; - let mut shell = self.common.shell.write(); match context { ActivationContext::UrgentOnly => { + let shell = self.common.shell.write(); if let Some((workspace, _output)) = shell.workspace_for_surface(&surface) { let mut workspace_guard = self.common.workspace_state.update(); workspace_guard.add_workspace_state(&workspace, WState::Urgent); } } ActivationContext::Workspace(_) => { - let seat = shell.seats.last_active().clone(); - let current_output = seat.active_output(); - - if let Some(element) = shell.element_for_surface(&surface).cloned() { - if element.is_minimized() { - shell.unminimize_request(&surface, &seat, &self.common.event_loop_handle); - } - - let Some((element_output, element_workspace)) = shell - .space_for(&element) - .map(|w| (w.output.clone(), w.handle)) - else { - return; - }; - let in_current_workspace = - element_workspace == shell.active_space(¤t_output).unwrap().handle; - - if !in_current_workspace { - let Some(idx) = shell - .workspaces - .idx_for_handle(&element_output, &element_workspace) - else { - warn!("Couldn't determine idx for elements workspace?"); - return; - }; - - if let Err(err) = shell.activate( - &element_output, - idx, - WorkspaceDelta::new_shortcut(), - &mut self.common.workspace_state.update(), - ) { - warn!("Failed to activate the workspace: {err:?}"); - } - } - - let current_workspace = shell.active_space_mut(¤t_output).unwrap(); - current_workspace - .floating_layer - .space - .raise_element(&element, true); - if element.is_stack() { - if let Some((window, _)) = element.windows().find(|(window, _)| { - let mut found = false; - window.with_surfaces(|wl_surface, _| { - if wl_surface == &surface { - found = true; - } - }); - found - }) { - element.set_active(&window); - } else { - warn!("Failed to find activated window in the stack"); - return; - } - } - - if seat.get_keyboard().unwrap().current_focus() != Some(element.clone().into()) - && current_workspace.is_tiled(&surface) - { - for mapped in current_workspace - .mapped() - .filter(|m| m.maximized_state.lock().unwrap().is_some()) - .cloned() - .collect::>() - .into_iter() - { - current_workspace.unmaximize_request(&mapped); - } - } - - std::mem::drop(shell); - Shell::set_focus( - self, - Some(&KeyboardFocusTarget::Element(element.clone())), - &seat, - None, - false, - ); - } else if let Some((workspace, _)) = shell.workspace_for_surface(&surface) { - let current_workspace = shell.active_space(¤t_output).unwrap(); - if workspace == current_workspace.handle { - let Some(target) = shell - .workspaces - .space_for_handle(&workspace) - .unwrap() - .get_fullscreen() - .cloned() - .map(KeyboardFocusTarget::Fullscreen) - else { - return; - }; - - std::mem::drop(shell); - Shell::set_focus(self, Some(&target), &seat, None, false); - } else { - if let Some(surface) = shell - .workspaces - .space_for_handle(&workspace) - .and_then(|w| w.get_fullscreen()) - .cloned() - { - shell.append_focus_stack(surface, &seat) - } - let mut workspace_guard = self.common.workspace_state.update(); - workspace_guard.add_workspace_state(&workspace, WState::Urgent); - } - } else { - shell - .pending_activations - .insert(ActivationKey::Wayland(surface), *context); - }; + self.activate_surface( + &surface, + Some((ActivationKey::Wayland(surface.clone()), *context)), + ); } } } } +impl State { + pub fn activate_surface( + &mut self, + surface: &WlSurface, + pending_activation: Option<(ActivationKey, ActivationContext)>, + ) { + let mut shell = self.common.shell.write(); + + let seat = shell.seats.last_active().clone(); + let current_output = seat.active_output(); + + if let Some(element) = shell.element_for_surface(surface).cloned() { + if element.is_minimized() { + shell.unminimize_request(surface, &seat, &self.common.event_loop_handle); + } + + let Some((element_output, element_workspace)) = shell + .space_for(&element) + .map(|w| (w.output.clone(), w.handle)) + else { + return; + }; + let in_current_workspace = + element_workspace == shell.active_space(¤t_output).unwrap().handle; + + if !in_current_workspace { + let Some(idx) = shell + .workspaces + .idx_for_handle(&element_output, &element_workspace) + else { + warn!("Couldn't determine idx for elements workspace?"); + return; + }; + + if let Err(err) = shell.activate( + &element_output, + idx, + WorkspaceDelta::new_shortcut(), + &mut self.common.workspace_state.update(), + ) { + warn!("Failed to activate the workspace: {err:?}"); + } + } + + let current_workspace = shell.active_space_mut(¤t_output).unwrap(); + current_workspace + .floating_layer + .space + .raise_element(&element, true); + if element.is_stack() { + if let Some((window, _)) = element.windows().find(|(window, _)| { + let mut found = false; + window.with_surfaces(|wl_surface, _| { + if wl_surface == surface { + found = true; + } + }); + found + }) { + element.set_active(&window); + } else { + warn!("Failed to find activated window in the stack"); + return; + } + } + + if seat.get_keyboard().unwrap().current_focus() != Some(element.clone().into()) + && current_workspace.is_tiled(surface) + { + for mapped in current_workspace + .mapped() + .filter(|m| m.maximized_state.lock().unwrap().is_some()) + .cloned() + .collect::>() + .into_iter() + { + current_workspace.unmaximize_request(&mapped); + } + } + + std::mem::drop(shell); + Shell::set_focus( + self, + Some(&KeyboardFocusTarget::Element(element.clone())), + &seat, + None, + false, + ); + } else if let Some((workspace, _)) = shell.workspace_for_surface(&surface) { + let current_workspace = shell.active_space(¤t_output).unwrap(); + if workspace == current_workspace.handle { + let Some(target) = shell + .workspaces + .space_for_handle(&workspace) + .unwrap() + .get_fullscreen() + .cloned() + .map(KeyboardFocusTarget::Fullscreen) + else { + return; + }; + + std::mem::drop(shell); + Shell::set_focus(self, Some(&target), &seat, None, false); + } else { + if let Some(surface) = shell + .workspaces + .space_for_handle(&workspace) + .and_then(|w| w.get_fullscreen()) + .cloned() + { + shell.append_focus_stack(surface, &seat) + } + let mut workspace_guard = self.common.workspace_state.update(); + workspace_guard.add_workspace_state(&workspace, WState::Urgent); + } + } else if let Some((activation_key, context)) = pending_activation { + shell.pending_activations.insert(activation_key, context); + }; + } +} + delegate_xdg_activation!(State); diff --git a/src/xwayland.rs b/src/xwayland.rs index 01c7f2a1..825a3839 100644 --- a/src/xwayland.rs +++ b/src/xwayland.rs @@ -1110,6 +1110,18 @@ impl XwmHandler for State { } } + fn active_window_request( + &mut self, + _xwm: XwmId, + window: X11Surface, + _timestamp: u32, + _currently_active_window: Option, + ) { + if let Some(surface) = window.wl_surface() { + self.activate_surface(&surface, None); + } + } + fn send_selection( &mut self, _xwm: XwmId,