Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 31 additions & 5 deletions rust/neomacs-display/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3419,7 +3419,9 @@ pub unsafe extern "C" fn neomacs_display_has_transition_snapshot(
// ============================================================================

#[cfg(feature = "winit-backend")]
use crate::thread_comm::{EmacsComms, InputEvent, RenderCommand, ThreadComms};
use crate::thread_comm::{
EmacsComms, InputEvent, RenderCommand, ThreadComms, THREADED_MAIN_WINDOW_ID,
};
#[cfg(feature = "winit-backend")]
use crate::render_thread::{RenderThread, SharedImageDimensions};

Expand Down Expand Up @@ -3540,13 +3542,20 @@ pub unsafe extern "C" fn neomacs_display_drain_input(
Ok(event) => {
let out = &mut *events.add(count as usize);
*out = NeomacsInputEvent::default();
out.window_id = THREADED_MAIN_WINDOW_ID;
out.timestamp = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_millis() as u64)
.unwrap_or(0);

match event {
InputEvent::Key {
window_id,
keysym,
modifiers,
pressed,
} => {
out.window_id = window_id;
out.kind = if pressed {
NEOMACS_EVENT_KEY_PRESS
} else {
Expand All @@ -3556,12 +3565,14 @@ pub unsafe extern "C" fn neomacs_display_drain_input(
out.modifiers = modifiers;
}
InputEvent::MouseButton {
window_id,
button,
x,
y,
pressed,
modifiers,
} => {
out.window_id = window_id;
out.kind = if pressed {
NEOMACS_EVENT_BUTTON_PRESS
} else {
Expand All @@ -3572,35 +3583,50 @@ pub unsafe extern "C" fn neomacs_display_drain_input(
out.button = button;
out.modifiers = modifiers;
}
InputEvent::MouseMove { x, y, modifiers } => {
InputEvent::MouseMove {
window_id,
x,
y,
modifiers,
} => {
out.window_id = window_id;
out.kind = NEOMACS_EVENT_MOUSE_MOVE;
out.x = x as i32;
out.y = y as i32;
out.modifiers = modifiers;
}
InputEvent::MouseScroll {
window_id,
delta_x,
delta_y,
x,
y,
modifiers,
} => {
out.window_id = window_id;
out.kind = NEOMACS_EVENT_SCROLL;
out.x = x as i32;
out.y = y as i32;
out.scroll_delta_x = delta_x;
out.scroll_delta_y = delta_y;
out.modifiers = modifiers;
}
InputEvent::WindowResize { width, height } => {
InputEvent::WindowResize {
window_id,
width,
height,
} => {
out.window_id = window_id;
out.kind = NEOMACS_EVENT_RESIZE;
out.width = width;
out.height = height;
}
InputEvent::WindowClose => {
InputEvent::WindowClose { window_id } => {
out.window_id = window_id;
out.kind = NEOMACS_EVENT_CLOSE;
}
InputEvent::WindowFocus { focused } => {
InputEvent::WindowFocus { window_id, focused } => {
out.window_id = window_id;
out.kind = if focused {
NEOMACS_EVENT_FOCUS_IN
} else {
Expand Down
63 changes: 57 additions & 6 deletions rust/neomacs-display/src/render_thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::core::types::{
AnimatedCursor, Color, CursorAnimStyle, Rect,
ease_out_quad, ease_out_cubic, ease_out_expo, ease_in_out_cubic, ease_linear,
};
use crate::thread_comm::{InputEvent, RenderCommand, RenderComms};
use crate::thread_comm::{InputEvent, RenderCommand, RenderComms, THREADED_MAIN_WINDOW_ID};

#[cfg(all(feature = "wpe-webkit", wpe_platform_available))]
use crate::backend::wpe::sys::platform as plat;
Expand Down Expand Up @@ -2044,18 +2044,28 @@ impl ApplicationHandler for RenderApp {
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
_window_id: WindowId,
window_id: WindowId,
event: WindowEvent,
) {
// Threaded mode currently has a single winit window mapped to Emacs window ID 1.
let emacs_window_id = THREADED_MAIN_WINDOW_ID;

match event {
WindowEvent::CloseRequested => {
log::info!("Window close requested");
self.comms.send_input(InputEvent::WindowClose);
log::info!("Window close requested (winit {:?})", window_id);
self.comms.send_input(InputEvent::WindowClose {
window_id: emacs_window_id,
});
event_loop.exit();
}

WindowEvent::Resized(size) => {
log::info!("WindowEvent::Resized: {}x{}", size.width, size.height);
log::info!(
"WindowEvent::Resized (winit {:?}): {}x{}",
window_id,
size.width,
size.height
);

// Handle wgpu surface resize
self.handle_resize(size.width, size.height);
Expand All @@ -2065,13 +2075,18 @@ impl ApplicationHandler for RenderApp {
let logical_h = (size.height as f64 / self.scale_factor) as u32;
log::info!("Sending WindowResize event to Emacs: {}x{} (logical)", logical_w, logical_h);
self.comms.send_input(InputEvent::WindowResize {
window_id: emacs_window_id,
width: logical_w,
height: logical_h,
});
}

WindowEvent::Focused(focused) => {
self.comms.send_input(InputEvent::WindowFocus { focused });
log::trace!("WindowEvent::Focused({}) for winit {:?}", focused, window_id);
self.comms.send_input(InputEvent::WindowFocus {
window_id: emacs_window_id,
focused,
});
}

WindowEvent::KeyboardInput {
Expand All @@ -2082,8 +2097,16 @@ impl ApplicationHandler for RenderApp {
..
} => {
let keysym = Self::translate_key(&logical_key);
log::trace!(
"WindowEvent::KeyboardInput: key={:?}, keysym=0x{:x}, state={:?}, mods=0x{:x}",
logical_key,
keysym,
state,
self.modifiers
);
if keysym != 0 {
self.comms.send_input(InputEvent::Key {
window_id: emacs_window_id,
keysym,
modifiers: self.modifiers,
pressed: state == ElementState::Pressed,
Expand All @@ -2100,7 +2123,16 @@ impl ApplicationHandler for RenderApp {
MouseButton::Forward => 5,
MouseButton::Other(n) => n as u32,
};
log::trace!(
"WindowEvent::MouseInput: button={}, state={:?}, pos=({}, {}), mods=0x{:x}",
btn,
state,
self.mouse_pos.0,
self.mouse_pos.1,
self.modifiers
);
self.comms.send_input(InputEvent::MouseButton {
window_id: emacs_window_id,
button: btn,
x: self.mouse_pos.0,
y: self.mouse_pos.1,
Expand All @@ -2114,7 +2146,16 @@ impl ApplicationHandler for RenderApp {
let lx = (position.x / self.scale_factor) as f32;
let ly = (position.y / self.scale_factor) as f32;
self.mouse_pos = (lx, ly);
log::trace!(
"WindowEvent::CursorMoved: physical=({}, {}), logical=({}, {}), mods=0x{:x}",
position.x,
position.y,
lx,
ly,
self.modifiers
);
self.comms.send_input(InputEvent::MouseMove {
window_id: emacs_window_id,
x: lx,
y: ly,
modifiers: self.modifiers,
Expand All @@ -2129,7 +2170,16 @@ impl ApplicationHandler for RenderApp {
(pos.y / self.scale_factor) as f32 / 10.0)
}
};
log::trace!(
"WindowEvent::MouseWheel: delta=({}, {}), pos=({}, {}), mods=0x{:x}",
dx,
dy,
self.mouse_pos.0,
self.mouse_pos.1,
self.modifiers
);
self.comms.send_input(InputEvent::MouseScroll {
window_id: emacs_window_id,
delta_x: dx,
delta_y: dy,
x: self.mouse_pos.0,
Expand Down Expand Up @@ -2158,6 +2208,7 @@ impl ApplicationHandler for RenderApp {
if state.super_key() {
self.modifiers |= NEOMACS_SUPER_MASK;
}
log::trace!("WindowEvent::ModifiersChanged: mods=0x{:x}", self.modifiers);
}

_ => {}
Expand Down
27 changes: 23 additions & 4 deletions rust/neomacs-display/src/thread_comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,55 @@
//!
//! Provides lock-free channels and wakeup mechanism between Emacs and render threads.

use crossbeam_channel::{bounded, unbounded, Receiver, Sender};
use crossbeam_channel::{bounded, unbounded, Receiver, Sender, TrySendError};
use std::os::unix::io::RawFd;

use crate::core::frame_glyphs::FrameGlyphBuffer;

/// Emacs window ID used by threaded-mode's single winit window.
pub const THREADED_MAIN_WINDOW_ID: u32 = 1;

/// Input event from render thread to Emacs
#[derive(Debug, Clone)]
pub enum InputEvent {
Key {
window_id: u32,
keysym: u32,
modifiers: u32,
pressed: bool,
},
MouseButton {
window_id: u32,
button: u32,
x: f32,
y: f32,
pressed: bool,
modifiers: u32,
},
MouseMove {
window_id: u32,
x: f32,
y: f32,
modifiers: u32,
},
MouseScroll {
window_id: u32,
delta_x: f32,
delta_y: f32,
x: f32,
y: f32,
modifiers: u32,
},
WindowResize {
window_id: u32,
width: u32,
height: u32,
},
WindowClose,
WindowClose {
window_id: u32,
},
WindowFocus {
window_id: u32,
focused: bool,
},
/// WebKit view title changed
Expand Down Expand Up @@ -331,8 +342,16 @@ pub struct RenderComms {
impl RenderComms {
/// Send input event to Emacs and wake it up
pub fn send_input(&self, event: InputEvent) {
if self.input_tx.try_send(event).is_ok() {
self.wakeup.wake();
match self.input_tx.try_send(event) {
Ok(()) => {
self.wakeup.wake();
}
Err(TrySendError::Full(event)) => {
log::warn!("Dropping input event because channel is full: {:?}", event);
}
Err(TrySendError::Disconnected(event)) => {
log::warn!("Dropping input event because channel is disconnected: {:?}", event);
}
}
}
}
Loading