From 88ba5ecf9cbb862af521cfde95d8db813ec21406 Mon Sep 17 00:00:00 2001 From: jess Date: Wed, 29 Apr 2026 12:04:12 -0700 Subject: [PATCH] The C-ABI? Who would want access to that? Oh, the Linux Viewport perhaps. --- linux/src/app.rs | 33 ++++++++---------- viewport/src/handle.rs | 78 ++++++++++++++++++++++-------------------- viewport/src/lib.rs | 2 +- 3 files changed, 55 insertions(+), 58 deletions(-) diff --git a/linux/src/app.rs b/linux/src/app.rs index 92a1925..bd6df90 100644 --- a/linux/src/app.rs +++ b/linux/src/app.rs @@ -10,7 +10,7 @@ use winit::keyboard::{Key, ModifiersState, NamedKey}; use winit::window::{Window, WindowAttributes, WindowId}; use acord_viewport::{ - viewport_create, viewport_destroy, viewport_render, viewport_resize, + viewport_destroy, viewport_render, viewport_resize, viewport_set_text, viewport_get_text, viewport_set_theme, viewport_set_lang, viewport_set_line_indicator, viewport_set_gutter_rainbow, viewport_set_auto_pair_flags, @@ -18,6 +18,7 @@ use acord_viewport::{ ViewportHandle, }; use acord_viewport::browser::{self, BrowserHandle}; +use acord_viewport::handle as viewport_handle; use crate::config::Config; use crate::shortcuts::{match_shortcut, MenuAction}; @@ -368,25 +369,19 @@ impl ApplicationHandler for App { let w = size.width as f32 / self.scale; let h = size.height as f32 / self.scale; - // Pass the raw display+window handle to the viewport. wgpu picks the - // X11 or Wayland backend automatically based on which RawDisplayHandle - // variant winit hands us, so a single binary works on both. - use raw_window_handle::HasWindowHandle; - let wh = window.window_handle().expect("window handle"); - let raw = wh.as_raw(); + use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; + let display = window.display_handle().expect("display handle").as_raw(); + let win_handle = window.window_handle().expect("window handle").as_raw(); - let surface_handle = match raw { - #[cfg(target_os = "linux")] - raw_window_handle::RawWindowHandle::Xlib(h) => h.window as *mut std::ffi::c_void, - #[cfg(target_os = "linux")] - raw_window_handle::RawWindowHandle::Xcb(h) => h.window.get() as *mut std::ffi::c_void, - #[cfg(target_os = "linux")] - raw_window_handle::RawWindowHandle::Wayland(h) => h.surface.as_ptr(), - _ => std::ptr::null_mut(), - }; - - self.handle = viewport_create(surface_handle, w, h, self.scale); - self.sync_settings(); + match viewport_handle::create_native(display, win_handle, w, h, self.scale) { + Some(h) => { + self.handle = Box::into_raw(Box::new(h)); + self.sync_settings(); + } + None => { + eprintln!("acord: failed to create viewport surface"); + } + } self.window = Some(window); } diff --git a/viewport/src/handle.rs b/viewport/src/handle.rs index f9fc131..43ce8e9 100644 --- a/viewport/src/handle.rs +++ b/viewport/src/handle.rs @@ -1,31 +1,19 @@ use std::ffi::c_void; +use std::ptr::NonNull; -use iced_graphics::Viewport; -use iced_runtime::user_interface::UserInterface; +use iced_graphics::{Shell, Viewport}; +use iced_runtime::user_interface::{self, UserInterface}; use iced_wgpu::core::renderer::Style; use iced_wgpu::core::time::Instant; -use iced_wgpu::core::{clipboard, keyboard, mouse, window, Color, Event, Size, Theme}; - -#[cfg(any(target_os = "macos", target_os = "windows"))] -use std::ptr::NonNull; -#[cfg(any(target_os = "macos", target_os = "windows"))] -use iced_graphics::Shell; -#[cfg(any(target_os = "macos", target_os = "windows"))] -use iced_runtime::user_interface; -#[cfg(any(target_os = "macos", target_os = "windows"))] -use iced_wgpu::core::{Font, Pixels, Point}; -#[cfg(any(target_os = "macos", target_os = "windows"))] +use iced_wgpu::core::{clipboard, keyboard, mouse, window, Color, Event, Font, Pixels, Point, Size, Theme}; use iced_wgpu::Engine; -#[cfg(any(target_os = "macos", target_os = "windows"))] use raw_window_handle::{RawDisplayHandle, RawWindowHandle}; #[cfg(target_os = "macos")] use raw_window_handle::{AppKitDisplayHandle, AppKitWindowHandle}; #[cfg(target_os = "windows")] use raw_window_handle::{Win32WindowHandle, WindowsDisplayHandle}; -#[cfg(any(target_os = "macos", target_os = "windows"))] -use crate::editor::EditorState; -use crate::editor::{Message, RenderMode}; +use crate::editor::{EditorState, Message, RenderMode}; use crate::palette; use crate::table_block::TableMessage; use crate::ViewportHandle; @@ -60,17 +48,10 @@ impl clipboard::Clipboard for AcordClipboard { } } -#[cfg(not(any(target_os = "macos", target_os = "windows")))] -pub fn create( - _native_handle: *mut c_void, - _width: f32, - _height: f32, - _scale: f32, -) -> Option { - None -} - -#[cfg(any(target_os = "macos", target_os = "windows"))] +/// Mac/Windows entry point used by the C FFI. Synthesizes the platform's +/// display handle from the window pointer the Swift bridge provides. +/// Returns None on platforms that need both display and window — those +/// shells should call `create_native` directly. pub fn create( native_handle: *mut c_void, width: f32, @@ -79,16 +60,6 @@ pub fn create( ) -> Option { let ptr = NonNull::new(native_handle)?; - #[cfg(target_os = "macos")] - let backends = wgpu::Backends::METAL; - #[cfg(target_os = "windows")] - let backends = wgpu::Backends::DX12; - - let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor { - backends, - ..Default::default() - }); - #[cfg(target_os = "macos")] let (raw_window, raw_display) = ( RawWindowHandle::AppKit(AppKitWindowHandle::new(ptr)), @@ -102,6 +73,37 @@ pub fn create( RawDisplayHandle::Windows(WindowsDisplayHandle::new()), ) }; + #[cfg(not(any(target_os = "macos", target_os = "windows")))] + { + let _ = (ptr, width, height, scale); + return None; + } + + #[cfg(any(target_os = "macos", target_os = "windows"))] + create_native(raw_display, raw_window, width, height, scale) +} + +/// Rust-native entry point. Takes typed handles directly so shells that own +/// a winit Window (Linux, future Windows refactor) can build a surface +/// without going through the C FFI's single-pointer compromise. +pub fn create_native( + raw_display: RawDisplayHandle, + raw_window: RawWindowHandle, + width: f32, + height: f32, + scale: f32, +) -> Option { + #[cfg(target_os = "macos")] + let backends = wgpu::Backends::METAL; + #[cfg(target_os = "windows")] + let backends = wgpu::Backends::DX12; + #[cfg(not(any(target_os = "macos", target_os = "windows")))] + let backends = wgpu::Backends::VULKAN | wgpu::Backends::GL; + + let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor { + backends, + ..Default::default() + }); let target = wgpu::SurfaceTargetUnsafe::RawHandle { raw_display_handle: raw_display, diff --git a/viewport/src/lib.rs b/viewport/src/lib.rs index 27c911e..98b029c 100644 --- a/viewport/src/lib.rs +++ b/viewport/src/lib.rs @@ -6,7 +6,7 @@ mod bridge; pub mod browser; mod editor; pub mod export; -mod handle; +pub mod handle; pub mod heading_block; pub mod hr_block; pub mod module;