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
29 changes: 17 additions & 12 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2804,6 +2804,11 @@ CPPFLAGS="$CPPFLAGS -x objective-c"
CFLAGS="$CFLAGS -x objective-c"
GNU_OBJC_CFLAGS=""
LIBS_GNUSTEP=
dnl When building with neomacs display engine, skip NS (Cocoa/GNUstep) detection
dnl entirely. Neomacs uses its own Rust display engine (winit + wgpu/Metal).
if test "${with_neomacs}" = "yes"; then
with_ns=no
fi
if test "${with_ns}" != no; then
# macfont.o requires macuvs.h which is absent after 'make extraclean',
# so avoid NS_IMPL_COCOA if macuvs.h is absent.
Expand Down Expand Up @@ -4009,18 +4014,17 @@ if test "$window_system" = "neomacs"; then
else
AC_MSG_ERROR([cairo required for Neomacs but not found.])
fi
dnl EGL is required for DMA-BUF zero-copy in webkit/video
PKG_CHECK_MODULES([EGL], [egl], [], [AC_MSG_ERROR([EGL required for Neomacs zero-copy rendering])])
dnl WPE WebKit for browser embedding (optional)
HAVE_NEOMACS_WEBKIT=no
PKG_CHECK_MODULES([WPEWEBKIT], [wpe-webkit-2.0], [HAVE_NEOMACS_WEBKIT=yes], [AC_MSG_WARN([WPE WebKit not found, webkit support disabled])])
PKG_CHECK_MODULES([WPEBACKEND], [wpebackend-fdo-1.0], [], [AC_MSG_WARN([wpebackend-fdo not found])])
dnl Wayland-server is needed for wl_shm_buffer functions (SHM fallback mode)
PKG_CHECK_MODULES([WAYLAND_SERVER], [wayland-server], [], [AC_MSG_WARN([wayland-server not found])])
dnl xkbcommon for key name resolution
PKG_CHECK_MODULES([XKBCOMMON], [xkbcommon], [], [AC_MSG_ERROR([xkbcommon required for Neomacs])])
NEOMACS_CFLAGS="$GSTREAMER_CFLAGS $CAIRO_CFLAGS $GLIB_CFLAGS $EGL_CFLAGS $XKBCOMMON_CFLAGS"
NEOMACS_LIBS="$NEOMACS_LIBS $GSTREAMER_LIBS $CAIRO_LIBS $GLIB_LIBS $EGL_LIBS $XKBCOMMON_LIBS -lpthread -lm -ldl"
dnl EGL is required for DMA-BUF zero-copy in webkit/video (Linux only; macOS uses Metal)
if test "$opsys" != "darwin"; then
PKG_CHECK_MODULES([EGL], [egl], [], [AC_MSG_ERROR([EGL required for Neomacs zero-copy rendering])])
dnl WPE WebKit for browser embedding (optional)
PKG_CHECK_MODULES([WPEWEBKIT], [wpe-webkit-2.0], [HAVE_NEOMACS_WEBKIT=yes], [AC_MSG_WARN([WPE WebKit not found, webkit support disabled])])
PKG_CHECK_MODULES([WPEBACKEND], [wpebackend-fdo-1.0], [], [AC_MSG_WARN([wpebackend-fdo not found])])
dnl Wayland-server is needed for wl_shm_buffer functions (SHM fallback mode)
PKG_CHECK_MODULES([WAYLAND_SERVER], [wayland-server], [], [AC_MSG_WARN([wayland-server not found])])
fi
NEOMACS_CFLAGS="$GSTREAMER_CFLAGS $CAIRO_CFLAGS $GLIB_CFLAGS $EGL_CFLAGS"
NEOMACS_LIBS="$NEOMACS_LIBS $GSTREAMER_LIBS $CAIRO_LIBS $GLIB_LIBS $EGL_LIBS -lpthread -lm -ldl"
if test "$HAVE_NEOMACS_WEBKIT" = yes; then
NEOMACS_CFLAGS="$NEOMACS_CFLAGS $WPEWEBKIT_CFLAGS $WPEBACKEND_CFLAGS $WAYLAND_SERVER_CFLAGS"
NEOMACS_LIBS="$NEOMACS_LIBS $WPEWEBKIT_LIBS $WPEBACKEND_LIBS $WAYLAND_SERVER_LIBS"
Expand All @@ -4031,6 +4035,7 @@ AC_SUBST([NEOMACS_LIBS])
AC_SUBST([NEOMACS_CFLAGS])
AC_SUBST([NEOMACS_PREBUILT])
AC_SUBST([NEOMACS_RUST_DYLIB_EXT])
AC_SUBST([HAVE_NEOMACS_WEBKIT])

