diff --git a/default-config/src/lib.rs b/default-config/src/lib.rs index 4a0320b7..40185538 100644 --- a/default-config/src/lib.rs +++ b/default-config/src/lib.rs @@ -2,7 +2,7 @@ use { chrono::{format::StrftimeItems, Local, Timelike}, jay_config::{ config, - drm::{get_connector, on_connector_connected, on_new_connector}, + drm::{get_connector, on_connector_connected, on_graphics_initialized, on_new_connector}, embedded::grab_input_device, get_timer, get_workspace, input::{ @@ -144,7 +144,10 @@ pub fn configure() { } set_env("GTK_THEME", "Adwaita:dark"); - Command::new("mako").spawn(); + + on_graphics_initialized(|| { + Command::new("mako").spawn(); + }); } config!(configure); diff --git a/jay-config/src/_private/client.rs b/jay-config/src/_private/client.rs index 61f51677..c7ea2000 100644 --- a/jay-config/src/_private/client.rs +++ b/jay-config/src/_private/client.rs @@ -38,6 +38,7 @@ pub(crate) struct Client { on_new_seat: RefCell>>, on_new_input_device: RefCell>>, on_connector_connected: RefCell>>, + on_graphics_initialized: Cell>>, on_new_connector: RefCell>>, bufs: RefCell>>, } @@ -120,6 +121,7 @@ pub unsafe extern "C" fn init( on_new_seat: Default::default(), on_new_input_device: Default::default(), on_connector_connected: Default::default(), + on_graphics_initialized: Default::default(), on_new_connector: Default::default(), bufs: Default::default(), }); @@ -411,6 +413,10 @@ impl Client { *self.on_connector_connected.borrow_mut() = Some(Rc::new(f)); } + pub fn on_graphics_initialized(&self, f: F) { + self.on_graphics_initialized.set(Some(Box::new(f))); + } + pub fn set_seat(&self, device: InputDevice, seat: Seat) { self.send(&ClientMessage::SetSeat { device, seat }) } @@ -551,6 +557,11 @@ impl Client { handler(); } } + ServerMessage::GraphicsInitialized => { + if let Some(handler) = self.on_graphics_initialized.take() { + handler(); + } + } } } diff --git a/jay-config/src/_private/ipc.rs b/jay-config/src/_private/ipc.rs index d50a3df9..7a394bc3 100644 --- a/jay-config/src/_private/ipc.rs +++ b/jay-config/src/_private/ipc.rs @@ -13,6 +13,7 @@ use { #[derive(Encode, BorrowDecode, Debug)] pub enum ServerMessage { Configure, + GraphicsInitialized, Response { response: Response, }, diff --git a/jay-config/src/drm.rs b/jay-config/src/drm.rs index 2c233c91..4faa61bf 100644 --- a/jay-config/src/drm.rs +++ b/jay-config/src/drm.rs @@ -96,6 +96,10 @@ pub fn on_connector_connected(f: F) { get!().on_connector_connected(f) } +pub fn on_graphics_initialized(f: F) { + get!().on_graphics_initialized(f) +} + pub fn get_connector(id: impl ToConnectorId) -> Connector { let (ty, idx) = match id.to_connector_id() { Ok(id) => id, diff --git a/src/backend.rs b/src/backend.rs index 217c1764..8007eb7b 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -111,6 +111,7 @@ pub enum InputDeviceAccelProfile { } pub enum BackendEvent { + GraphicsInitialized, NewConnector(Rc), NewInputDevice(Rc), } diff --git a/src/backends/metal.rs b/src/backends/metal.rs index 3accc475..eb88cfab 100644 --- a/src/backends/metal.rs +++ b/src/backends/metal.rs @@ -6,8 +6,8 @@ use { crate::{ async_engine::{AsyncError, AsyncFd, SpawnedFuture}, backend::{ - Backend, InputDevice, InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId, - InputEvent, KeyState, + Backend, BackendEvent, InputDevice, InputDeviceAccelProfile, InputDeviceCapability, + InputDeviceId, InputEvent, KeyState, }, backends::metal::video::{MetalDrmDevice, PendingDrmDevice}, dbus::{DbusError, SignalHandler}, @@ -128,6 +128,9 @@ impl MetalBackend { if let Err(e) = self.enumerate_devices() { return Err(MetalError::Enumerate(Box::new(e))); } + self.state + .backend_events + .push(BackendEvent::GraphicsInitialized); pending().await } } diff --git a/src/backends/x.rs b/src/backends/x.rs index ae1a6ca2..b5829d26 100644 --- a/src/backends/x.rs +++ b/src/backends/x.rs @@ -254,6 +254,10 @@ pub struct XBackend { impl XBackend { async fn run(self: Rc) -> Result<(), XBackendError> { + self.state + .backend_events + .push(BackendEvent::GraphicsInitialized); + self.query_devices(INPUT_DEVICE_ALL_MASTER).await?; let _events = self.state.eng.spawn(self.clone().event_handler()); diff --git a/src/client.rs b/src/client.rs index a6595d0e..c90c1214 100644 --- a/src/client.rs +++ b/src/client.rs @@ -127,6 +127,8 @@ impl Clients { tracker: Default::default(), xwayland_queue, secure, + last_serial: Cell::new(0), + last_enter_serial: Cell::new(0), }); track!(data, data); let display = Rc::new(WlDisplay::new(&data)); @@ -224,6 +226,8 @@ pub struct Client { pub tracker: Tracker, pub xwayland_queue: Option>>, pub secure: bool, + pub last_serial: Cell, + pub last_enter_serial: Cell, } impl Client { @@ -251,6 +255,18 @@ impl Client { } } + pub fn validate_serial(&self, serial: u32) -> Result<(), ClientError> { + if serial > self.last_serial.get() { + Err(ClientError::InvalidSerial) + } else { + Ok(()) + } + } + + pub fn next_serial(&self) -> u32 { + self.state.next_serial(Some(self)) + } + pub fn new_id>(&self) -> Result { self.objects.id(self) } diff --git a/src/client/error.rs b/src/client/error.rs index 54b4b9de..8affc77c 100644 --- a/src/client/error.rs +++ b/src/client/error.rs @@ -12,6 +12,8 @@ use { #[derive(Debug, Error)] pub enum ClientError { + #[error("Client sent an invalid serial")] + InvalidSerial, #[error("An error occurred in the async engine")] Async(#[from] AsyncError), #[error("An error occurred reading from/writing to the client")] diff --git a/src/compositor.rs b/src/compositor.rs index b71cdcd9..40677dd8 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -147,6 +147,7 @@ fn start_compositor2( handler: Default::default(), }, socket_path: Default::default(), + serial: Default::default(), }); create_dummy_output(&state); let socket_path = Acceptor::install(&state)?; diff --git a/src/config.rs b/src/config.rs index e036a506..5cc6829d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -79,6 +79,10 @@ impl ConfigProxy { device: InputDevice(dev.raw() as _), }); } + + pub fn graphics_initialized(&self) { + self.handler.send(&ServerMessage::GraphicsInitialized); + } } impl Drop for ConfigProxy { diff --git a/src/ifs/ipc/wl_data_device.rs b/src/ifs/ipc/wl_data_device.rs index 9ccf8b6b..fd022623 100644 --- a/src/ifs/ipc/wl_data_device.rs +++ b/src/ifs/ipc/wl_data_device.rs @@ -61,10 +61,10 @@ impl WlDataDevice { self.manager.client.event(Leave { self_id: self.id }) } - pub fn send_enter(&self, surface: WlSurfaceId, x: Fixed, y: Fixed, offer: WlDataOfferId) { + pub fn send_enter(&self, surface: WlSurfaceId, x: Fixed, y: Fixed, offer: WlDataOfferId, serial: u32) { self.manager.client.event(Enter { self_id: self.id, - serial: 0, + serial, surface, x, y, @@ -87,6 +87,7 @@ impl WlDataDevice { fn start_drag(&self, parser: MsgParser<'_, '_>) -> Result<(), StartDragError> { let req: StartDrag = self.manager.client.parse(self, parser)?; + self.manager.client.validate_serial(req.serial)?; let origin = self.manager.client.lookup(req.origin)?; let source = if req.source.is_some() { Some(self.manager.client.lookup(req.source)?) @@ -100,18 +101,29 @@ impl WlDataDevice { } else { None }; - self.seat.global.start_drag(&origin, source, icon)?; + self.seat + .global + .start_drag(&origin, source, icon, req.serial)?; Ok(()) } fn set_selection(&self, parser: MsgParser<'_, '_>) -> Result<(), SetSelectionError> { let req: SetSelection = self.manager.client.parse(self, parser)?; + self.manager.client.validate_serial(req.serial)?; + if !self + .seat + .global + .may_modify_selection(&self.seat.client, req.serial) + { + log::warn!("Ignoring disallowed set_selection request"); + return Ok(()); + } let src = if req.source.is_none() { None } else { Some(self.manager.client.lookup(req.source)?) }; - self.seat.global.set_selection(src)?; + self.seat.global.set_selection(src, Some(req.serial))?; Ok(()) } diff --git a/src/ifs/ipc/wl_data_offer.rs b/src/ifs/ipc/wl_data_offer.rs index 6c009c0d..1b4b2a0a 100644 --- a/src/ifs/ipc/wl_data_offer.rs +++ b/src/ifs/ipc/wl_data_offer.rs @@ -63,6 +63,7 @@ impl WlDataOffer { fn accept(&self, parser: MsgParser<'_, '_>) -> Result<(), AcceptError> { let req: Accept = self.client.parse(self, parser)?; + let _ = req.serial; // unused let mut state = self.data.shared.state.get(); if state.contains(OFFER_STATE_FINISHED) { return Err(AcceptError::AlreadyFinished); diff --git a/src/ifs/ipc/zwp_primary_selection_device_v1.rs b/src/ifs/ipc/zwp_primary_selection_device_v1.rs index 27201ee9..424a4cde 100644 --- a/src/ifs/ipc/zwp_primary_selection_device_v1.rs +++ b/src/ifs/ipc/zwp_primary_selection_device_v1.rs @@ -63,12 +63,17 @@ impl ZwpPrimarySelectionDeviceV1 { fn set_selection(&self, parser: MsgParser<'_, '_>) -> Result<(), SetSelectionError> { let req: SetSelection = self.manager.client.parse(self, parser)?; + self.seat.client.validate_serial(req.serial)?; + if !self.seat.global.may_modify_primary_selection(&self.seat.client, req.serial) { + log::warn!("Ignoring disallowed set_selection request"); + return Ok(()); + } let src = if req.source.is_none() { None } else { Some(self.manager.client.lookup(req.source)?) }; - self.seat.global.set_primary_selection(src)?; + self.seat.global.set_primary_selection(src, Some(req.serial))?; Ok(()) } diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index 70aa36d1..10e24207 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -43,7 +43,6 @@ use { copyhashmap::CopyHashMap, errorfmt::ErrorFmt, linkedlist::{LinkedList, LinkedNode}, - numcell::NumCell, rc_eq::rc_eq, }, wire::{ @@ -127,10 +126,11 @@ pub struct WlSeatGlobal { kb_map: CloneCell>, kb_state: RefCell, cursor: CloneCell>>, - serial: NumCell, tree_changed: Rc, selection: CloneCell>>, + selection_serial: Cell, primary_selection: CloneCell>>, + primary_selection_serial: Cell, pointer_owner: PointerOwnerHolder, kb_owner: KbOwnerHolder, dropped_dnd: RefCell>, @@ -164,10 +164,11 @@ impl WlSeatGlobal { kb_map: CloneCell::new(state.default_keymap.clone()), kb_state: RefCell::new(state.default_keymap.state().unwrap()), cursor: Default::default(), - serial: Default::default(), tree_changed: Default::default(), selection: Default::default(), + selection_serial: Cell::new(0), primary_selection: Default::default(), + primary_selection_serial: Cell::new(0), pointer_owner: Default::default(), kb_owner: Default::default(), dropped_dnd: RefCell::new(None), @@ -333,8 +334,9 @@ impl WlSeatGlobal { origin: &Rc, source: Option>, icon: Option>, + serial: u32, ) -> Result<(), WlSeatError> { - self.pointer_owner.start_drag(self, origin, source, icon) + self.pointer_owner.start_drag(self, origin, source, icon, serial) } pub fn cancel_dnd(self: &Rc) { @@ -342,24 +344,49 @@ impl WlSeatGlobal { } pub fn unset_selection(self: &Rc) { - let _ = self.set_selection(None); + let _ = self.set_selection(None, None); } pub fn set_selection( self: &Rc, selection: Option>, + serial: Option, ) -> Result<(), WlSeatError> { + if let Some(serial) = serial { + self.selection_serial.set(serial); + } self.set_selection_::(&self.selection, selection) } + pub fn may_modify_selection(&self, client: &Rc, serial: u32) -> bool { + let dist = serial.wrapping_sub(self.selection_serial.get()) as i32; + if dist < 0 { + return false; + } + self.keyboard_node.get().node_client_id() == Some(client.id) + } + + pub fn may_modify_primary_selection(&self, client: &Rc, serial: u32) -> bool { + let dist = serial.wrapping_sub(self.primary_selection_serial.get()) as i32; + if dist < 0 { + return false; + } + self.keyboard_node.get().node_client_id() == Some(client.id) + || self.pointer_node().and_then(|n| n.node_client_id()) == Some(client.id) + } + pub fn unset_primary_selection(self: &Rc) { - let _ = self.set_primary_selection(None); + let _ = self.set_primary_selection(None, None); } pub fn set_primary_selection( self: &Rc, selection: Option>, + serial: Option, ) -> Result<(), WlSeatError> { + if let Some(serial) = serial { + self.primary_selection_serial.set(serial); + } self.set_selection_::(&self.primary_selection, selection) } diff --git a/src/ifs/wl_seat/event_handling.rs b/src/ifs/wl_seat/event_handling.rs index 7c873b2b..02380a13 100644 --- a/src/ifs/wl_seat/event_handling.rs +++ b/src/ifs/wl_seat/event_handling.rs @@ -457,12 +457,17 @@ impl WlSeatGlobal { // Button callbacks impl WlSeatGlobal { - pub fn button_surface(self: &Rc, surface: &Rc, button: u32, state: KeyState) { + pub fn button_surface( + self: &Rc, + surface: &Rc, + button: u32, + state: KeyState, + serial: u32, + ) { let (state, pressed) = match state { KeyState::Released => (wl_pointer::RELEASED, false), KeyState::Pressed => (wl_pointer::PRESSED, true), }; - let serial = self.serial.fetch_add(1); self.surface_pointer_event(0, surface, |p| p.send_button(serial, 0, button, state)); self.surface_pointer_frame(surface); if pressed && surface.accepts_kb_focus() { @@ -522,7 +527,8 @@ impl WlSeatGlobal { } pub fn enter_surface(&self, n: &WlSurface, x: Fixed, y: Fixed) { - let serial = self.serial.fetch_add(1); + let serial = n.client.next_serial(); + n.client.last_enter_serial.set(serial); self.surface_pointer_event(0, n, |p| p.send_enter(serial, n.id, x, y)); self.surface_pointer_frame(n); } @@ -531,7 +537,7 @@ impl WlSeatGlobal { // Leave callbacks impl WlSeatGlobal { pub fn leave_surface(&self, n: &WlSurface) { - let serial = self.serial.fetch_add(1); + let serial = n.client.next_serial(); self.surface_pointer_event(0, n, |p| p.send_leave(serial, n.id)); self.surface_pointer_frame(n); } @@ -540,7 +546,8 @@ impl WlSeatGlobal { // Unfocus callbacks impl WlSeatGlobal { pub fn unfocus_surface(&self, surface: &WlSurface) { - self.surface_kb_event(0, surface, |k| k.send_leave(0, surface.id)) + let serial = surface.client.next_serial(); + self.surface_kb_event(0, surface, |k| k.send_leave(serial, surface.id)) } } @@ -548,7 +555,7 @@ impl WlSeatGlobal { impl WlSeatGlobal { pub fn focus_surface(&self, surface: &WlSurface) { let pressed_keys: Vec<_> = self.pressed_keys.borrow().iter().copied().collect(); - let serial = self.serial.fetch_add(1); + let serial = surface.client.next_serial(); self.surface_kb_event(0, surface, |k| { k.send_enter(serial, surface.id, &pressed_keys) }); @@ -559,7 +566,7 @@ impl WlSeatGlobal { group, .. } = self.kb_state.borrow().mods(); - let serial = self.serial.fetch_add(1); + let serial = surface.client.next_serial(); self.surface_kb_event(0, surface, |k| { k.send_modifiers(serial, mods_depressed, mods_latched, mods_locked, group) }); @@ -577,7 +584,7 @@ impl WlSeatGlobal { // Key callbacks impl WlSeatGlobal { pub fn key_surface(&self, surface: &WlSurface, key: u32, state: u32) { - let serial = self.serial.fetch_add(1); + let serial = surface.client.next_serial(); self.surface_kb_event(0, surface, |k| k.send_key(serial, 0, key, state)); } } @@ -585,7 +592,7 @@ impl WlSeatGlobal { // Modifiers callbacks impl WlSeatGlobal { pub fn mods_surface(&self, surface: &WlSurface, mods: ModifierState) { - let serial = self.serial.fetch_add(1); + let serial = surface.client.next_serial(); self.surface_kb_event(0, surface, |k| { k.send_modifiers( serial, @@ -624,16 +631,16 @@ impl WlSeatGlobal { surface.client.flush(); } - pub fn dnd_surface_enter(&self, surface: &WlSurface, dnd: &Dnd, x: Fixed, y: Fixed) { + pub fn dnd_surface_enter(&self, surface: &WlSurface, dnd: &Dnd, x: Fixed, y: Fixed, serial: u32) { if let Some(src) = &dnd.src { ipc::offer_source_to::(src, &surface.client); src.for_each_data_offer(|offer| { - offer.device.send_enter(surface.id, x, y, offer.id); + offer.device.send_enter(surface.id, x, y, offer.id, serial); offer.send_source_actions(); }) } else if surface.client.id == dnd.client.id { self.for_each_data_device(0, dnd.client.id, |dd| { - dd.send_enter(surface.id, x, y, WlDataOfferId::NONE); + dd.send_enter(surface.id, x, y, WlDataOfferId::NONE, serial); }) } surface.client.flush(); diff --git a/src/ifs/wl_seat/pointer_owner.rs b/src/ifs/wl_seat/pointer_owner.rs index 185c7615..62beff78 100644 --- a/src/ifs/wl_seat/pointer_owner.rs +++ b/src/ifs/wl_seat/pointer_owner.rs @@ -68,8 +68,11 @@ impl PointerOwnerHolder { origin: &Rc, source: Option>, icon: Option>, + serial: u32, ) -> Result<(), WlSeatError> { - self.owner.get().start_drag(seat, origin, source, icon) + self.owner + .get() + .start_drag(seat, origin, source, icon, serial) } pub fn cancel_dnd(&self, seat: &Rc) { @@ -103,6 +106,7 @@ trait PointerOwner { origin: &Rc, source: Option>, icon: Option>, + serial: u32, ) -> Result<(), WlSeatError>; fn cancel_dnd(&self, seat: &Rc); fn revert_to_default(&self, seat: &Rc); @@ -116,6 +120,7 @@ struct DefaultPointerOwner; struct GrabPointerOwner { buttons: SmallMap, node: Rc, + serial: u32, } struct DndPointerOwner { @@ -136,12 +141,14 @@ impl PointerOwner for DefaultPointerOwner { Some(n) => n, _ => return, }; + let serial = seat.state.next_serial(pn.node_client().as_deref()); seat.pointer_owner.owner.set(Rc::new(GrabPointerOwner { buttons: SmallMap::new_with(button, ()), node: pn.clone(), + serial, })); pn.node_seat_state().add_pointer_grab(seat); - pn.node_button(seat, button, state); + pn.node_button(seat, button, state, serial); } fn axis_node(&self, seat: &Rc) -> Option> { @@ -217,6 +224,7 @@ impl PointerOwner for DefaultPointerOwner { _origin: &Rc, source: Option>, _icon: Option>, + _serial: u32, ) -> Result<(), WlSeatError> { if let Some(src) = source { src.send_cancelled(); @@ -262,7 +270,8 @@ impl PointerOwner for GrabPointerOwner { self.buttons.insert(button, ()); } } - self.node.clone().node_button(seat, button, state); + let serial = seat.state.next_serial(self.node.node_client().as_deref()); + self.node.clone().node_button(seat, button, state, serial); } fn axis_node(&self, _seat: &Rc) -> Option> { @@ -284,6 +293,7 @@ impl PointerOwner for GrabPointerOwner { origin: &Rc, src: Option>, icon: Option>, + serial: u32, ) -> Result<(), WlSeatError> { let button = match self.buttons.iter().next() { Some((b, _)) => b, @@ -292,6 +302,9 @@ impl PointerOwner for GrabPointerOwner { if self.buttons.len() != 1 { return Ok(()); } + if serial != self.serial { + return Ok(()); + } if self.node.node_id() != origin.node_id { return Ok(()); } @@ -413,7 +426,7 @@ impl PointerOwner for DndPointerOwner { target.node_dnd_leave(&self.dnd); target.node_seat_state().remove_dnd_target(seat); target = node; - target.node_dnd_enter(&self.dnd, x, y); + target.node_dnd_enter(&self.dnd, x, y, seat.state.next_serial(target.node_client().as_deref())); target.node_seat_state().add_dnd_target(seat); self.target.set(target); } else if (self.pos_x.get(), self.pos_y.get()) != (x, y) { @@ -429,6 +442,7 @@ impl PointerOwner for DndPointerOwner { _origin: &Rc, source: Option>, _icon: Option>, + _serial: u32, ) -> Result<(), WlSeatError> { if let Some(src) = source { src.send_cancelled(); diff --git a/src/ifs/wl_seat/wl_pointer.rs b/src/ifs/wl_seat/wl_pointer.rs index 3deacbc8..b380b7ea 100644 --- a/src/ifs/wl_seat/wl_pointer.rs +++ b/src/ifs/wl_seat/wl_pointer.rs @@ -156,6 +156,7 @@ impl WlPointer { fn set_cursor(&self, parser: MsgParser<'_, '_>) -> Result<(), SetCursorError> { let req: SetCursor = self.seat.client.parse(self, parser)?; + self.seat.client.validate_serial(req.serial)?; let mut cursor_opt = None; if req.surface.is_some() { let surface = self.seat.client.lookup(req.surface)?; @@ -163,7 +164,7 @@ impl WlPointer { cursor.set_hotspot(req.hotspot_x, req.hotspot_y); cursor_opt = Some(cursor as Rc); } - let pointer_node = match self.seat.global.pointer_stack.borrow().last().cloned() { + let pointer_node = match self.seat.global.pointer_node() { Some(n) => n, _ => { // cannot happen @@ -173,6 +174,9 @@ impl WlPointer { if pointer_node.node_client_id() != Some(self.seat.client.id) { return Ok(()); } + if req.serial != self.seat.client.last_enter_serial.get() { + return Ok(()); + } self.seat.global.set_app_cursor(cursor_opt); Ok(()) } diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index 66b6d8ae..f7f9ef21 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -795,8 +795,8 @@ impl SizedNode for WlSurface { seat.mods_surface(self, mods); } - fn button(self: &Rc, seat: &Rc, button: u32, state: KeyState) { - seat.button_surface(&self, button, state); + fn button(self: &Rc, seat: &Rc, button: u32, state: KeyState, serial: u32) { + seat.button_surface(&self, button, state, serial); } fn axis_event(self: &Rc, seat: &WlSeatGlobal, event: &PendingScroll) { @@ -859,8 +859,8 @@ impl SizedNode for WlSurface { dnd.seat.dnd_surface_leave(self, dnd); } - fn dnd_enter(&self, dnd: &Dnd, x: Fixed, y: Fixed) { - dnd.seat.dnd_surface_enter(self, dnd, x, y); + fn dnd_enter(&self, dnd: &Dnd, x: Fixed, y: Fixed, serial: u32) { + dnd.seat.dnd_surface_enter(self, dnd, x, y, serial); } fn dnd_motion(&self, dnd: &Dnd, x: Fixed, y: Fixed) { diff --git a/src/ifs/wl_surface/xwindow.rs b/src/ifs/wl_surface/xwindow.rs index a2510fda..def34d6d 100644 --- a/src/ifs/wl_surface/xwindow.rs +++ b/src/ifs/wl_surface/xwindow.rs @@ -278,9 +278,12 @@ impl Xwindow { match map_change { Change::None => return, Change::Unmap => { - self.data.info.pending_extents.set(self.data.info.extents.take()); + self.data + .info + .pending_extents + .set(self.data.info.extents.take()); self.node_destroy(true); - }, + } Change::Map if self.data.info.override_redirect.get() => { self.change_extents(&self.data.info.pending_extents.get()); *self.display_link.borrow_mut() = diff --git a/src/state.rs b/src/state.rs index 10281594..079d35d7 100644 --- a/src/state.rs +++ b/src/state.rs @@ -27,7 +27,8 @@ use { }, utils::{ asyncevent::AsyncEvent, clonecell::CloneCell, copyhashmap::CopyHashMap, - errorfmt::ErrorFmt, fdcloser::FdCloser, linkedlist::LinkedList, queue::AsyncQueue, + errorfmt::ErrorFmt, fdcloser::FdCloser, linkedlist::LinkedList, numcell::NumCell, + queue::AsyncQueue, }, wheel::Wheel, xkbcommon::{XkbContext, XkbKeymap}, @@ -37,6 +38,7 @@ use { jay_config::Direction, std::{ cell::{Cell, RefCell}, + num::Wrapping, rc::Rc, sync::Arc, time::Duration, @@ -84,6 +86,7 @@ pub struct State { pub run_args: RunArgs, pub xwayland: XWaylandState, pub socket_path: CloneCell>, + pub serial: NumCell>, } pub struct XWaylandState { @@ -325,4 +328,12 @@ impl State { *handler = Some(self.eng.spawn(xwayland::manage(self.clone()))); } } + + pub fn next_serial(&self, client: Option<&Client>) -> u32 { + let serial = self.serial.fetch_add(Wrapping(1)).0; + if let Some(client) = client { + client.last_serial.set(serial); + } + serial + } } diff --git a/src/tasks/backend.rs b/src/tasks/backend.rs index 02dad2e9..20c27e7f 100644 --- a/src/tasks/backend.rs +++ b/src/tasks/backend.rs @@ -23,6 +23,11 @@ impl BackendEventHandler { match event { BackendEvent::NewConnector(connector) => connector::handle(&self.state, &connector), BackendEvent::NewInputDevice(s) => input_device::handle(&self.state, s), + BackendEvent::GraphicsInitialized => { + if let Some(config) = self.state.config.get() { + config.graphics_initialized(); + } + } } } } diff --git a/src/tasks/idle.rs b/src/tasks/idle.rs index 1b10602a..85724a50 100644 --- a/src/tasks/idle.rs +++ b/src/tasks/idle.rs @@ -100,8 +100,8 @@ fn now() -> c::timespec { fn duration_since(start: c::timespec) -> Duration { let now = now(); - let mut nanos = - (now.tv_sec as i64 - start.tv_sec as i64) * 1_000_000_000 + (now.tv_nsec as i64 - start.tv_nsec as i64); + let mut nanos = (now.tv_sec as i64 - start.tv_sec as i64) * 1_000_000_000 + + (now.tv_nsec as i64 - start.tv_nsec as i64); if nanos < 0 { log::error!("Time has gone backwards."); nanos = 0; diff --git a/src/tree.rs b/src/tree.rs index d1b22524..65eb99dd 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -195,10 +195,11 @@ pub trait SizedNode: Sized + 'static { let _ = mods; } - fn button(self: &Rc, seat: &Rc, button: u32, state: KeyState) { + fn button(self: &Rc, seat: &Rc, button: u32, state: KeyState, serial: u32) { let _ = seat; let _ = button; let _ = state; + let _ = serial; } fn axis_event(self: &Rc, seat: &WlSeatGlobal, event: &PendingScroll) { @@ -346,10 +347,11 @@ pub trait SizedNode: Sized + 'static { let _ = dnd; } - fn dnd_enter(&self, dnd: &Dnd, x: Fixed, y: Fixed) { + fn dnd_enter(&self, dnd: &Dnd, x: Fixed, y: Fixed, serial: u32) { let _ = dnd; let _ = x; let _ = y; + let _ = serial; } fn dnd_motion(&self, dnd: &Dnd, x: Fixed, y: Fixed) { @@ -397,7 +399,13 @@ pub trait Node { fn node_active_changed(&self, active: bool); fn node_key(&self, seat: &WlSeatGlobal, key: u32, state: u32); fn node_mods(&self, seat: &WlSeatGlobal, mods: ModifierState); - fn node_button(self: Rc, seat: &Rc, button: u32, state: KeyState); + fn node_button( + self: Rc, + seat: &Rc, + button: u32, + state: KeyState, + serial: u32, + ); fn node_axis_event(self: Rc, seat: &WlSeatGlobal, event: &PendingScroll); fn node_focus(self: Rc, seat: &Rc); fn node_focus_parent(&self, seat: &Rc); @@ -431,7 +439,7 @@ pub trait Node { fn node_into_surface(self: Rc) -> Option>; fn node_dnd_drop(&self, dnd: &Dnd); fn node_dnd_leave(&self, dnd: &Dnd); - fn node_dnd_enter(&self, dnd: &Dnd, x: Fixed, y: Fixed); + fn node_dnd_enter(&self, dnd: &Dnd, x: Fixed, y: Fixed, serial: u32); fn node_dnd_motion(&self, dnd: &Dnd, x: Fixed, y: Fixed); } @@ -537,8 +545,14 @@ impl Node for T { fn node_mods(&self, seat: &WlSeatGlobal, mods: ModifierState) { ::mods(self, seat, mods) } - fn node_button(self: Rc, seat: &Rc, button: u32, state: KeyState) { - ::button(&self, seat, button, state) + fn node_button( + self: Rc, + seat: &Rc, + button: u32, + state: KeyState, + serial: u32, + ) { + ::button(&self, seat, button, state, serial) } fn node_axis_event(self: Rc, seat: &WlSeatGlobal, event: &PendingScroll) { ::axis_event(&self, seat, event) @@ -639,8 +653,8 @@ impl Node for T { fn node_dnd_leave(&self, dnd: &Dnd) { ::dnd_leave(self, dnd) } - fn node_dnd_enter(&self, dnd: &Dnd, x: Fixed, y: Fixed) { - ::dnd_enter(self, dnd, x, y) + fn node_dnd_enter(&self, dnd: &Dnd, x: Fixed, y: Fixed, serial: u32) { + ::dnd_enter(self, dnd, x, y, serial) } fn node_dnd_motion(&self, dnd: &Dnd, x: Fixed, y: Fixed) { ::dnd_motion(self, dnd, x, y) diff --git a/src/tree/container.rs b/src/tree/container.rs index 939b8b89..b9fde514 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -1040,7 +1040,13 @@ impl SizedNode for ContainerNode { self.parent.get().node_child_active_changed(self, active, 1); } - fn button(self: &Rc, seat: &Rc, button: u32, state: KeyState) { + fn button( + self: &Rc, + seat: &Rc, + button: u32, + state: KeyState, + _serial: u32, + ) { if button != BTN_LEFT { return; } diff --git a/src/tree/float.rs b/src/tree/float.rs index dcdfc45a..19b6be07 100644 --- a/src/tree/float.rs +++ b/src/tree/float.rs @@ -377,7 +377,13 @@ impl SizedNode for FloatNode { self.position.get() } - fn button(self: &Rc, seat: &Rc, button: u32, state: KeyState) { + fn button( + self: &Rc, + seat: &Rc, + button: u32, + state: KeyState, + _serial: u32, + ) { if button != BTN_LEFT { return; } diff --git a/src/xwayland/xwm.rs b/src/xwayland/xwm.rs index 0716f9c1..6540708c 100644 --- a/src/xwayland/xwm.rs +++ b/src/xwayland/xwm.rs @@ -1359,14 +1359,6 @@ impl Wm { Some(d) => d, _ => return Ok(()), }; - let extents = Rect::new_sized( - event.x as _, - event.y as _, - event.width as _, - event.height as _, - ) - .unwrap(); - // log::info!("xwin {} configure_notify {:?}", data.window_id, extents); self.update_override_redirect(data, event.override_redirect); if data.info.override_redirect.get() { let extents = Rect::new_sized( @@ -1375,7 +1367,7 @@ impl Wm { event.width as _, event.height as _, ) - .unwrap(); + .unwrap(); if let Some(window) = data.window.get() { window.change_extents(&extents); self.state.tree_changed();