feat: support xdg foreign parenting
This commit is contained in:
1 parent
e59a524827
commit
e57d355db2
3 files changed
+72
No files matched your search
@@ -27,6 +27,7 @@ use smithay::{
|
|||||||
PrimarySelectionHandler, PrimarySelectionState, set_primary_focus,
|
PrimarySelectionHandler, PrimarySelectionState, set_primary_focus,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
xdg_foreign::{XdgForeignHandler, XdgForeignState},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -150,6 +151,12 @@ impl PrimarySelectionHandler for Ferese {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl XdgForeignHandler for Ferese {
|
||||||
|
fn xdg_foreign_state(&mut self) -> &mut XdgForeignState {
|
||||||
|
&mut self.xdg_foreign_state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
smithay::delegate_compositor!(Ferese);
|
smithay::delegate_compositor!(Ferese);
|
||||||
smithay::delegate_data_device!(Ferese);
|
smithay::delegate_data_device!(Ferese);
|
||||||
smithay::delegate_fractional_scale!(Ferese);
|
smithay::delegate_fractional_scale!(Ferese);
|
||||||
@@ -165,4 +172,5 @@ smithay::delegate_single_pixel_buffer!(Ferese);
|
|||||||
smithay::delegate_viewporter!(Ferese);
|
smithay::delegate_viewporter!(Ferese);
|
||||||
smithay::delegate_xdg_activation!(Ferese);
|
smithay::delegate_xdg_activation!(Ferese);
|
||||||
smithay::delegate_xdg_decoration!(Ferese);
|
smithay::delegate_xdg_decoration!(Ferese);
|
||||||
|
smithay::delegate_xdg_foreign!(Ferese);
|
||||||
smithay::delegate_xdg_shell!(Ferese);
|
smithay::delegate_xdg_shell!(Ferese);
|
||||||
@@ -51,6 +51,31 @@ impl XdgShellHandler for Ferese {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parent_changed(&mut self, surface: ToplevelSurface) {
|
||||||
|
let Some(parent) = surface.parent() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let parent = self.window_ids.iter().find_map(|(window, id)| {
|
||||||
|
window
|
||||||
|
.toplevel()
|
||||||
|
.is_some_and(|toplevel| toplevel.wl_surface() == &parent)
|
||||||
|
.then_some(*id)
|
||||||
|
});
|
||||||
|
let child = self
|
||||||
|
.space
|
||||||
|
.elements()
|
||||||
|
.find(|window| {
|
||||||
|
window
|
||||||
|
.toplevel()
|
||||||
|
.is_some_and(|toplevel| toplevel.wl_surface() == surface.wl_surface())
|
||||||
|
})
|
||||||
|
.cloned();
|
||||||
|
|
||||||
|
if let (Some(parent), Some(child)) = (parent, child) {
|
||||||
|
self.make_window_transient(&child, parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn toplevel_destroyed(&mut self, surface: ToplevelSurface) {
|
fn toplevel_destroyed(&mut self, surface: ToplevelSurface) {
|
||||||
let Some(window) = self
|
let Some(window) = self
|
||||||
.space
|
.space
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ use smithay::{
|
|||||||
socket::ListeningSocketSource,
|
socket::ListeningSocketSource,
|
||||||
viewporter::ViewporterState,
|
viewporter::ViewporterState,
|
||||||
xdg_activation::XdgActivationState,
|
xdg_activation::XdgActivationState,
|
||||||
|
xdg_foreign::XdgForeignState,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -80,6 +81,7 @@ pub struct Ferese {
|
|||||||
pub viewporter_state: ViewporterState,
|
pub viewporter_state: ViewporterState,
|
||||||
pub layer_shell_state: WlrLayerShellState,
|
pub layer_shell_state: WlrLayerShellState,
|
||||||
pub xdg_activation_state: XdgActivationState,
|
pub xdg_activation_state: XdgActivationState,
|
||||||
|
pub xdg_foreign_state: XdgForeignState,
|
||||||
pub xdg_shell_state: XdgShellState,
|
pub xdg_shell_state: XdgShellState,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,6 +107,7 @@ impl Ferese {
|
|||||||
let viewporter_state = ViewporterState::new::<Self>(&display_handle);
|
let viewporter_state = ViewporterState::new::<Self>(&display_handle);
|
||||||
let layer_shell_state = WlrLayerShellState::new::<Self>(&display_handle);
|
let layer_shell_state = WlrLayerShellState::new::<Self>(&display_handle);
|
||||||
let xdg_activation_state = XdgActivationState::new::<Self>(&display_handle);
|
let xdg_activation_state = XdgActivationState::new::<Self>(&display_handle);
|
||||||
|
let xdg_foreign_state = XdgForeignState::new::<Self>(&display_handle);
|
||||||
let mut seat_state = SeatState::new();
|
let mut seat_state = SeatState::new();
|
||||||
let mut seat = seat_state.new_wl_seat(&display_handle, "ferese-winit");
|
let mut seat = seat_state.new_wl_seat(&display_handle, "ferese-winit");
|
||||||
seat.add_keyboard(Default::default(), 200, 25)?;
|
seat.add_keyboard(Default::default(), 200, 25)?;
|
||||||
@@ -145,6 +148,7 @@ impl Ferese {
|
|||||||
viewporter_state,
|
viewporter_state,
|
||||||
layer_shell_state,
|
layer_shell_state,
|
||||||
xdg_activation_state,
|
xdg_activation_state,
|
||||||
|
xdg_foreign_state,
|
||||||
xdg_shell_state,
|
xdg_shell_state,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -347,6 +351,41 @@ impl Ferese {
|
|||||||
self.relayout();
|
self.relayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn make_window_transient(&mut self, window: &Window, parent: WindowId) {
|
||||||
|
let Some(id) = self.window_ids.get(window).copied() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if self.workspaces.workspace_for_window(id) != self.workspaces.workspace_for_window(parent)
|
||||||
|
{
|
||||||
|
tracing::warn!(
|
||||||
|
?id,
|
||||||
|
?parent,
|
||||||
|
"ignored transient parent on another workspace"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let Some(bounds) = self.output_bounds() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let parent_rect = self.logical_window_rect(parent, bounds).unwrap_or(bounds);
|
||||||
|
let rect = centered_transient_rect(parent_rect);
|
||||||
|
let result = match self.workspaces.placement(id) {
|
||||||
|
Some(WindowPlacement::Tiled) => self
|
||||||
|
.workspaces
|
||||||
|
.toggle_floating(id, rect, Axis::Horizontal, 0.5)
|
||||||
|
.map(|_| ()),
|
||||||
|
Some(WindowPlacement::Floating { .. }) => self.workspaces.set_floating_rect(id, rect),
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(error) = result {
|
||||||
|
tracing::warn!(%error, ?id, ?parent, "failed to apply transient placement");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.relayout();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn remove_tiled_window(&mut self, window: &Window) {
|
pub fn remove_tiled_window(&mut self, window: &Window) {
|
||||||
let Some(id) = self.window_ids.remove(window) else {
|
let Some(id) = self.window_ids.remove(window) else {
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in new issue
Block a user