aboutsummaryrefslogtreecommitdiff
path: root/src/handlers
diff options
context:
space:
mode:
Diffstat (limited to 'src/handlers')
-rw-r--r--src/handlers/compositor.rs57
-rw-r--r--src/handlers/mod.rs54
-rw-r--r--src/handlers/xdg_shell.rs163
3 files changed, 274 insertions, 0 deletions
diff --git a/src/handlers/compositor.rs b/src/handlers/compositor.rs
new file mode 100644
index 00000000..fcb0dc02
--- /dev/null
+++ b/src/handlers/compositor.rs
@@ -0,0 +1,57 @@
+use crate::{grabs::resize_grab, state::ClientState, Smallvil};
+use smithay::{
+ backend::renderer::utils::on_commit_buffer_handler,
+ delegate_compositor, delegate_shm,
+ reexports::wayland_server::{
+ protocol::{wl_buffer, wl_surface::WlSurface},
+ Client,
+ },
+ wayland::{
+ buffer::BufferHandler,
+ compositor::{
+ get_parent, is_sync_subsurface, CompositorClientState, CompositorHandler, CompositorState,
+ },
+ shm::{ShmHandler, ShmState},
+ },
+};
+
+use super::xdg_shell;
+
+impl CompositorHandler for Smallvil {
+ fn compositor_state(&mut self) -> &mut CompositorState {
+ &mut self.compositor_state
+ }
+
+ fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState {
+ &client.get_data::<ClientState>().unwrap().compositor_state
+ }
+
+ fn commit(&mut self, surface: &WlSurface) {
+ on_commit_buffer_handler::<Self>(surface);
+ if !is_sync_subsurface(surface) {
+ let mut root = surface.clone();
+ while let Some(parent) = get_parent(&root) {
+ root = parent;
+ }
+ if let Some(window) = self.space.elements().find(|w| w.toplevel().wl_surface() == &root) {
+ window.on_commit();
+ }
+ };
+
+ xdg_shell::handle_commit(&self.space, surface);
+ resize_grab::handle_commit(&mut self.space, surface);
+ }
+}
+
+impl BufferHandler for Smallvil {
+ fn buffer_destroyed(&mut self, _buffer: &wl_buffer::WlBuffer) {}
+}
+
+impl ShmHandler for Smallvil {
+ fn shm_state(&self) -> &ShmState {
+ &self.shm_state
+ }
+}
+
+delegate_compositor!(Smallvil);
+delegate_shm!(Smallvil);
diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs
new file mode 100644
index 00000000..bc2cd23f
--- /dev/null
+++ b/src/handlers/mod.rs
@@ -0,0 +1,54 @@
+mod compositor;
+mod xdg_shell;
+
+use crate::Smallvil;
+
+//
+// Wl Seat
+//
+
+use smithay::input::{SeatHandler, SeatState};
+use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
+use smithay::wayland::data_device::{ClientDndGrabHandler, DataDeviceHandler, ServerDndGrabHandler};
+use smithay::{delegate_data_device, delegate_output, delegate_seat};
+
+impl SeatHandler for Smallvil {
+ type KeyboardFocus = WlSurface;
+ type PointerFocus = WlSurface;
+
+ fn seat_state(&mut self) -> &mut SeatState<Smallvil> {
+ &mut self.seat_state
+ }
+
+ fn cursor_image(
+ &mut self,
+ _seat: &smithay::input::Seat<Self>,
+ _image: smithay::input::pointer::CursorImageStatus,
+ ) {
+ }
+ fn focus_changed(&mut self, _seat: &smithay::input::Seat<Self>, _focused: Option<&WlSurface>) {}
+}
+
+delegate_seat!(Smallvil);
+
+//
+// Wl Data Device
+//
+
+impl DataDeviceHandler for Smallvil {
+ type SelectionUserData = ();
+ fn data_device_state(&self) -> &smithay::wayland::data_device::DataDeviceState {
+ &self.data_device_state
+ }
+}
+
+impl ClientDndGrabHandler for Smallvil {}
+impl ServerDndGrabHandler for Smallvil {}
+
+delegate_data_device!(Smallvil);
+
+//
+// Wl Output & Xdg Output
+//
+
+delegate_output!(Smallvil);
diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs
new file mode 100644
index 00000000..7351d3bf
--- /dev/null
+++ b/src/handlers/xdg_shell.rs
@@ -0,0 +1,163 @@
+use smithay::{
+ delegate_xdg_shell,
+ desktop::{Space, Window},
+ input::{
+ pointer::{Focus, GrabStartData as PointerGrabStartData},
+ Seat,
+ },
+ reexports::{
+ wayland_protocols::xdg::shell::server::xdg_toplevel,
+ wayland_server::{
+ protocol::{wl_seat, wl_surface::WlSurface},
+ Resource,
+ },
+ },
+ utils::{Rectangle, Serial},
+ wayland::{
+ compositor::with_states,
+ shell::xdg::{
+ PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState,
+ XdgToplevelSurfaceData,
+ },
+ },
+};
+
+use crate::{
+ grabs::{MoveSurfaceGrab, ResizeSurfaceGrab},
+ Smallvil,
+};
+
+impl XdgShellHandler for Smallvil {
+ fn xdg_shell_state(&mut self) -> &mut XdgShellState {
+ &mut self.xdg_shell_state
+ }
+
+ fn new_toplevel(&mut self, surface: ToplevelSurface) {
+ let window = Window::new(surface);
+ self.space.map_element(window, (0, 0), false);
+ }
+
+ fn new_popup(&mut self, _surface: PopupSurface, _positioner: PositionerState) {
+ // TODO: Popup handling using PopupManager
+ }
+
+ fn move_request(&mut self, surface: ToplevelSurface, seat: wl_seat::WlSeat, serial: Serial) {
+ let seat = Seat::from_resource(&seat).unwrap();
+
+ let wl_surface = surface.wl_surface();
+
+ if let Some(start_data) = check_grab(&seat, wl_surface, serial) {
+ let pointer = seat.get_pointer().unwrap();
+
+ let window = self
+ .space
+ .elements()
+ .find(|w| w.toplevel().wl_surface() == wl_surface)
+ .unwrap()
+ .clone();
+ let initial_window_location = self.space.element_location(&window).unwrap();
+
+ let grab = MoveSurfaceGrab {
+ start_data,
+ window,
+ initial_window_location,
+ };
+
+ pointer.set_grab(self, grab, serial, Focus::Clear);
+ }
+ }
+
+ fn resize_request(
+ &mut self,
+ surface: ToplevelSurface,
+ seat: wl_seat::WlSeat,
+ serial: Serial,
+ edges: xdg_toplevel::ResizeEdge,
+ ) {
+ let seat = Seat::from_resource(&seat).unwrap();
+
+ let wl_surface = surface.wl_surface();
+
+ if let Some(start_data) = check_grab(&seat, wl_surface, serial) {
+ let pointer = seat.get_pointer().unwrap();
+
+ let window = self
+ .space
+ .elements()
+ .find(|w| w.toplevel().wl_surface() == wl_surface)
+ .unwrap()
+ .clone();
+ let initial_window_location = self.space.element_location(&window).unwrap();
+ let initial_window_size = window.geometry().size;
+
+ surface.with_pending_state(|state| {
+ state.states.set(xdg_toplevel::State::Resizing);
+ });
+
+ surface.send_pending_configure();
+
+ let grab = ResizeSurfaceGrab::start(
+ start_data,
+ window,
+ edges.into(),
+ Rectangle::from_loc_and_size(initial_window_location, initial_window_size),
+ );
+
+ pointer.set_grab(self, grab, serial, Focus::Clear);
+ }
+ }
+
+ fn grab(&mut self, _surface: PopupSurface, _seat: wl_seat::WlSeat, _serial: Serial) {
+ // TODO popup grabs
+ }
+}
+
+// Xdg Shell
+delegate_xdg_shell!(Smallvil);
+
+fn check_grab(
+ seat: &Seat<Smallvil>,
+ surface: &WlSurface,
+ serial: Serial,
+) -> Option<PointerGrabStartData<Smallvil>> {
+ let pointer = seat.get_pointer()?;
+
+ // Check that this surface has a click grab.
+ if !pointer.has_grab(serial) {
+ return None;
+ }
+
+ let start_data = pointer.grab_start_data()?;
+
+ let (focus, _) = start_data.focus.as_ref()?;
+ // If the focus was for a different surface, ignore the request.
+ if !focus.id().same_client_as(&surface.id()) {
+ return None;
+ }
+
+ Some(start_data)
+}
+
+/// Should be called on `WlSurface::commit`
+pub fn handle_commit(space: &Space<Window>, surface: &WlSurface) -> Option<()> {
+ let 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();
+ }
+
+ Some(())
+}