Skip to content

Commit

Permalink
Smallvil fixes 2 (#1100)
Browse files Browse the repository at this point in the history
* smallvil: Store DisplayHandle in State

Will be useful for the data device focus.

* smallvil: Set data device focus

Makes clipboard work across clients.

* smallvil: Add basic PopupManager implementation

Doesn't handle popup grabs but gets smallvil far enough.
  • Loading branch information
YaLTeR authored Aug 15, 2023
1 parent c569c87 commit e241ccb
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 33 deletions.
2 changes: 1 addition & 1 deletion smallvil/src/handlers/compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl CompositorHandler for Smallvil {
}
};

xdg_shell::handle_commit(&self.space, surface);
xdg_shell::handle_commit(&mut self.popups, &self.space, surface);
resize_grab::handle_commit(&mut self.space, surface);
}
}
Expand Down
19 changes: 11 additions & 8 deletions smallvil/src/handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ use crate::Smallvil;
// Wl Seat
//

use smithay::input::{SeatHandler, SeatState};
use smithay::input::{Seat, SeatHandler, SeatState};
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
use smithay::wayland::data_device::{ClientDndGrabHandler, DataDeviceHandler, ServerDndGrabHandler};
use smithay::reexports::wayland_server::Resource;
use smithay::wayland::data_device::{
set_data_device_focus, ClientDndGrabHandler, DataDeviceHandler, ServerDndGrabHandler,
};
use smithay::{delegate_data_device, delegate_output, delegate_seat};

