xwayland: Add initial support

This commit is contained in:
Victoria Brekenfeld 2023-01-18 20:23:41 +01:00
parent 78ffe3a93d
commit 1d28574088
23 changed files with 781 additions and 185 deletions

View file

@ -7,14 +7,11 @@ use smithay::{
find_popup_root_surface, PopupGrab, PopupKeyboardGrab, PopupKind, PopupPointerGrab,
PopupUngrabStrategy, Window,
},
input::{
pointer::{Focus, GrabStartData as PointerGrabStartData},
Seat,
},
input::{pointer::Focus, Seat},
output::Output,
reexports::{
wayland_protocols::xdg::shell::server::xdg_toplevel,
wayland_server::protocol::{wl_output::WlOutput, wl_seat::WlSeat, wl_surface::WlSurface},
wayland_server::protocol::{wl_output::WlOutput, wl_seat::WlSeat},
},
utils::Serial,
wayland::{
@ -70,7 +67,7 @@ impl XdgShellHandler for State {
let kind = PopupKind::Xdg(surface);
if let Some(root) = find_popup_root_surface(&kind)
.ok()
.and_then(|root| self.common.shell.element_for_surface(&root))
.and_then(|root| self.common.shell.element_for_wl_surface(&root))
{
let target = root.clone().into();
let ret = self
@ -138,38 +135,7 @@ impl XdgShellHandler for State {
fn move_request(&mut self, surface: ToplevelSurface, seat: WlSeat, serial: Serial) {
let seat = Seat::from_resource(&seat).unwrap();
if let Some(start_data) = check_grab_preconditions(&seat, surface.wl_surface(), serial) {
if let Some(mapped) = self
.common
.shell
.element_for_surface(surface.wl_surface())
.cloned()
{
if let Some(workspace) = self.common.shell.space_for_mut(&mapped) {
let output = seat.active_output();
let (window, _) = mapped
.windows()
.find(|(w, _)| w.wl_surface().as_ref() == Some(surface.wl_surface()))
.unwrap();
if let Some(grab) =
workspace.move_request(&window, &seat, &output, serial, start_data)
{
let handle = workspace.handle;
self.common
.shell
.toplevel_info_state
.toplevel_leave_workspace(&window, &handle);
self.common
.shell
.toplevel_info_state
.toplevel_leave_output(&window, &output);
seat.get_pointer()
.unwrap()
.set_grab(self, grab, serial, Focus::Clear);
}
}
}
}
Shell::move_request(self, surface.wl_surface(), &seat, serial)
}
fn resize_request(
@ -180,24 +146,7 @@ impl XdgShellHandler for State {
edges: xdg_toplevel::ResizeEdge,
) {
let seat = Seat::from_resource(&seat).unwrap();
if let Some(start_data) = check_grab_preconditions(&seat, surface.wl_surface(), serial) {
if let Some(mapped) = self
.common
.shell
.element_for_surface(surface.wl_surface())
.cloned()
{
if let Some(workspace) = self.common.shell.space_for_mut(&mapped) {
if let Some(grab) =
workspace.resize_request(&mapped, &seat, serial, start_data, edges)
{
seat.get_pointer()
.unwrap()
.set_grab(self, grab, serial, Focus::Clear);
}
}
}
}
Shell::resize_request(self, surface.wl_surface(), &seat, serial, edges.into())
}
fn maximize_request(&mut self, surface: ToplevelSurface) {
@ -207,7 +156,7 @@ impl XdgShellHandler for State {
if let Some(mapped) = self
.common
.shell
.element_for_surface(surface.wl_surface())
.element_for_wl_surface(surface.wl_surface())
.cloned()
{
if let Some(workspace) = self.common.shell.space_for_mut(&mapped) {
@ -224,7 +173,7 @@ impl XdgShellHandler for State {
if let Some(mapped) = self
.common
.shell
.element_for_surface(surface.wl_surface())
.element_for_wl_surface(surface.wl_surface())
.cloned()
{
if let Some(workspace) = self.common.shell.space_for_mut(&mapped) {
@ -249,7 +198,7 @@ impl XdgShellHandler for State {
if let Some(mapped) = self
.common
.shell
.element_for_surface(surface.wl_surface())
.element_for_wl_surface(surface.wl_surface())
.cloned()
{
if let Some(workspace) = self.common.shell.space_for_mut(&mapped) {
@ -266,7 +215,7 @@ impl XdgShellHandler for State {
if let Some(mapped) = self
.common
.shell
.element_for_surface(surface.wl_surface())
.element_for_wl_surface(surface.wl_surface())
.cloned()
{
if let Some(workspace) = self.common.shell.space_for_mut(&mapped) {
@ -319,36 +268,4 @@ impl XdgShellHandler for State {
}
}
fn check_grab_preconditions(
seat: &Seat<State>,
surface: &WlSurface,
serial: Serial,
) -> Option<PointerGrabStartData<State>> {
use smithay::reexports::wayland_server::Resource;
// TODO: touch resize.
let pointer = seat.get_pointer().unwrap();
// Check that this surface has a click grab.
if !pointer.has_grab(serial) {
return None;
}
let start_data = pointer.grab_start_data().unwrap();
// If the focus was for a different surface, ignore the request.
if start_data.focus.is_none()
|| !start_data
.focus
.as_ref()
.unwrap()
.0
.same_client_as(&surface.id())
{
return None;
}
Some(start_data)
}
delegate_xdg_shell!(State);

View file

@ -28,7 +28,7 @@ use std::sync::Mutex;
impl Shell {
pub fn unconstrain_popup(&self, surface: &PopupSurface, positioner: &PositionerState) {
if let Some(parent) = get_popup_toplevel(&surface) {
if let Some(elem) = self.element_for_surface(&parent) {
if let Some(elem) = self.element_for_wl_surface(&parent) {
let workspace = self.space_for(elem).unwrap();
let element_geo = workspace.element_geometry(elem).unwrap();
let (window, offset) = elem