AC_CHECK_FUNCS([malloc_trim])

Expand Down
36 changes: 35 additions & 1 deletion rust/neomacs-display/src/ffi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,25 @@ pub(crate) static DROPPED_FILES: std::sync::Mutex<Vec<Vec<String>>> = std::sync:
/// Each entry is (terminal_id, new_title).
pub(crate) static TERMINAL_TITLES: std::sync::Mutex<Vec<(u32, String)>> = std::sync::Mutex::new(Vec::new());

// ============================================================================
// macOS pump_events integration
// ============================================================================
// On macOS, winit's EventLoop must be on the main thread. Instead of
// blocking in run_app(), we store the EventLoop and RenderApp in
// thread-local storage and call pump_app_events() periodically from
// Emacs's read_socket hook (neomacs_read_socket) on the main thread.
#[cfg(target_os = "macos")]
pub mod macos_pump {
use std::cell::RefCell;
use winit::event_loop::EventLoop;
use crate::render_thread::RenderApp;

thread_local! {
pub static EVENT_LOOP: RefCell<Option<EventLoop<()>>> = RefCell::new(None);
pub static RENDER_APP: RefCell<Option<RenderApp>> = RefCell::new(None);
}
}

use crate::backend::tty::TtyBackend;
use crate::core::types::{Color, Rect};
use crate::core::scene::{Scene, WindowScene, CursorState, SceneCursorStyle};
Expand Down Expand Up @@ -129,6 +148,21 @@ pub unsafe extern "C" fn neomacs_display_shutdown(handle: *mut NeomacsDisplay) {
return;
}

// On macOS, explicitly drop RenderApp and EventLoop from thread-local
// storage before the process exits. This prevents a panic in winit's
// window_will_close callback, which accesses TLS and fires when the
// Window is dropped. By dropping here (while TLS is still valid) we
// ensure the window is closed cleanly before TLS destructors run.
#[cfg(target_os = "macos")]
{
macos_pump::RENDER_APP.with(|cell: &std::cell::RefCell<Option<crate::render_thread::RenderApp>>| {
let _ = cell.borrow_mut().take();
});
macos_pump::EVENT_LOOP.with(|cell| {
let _ = cell.borrow_mut().take();
});
}

let mut display = Box::from_raw(handle);

if let Some(backend) = display.get_backend() {
Expand Down Expand Up @@ -211,7 +245,7 @@ pub(crate) static TERMINAL_ID_COUNTER: std::sync::atomic::AtomicU32 = std::sync:
// Threaded State
// ============================================================================

use crate::thread_comm::{EmacsComms, EffectUpdater, InputEvent, MenuBarItem, PopupMenuItem, RenderCommand, ThreadComms, ToolBarItem};
use crate::thread_comm::{EmacsComms, EffectUpdater, InputEvent, MenuBarItem, PopupMenuItem, RenderCommand, RenderComms, ThreadComms, ToolBarItem};
use crate::render_thread::{RenderThread, SharedImageDimensions, SharedMonitorInfo};

/// Global state for threaded mode
Expand Down
Loading