impl SeatHandler for Smallvil {
Expand All @@ -20,13 +23,13 @@ impl SeatHandler for Smallvil {
&mut self.seat_state
}

fn cursor_image(
&mut self,
_seat: &smithay::input::Seat<Self>,
_image: smithay::input::pointer::CursorImageStatus,
) {
fn cursor_image(&mut self, _seat: &Seat<Self>, _image: smithay::input::pointer::CursorImageStatus) {}

fn focus_changed(&mut self, seat: &Seat<Self>, focused: Option<&WlSurface>) {
let dh = &self.display_handle;
let client = focused.and_then(|s| dh.get_client(s.id()).ok());
set_data_device_focus(dh, seat, client);
}
fn focus_changed(&mut self, _seat: &smithay::input::Seat<Self>, _focused: Option<&WlSurface>) {}
}

delegate_seat!(Smallvil);
Expand Down
77 changes: 55 additions & 22 deletions smallvil/src/handlers/xdg_shell.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use smithay::{
delegate_xdg_shell,
desktop::{Space, Window},
desktop::{PopupKind, PopupManager, Space, Window},
input::{
pointer::{Focus, GrabStartData as PointerGrabStartData},
Seat,
Expand All @@ -16,8 +16,8 @@ use smithay::{
wayland::{
compositor::with_states,
shell::xdg::{
PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState,
XdgToplevelSurfaceData,
PopupSurface, PositionerState, ToplevelSurface, XdgPopupSurfaceData, XdgShellHandler,
XdgShellState, XdgToplevelSurfaceData,
},
},
};
Expand All @@ -37,8 +37,21 @@ impl XdgShellHandler for Smallvil {
self.space.map_element(window, (0, 0), false);
}

fn new_popup(&mut self, _surface: PopupSurface, _positioner: PositionerState) {
// TODO: Popup handling using PopupManager
fn new_popup(&mut self, surface: PopupSurface, _positioner: PositionerState) {
let _ = self.popups.track_popup(PopupKind::Xdg(surface));
}

fn reposition_request(&mut self, surface: PopupSurface, positioner: PositionerState, token: u32) {
surface.with_pending_state(|state| {
// NOTE: This is again a simplification, a proper compositor would
// calculate the geometry of the popup here. For simplicity we just
// use the default implementation here that does not take the
// window position and output constraints into account.
let geometry = positioner.get_geometry();
state.geometry = geometry;
state.positioner = positioner;
});
surface.send_repositioned(token);
}

fn move_request(&mut self, surface: ToplevelSurface, seat: wl_seat::WlSeat, serial: Serial) {
Expand Down Expand Up @@ -139,25 +152,45 @@ fn check_grab(
}

/// Should be called on `WlSurface::commit`
pub fn handle_commit(space: &Space<Window>, surface: &WlSurface) -> Option<()> {
let window = space
pub fn handle_commit(popups: &mut PopupManager, space: &Space<Window>, surface: &WlSurface) {
// Handle toplevel commits.
if let Some(window) = space
.elements()
.find(|w| w.toplevel().wl_surface() == surface)
.cloned()?;

let initial_configure_sent = with_states(surface, |states| {
states
.data_map
.get::<XdgToplevelSurfaceData>()
.unwrap()
.lock()
.unwrap()
.initial_configure_sent
});

if !initial_configure_sent {
window.toplevel().send_configure();
.cloned()
{
let initial_configure_sent = with_states(surface, |states| {
states
.data_map
.get::<XdgToplevelSurfaceData>()
.unwrap()
.lock()
.unwrap()
.initial_configure_sent
});

if !initial_configure_sent {
window.toplevel().send_configure();
}
}

Some(())
// Handle popup commits.
popups.commit(surface);
if let Some(popup) = popups.find_popup(surface) {
let PopupKind::Xdg(ref popup) = popup;
let initial_configure_sent = with_states(surface, |states| {
states
.data_map
.get::<XdgPopupSurfaceData>()
.unwrap()
.lock()
.unwrap()
.initial_configure_sent
});
if !initial_configure_sent {
// NOTE: This should never fail as the initial configure is always
// allowed.
popup.send_configure().expect("initial configure failed");
}
}
}
9 changes: 7 additions & 2 deletions smallvil/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use std::{ffi::OsString, os::unix::io::AsRawFd, sync::Arc};

use smithay::{
desktop::{Space, Window, WindowSurfaceType},
desktop::{PopupManager, Space, Window, WindowSurfaceType},
input::{Seat, SeatState},
reexports::{
calloop::{generic::Generic, EventLoop, Interest, LoopSignal, Mode, PostAction},
wayland_server::{
backend::{ClientData, ClientId, DisconnectReason},
protocol::wl_surface::WlSurface,
Display,
Display, DisplayHandle,
},
},
utils::{Logical, Point},
Expand All @@ -27,6 +27,7 @@ use crate::CalloopData;
pub struct Smallvil {
pub start_time: std::time::Instant,
pub socket_name: OsString,
pub display_handle: DisplayHandle,

pub space: Space<Window>,
pub loop_signal: LoopSignal,
Expand All @@ -38,6 +39,7 @@ pub struct Smallvil {
pub output_manager_state: OutputManagerState,
pub seat_state: SeatState<Smallvil>,
pub data_device_state: DataDeviceState,
pub popups: PopupManager,

pub seat: Seat<Self>,
}
Expand All @@ -54,6 +56,7 @@ impl Smallvil {
let output_manager_state = OutputManagerState::new_with_xdg_output::<Self>(&dh);
let mut seat_state = SeatState::new();
let data_device_state = DataDeviceState::new::<Self>(&dh);
let popups = PopupManager::default();

// A seat is a group of keyboards, pointer and touch devices.
// A seat typically has a pointer and maintains a keyboard focus and a pointer focus.
Expand All @@ -80,6 +83,7 @@ impl Smallvil {

Self {
start_time,
display_handle: dh,

space,
loop_signal,
Expand All @@ -91,6 +95,7 @@ impl Smallvil {
output_manager_state,
seat_state,
data_device_state,
popups,
seat,
}
}
Expand Down
1 change: 1 addition & 0 deletions smallvil/src/winit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ pub fn winit_dispatch(
});

state.space.refresh();
state.popups.cleanup();
display.flush_clients()?;

Ok(())
Expand Down

0 comments on commit e241ccb

Please sign in to comment.