From 1f30071f6e0ab6f80ed8062d436ba26d35f6b80d Mon Sep 17 00:00:00 2001 From: Avril Date: Thu, 10 Sep 2020 11:14:54 +0100 Subject: [PATCH] initial commit --- .gitignore | 3 + Cargo.toml | 13 +++ README.org | 81 +++++++++++++++++ build.rs | 24 +++++ src/c.rs | 40 +++++++++ src/event.rs | 62 +++++++++++++ src/handle.rs | 22 +++++ src/lib.rs | 30 +++++++ src/types.rs | 239 ++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 514 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 README.org create mode 100644 build.rs create mode 100644 src/c.rs create mode 100644 src/event.rs create mode 100644 src/handle.rs create mode 100644 src/lib.rs create mode 100644 src/types.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5a472f3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +target/ +Cargo.lock +*~ diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..bc1eee3 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "ghost" +version = "0.1.0" +authors = ["Avril "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2.76" + +[build-dependencies] +rustc_version = "0.2" diff --git a/README.org b/README.org new file mode 100644 index 0000000..f2088d6 --- /dev/null +++ b/README.org @@ -0,0 +1,81 @@ +* GHOST Rust bindings + Rust bindings and interop for GHOST. + +** Layout + ABI-compatable types and functions are all prefixed with `GHOST_` and are exported in the `c` module (TODO). + I've attempted to provide more Rust-idiomatic API variants as well, which have non-prefixed names. + +** Implementation log + +*** Implemented C compatable ABI + Note: List is in-progress and doesn't show everything + + - [-] `GHOST_Types.h` + - [X] /Handles/ + - [X] GHOST_SystemHandle + - [X] GHOST_TimerTaskHandle + - [X] GHOST_WindowHandle + - [X] GHOST_EventHandle + - [X] GHOST_RectangleHandle + - [X] GHOST_EventConsumerHandle + - [X] GHOST_ContextHandle + - [X] GHOST_XrContextHandle + - [-] /Primitives/ (ones that begin with =T= I count as `primitive') + - [X] GHOST_TInt8 + - [X] GHOST_TUns8 + - [X] GHOST_Tint16 + - [X] GHOST_TUns16 + - [X] GHOST_Tint32 + - [X] GHOST_TUns32 + - [X] GHOST_TInt64 + - [X] GHOST_TUns64 + - [X] GHOST_TUserDataPtr + - [X] GHOST_TSuccess + - [X] GHOST_TTabletMode + - [X] GHOST_TTabletAPI + - [X] GHOST_TVisibility + - [X] GHOST_TFireTimeConstant + - [X] GHOST_TModifierKeyMask + - [X] GHOST_TWindowState + - [X] GHOST_TWindowOrder + - [X] GHOST_TDrawingContextType + - [X] GHOST_TButtonMask + - [X] GHOST_TEventType + - [ ] GHOST_TStandardCursor + - [ ] GHOST_TKey + - [X] /Structures/ + - [X] GHOST_GLSettings + - [X] GHOST_GLFlags + - [X] GHOST_DialogOptions + - [X] GHOST_TabletData + - [X] /Constants/ + - [X] =GHOST_TABLET_DATA_NONE= + * reimpl as ~const fn~ (~GHOST_TabletData::none()~) + +*** Native Rust API + I provide more Rust idiomatic API for some things. They may or may not share ABI, if they do they will have type aliases to the corresponding ~GHOST_~ identifier, so always use those when ABI compatability is desired. + +**** Overview + List and implementation status of features + + - [-] Types + - [X] [[Handles]]: ~handle.rs~ + - [ ] Events: ~event.rs~ + +**** Handles + Handles keep the C ABI, but are re-wrtten with traits to be more idiomatic. + + The trait ~GhostHandle~ is provided, which should be implemented on a structure that is not intended to be instantiated, but instead used as a `marker' for `Handle'. + These types are ABI equivalent, and are present (with their corresponding ~GHOST_~ alias in =handle.rs=) + Since handles are just types pointers, they are only ever used as such and shouldn't exist themselves. +***** Example + #+BEGIN_SRC rust + extern "C" unsafe fn internal_call(window: GHOST_WindowHandle) -> GHOST_TSuccess; + + fn do_something_to_window(window: &mut Handle) -> Result<()> + { + unsafe { + internal_call(window as GHOST_WindowHandle).into() + } + } + #+END_SRC diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..6399463 --- /dev/null +++ b/build.rs @@ -0,0 +1,24 @@ + +extern crate rustc_version; +use rustc_version::{version, version_meta, Channel}; + +fn main() { + // Assert we haven't travelled back in time + assert!(version().unwrap().major >= 1); + + // Set cfg flags depending on release channel + match version_meta().unwrap().channel { + Channel::Stable => { + println!("cargo:rustc-cfg=stable"); + } + Channel::Beta => { + println!("cargo:rustc-cfg=beta"); + } + Channel::Nightly => { + println!("cargo:rustc-cfg=nightly"); + } + Channel::Dev => { + println!("cargo:rustc-cfg=dev"); + } + } +} diff --git a/src/c.rs b/src/c.rs new file mode 100644 index 0000000..1e815e0 --- /dev/null +++ b/src/c.rs @@ -0,0 +1,40 @@ +//! Re-exports of all ABI-compatable types and functions + +pub use super::{ + types::{ + GHOST_TInt8, + GHOST_TUns8, + GHOST_TUns16, + GHOST_TInt32, + GHOST_TUns32, + GHOST_TInt64, + GHOST_TUns64, + GHOST_TUserDataPtr, + GHOST_TSuccess, + GHOST_TTabletMode, + GHOST_TTabletAPI, + GHOST_TVisibility, + GHOST_TFireTimeConstant, + GHOST_TModifierKeyMask, + GHOST_TWindowState, + GHOST_TWindowOrder, + GHOST_TDrawingContextType, + GHOST_TButtonMask, + GHOST_TEventType, + + GHOST_GLSettings, + GHOST_GLFlags, + GHOST_DialogOptions, + GHOST_TabletData, + }, + handle::{ + GHOST_SystemHandle, + GHOST_TimerTaskHandle, + GHOST_WindowHandle, + GHOST_EventHandle, + GHOST_RectangleHandle, + GHOST_EventConsumerHandle, + GHOST_ContextHandle, + GHOST_XrContextHandle, + }, +}; diff --git a/src/event.rs b/src/event.rs new file mode 100644 index 0000000..5feb610 --- /dev/null +++ b/src/event.rs @@ -0,0 +1,62 @@ +//! Rust interface for Event handlers (`GHOST_TEventType` et. al) +use super::*; + +pub enum CursorEventType +{ + Move, + ButtonDown, + ButtonUp, + Wheel, + Trackpad, +} + +pub enum KeyboardEventType +{ + KeyUp, + KeyDown, + // Auto, +} + +pub enum WindowEventType +{ + Close, + Activate, + Deactivate, + Update, + Size, + Move, + DPIHintChanged, +} + +pub enum DragEventType +{ + Entered, + Updated, + Exited, + DropDone, +} + +pub enum ImeCompositionEventType +{ + Composition, + Start, + End, +} + +pub enum EventType +{ + Cursor(CursorEventType), + Keyboard(KeyboardEventType), + + QuitRequest, + Window(WindowEventType), + + Drag(DragEventType), + + OpenMainFile, + NativeResolutionChange, + + Timer, + + ImeComposition(ImeCompositionEventType), +} diff --git a/src/handle.rs b/src/handle.rs new file mode 100644 index 0000000..d159bd2 --- /dev/null +++ b/src/handle.rs @@ -0,0 +1,22 @@ +//! GHOST_Types.h +use super::*; + +use types::{Handle,GhostHandle}; + +macro_rules! handle { + ($name:ident, $inner_name:ident) => { + #[cfg(nightly)] pub struct $inner_name(!); + #[cfg(not(nightly))] pub struct $inner_name(()); + impl GhostHandle for $inner_name{} + pub type $name = *mut Handle<$inner_name>; + }; +} + +handle!(GHOST_SystemHandle, System); +handle!(GHOST_TimerTaskHandle, TimerTask); +handle!(GHOST_WindowHandle, Window); +handle!(GHOST_EventHandle, Event); +handle!(GHOST_RectangleHandle, Rectangle); +handle!(GHOST_EventConsumerHandle, EventConsumer); +handle!(GHOST_ContextHandle, Context); +handle!(GHOST_XrContextHandle, XrContextHandle); diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..b1fcebd --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,30 @@ +//! Rust bindings and interop for GHOST. +//! +//! # Layout +//! ABI-compatable types and functions are all prefixed with `GHOST_` and are exported in the `c` module (TODO). +//! I've attempted to provide more Rust-idiomatic API variants as well, which have non-prefixed names. + +#![cfg_attr(nightly, feature(never_type))] + +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +#[cfg(nightly)] pub type PVoid = *const !; +#[cfg(not(nightly))] pub type PVoid = *const libc::c_void; +#[cfg(nightly)] pub type PVoidMut = *mut !; +#[cfg(not(nightly))] pub type PVoidMut = *mut libc::c_void; + +pub mod handle; +pub mod event; +pub mod types; + +pub mod c; + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn it_works() { + // nothing yet. + } +} diff --git a/src/types.rs b/src/types.rs new file mode 100644 index 0000000..33d98e3 --- /dev/null +++ b/src/types.rs @@ -0,0 +1,239 @@ +//! GHOST_Types.h +use super::*; +use libc::{ + c_int, +}; +use std::{ + marker::{ + PhantomData, + }, +}; + +/// Trait for opaque types that represent GHOST handles +/// API maps vaguely to `GHOST_DECLARE_HANDLE`. +pub trait GhostHandle{} + +/// Opaque handle type for GHOST C++ object. +#[repr(C)] +pub struct Handle(c_int, PhantomData) +where T: GhostHandle; + +pub type GHOST_TInt8 = libc::c_char; +pub type GHOST_TUns8 = libc::c_uchar; +pub type GHOST_TUns16 = libc::c_ushort; +pub type GHOST_TInt32 = libc::c_int; +pub type GHOST_TUns32 = libc::c_uint; +// -- skip MSVC specific shit. I'm not testing on that +pub type GHOST_TInt64 = libc::c_longlong; +pub type GHOST_TUns64 = libc::c_ulonglong; +pub type GHOST_TUserDataPtr = PVoidMut; + +#[repr(C)] +pub struct GHOST_GLSettings +{ + pub flags: c_int, +} + +#[repr(C)] +pub enum GHOST_GLFlags +{ + StereoVisual = 1<<0, + DebugContext = 1<<1, + AlphaBackground = 1<<2, +} + +#[repr(C)] +pub enum GHOST_DialogOptions +{ + DialogWarning = 1<<0, + DialogError = 1<<1, +} + +pub type DialogOptions = GHOST_DialogOptions; + +#[repr(C)] +pub enum GHOST_TSuccess +{ + Failure = 0, + Success, +} + +#[repr(C)] +pub enum GHOST_TTabletMode +{ + None = 0, + Stylus, + Eraser, +} + +impl Default for GHOST_TTabletMode +{ + #[inline] + fn default() -> Self + { + Self::None + } +} + + +#[repr(C)] +pub enum GHOST_TTabletAPI +{ + None = 0, + Native, + Wintab, +} + +impl Default for GHOST_TTabletAPI +{ + #[inline] + fn default() -> Self + { + Self::None + } +} + + +#[repr(C)] +pub struct GHOST_TabletData +{ + pub active: GHOST_TTabletMode, + pub pressure: f32, + pub xtilt: f32, + pub ytilt: f32, +} + +impl GHOST_TabletData +{ + pub const fn none() -> Self{ + Self{active: GHOST_TTabletMode::None, pressure: 1.0, xtilt: 0.0, ytilt: 0.0} + } +} + +impl Default for GHOST_TabletData +{ + #[inline] fn default() -> Self + { + Self::none() + } +} + +#[repr(C)] +pub enum GHOST_TVisibility +{ + Not =0, + Partially, + Fully, +} + +impl Default for GHOST_TVisibility +{ + #[inline] + fn default() -> Self + { + Self::Not + } +} + +#[repr(C)] +pub enum GHOST_TFireTimeConstant +{ + Never = 0xFFFFFFFF, +} + + +#[repr(C)] +pub enum GHOST_TModifierKeyMask { + LeftShift = 0, + RightShift, + LeftAlt, + RightAlt, + LeftControl, + RightControl, + OS, + NumMasks +} + +#[repr(C)] +pub enum GHOST_TWindowState { + Normal = 0, + Maximized, + Minimized, + FullScreen, + Embedded, + // Modified, + // UnModified, +} + +#[repr(C)] +pub enum GHOST_TWindowOrder +{ + Top =0, + Bottom, +} + +#[repr(C)] +pub enum GHOST_TDrawingContextType { + None = 0, + OpenGL, + //D3D, //lol nope +} + +#[repr(C)] +pub enum GHOST_TButtonMask{ + Left = 0, + Middle, + Right, + Button4, + Button5, + /* Trackballs and programmable buttons */ + Button6, + Button7, + NumMasks // Should we even keep this? I guess yeah for ABI compatability +} + +#[repr(C)] +pub enum GHOST_TEventType { + Unknown = 0, + + CursorMove, + ButtonDown, + ButtonUp, + Wheel, + Trackpad, + +//#ifdef WITH_INPUT_NDOF +// NDOFMotion, /// N degree of freedom device motion event +// NDOFButton, /// N degree of freedom device button event +//#endif + + KeyDown, + KeyUp, + // KeyAuto, + + QuitRequest, + + WindowClose, + WindowActivate, + WindowDeactivate, + WindowUpdate, + WindowSize, + WindowMove, + WindowDPIHintChanged, + + DraggingEntered, + DraggingUpdated, + DraggingExited, + DraggingDropDone, + + OpenMainFile, // Needed for Cocoa to open double-clicked .blend file at startup + NativeResolutionChange, // Needed for Cocoa when window moves to other display + + Timer, + + ImeCompositionStart, + ImeComposition, + ImeCompositionEnd, + + NumEventTypes +}